ЛР7. Добавление методички

This commit is contained in:
Andrei Solodovnikov
2023-10-16 13:15:24 +03:00
committed by GitHub
parent 70d703154e
commit c2d903da7c

View File

@@ -1 +1,86 @@
# PLACEHOLDER # Лабораторная работа 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 == 0` или `write_enable_i == 1` (т.е. когда не выполняется операция чтения), на выходе `read_data_o` должно оказаться значение `32'hfa11_1eaf`.
- В случае, если `mem_req_i == 1` и значение `addr_i` **попадает** в диапазон `[0:16383]` (4096*4-1), на выходе `read_data_o` должно оказаться значение ячейки по адресу в 4 раза меньше пришедшего.
- В случае, если `mem_req_i == 1` и значение `addr_i` **не попадает** в диапазон `[0:16383]`, на выходе `read_data_o` должно оказаться магическое число `32'hdead_beef`.
Данные условия должны проверяться **строго** в указанном порядке (с указанным **приоритетом**) с помощью цепочки `if-else-if-else`, причем обязательно с блоками `else`.
Иными словами, логика реализации порта на чтение повторяет эту логику из памяти данных лабораторной работы №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" и убедиться, что в логе есть сообщение о завершении теста!**