mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 17:20:10 +00:00
В основном вставка пропущенных запятых и удаление лишнего пробела из союза "а также", но были и другие ошибки и опечатки.
81 lines
8.9 KiB
Markdown
81 lines
8.9 KiB
Markdown
# Лабораторная работа 7 "Внешняя память"
|
||
|
||
Ранее вы реализовали процессор архитектуры RISC-V с оговоркой что он не поддерживает инструкции `sh`, `sb`, `lh`, `lhu`, `lb`, `lbu`. Данное ограничение имеет две причины:
|
||
|
||
- вам нужен модуль, который будет определенным образом взаимодействовать с памятью в зависимости от конкретной инструкции загрузки или сохранения (**модуль загрузки и сохранения**, о котором будет рассказано на [следующей](../08.%20Load-store%20unit) лабораторной работе);
|
||
- вам нужна внешняя память, которая будет способна делать то, что от нее запросит модуль загрузки и сохранения.
|
||
|
||
Реализации такой памяти и будет посвящена эта лабораторная работа.
|
||
|
||
## Цель
|
||
|
||
Описать внешнюю память данных, полностью поддерживающую побайтовую адресацию.
|
||
|
||
## Допуск к лабораторной работе
|
||
|
||
Для успешного выполнения лабораторной работы, вам необходимо:
|
||
|
||
- выполнить [лабораторную работу №3](../03.%20Register%20file%20and%20memory/) "Регистровый файл и внешняя память";
|
||
- освоить оператор конкатенации ([Concatenation.md](../../Basic%20Verilog%20structures/Concatenation.md)).
|
||
|
||
## Теория
|
||
|
||
В задании по реализации памяти инструкций [лабораторной работы №3](../03.%20Register%20file%20and%20memory/) байтовая адресация была описана следующим образом:
|
||
|
||
> Байтовая адресация означает, что процессор способен обращаться к отдельным байтам в памяти (за каждым байтом памяти закреплен свой индивидуальный адрес).
|
||
|
||
Данное описание было дано не совсем корректным образом, чтобы в третьей лабораторной работе было более четкое понимание задания. В чем заключается некорректность? Процессор должен быть способен не только **обращаться** к отдельным байтам в памяти, но и **обновлять** в памяти любой отдельный байт, а также **считывать** отдельные байты.
|
||
|
||
Вопрос считывания отдельного байта будет решаться модулем загрузки и сохранения, данному модулю будет достаточно возвращать все слово, содержащее запрашиваемый байт как это было сделано в рамках лабораторной работы №3.
|
||
|
||
Нас интересует возможность памяти обновлять любой из байт в слове. Для этого используется специальный сигнал, который называется `byte_enable_i`. Разрядность этого сигнала равна числу байт в ячейке памяти (в данном случае разрядность `byte_enable_i` составляет 4). Вы можете представить `byte_enable_i`, как 4 провода, каждый из которых является сигналом разрешения записи для 8-ми D-триггеров, формирующих соответствующий этому проводу байт.
|
||
|
||
При этом не стоит забывать о том, что записью управляет еще и сигнал `write_enable_i`, определяющий режим работы памяти: запись или чтение.
|
||
|
||
Таким образом, для каждого байта `addr_i / 4`-ой ячейки памяти:
|
||
|
||
**если** `write_enable_i` равен единице **и** соответствующий этому байту бит сигнала `byte_enable_i`, то в данный байт памяти записывается соответствующий байт сигнала `write_data_i`.
|
||
|
||
При этом значение `byte_enable_i` может быть любым: если `byte_enable_i == 4'b1001` (при `write_enable == 1'b1`), то данные должны быть записаны в старший и младший байты `addr_i / 4`-ой ячейки памяти.
|
||
|
||
## Задание
|
||
|
||
Реализовать память данных с поддержкой обновления отдельных байт в выбранной ячейке памяти. Прототип модуля следующий (обратите внимание что название модуля отличается от названия памяти данных из третьей лабораторной работы — так мы сможем различать их):
|
||
|
||
```SystemVerilog
|
||
module ext_mem(
|
||
input logic clk_i,
|
||
input logic mem_req_i,
|
||
input logic write_enable_i,
|
||
input logic [ 3:0] byte_enable_i,
|
||
input logic [31:0] addr_i,
|
||
input logic [31:0] write_data_i,
|
||
output logic [31:0] read_data_o,
|
||
output logic ready_o
|
||
);
|
||
```
|
||
|
||
Как и память данных из лабораторной работы №3, память данных в данной лабораторной состоит из 4096-и 32-разрядных ячеек и обладает портом синхронного чтения, обновляющим данные только по запросу на чтение (`mem_req_i & !write_enable_i`).
|
||
|
||
Иными словами, логика реализации порта на чтение повторяет логику памяти данных лабораторной работы №3 (можно скопировать эту логику).
|
||
|
||
Если `mem_req_i == 1` и `write_enable_i == 1` (т.е. если происходит запрос на запись в память), то необходимо обновить данные в тех байтах `addr_i / 4`-ой ячейки памяти, которые соответствуют единичным битам сигнала `byte_enable_i`.
|
||
|
||
Сигнал `ready_o` тождественно равен единице.
|
||
|
||
## Порядок выполнения работы
|
||
|
||
1. Внимательно ознакомьтесь с заданием. В случае возникновения вопросов, проконсультируйтесь с преподавателем.
|
||
2. Реализуйте память данных. Для этого:
|
||
1. В `Design Sources` проекта создайте `SystemVerilog`-файл `ext_mem.sv`.
|
||
2. Опишите в нем модуль памяти данных с таким же именем и портами, как указано в задании.
|
||
1. Данный модуль будет очень похож на память данных из лабораторной работы №3 (в частности, логика порта на чтение будет в точности повторять логику той памяти данных).
|
||
2. Отличие заключается в двух новых сигналах `ready_o` и `byte_enable_i`.
|
||
1. Сигнал `ready_o` тождественно равен единице.
|
||
2. Сигнал `byte_enable_i` используется в качестве сигнала, разрешающего запись (в случае операции записи) в конкретный байт ячейки памяти.
|
||
3. После описания памяти данных, её необходимо проверить с помощью тестового окружения.
|
||
1. Тестовое окружение находится [`здесь`](tb_ext_mem.sv).
|
||
2. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md).
|
||
3. Перед запуском симуляции убедитесь, что в качестве top-level модуля выбран корректный (`tb_ext_mem`).
|
||
4. **Во время симуляции, вы должны прожать "Run All" и убедиться, что в логе есть сообщение о завершении теста!**
|