# Лабораторная работа 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" и убедиться, что в логе есть сообщение о завершении теста!**