From 85883858ac4bca3706ac9473a264684c8d7a7fba Mon Sep 17 00:00:00 2001 From: Andrei Solodovnikov Date: Tue, 2 Jul 2024 10:24:41 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=BA=D0=B0=20=D0=BB=D0=B0=D0=B1=D0=BE=D1=80=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=BD=D1=8B=D1=85=20=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82,=20=D1=81=D0=B2=D1=8F=D0=B7=D0=B0=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D1=85=20=D1=81=20=D0=BF=D0=B0=D0=BC=D1=8F=D1=82=D1=8C=D1=8E=20?= =?UTF-8?q?(#89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Переработка лабораторных работ, связанных с памятью Существенно переработаны ЛР3 и ЛР7: Из ЛР3 убрано задание реализовать память данных. Эта память использовалась только студентами ИВТ и только в рамках одной лабы. В итоге использовалась готовая память, и ничего не мешает использовать ее с самого начала. Задание по реализации памяти инструкций также претерпело изменения. Теперь код памяти инструкций предоставляется сразу. Это объясняется тем, что код модуля состоит в общем-то из 4х строк, на которые тратится слишком много времени (с учетом добавления тестбенча и проверок). Кроме того, использование готового кода позволяет дать модуль чуть посложнее (с параметризацией размера). По итогу правок, третья лабораторная работа превращается чисто в лабораторную по написанию регистрового файла, что должно положительно сказаться на кривой сложности лаб. После второй лабы происходит слишком резкий скачок в объемах работы. Соответственно, в связи с тем, что память данных больше не делается на третьей лабе, дополнительная ЛР по памяти данных с byte enable необходимо перенести до реализации тракта данных. * ЛР3, 5, 6. Правки из ревью * ЛР7. Добавление иллюстраций --- .github/SUMMARY.md | 4 +- .github/index.md | 4 +- .pic/Labs/lab_06_dp/fig_02.drawio.svg | 4 - .pic/Labs/lab_06_main_memory/fig_01.png | Bin 0 -> 7051 bytes .pic/Labs/lab_06_main_memory/fig_01.xlsx | Bin 0 -> 9885 bytes .../lab_06_main_memory/fig_02.wavedrom.svg | 4 + .../lab_06_main_memory/fig_03.wavedrom.svg | 4 + ....drawio.svg => lab_07_datapath.drawio.svg} | 0 .../fig_01.drawio.svg | 0 .pic/Labs/lab_07_dp/fig_02.drawio.svg | 4 + .../{lab_06_dp => lab_07_dp}/fig_02.excel.png | Bin .../Labs/{lab_06_dp => lab_07_dp}/fig_02.xlsx | Bin Labs/03. Register file and memory/README.md | 117 ++++++++--------- .../memory_pkg.sv | 18 +++ .../tb_data_mem.sv | 110 ---------------- .../tb_instr_mem.sv | 75 ----------- Labs/05. Main decoder/README.md | 8 +- .../{riscv_pkg.sv => decoder_pkg.sv} | 4 +- Labs/05. Main decoder/tb_decoder_riscv.sv | 2 +- Labs/06. Main memory/README.md | 122 ++++++++++++++++++ Labs/06. Main memory/memory_pkg.sv | 18 +++ Labs/{06. Datapath => 07. Datapath}/README.md | 16 +-- .../alu_opcodes_pkg.sv | 0 .../board files/README.md | 2 +- .../board files/nexys_a7_100t.xdc | 0 .../board files/nexys_riscv_unit.sv | 2 +- .../{06. Datapath => 07. Datapath}/csr_pkg.sv | 0 .../decoder_pkg.sv} | 2 +- Labs/07. Datapath/memory_pkg.sv | 18 +++ .../program.mem | 0 .../tb_riscv_unit.sv | 0 Labs/07. External memory/README.md | 80 ------------ Labs/08. Load-store unit/tb_lsu.sv | 4 +- .../{lab_07.ext_mem.sv => lab_06.data_mem.sv} | 2 +- Labs/Made-up modules/lab_08.lsu.sv | 2 +- Labs/README.md | 20 +-- 36 files changed, 278 insertions(+), 368 deletions(-) delete mode 100644 .pic/Labs/lab_06_dp/fig_02.drawio.svg create mode 100644 .pic/Labs/lab_06_main_memory/fig_01.png create mode 100644 .pic/Labs/lab_06_main_memory/fig_01.xlsx create mode 100644 .pic/Labs/lab_06_main_memory/fig_02.wavedrom.svg create mode 100644 .pic/Labs/lab_06_main_memory/fig_03.wavedrom.svg rename .pic/Labs/{lab_06_datapath.drawio.svg => lab_07_datapath.drawio.svg} (100%) rename .pic/Labs/{lab_06_dp => lab_07_dp}/fig_01.drawio.svg (100%) create mode 100644 .pic/Labs/lab_07_dp/fig_02.drawio.svg rename .pic/Labs/{lab_06_dp => lab_07_dp}/fig_02.excel.png (100%) rename .pic/Labs/{lab_06_dp => lab_07_dp}/fig_02.xlsx (100%) create mode 100644 Labs/03. Register file and memory/memory_pkg.sv delete mode 100644 Labs/03. Register file and memory/tb_data_mem.sv delete mode 100644 Labs/03. Register file and memory/tb_instr_mem.sv rename Labs/05. Main decoder/{riscv_pkg.sv => decoder_pkg.sv} (98%) create mode 100644 Labs/06. Main memory/README.md create mode 100644 Labs/06. Main memory/memory_pkg.sv rename Labs/{06. Datapath => 07. Datapath}/README.md (96%) rename Labs/{06. Datapath => 07. Datapath}/alu_opcodes_pkg.sv (100%) rename Labs/{06. Datapath => 07. Datapath}/board files/README.md (92%) rename Labs/{06. Datapath => 07. Datapath}/board files/nexys_a7_100t.xdc (100%) rename Labs/{06. Datapath => 07. Datapath}/board files/nexys_riscv_unit.sv (99%) rename Labs/{06. Datapath => 07. Datapath}/csr_pkg.sv (100%) rename Labs/{06. Datapath/riscv_pkg.sv => 07. Datapath/decoder_pkg.sv} (98%) create mode 100644 Labs/07. Datapath/memory_pkg.sv rename Labs/{06. Datapath => 07. Datapath}/program.mem (100%) rename Labs/{06. Datapath => 07. Datapath}/tb_riscv_unit.sv (100%) delete mode 100644 Labs/07. External memory/README.md rename Labs/Made-up modules/{lab_07.ext_mem.sv => lab_06.data_mem.sv} (99%) diff --git a/.github/SUMMARY.md b/.github/SUMMARY.md index f00a9d0..9217a76 100644 --- a/.github/SUMMARY.md +++ b/.github/SUMMARY.md @@ -21,8 +21,8 @@ - [Лабораторная №3. Регистровый файл и внешняя память](Labs/03.%20Register%20file%20and%20memory/README.md) - [Лабораторная №4. Простейшее программируемое устройство](Labs/04.%20Primitive%20programmable%20device/README.md) - [Лабораторная №5. Основной дешифратор](Labs/05.%20Main%20decoder/README.md) -- [Лабораторная №6. Тракт данных](Labs/06.%20Datapath/README.md) -- [Лабораторная №7. Внешняя память](Labs/07.%20External%20memory/README.md) +- [Лабораторная №6. Основная память](Labs/06.%20Main%20memory/README.md) +- [Лабораторная №7. Тракт данных](Labs/07.%20Datapath/README.md) - [Лабораторная №8. Блок загрузки и сохранения](Labs/08.%20Load-store%20unit/README.md) - [Лабораторная №9. Интеграция LSU](Labs/09.%20LSU%20Integration/README.md) - [Лабораторная №10. Подсистема прерываний](Labs/10.%20Interrupt%20subsystem/README.md) diff --git a/.github/index.md b/.github/index.md index 7a31586..31d857a 100644 --- a/.github/index.md +++ b/.github/index.md @@ -24,7 +24,7 @@ 4. Простейшее программируемое устройство ([04. Primitive programmable device](Labs/04.%20Primitive%20programmable%20device)) 5. Основной дешифратор ([05. Main decoder](Labs/05.%20Main%20decoder)) 6. - 1. Тракт данных ([06. Datapath](Labs/06.%20Datapath)) + 1. Тракт данных ([07. Datapath](Labs/07.%20Datapath)) 2. Интеграция блока загрузки и сохранения ([09. LSU Integration](Labs/09.%20LSU%20Integration)) 3. Интеграция подсистемы прерываний ([11. Interrupt Integration](Labs/11.%20Interrupt%20integration)) 7. Периферийные устройства ([13. Peripheral units](Labs/13.%20Peripheral%20units)) @@ -37,7 +37,7 @@ 1. Память ([03. Register file and memory](Labs/03.%20Register%20file%20and%20memory)), 2. Простейшее программируемое устройство ([04. Primitive programmable device](Labs/04.%20Primitive%20programmable%20device)) 3. Основной дешифратор ([05. Main decoder](Labs/05.%20Main%20decoder)) -4. Тракт данных ([06. Datapath](Labs/06.%20Datapath)) +4. Тракт данных ([07. Datapath](Labs/07.%20Datapath)) 5. 1. Модуль загрузки и сохранения ([08. Load-store unit](Labs/08.%20Load-store%20unit)) 2. Интеграция блока загрузки и сохранения ([09. LSU Integration](Labs/09.%20LSU%20Integration)) diff --git a/.pic/Labs/lab_06_dp/fig_02.drawio.svg b/.pic/Labs/lab_06_dp/fig_02.drawio.svg deleted file mode 100644 index 2810694..0000000 --- a/.pic/Labs/lab_06_dp/fig_02.drawio.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -
Core

rst_i
mem_rd_i
clk_i
Instruction
Memory
A
RD

32
/

instr_i
mem_size_o

/

32

rst_i

instr_addr
instr
clk_i

rst_i

- входные сигналы
mem_we_o
mem_req_o
mem_wd_o
mem_addr_o
instr_addr_o
не подключен
3
stall_i
stall
clk_i
Data
Memory
A
WE
RD

32
/

clk_i
req
WD
32
32

rst_i

\ No newline at end of file diff --git a/.pic/Labs/lab_06_main_memory/fig_01.png b/.pic/Labs/lab_06_main_memory/fig_01.png new file mode 100644 index 0000000000000000000000000000000000000000..79193bdea596fb6a027855f5e984386ce5c5f3dc GIT binary patch literal 7051 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 + + +clkmem_req_iaddr_i0x80x90x4write_enable_iread_data_o0xDEAD_BEEF0xBABE_FACE0xFA11_1EAFready_o \ No newline at end of file diff --git a/.pic/Labs/lab_06_main_memory/fig_03.wavedrom.svg b/.pic/Labs/lab_06_main_memory/fig_03.wavedrom.svg new file mode 100644 index 0000000..8857455 --- /dev/null +++ b/.pic/Labs/lab_06_main_memory/fig_03.wavedrom.svg @@ -0,0 +1,4 @@ + + + +clkmem_req_iwrite_enable_ibyte_enable_i0b11110b00010b00110b11000b1111write_data_i0xDEAD_BEEF0xBABE_FACE0xFA11_1EAF0xFE11_0BAD0x000000000xAFmem[addr]0x000000000xDEAD_BEEF0xDEAD_BECE0xDEAD_1EAF0xFE11_1EAF0x00000000 \ No newline at end of file diff --git a/.pic/Labs/lab_06_datapath.drawio.svg b/.pic/Labs/lab_07_datapath.drawio.svg similarity index 100% rename from .pic/Labs/lab_06_datapath.drawio.svg rename to .pic/Labs/lab_07_datapath.drawio.svg diff --git a/.pic/Labs/lab_06_dp/fig_01.drawio.svg b/.pic/Labs/lab_07_dp/fig_01.drawio.svg similarity index 100% rename from .pic/Labs/lab_06_dp/fig_01.drawio.svg rename to .pic/Labs/lab_07_dp/fig_01.drawio.svg diff --git a/.pic/Labs/lab_07_dp/fig_02.drawio.svg b/.pic/Labs/lab_07_dp/fig_02.drawio.svg new file mode 100644 index 0000000..2ca6f50 --- /dev/null +++ b/.pic/Labs/lab_07_dp/fig_02.drawio.svg @@ -0,0 +1,4 @@ + + + +
Core

rst_i
mem_rd_i
clk_i
Instruction
Memory
A
RD

32
/

instr_i
mem_size_o

/

32

rst_i

instr_addr
instr
clk_i

rst_i

- входные сигналы
mem_we_o
mem_req_o
mem_wd_o
mem_addr_o
instr_addr_o
не подключен
3
stall_i
stall
clk_i

32
/

32
32

rst_i

Data
Memory
A
WE
RD
clk_i
req
WD
BE
READY
не подключен
4'b1111
4
\ No newline at end of file diff --git a/.pic/Labs/lab_06_dp/fig_02.excel.png b/.pic/Labs/lab_07_dp/fig_02.excel.png similarity index 100% rename from .pic/Labs/lab_06_dp/fig_02.excel.png rename to .pic/Labs/lab_07_dp/fig_02.excel.png diff --git a/.pic/Labs/lab_06_dp/fig_02.xlsx b/.pic/Labs/lab_07_dp/fig_02.xlsx similarity index 100% rename from .pic/Labs/lab_06_dp/fig_02.xlsx rename to .pic/Labs/lab_07_dp/fig_02.xlsx diff --git a/Labs/03. Register file and memory/README.md b/Labs/03. Register file and memory/README.md index f46e522..ee1b55d 100644 --- a/Labs/03. Register file and memory/README.md +++ b/Labs/03. Register file and memory/README.md @@ -1,4 +1,4 @@ -# Лабораторная работа 3 "Регистровый файл и внешняя память" +# Лабораторная работа 3 "Регистровый файл и память инструкций" Процессор — это программно-управляемое устройство, выполняющее обработку информации и управление этим процессом. Очевидно, программа, которая управляет процессором, должна где-то храниться. Данные, с которыми процессор работает, тоже должны быть в доступном месте. Нужна память! @@ -6,11 +6,10 @@ Описать на языке SystemVerilog элементы памяти для будущего процессора: -- память команд (Instruction Memory); -- память данных (Data Memory); +- память инструкций (Instruction Memory); - регистровый файл (Register File). -## Допуск к лабораторной работе +## Материалы для подготовки к лабораторной работе Для успешного выполнения лабораторной работы, вам необходимо освоить: @@ -21,7 +20,7 @@ 1. Изучить способы организации памяти (раздел [#теория про память](#теория-про-память)). 2. Изучить конструкции SystemVerilog для реализации запоминающих элементов (раздел [#инструменты](#инструменты-для-реализации-памяти)). -3. В проекте с прошлой лабораторной реализовать модули: Instruction Memory, Data Memory и Register File ([#задание](#задание-по-реализации-памяти)). +3. В проекте с прошлой лабораторной реализовать модули: Instruction Memory и Register File ([#задание](#задание-по-реализации-памяти)). 4. Проверить с помощью тестового окружения корректность их работы. 5. Проверить работу регистрового файла в ПЛИС. @@ -66,7 +65,7 @@ _Рисунок 1. Примеры блоков ПЗУ и ОЗУ._ _Рисунок 2. Структурная схема логического блока в ПЛИС[[1]](https://en.wikipedia.org/wiki/Field-programmable_gate_array)._ -В логическом блоке есть **таблицы подстановки** (Look Up Table, LUT), которые представляют собой не что иное как память, которая переконфигурируется под нужды хранения, а не реализацию логики. Таким образом, трехвходовой LUT может выступать в роли восьмиразрядной памяти. +В логическом блоке есть **таблицы подстановки** (Look Up Table, LUT), которые представляют собой не что иное как память, которая переконфигурируется под нужды хранения, а не реализацию логики. Таким образом, трехвходовой LUT может выступать в роли 8-битной памяти. Однако LUT будет сложно приспособить под многопортовую память: посмотрим на схему еще раз: три входа LUT формируют адрес одной из восьми ячеек. Это означает, что среди этих восьми ячеек нельзя обратиться к двум из них одновременно. @@ -116,6 +115,12 @@ logic [19:0] memory3 [1:16]; // А вот memory3 хоть и совпадае Для обращения к конкретной ячейке памяти используются квадратные скобки с указанием нужного адреса `memory[addr]`. Грубо говоря, то, что указывается в квадратных скобках будет подключено ко входу адреса памяти `memory`. +Чтение из памяти может быть сделано двумя способами: синхронно и асинхронно. + +Синхронное чтение подразумевает ожидание следующего тактового синхроимпульса для выдачи данных после получения адреса. Иными словами, данные будут установлены на выходе не в тот же такт, когда был выставлен адрес на вход памяти данных, а на следующий. Не смотря на то, что в таком случае на каждой операции чтения "теряется" один такт, память с синхронным чтением имеет значительно меньший критический путь, чем положительно сказывается на временных характеристиках итоговой схемы. + +Память с асинхронным чтением выдает данные в том же такте, что и получает адрес (т.е. ведет себя как комбинационная схема). Несмотря на то, что такой подход кажется быстрее, память с асинхронным чтением обладает длинным критическим путем, причем чем большего объема будет память, тем длиннее будет критический путь. + Реализация асинхронного подключения к выходу памяти осуществляется оператором `assign`. А, если требуется создать память с синхронным чтением, то присваивание выходу требуется описать внутри блока`always_ff`. Так как запись в память является синхронным событием, то описывается она в конструкции `always_ff`. При этом, как и при описании регистра, можно реализовать управляющий сигнал разрешения на запись через блок вида `if(write_enable)`. @@ -186,7 +191,7 @@ module rom16_8 ( logic [7:0] ROM [0:15]; // создать память с 16-ю 8-битными ячейками initial begin - $readmemh("rom_data.mem", ROM); // поместить в память RAM содержимое + $readmemh("rom_data.mem", ROM); // поместить в память ROM содержимое end // файла rom_data.mem @@ -210,11 +215,10 @@ endmodule ## Задание по реализации памяти -Необходимо описать на языке SystemVerilog три вида памяти: +Необходимо описать на языке SystemVerilog два вида памяти: 1. память инструкций; -2. память данных; -3. регистровый файл. +2. регистровый файл. ### 1. Память инструкций @@ -234,44 +238,53 @@ mоdulе instr_mеm( При этом по спецификации процессор RISC-V использует память с побайтовой адресацией. Байтовая адресация означает, что процессор способен обращаться к отдельным байтам в памяти (за каждым байтом памяти закреплен свой индивидуальный адрес). -Однако, если у памяти будут 32-рязрядные ячейки, доступ к конкретному байту будет осложнен, ведь каждая ячейка — это 4 байта. Как получить данные третьего байта памяти? Если обратиться к третьей ячейке в массиве — придут данные 12-15-ых байт (поскольку каждая ячейка содержит по 4 байта). Чтобы получить данные третьего байта, необходимо **разделить значение пришедшего адреса на 4** (отбросив остаток от деления). `3 / 4 = 0` — и действительно, если обратиться к нулевой ячейке памяти — будут получены данные 3-го, 2-го, 1-го и 0-го байт. То, что помимо значения третьего байта есть еще данные других байт нас в данный момент не интересует, важна только сама возможность указать адрес конкретного байта. +Однако, если у памяти будут 32-битные ячейки, доступ к конкретному байту будет осложнен, ведь каждая ячейка — это 4 байта. Как получить данные третьего байта памяти? Если обратиться к третьей ячейке в массиве — придут данные 12-15-ых байт (поскольку каждая ячейка содержит по 4 байта). Чтобы получить данные третьего байта, необходимо **разделить значение пришедшего адреса на 4** (отбросив остаток от деления). `3 / 4 = 0` — и действительно, если обратиться к нулевой ячейке памяти — будут получены данные 3-го, 2-го, 1-го и 0-го байт. То, что помимо значения третьего байта есть еще данные других байт нас в данный момент не интересует, важна только сама возможность указать адрес конкретного байта. Деление на 2n можно осуществить, отбросив `n` младших бит числа. Учитывая то, что для адресации 1024 ячеек памяти мы будем использовать 10 бит адреса, память инструкций должна выдавать на выход данные, расположенные по адресу `addr_i[11:2]`. -### 2. Память данных +Не смотря на заданный размер памяти инструкций в 1024 32-битных ячейки, на практике удобно параметризовать это значение, чтобы в ситуациях, когда требуется меньше или больше памяти можно было получить обновленное значение, не переписывая код во множестве мест. Подобное новшество вы сможете оценить на практике, получив возможность существенно сокращать время синтеза процессора, уменьшая размер памяти до необходимого минимума путем изменения значения одного лишь параметра. -У данного модуля будет шесть входных/выходных сигналов: +Для этого можно например создать параметр: `INSTR_MEM_SIZE_BYTES`, показывающий размер памяти инструкций в байтах. Однако, поскольку у данной памяти 32-битные ячейки, нам было бы удобно иметь и параметр `INSTR_MEM_SIZE_WORDS`, который говорит сколько в памяти 32-битных ячеек. +При этом `INSTR_MEM_SIZE_WORDS = INSTR_MEM_SIZE_BYTES / 4` (т.е. в 32-битном слове 4 байта). -- вход тактового синхроимпульса -- вход запроса на работу с памятью -- вход сигнала разрешения записи -- 32-битный вход адреса -- 32-битный вход данных записи -- 32-битный выход данных синхронного чтения +В случае подобной параметризации, необходимо иметь возможность подстраивать количество используемых бит адреса. Для 1024 ячеек памяти мы использовали 10 бит адреса, для 512 ячеек нам потребуется уже 9 бит. Нетрудно заметить, что нам нужно такое число бит данных, возведя в степень которого `2`, мы получим размер нашей памяти (либо число, превышающее этот размер в случае, если размер памяти не является степенью двойки). Иными словами, нам нужен логарифм по основанию 2 от размера памяти, с округлением до целого вверх. И неудивительно, что в SystemVerilog есть специальная конструкция, которая позволяет считать подобные числа. Эта конструкция называется `$clog2` (`с` означает "ceil" — операцию округления вверх). + +Поскольку реализация памяти состоит буквально из нескольких строчек, но при этом использование параметров может вызвать некоторые затруднения, код памяти инструкций предоставляется в готовом виде: ```SystemVerilog -mоdulе data_mеm( - inрut logic clk_i, - input logic mem_req_i, - inрut logic write_enable_i, +mоdulе instr_mеm +import memory_pkg::INSTR_MEM_SIZE_BYTES; +import memory_pkg::INSTR_MEM_SIZE_WORDS; +( inрut logic [31:0] addr_i, - inрut logic [31:0] write_data_i, оutрut logic [31:0] rеаd_dаtа_o ); + logic [31:0] ROM [INSTR_MEM_SIZE_WORDS]; // создать память с + // + // 32-битных ячеек + + initial begin + $readmemh("program.mem", ROM); // поместить в память ROM содержимое + end // файла program.mem + + // Реализация асинхронного порта на чтение, где на выход идет ячейка памяти + // инструкций, расположенная по адресу addr_i, в котором обнулены два младших + // бита, а также биты, двоичный вес которых превышает размер памяти данных + // в байтах. + // Два младших бита обнулены, чтобы обеспечить выровненный доступ к памяти, + // в то время как старшие биты обнулены, чтобы не дать обращаться в память + // по адресам несуществующих ячеек (вместо этого будут выданы данные ячеек, + // расположенных по младшим адресам). + assign rеаd_dаtа_o = R0M[addr_i[$clog2(INSTR_MEM_SIZE_BYTES)-1:2]]; + +endmodule ``` -Как и память инструкций, память данных будет состоять из 32-разрядных ячеек. Только теперь их будет 4096, а значит при обращении к ячейкам памяти нужно использовать не 10 бит адреса, а 12. При этом по-прежнему необходимо разделить пришедший адрес на 4, т.е. нужно отбросить два младших бита. Таким образом, обращение к ячейкам памяти (для записи и чтения) должно осуществляться по адресу `addr_i[13:2]`. - -Однако в отличие от памяти инструкций, в память данных добавлено два управляющих сигнала (`mem_req_i`и `write_enable_i`). Сигнал `mem_req_i` является сигналом запроса на работу с памятью. Без этого сигнала память не должна выполнять операции чтения/записи (вне зависимости от сигнала `write_enable`, определяющего происходит сейчас запись или чтение). Как сделать так, чтобы не происходило чтение без запроса? Например, не обновлять значение, считанное во время предыдущей операции чтения. - -Если `mem_req_i == 1` и `write_enable_i == 1`, то происходит запрос на запись в память. В этом случае, необходимо записать значение `write_data_i` в ячейку по адресу `addr_i[13:2]`. Во всех других случаях (любой из сигналов `mem_req_i`, `write_enable_i` равен нулю), запись в память не производится. - -Если `mem_req_i == 1` и `write_enable_i == 0`, то происходит запрос на чтение из памяти. В этом случае, необходимо записать в выходной регистр `read_data_o` значение из ячейки по адресу `addr_i[13:2]`. Во всех других случаях чтение из памяти не производится (`read_data_o` сохраняет предыдущее значение). - - ### 3. Регистровый файл +На языке SystemVerilog необходимо реализовать модуль регистрового файла (`rf_r𝚒sсv`) для процессора с архитектурой RISC-V, представляющего собой трехпортовое ОЗУ с двумя портами на чтение и одним портом на запись и состоящей из 32-х 32-битных регистров, объединенных в массив с именем `rf_mem`. + У данного модуля будет восемь входных/выходных сигналов: - вход тактового синхроимпульса @@ -299,46 +312,24 @@ mоdulе rf_r𝚒sсv( ``` -На языке SystemVerilog необходимо реализовать модуль регистрового файла (`rf_r𝚒sсv`) для процессора с архитектурой RISC-V, представляющего собой трехпортовую ОЗУ с двумя портами на чтение и одним портом на запись и состоящей из 32-х 32-битных регистров с именем `rf_mem`. +По адресу `0` должно всегда считываться значение `0` вне зависимости от того, какое значение в этой ячейке памяти, и есть ли она вообще. Такая особенность обусловлена тем, что при выполнении операций очень часто используется ноль (сравнение с нулем, инициализация переменных нулевым значением, копирование значения одного регистра в другой посредством сложения с нулем и записи результата и т.п.). Эту особенность регистрового файла можно реализовать несколькими способами: -При этом по адресу `0` должно всегда считываться значение `0` вне зависимости от того, какое значение в этой ячейке памяти, и есть ли она вообще. Такая особенность обусловлена тем, что при выполнении операций очень часто используется ноль (сравнение с нулем, инициализация переменных нулевым значением, копирование значения одного регистра в другой посредством сложения с нулем и записи результата и т.п.). +- можно решить эту задачу с помощью мультиплексора, управляющим сигналом которого является сигнал сравнения адреса на чтение с нулем; +- либо же можно проинициализировать нулевую ячейку памяти нулем с запретом записи в неё каких-либо значений. В этом случае в ячейке всегда будет ноль, а значит и считываться с нулевого адреса будет только он. -Как и в случае реализации [памяти инструкций](#1-память-инструкций), вы можете решить эту задачу с помощью мультиплексора, управляющим сигналом которого является сигнал сравнения адреса на чтение с нулем. - -Либо же можно проинициализировать нулевую ячейку памяти нулем с запретом записи в неё каких-либо значений. В этом случае в ячейке всегда будет ноль, а значит и считываться с нулевого адреса будет только он. +Инициализация ячейки памяти может быть осуществлена (только при проектировании под ПЛИС) с помощью присваивания в блоке `initial`. ## Порядок выполнения работы 1. Внимательно ознакомьтесь с заданием. В случае возникновения вопросов, проконсультируйтесь с преподавателем. -2. Реализуйте память инструкций. Для этого: +2. Добавьте в проект файл [`memory_pkg.sv`](memory_pkg.sv). Этот файл содержит объявление пакета `memory_pkg`, в котором прописаны размеры памяти инструкций и памяти данных (реализуется позднее). +3. Реализуйте память инструкций. Для этого: 1. В `Design Sources` проекта с предыдущих лаб, создайте `SystemVerilog`-файл `instr_mem.sv`. - 2. Опишите в нем модуль памяти инструкций с таким же именем и портами, как указано в задании. - 1. Сперва необходимо создать память (массив регистров). Как это сделать, сказано в разделе [описание памяти на языке SystemVerilog](#описание-памяти-на-языке-systemverilog). Разрядность ячеек памяти должна быть 32 бита, количество ячеек — 1024. - 2. Добавить в `Design Sources` проекта [`файл с содержимым памяти инструкций`](program.mem). Данный файл будет использоваться при вызове системной функции `$readmemh` в описании памяти инструкций. - 3. К созданной памяти необходимо подключить выход модуля `read_data_o`. При подключении должен быть использован вход модуля `addr_i`, значение которого должно быть уменьшено в 4 раза (побайтовая адресация). - 4. При реализации выхода `read_data_o` помните, что обращаясь к ячейке памяти, вам необходимо использовать `[11:2]` биты адреса. - 5. Реализуемый порт на чтение памяти инструкций должен быть **асинхронным**. - 3. После описания памяти инструкций, её необходимо проверить с помощью тестового окружения. - 1. Тестовое окружение находится [`здесь`](tb_instr_mem.sv). - 2. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md). - 3. Перед запуском симуляции убедитесь, что в качестве top-level модуля выбран корректный (`tb_instr_mem`). - 4. **Во время симуляции, вы должны прожать "Run All" и убедиться, что в логе есть сообщение о завершении теста!** -3. Реализуйте память данных. Для этого: - 1. В `Design Sources` проекта создайте `SystemVerilog`-файл `data_mem.sv`. - 2. Опишите в нем модуль памяти данных с таким же именем и портами, как указано в задании. - 1. Описание модуля будет схожим с описанием модуля памяти инструкций, однако порт чтения в этот раз будет **синхронным** (запись в него будет происходить в блоке `always_ff`). Количество ячеек в памяти данных — 4096. Кроме того, необходимо будет описать логику записи данных в память. - 2. Запись в ячейки памяти описывается подобно записи данных в [регистры](../../Basic%20Verilog%20structures/Registers.md), только при этом, происходит доступ к конкретной ячейке памяти с помощью входа `addr_i` (как осуществляется доступ к ячейкам памяти сказано в разделе [описание памяти на языке SystemVerilog](#описание-памяти-на-языке-systemverilog)). - 3. Доступ к ячейкам (на запись и чтение) осуществляется по адресу `addr_i[13:2]`. - 4. Обратите внимание что работа с памятью должна осуществляться только когда сигнал `mem_req_i == 1`, в противном случае запись не должна производиться, а на шине `read_data_o` должен оставаться результат предыдущего чтения. - 3. После описания памяти данных, её необходимо проверить с помощью тестового окружения. - 1. Тестовое окружение находится [`здесь`](tb_data_mem.sv). - 2. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md). - 3. Перед запуском симуляции убедитесь, что в качестве top-level модуля выбран корректный (`tb_data_mem`). - 4. **Во время симуляции, вы должны прожать "Run All" и убедиться, что в логе есть сообщение о завершении теста!** + 2. Опишите в нем модуль памяти инструкций по предоставленному коду. 4. Реализуйте регистровый файл. Для этого: 1. В `Design Sources` проекта создайте `SystemVerilog`-файл `rf_riscv.sv`. 2. Опишите в нем модуль регистрового файла с таким же именем и портами, как указано в задании. - 1. Обратите внимание, что имя памяти (не название модуля, а имя объекта памяти внутри модуля) должно быть `rf_mem`. Такое имя необходимо для корректной работы верификационного окружения. + 1. Обратите внимание, что имя памяти (не название модуля, а имя массива регистров внутри модуля) должно быть `rf_mem`. Такое имя необходимо для корректной работы верификационного окружения. 2. Как и у памяти инструкций, порты чтения регистрового файла должны быть **асинхронными**. 3. Не забывайте, что у вас 2 порта на чтение и 1 порт на запись, при этом каждый порт не зависит от остальных (в модуле 3 независимых входа адреса). 4. Чтение из нулевого регистра (чтение по адресу 0) всегда должно возвращать нулевое значение. Этого можно добиться двумя путями: diff --git a/Labs/03. Register file and memory/memory_pkg.sv b/Labs/03. Register file and memory/memory_pkg.sv new file mode 100644 index 0000000..557c0c2 --- /dev/null +++ b/Labs/03. Register file and memory/memory_pkg.sv @@ -0,0 +1,18 @@ +/* ----------------------------------------------------------------------------- +* Project Name : Architectures of Processor Systems (APS) lab work +* Organization : National Research University of Electronic Technology (MIET) +* Department : Institute of Microdevices and Control Systems +* Author(s) : Andrei Solodovnikov +* Email(s) : hepoh@org.miet.ru + +See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. +* ------------------------------------------------------------------------------ +*/ +package memory_pkg; + + localparam INSTR_MEM_SIZE_BYTES = 512; + localparam INSTR_MEM_SIZE_WORDS = INSTR_MEM_SIZE_BYTES / 4; + localparam DATA_MEM_SIZE_BYTES = 512; + localparam DATA_MEM_SIZE_BYTES = DATA_MEM_SIZE_BYTES / 4; + +endpackage \ No newline at end of file diff --git a/Labs/03. Register file and memory/tb_data_mem.sv b/Labs/03. Register file and memory/tb_data_mem.sv deleted file mode 100644 index a23793f..0000000 --- a/Labs/03. Register file and memory/tb_data_mem.sv +++ /dev/null @@ -1,110 +0,0 @@ -/* ----------------------------------------------------------------------------- -* Project Name : Architectures of Processor Systems (APS) lab work -* Organization : National Research University of Electronic Technology (MIET) -* Department : Institute of Microdevices and Control Systems -* Author(s) : Nikita Bulavin -* Email(s) : nekkit6@edu.miet.ru - -See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. -* ------------------------------------------------------------------------------ -*/ -module tb_data_mem(); - -parameter ADDR_SIZE = 16384; -parameter TIME_OPERATION = 20; -parameter STEP = 8; - - logic CLK; - logic REQ; - logic WE; - logic [31:0] A; - logic [31:0] WD; - logic [31:0] RD; - - data_mem DUT ( - .clk_i (CLK), - .mem_req_i (REQ), - .write_enable_i (WE ), - .addr_i (A ), - .write_data_i (WD), - .read_data_o (RD) - ); - - logic [31:0] RDa; - integer i, hash, err_count = 0; - assign A = i; - - parameter CLK_FREQ_MHz = 100; - parameter CLK_SEMI_PERIOD= 1e3/CLK_FREQ_MHz/2; - - initial CLK <= 0; - always #CLK_SEMI_PERIOD CLK = ~CLK; - - initial begin - $timeformat(-9, 2, " ns", 3); - $display( "\nStart test: \n\n==========================\nCLICK THE BUTTON 'Run All'\n==========================\n"); $stop(); - REQ = 1; - WE = 0; - @(posedge CLK); - for (i = 0; i < ADDR_SIZE; i = i + STEP) begin - hash = (i+4)*8/15*16/23*42; - WE = 1; - WD = hash; - @(posedge CLK)#3; - end - WE = 0; - @(posedge CLK); - for (i = 0; i < ADDR_SIZE; i = i + STEP) begin - @(posedge CLK)#3; - hash = (i+4)*8/15*16/23*42; - if(RD !== hash) begin - $error("Read data: %0h is unequal written data: %0h at addres: %0h, time: %t", RD, hash, i, $time); - err_count = err_count + 1; - end - end - for (i = 0; i < (ADDR_SIZE+STEP); i = i + 1 + $urandom() % STEP) begin - REQ = |($urandom %10); - WE = 0; - #TIME_OPERATION; - RDa = RD; - WD = $urandom; - #TIME_OPERATION; - WE = $urandom % 2; - #TIME_OPERATION; - if ((!WE && REQ) && RD !== RDa) begin - $error("When reading (write_enable_i = %h), the data %h is overwritten with data %h at address %h, time: %t", WE, RDa, RD, A, $time); - err_count = err_count + 1; - end - #TIME_OPERATION; - end - #TIME_OPERATION; - REQ = 1; - WE = 0; - #TIME_OPERATION; - for (i = 0; i < 4; i = i + 1) begin - if(i==0) begin - repeat(2)@(posedge CLK); - #1; RDa = RD; - end else - if(RD !== RDa) begin - $error("incorrect conversion of the reading address = %h, time: %t", A, $time); - err_count = err_count + 1; - end - #TIME_OPERATION; - end - i = 0; WE = 0; REQ = 1; - @(posedge CLK); - @(negedge CLK); - i = 4; - #1; RDa = RD; - @(posedge CLK); #1; - if (RD == RDa) begin - $error("reading from data memory must be synchronous, time: %t", $time); - err_count = err_count + 1; - end - @(posedge CLK); - $display("Number of errors: %d", err_count); - if( !err_count ) $display("\ndata_mem SUCCESS!!!\n"); - $finish(); - end -endmodule diff --git a/Labs/03. Register file and memory/tb_instr_mem.sv b/Labs/03. Register file and memory/tb_instr_mem.sv deleted file mode 100644 index 74c058d..0000000 --- a/Labs/03. Register file and memory/tb_instr_mem.sv +++ /dev/null @@ -1,75 +0,0 @@ -/* ----------------------------------------------------------------------------- -* Project Name : Architectures of Processor Systems (APS) lab work -* Organization : National Research University of Electronic Technology (MIET) -* Department : Institute of Microdevices and Control Systems -* Author(s) : Nikita Bulavin -* Email(s) : nekkit6@edu.miet.ru - -See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. -* ------------------------------------------------------------------------------ -*/ -module tb_instr_mem(); - -parameter ADDR_SIZE = 4096; -parameter TIME_OPERATION = 10; -parameter STEP = 8; - - logic [31:0] addr; - logic [31:0] RD; - logic [31:0] RDref; - - instr_mem_ref DUTref( - .addr_i(addr), - .read_data_o(RDref) - ); - - instr_mem DUT ( - .addr_i(addr), - .read_data_o(RD) - ); - - integer i, err_count = 0; - - assign addr = i; - - initial begin - $timeformat (-9, 2, "ns"); - $display( "\nStart test: \n\n==========================\nCLICK THE BUTTON 'Run All'\n==========================\n"); $stop(); - for (i = 0; i < ADDR_SIZE + STEP; i = i + 1 + $urandom() % STEP) begin - #TIME_OPERATION; - if ( RD !== RDref) begin - $display("time = %0t, address %d. Invalid data %h, correct data %h", $time, addr, RD, RDref); - err_count = err_count + 1; - end - end - $display("Number of errors: %d", err_count); - if( !err_count ) $display("\n instr_mem SUCCESS!!!\n"); - $finish(); - end - -endmodule - -module instr_mem_ref( - input [31:0] addr_i, - output logic [31:0] read_data_o - ); - -`define akjsdnnaskjdn $clog2(128) -`define cdyfguvhbjnmk $clog2(`akjsdnnaskjdn) -`define qwenklfsaklasd $clog2(`cdyfguvhbjnmk) -`define asdasdhkjasdsa (34 >> `cdyfguvhbjnmk) - -reg [31:0] RAM [0:1023]; -initial $readmemh("program.mem", RAM); - -always_comb begin - read_data_o['h1f:'h1c]=RAM[{2'b00, addr_i[5'd28^5'o27:2]}][{5{1'b1}}:{3'd7,2'b00}]; - read_data_o[42-23-:`asdasdhkjasdsa]=RAM[{2'b00, addr_i[5'h1C-5'd17:2]}][19:{1'b1,4'h0}]; - read_data_o[`akjsdnnaskjdn-:`asdasdhkjasdsa]=RAM[{2'b00, addr_i[5'd28^5'o27:2]}][{3{1'b1}}:{1'b1,2'h0}]; - read_data_o[42-19-:`asdasdhkjasdsa]=RAM[{2'b00, addr_i[5'h1C-5'd17:2]}][23:{{2{2'b10}},1'b0}]; - read_data_o['h1b:'h18]=RAM[{2'b00, addr_i[5'h1C-5'd17:2]}][27:{2'b11,3'b000}]; - read_data_o[`akjsdnnaskjdn+`asdasdhkjasdsa:(`akjsdnnaskjdn+`asdasdhkjasdsa)-`cdyfguvhbjnmk]=RAM[{2'b00, addr_i[5'h1C-5'd17:2]}][11:8]; - read_data_o[`akjsdnnaskjdn-`asdasdhkjasdsa-:`asdasdhkjasdsa]=RAM[{2'b00, addr_i[5'd28^5'o27:2]}][3:0]; - read_data_o[(`akjsdnnaskjdn<<(`asdasdhkjasdsa-`cdyfguvhbjnmk)) + (`asdasdhkjasdsa-`cdyfguvhbjnmk):12 ]=RAM[{2'b00, addr_i[5'h1C-5'd17:2]}][{4{1'b1}}:12]; -end -endmodule diff --git a/Labs/05. Main decoder/README.md b/Labs/05. Main decoder/README.md index 379887a..0ea097b 100644 --- a/Labs/05. Main decoder/README.md +++ b/Labs/05. Main decoder/README.md @@ -117,7 +117,7 @@ _Таблица 1. Описание портов декодера инструк - `mem_req_o` — этот сигнал должен быть выставлен в 1 каждый раз, когда необходимо обратиться к памяти (считать или записать данные); - `mem_we_o` — этот сигнал должен быть выставлен в 1, если необходимо записать данные в память, (0 при чтении); -- `mem_size_o`— этот сигнал указывает размер порции данных для передачи (возможные значения этого сигнала указаны в _Таблице 2_). Для удобства использования, данные значения определены в виде параметров в пакете `riscv_pkg`. +- `mem_size_o`— этот сигнал указывает размер порции данных для передачи (возможные значения этого сигнала указаны в _Таблице 2_). Для удобства использования, данные значения определены в виде параметров в пакете `decoder_pkg`. |Параметр|Значение `mem_size_o`| Пояснение | |--------|---------------------|------------------------------| @@ -218,7 +218,7 @@ _Таблица 4. Описание типов форматов кодирова В _Таблице 5_ представлены все опкоды реализуемых нами инструкций. Представленные в ней коды операций 5-битные потому, что 2 младших бита полноценного 7-битного кода операции в реализуемых нами инструкциях должны всегда быть равны `11`. Если это не так, то вся инструкция уже запрещенная и не нуждается в дальнейшем декодировании. -Для удобства, значения кодов операций определены в виде параметров в пакете riscv_pkg. +Для удобства, значения кодов операций определены в виде параметров в пакете `decoder_pkg`. |Параметр|Opcode| Описание группы операций | Краткая запись | |--------|------|-------------------------------------------------------------------------------------------------------|------------------------------------| @@ -398,7 +398,7 @@ module decoder_riscv ( output logic jalr_o, output logic mret_o ); - import riscv_pkg::*; + import decoder_pkg::*; endmodule ``` @@ -412,7 +412,7 @@ endmodule 1. В `Design Sources` проекта с предыдущих лаб, создайте `SystemVerilog`-файл `decoder_riscv.sv`. 2. Опишите в нем модуль декодера инструкций с таким же именем и портами, как указано в [задании](#задание). 1. Для удобства дальнейшего описания модуля, рекомендуется сперва создать сигналы `opcode`, `func3`, `func7` и присвоить им соответствующие биты входного сигнала инструкции. - 2. При описании модуля вы можете воспользоваться параметрами, объявленными **пакетах** `riscv_pkg`, `csr_pkg` и `alu_opcodes_pkg`, описанных в файлах [riscv_pkg.sv](riscv_pkg.sv), [csr_pkg.sv](csr_pkg.sv) и [alu_opcodes_pkg.sv](alu_opcodes_pkg.sv) соответственно. + 2. При описании модуля вы можете воспользоваться параметрами, объявленными **пакетах** `decoder_pkg`, `csr_pkg` и `alu_opcodes_pkg`, описанных в файлах [decoder_pkg.sv](decoder_pkg.sv), [csr_pkg.sv](csr_pkg.sv) и [alu_opcodes_pkg.sv](alu_opcodes_pkg.sv) соответственно. 3. Модуль может быть описан множеством способов: каждый выходной сигнал может быть описан через собственную комбинационную логику в отдельном блоке `case`, однако проще всего будет описать все сигналы через вложенные `case` внутри одного блока `always_comb`. 4. Внутри блока `always_comb` до начала блока `case` можно указать базовые значения для всех выходных сигналов. Это не то же самое, что вариант `default` в блоке `case`. Здесь вы можете описать состояния, которые будут использованы чаще всего, и в этом случае, присваивание сигналу будет выполняться только в том месте, где появится инструкция, требующая значение этого сигнала, отличное от базового. 5. Далее вы можете описать базовый блок `case`, где будет определен тип операции по ее коду. diff --git a/Labs/05. Main decoder/riscv_pkg.sv b/Labs/05. Main decoder/decoder_pkg.sv similarity index 98% rename from Labs/05. Main decoder/riscv_pkg.sv rename to Labs/05. Main decoder/decoder_pkg.sv index 4b977b1..dc0ec49 100644 --- a/Labs/05. Main decoder/riscv_pkg.sv +++ b/Labs/05. Main decoder/decoder_pkg.sv @@ -8,7 +8,7 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. * ------------------------------------------------------------------------------ */ -package riscv_pkg; +package decoder_pkg; import alu_opcodes_pkg::*; import csr_pkg::*; @@ -54,7 +54,7 @@ package riscv_pkg; /* Hack that makes nested opcodes be visible with just one import of - riscv_pkg + decoder_pkg */ export alu_opcodes_pkg::ALU_OP_WIDTH; diff --git a/Labs/05. Main decoder/tb_decoder_riscv.sv b/Labs/05. Main decoder/tb_decoder_riscv.sv index 83d32c4..2e9b260 100644 --- a/Labs/05. Main decoder/tb_decoder_riscv.sv +++ b/Labs/05. Main decoder/tb_decoder_riscv.sv @@ -11,7 +11,7 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. module tb_decoder_riscv(); - import riscv_pkg::*; + import decoder_pkg::*; typedef class riscv_instr; riscv_instr instr = new(); diff --git a/Labs/06. Main memory/README.md b/Labs/06. Main memory/README.md new file mode 100644 index 0000000..9dd4c1d --- /dev/null +++ b/Labs/06. Main memory/README.md @@ -0,0 +1,122 @@ +# Лабораторная работа 6 "Основная память" + +Процессор CYBERcobra 2000 использовал в качестве основного хранилища данных регистровый файл, однако на практике 31-го регистра недостаточно для выполнения сложных программ. Для этих целей используется **основная память**, роль которой в нашей системе будет выполнять **память данных**. + +## Цель + +Описать память данных, с побайтовой адресацией. + +## Материал для подготовки к лабораторной работе + +Для успешного выполнения лабораторной работы, вам необходимо использовать навыки, полученные при написании [лабораторной работы №3](../03.%20Register%20file%20and%20memory/) "Регистровый файл и память инструкций"; + +## Теория + +В задании по реализации памяти инструкций [лабораторной работы №3](../03.%20Register%20file%20and%20memory/) байтовая адресация была описана следующим образом: + +> Байтовая адресация означает, что процессор способен обращаться к отдельным байтам в памяти (за каждым байтом памяти закреплен свой индивидуальный адрес). + +Данное описание было дано не совсем корректным образом, чтобы в третьей лабораторной работе было более четкое понимание задания. В чем заключается некорректность? Процессор должен быть способен не только **обращаться** к отдельным байтам в памяти, но и **обновлять** в памяти любой отдельный байт, а также **считывать** отдельные байты. + +Вопрос считывания отдельного байта будет решаться специальным модулем **загрузки и сохранения**, памяти данных при этом будет достаточно возвращать всё слово, содержащее запрашиваемый байт как это было уже делалось для памяти инструкций. + +Нас интересует возможность памяти обновлять любой из байт в слове. Подобный функционал часто используется при реализации памяти и в системных интерфейсах, например AXI4 или APB. Для этого используется специальный сигнал, который называется `byte enable`. Разрядность этого сигнала равна числу байт в шине данных (в нашем случае разрядность `byte enable` составляет 4). Вы можете представить этот сигнал, как 4 провода, каждый из которых является сигналом разрешения записи для отдельной памяти с шириной данный в 1 байт. + +Давайте разберемся как это будет работать. Допустим, мы хотим записать значение `0xA5` по адресу `0x6`. Поскольку мы работаем с байтовой адресацией, как и при реализации памяти инструкций, пришедший адрес необходимо будет разделить на 4 (см. _рис. 1_). В итоге мы получим указатель на первую 32-битную ячейку памяти (`6 / 4 = 1`). Однако, чтобы пришедшие данные были в итоге записаны не в нулевой байт первого слова (четвертый байт памяти), во второй, мы будем использовать сигнал `byte enable`, второй бит которого будет равен единице. + + + +Чтобы данные остальных байт не были испорчены, при описании памяти на SystemVerilog нужно разделить запись в отдельные байты. Для того, чтобы получить доступ к отдельным диапазонам бит ячейки памяти, после указания индекса ячейки необходимо указать диапазон бит, к которым вы хотите получить доступ. К примеру, чтобы получить доступ к битам с 5-го по 3-ий 18-ой ячейки памяти, необходимо использовать следующую запись: + +```SystemVerilog +mem[18][5:3]; +``` + +Учитывайте и то, что комбинации значений бит в сигнале `byte enable` могут быть любыми: `0000`, `0100`, `0110`, `1111` и т.п. + +## Задание + +Реализовать память данных с поддержкой обновления отдельных байт в выбранной ячейке памяти. + +У данного модуля будет шесть входных/выходных сигналов: + +- вход тактового синхроимпульса +- вход запроса на работу с памятью +- вход сигнала разрешения записи +- 32-битный вход адреса +- 32-битный вход данных записи +- 32-битный выход данных синхронного чтения + +Прототип модуля следующий: + +```SystemVerilog +module data_mem +import memory_pkg::DATA_MEM_SIZE_BYTES; +import memory_pkg::DATA_MEM_SIZE_WORDS; +( + 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 +); +``` + +Как и память инструкций, память данных будет состоять из 32-битных ячеек, количество которых определяется параметром. Как и в памяти инструкций, необходимо использовать только младшие биты адреса в количестве, равном логарифму по основанию 2 от количества ячеек памяти, начиная со второго бита (см. код памяти инструкций из ЛР№3). + +Отличие от памяти инструкций будет заключаться в: + +- синхронном порте на чтение; +- наличии порта на запись; + - посредством этого порта на запись можно менять отдельные байты ячейки памяти. + +Синхронный порт на чтение означает, что выдача данных по предоставленному адресу осуществляется не сразу же, а на следующий такт (см. _рис. 2_). Для этого, перед выходным сигналом ставится отдельный регистр. Таким образом, выдача данных с порта на чтение будет осуществляться не с помощью непрерывного присваивания, а посредством блока `always_ff` (см. практическую часть ЛР№3). + +Также в памяти появилось три управляющих сигнала: + +- `mem_req_i`, +- `write_enable_i`, +- `byte_enable_i` + +и один статусный: + +- `ready_o`. + +Сигнал `mem_req_i` является сигналом запроса на работу с памятью. Без этого сигнала память не должна выполнять операции чтения/записи. Как сделать так, чтобы не происходило чтение без запроса? Например, не обновлять значение, считанное во время предыдущей операции чтения. + +Сигнал `write_enable_i` является сигналом разрешения записи. Этот сигнал определяет, является ли пришедший запрос в память **запросом на запись**, либо же **запросом на чтение**. + +Если `mem_req_i == 1` и `write_enable_i == 0`, то происходит запрос на чтение из памяти. В этом случае, необходимо записать в выходной регистр `read_data_o` значение из ячейки, на которую указывает `addr_i`. Во всех других случаях чтение из памяти не производится (`read_data_o` сохраняет предыдущее значение). + +![../../.pic/Labs/lab_06_main_memory/fig_02.wavedrom.svg](../../.pic/Labs/lab_06_main_memory/fig_02.wavedrom.svg) + +_Рисунок 2. Операции запросов на чтение._ + +Если `mem_req_i == 1` и `write_enable_i == 1`, то происходит запрос на запись в память. В этом случае, необходимо записать значение `write_data_i` в ячейку по, на которую указывает `addr_i`. Во всех других случаях (любой из сигналов `mem_req_i`, `write_enable_i` равен нулю), запись в память не производится. Запись необходимо производить только в те байты указанной ячейки, которым соответствуют биты сигнала `byte_enable_i`, равные единице. + +![../../.pic/Labs/lab_06_main_memory/fig_03.wavedrom.svg](../../.pic/Labs/lab_06_main_memory/fig_03.wavedrom.svg) + +_Рисунок 3. Операции запросов на запись._ + +Перед выходом `ready_o` должен стоять регистр, в который каждый такт записывается значение `mem_req_i` (см. _рис. 2_). Такая простая логика этого сигнала обеспечивается тем, что любой запрос обрабатывается гарантированно за 1 такт. В реальности, обращение в память может занимать сотни тактов процессора, причем их число бывает недетерминированным (нельзя заранее предсказать сколько тактов займет очередной запрос в память). Именно поэтому стандартные интерфейсы обычно используют такие сигналы как `ready` или `valid`, позволяющие синхронизировать разные блоки системы. + +## Порядок выполнения работы + +1. Внимательно ознакомьтесь с заданием. В случае возникновения вопросов, проконсультируйтесь с преподавателем. +2. Реализуйте память данных. Для этого: + 1. В `Design Sources` проекта создайте `SystemVerilog`-файл `data_mem.sv`. + 2. Опишите в нем модуль памяти данных с таким же именем и портами, как указано в задании. + 1. Описание модуля будет схожим с описанием модуля памяти инструкций, однако порт чтения в этот раз будет **синхронным** (запись в него будет происходить в блоке `always_ff`). Количество ячеек памяти данных определяется параметром `DATA_MEM_SIZE_WORDS`, определенным в `memory_pkg`. Кроме того, необходимо будет описать логику записи данных в память. + 2. Запись в ячейки памяти описывается подобно записи данных в [регистры](../../Basic%20Verilog%20structures/Registers.md), только при этом, происходит доступ к конкретной ячейке памяти с помощью входа `addr_i`. + 3. Перед тем как обратиться к ячейке памяти, значение с `addr_i` необходимо преобразовать по аналогии с памятью инструкций. + 4. Обратите внимание что работа с памятью должна осуществляться только когда сигнал `mem_req_i == 1`. В противном случае запись не должна производиться, а на шине `read_data_o` должен оставаться результат предыдущего чтения. + 5. При этом запись должна вестись только в те байты выбранной ячейки памяти, которым соответствуют биты сигнала `byte_enable_i`, выставленные в `1`. + 6. У памяти есть дополнительный выход `ready_o`, перед которым необходимо реализовать регистр, в который каждый такт записывается значение `mem_req_i`. + 3. После описания памяти данных, её необходимо проверить с помощью тестового окружения. + 1. Тестовое окружение находится [`здесь`](tb_data_mem.sv). + 2. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md). + 3. Перед запуском симуляции убедитесь, что в качестве top-level модуля выбран корректный (`tb_data_mem`). + 4. **Во время симуляции, вы должны прожать "Run All" и убедиться, что в логе есть сообщение о завершении теста!** diff --git a/Labs/06. Main memory/memory_pkg.sv b/Labs/06. Main memory/memory_pkg.sv new file mode 100644 index 0000000..557c0c2 --- /dev/null +++ b/Labs/06. Main memory/memory_pkg.sv @@ -0,0 +1,18 @@ +/* ----------------------------------------------------------------------------- +* Project Name : Architectures of Processor Systems (APS) lab work +* Organization : National Research University of Electronic Technology (MIET) +* Department : Institute of Microdevices and Control Systems +* Author(s) : Andrei Solodovnikov +* Email(s) : hepoh@org.miet.ru + +See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. +* ------------------------------------------------------------------------------ +*/ +package memory_pkg; + + localparam INSTR_MEM_SIZE_BYTES = 512; + localparam INSTR_MEM_SIZE_WORDS = INSTR_MEM_SIZE_BYTES / 4; + localparam DATA_MEM_SIZE_BYTES = 512; + localparam DATA_MEM_SIZE_BYTES = DATA_MEM_SIZE_BYTES / 4; + +endpackage \ No newline at end of file diff --git a/Labs/06. Datapath/README.md b/Labs/07. Datapath/README.md similarity index 96% rename from Labs/06. Datapath/README.md rename to Labs/07. Datapath/README.md index 669ce2c..7eeb875 100644 --- a/Labs/06. Datapath/README.md +++ b/Labs/07. Datapath/README.md @@ -4,7 +4,7 @@ ## Цель -Описать на языке **SystemVerilog** процессор с архитектурой **RISC-V**, реализовав его тракт данных, используя разработанные ранее блоки, и подключив к нему устройство управления. Итогом текущей лабораторной работы станет процессор RISC-V, который пока что сможет обрабатывать лишь слова (то есть БЕЗ инструкций, связанных с байтами и полусловами: `lh`, `lhu`, `lb`, `lbu`, `sh`, `sb`). +Описать на языке **SystemVerilog** процессор с архитектурой **RISC-V**, реализовав его тракт данных, используя разработанные ранее блоки, и подключив к нему устройство управления. Итогом текущей лабораторной работы станет процессор RISC-V, который пока что сможет работать с памятью данных лишь посредством 32-битных слов (то есть БЕЗ инструкций, связанных с байтами и полусловами: `lh`, `lhu`, `lb`, `lbu`, `sh`, `sb`). ## Ход работы @@ -40,7 +40,7 @@ module riscv_core ( endmodule ``` -![../../.pic/Labs/lab_06_dp/fig_01.drawio.svg](../../.pic/Labs/lab_06_dp/fig_01.drawio.svg) +![../../.pic/Labs/lab_07_dp/fig_01.drawio.svg](../../.pic/Labs/lab_07_dp/fig_01.drawio.svg) _Рисунок 1. Микроархитектура ядра процессора RISC-V._ @@ -69,7 +69,7 @@ module riscv_unit( endmodule ``` -![../../.pic/Labs/lab_06_dp/fig_02.drawio.svg](../../.pic/Labs/lab_06_dp/fig_02.drawio.svg) +![../../.pic/Labs/lab_07_dp/fig_02.drawio.svg](../../.pic/Labs/lab_07_dp/fig_02.drawio.svg) _Рисунок 2. Микроархитектура процессора._ @@ -90,7 +90,7 @@ _Рисунок 2. Микроархитектура процессора._ Предположим, мы описываем содержимое памяти инструкций и у нас есть очередная инструкция `0xDEADBEEF` (`jal`). Если она должна быть размещена в памяти, начиная с адреса `4`, то байт `EF` должен находиться по 4-ому адресу, байт `BE` — по пятому и т.п. Допустим, мы разделили байты инструкций символами переноса строк (и что строки в файле нумеруются с нуля). Тогда соответствие между строкой, байтом инструкции и адресом в памяти, где этот байт должен быть расположен будет следующим: -![../../.pic/Labs/lab_06_dp/fig_02.excel.png](../../.pic/Labs/lab_06_dp/fig_02.excel.png) +![../../.pic/Labs/lab_07_dp/fig_02.excel.png](../../.pic/Labs/lab_07_dp/fig_02.excel.png) Если после разделения инструкции переносами, мы не изменим порядок байт в файле, при считывании файла САПР будет инициализировать память наоборот: ячейка с младшим адресом будет проинициализирована строкой с младшим номером. Если оставить все как есть, процессор считает из памяти инструкцию `0xEFBEADDE` (вместо jal получаем нелегальную инструкцию, т.к. младшие 2 бита не равны 1). @@ -189,12 +189,12 @@ _Рисунок 2. Микроархитектура процессора._ 5. **Во время симуляции убедитесь, что в логе есть сообщение о завершении теста!** 6. Вполне возможно, что после первого запуска вы столкнетесь с сообщениями о множестве ошибок. Вам необходимо [исследовать](../../Vivado%20Basics/Debug%20manual.md) эти ошибки на временной диаграмме и исправить их в вашем модуле. 4. Проверьте работоспособность вашей цифровой схемы в ПЛИС. Для этого: - 1. Добавьте файлы из папки [`board files`](https://github.com/MPSU/APS/tree/master/Labs/06.%20Datapath/board%20files) в проект. - 1. Файл [nexys_riscv_unit.sv](https://github.com/MPSU/APS/tree/master/Labs/06.%20Datapath/board%20files/nexys_riscv_unit.sv) необходимо добавить в `Design Sources` проекта. - 2. Файл [nexys_a7_100t.xdc](https://github.com/MPSU/APS/tree/master/Labs/06.%20Datapath/board%20files/nexys_a7_100t.xdc) необходимо добавить в `Constraints` проекта. В случае, если вы уже добавляли одноименный файл в рамках предыдущих лабораторных работ, его содержимое необходимо заменить содержимым нового файла. + 1. Добавьте файлы из папки [`board files`](https://github.com/MPSU/APS/tree/master/Labs/07.%20Datapath/board%20files) в проект. + 1. Файл [nexys_riscv_unit.sv](https://github.com/MPSU/APS/tree/master/Labs/07.%20Datapath/board%20files/nexys_riscv_unit.sv) необходимо добавить в `Design Sources` проекта. + 2. Файл [nexys_a7_100t.xdc](https://github.com/MPSU/APS/tree/master/Labs/07.%20Datapath/board%20files/nexys_a7_100t.xdc) необходимо добавить в `Constraints` проекта. В случае, если вы уже добавляли одноименный файл в рамках предыдущих лабораторных работ, его содержимое необходимо заменить содержимым нового файла. 2. Выберите `nexys_riscv_unit` в качестве модуля верхнего уровня (`top-level`). 3. Выполните генерацию битстрима и сконфигурируйте ПЛИС. Для этого воспользуйтесь [следующей инструкцией](../../Vivado%20Basics/How%20to%20program%20an%20fpga%20board.md). - 4. Описание логики работы модуля верхнего уровня и связи периферии ПЛИС с реализованным модулем находится в папке [`board files`](https://github.com/MPSU/APS/tree/master/Labs/06.%20Datapath/board%20files). + 4. Описание логики работы модуля верхнего уровня и связи периферии ПЛИС с реализованным модулем находится в папке [`board files`](https://github.com/MPSU/APS/tree/master/Labs/07.%20Datapath/board%20files). --- diff --git a/Labs/06. Datapath/alu_opcodes_pkg.sv b/Labs/07. Datapath/alu_opcodes_pkg.sv similarity index 100% rename from Labs/06. Datapath/alu_opcodes_pkg.sv rename to Labs/07. Datapath/alu_opcodes_pkg.sv diff --git a/Labs/06. Datapath/board files/README.md b/Labs/07. Datapath/board files/README.md similarity index 92% rename from Labs/06. Datapath/board files/README.md rename to Labs/07. Datapath/board files/README.md index 38c8a21..80d4cbf 100644 --- a/Labs/06. Datapath/board files/README.md +++ b/Labs/07. Datapath/board files/README.md @@ -33,7 +33,7 @@ _Рисунок 1. Структурная схема модуля `nexys_riscv_u Прототип определяет тип операции по младшим 7 битам инструкции. -Если тип операции является легальным в рамках процессорного устройства, реализуемого на лабораторных работах, то отображается соответствующий опкод. Опкоды описаны в [riscv_pkg.sv](../../05.%20Main%20decoder/riscv_pkg.sv). Если определенный прототипом тип операции является нелегальным, то на семисегментных индикаторах отображается `ILL` (от **ill**egal). +Если тип операции является легальным в рамках процессорного устройства, реализуемого на лабораторных работах, то отображается соответствующий опкод. Опкоды описаны в [decoder_pkg.sv](../../05.%20Main%20decoder/decoder_pkg.sv). Если определенный прототипом тип операции является нелегальным, то на семисегментных индикаторах отображается `ILL` (от **ill**egal). Соответствие операции ее отображению на семисегментных индикаторах представлено на _рис. 2_: diff --git a/Labs/06. Datapath/board files/nexys_a7_100t.xdc b/Labs/07. Datapath/board files/nexys_a7_100t.xdc similarity index 100% rename from Labs/06. Datapath/board files/nexys_a7_100t.xdc rename to Labs/07. Datapath/board files/nexys_a7_100t.xdc diff --git a/Labs/06. Datapath/board files/nexys_riscv_unit.sv b/Labs/07. Datapath/board files/nexys_riscv_unit.sv similarity index 99% rename from Labs/06. Datapath/board files/nexys_riscv_unit.sv rename to Labs/07. Datapath/board files/nexys_riscv_unit.sv index 2ca9045..ea88c6a 100644 --- a/Labs/06. Datapath/board files/nexys_riscv_unit.sv +++ b/Labs/07. Datapath/board files/nexys_riscv_unit.sv @@ -116,7 +116,7 @@ module nexys_riscv_unit( assign opcode = instr[6:0]; Char op_chars[0:3]; - import riscv_pkg::*; + import decoder_pkg::*; always_comb begin op_chars = '{4{CH_SPACE}}; diff --git a/Labs/06. Datapath/csr_pkg.sv b/Labs/07. Datapath/csr_pkg.sv similarity index 100% rename from Labs/06. Datapath/csr_pkg.sv rename to Labs/07. Datapath/csr_pkg.sv diff --git a/Labs/06. Datapath/riscv_pkg.sv b/Labs/07. Datapath/decoder_pkg.sv similarity index 98% rename from Labs/06. Datapath/riscv_pkg.sv rename to Labs/07. Datapath/decoder_pkg.sv index 4aa4891..ec82cee 100644 --- a/Labs/06. Datapath/riscv_pkg.sv +++ b/Labs/07. Datapath/decoder_pkg.sv @@ -8,7 +8,7 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. * ------------------------------------------------------------------------------ */ -package riscv_pkg; +package decoder_pkg; import alu_opcodes_pkg::*; export alu_opcodes_pkg::*; diff --git a/Labs/07. Datapath/memory_pkg.sv b/Labs/07. Datapath/memory_pkg.sv new file mode 100644 index 0000000..557c0c2 --- /dev/null +++ b/Labs/07. Datapath/memory_pkg.sv @@ -0,0 +1,18 @@ +/* ----------------------------------------------------------------------------- +* Project Name : Architectures of Processor Systems (APS) lab work +* Organization : National Research University of Electronic Technology (MIET) +* Department : Institute of Microdevices and Control Systems +* Author(s) : Andrei Solodovnikov +* Email(s) : hepoh@org.miet.ru + +See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. +* ------------------------------------------------------------------------------ +*/ +package memory_pkg; + + localparam INSTR_MEM_SIZE_BYTES = 512; + localparam INSTR_MEM_SIZE_WORDS = INSTR_MEM_SIZE_BYTES / 4; + localparam DATA_MEM_SIZE_BYTES = 512; + localparam DATA_MEM_SIZE_BYTES = DATA_MEM_SIZE_BYTES / 4; + +endpackage \ No newline at end of file diff --git a/Labs/06. Datapath/program.mem b/Labs/07. Datapath/program.mem similarity index 100% rename from Labs/06. Datapath/program.mem rename to Labs/07. Datapath/program.mem diff --git a/Labs/06. Datapath/tb_riscv_unit.sv b/Labs/07. Datapath/tb_riscv_unit.sv similarity index 100% rename from Labs/06. Datapath/tb_riscv_unit.sv rename to Labs/07. Datapath/tb_riscv_unit.sv diff --git a/Labs/07. External memory/README.md b/Labs/07. External memory/README.md deleted file mode 100644 index ab1bd65..0000000 --- a/Labs/07. External memory/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# Лабораторная работа 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" и убедиться, что в логе есть сообщение о завершении теста!** diff --git a/Labs/08. Load-store unit/tb_lsu.sv b/Labs/08. Load-store unit/tb_lsu.sv index f72da0e..b3b042c 100644 --- a/Labs/08. Load-store unit/tb_lsu.sv +++ b/Labs/08. Load-store unit/tb_lsu.sv @@ -9,7 +9,7 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. * ------------------------------------------------------------------------------ */ module tb_lsu(); -import riscv_pkg::*; +import decoder_pkg::*; logic clk_i ; logic rst_i ; logic core_req_i ; @@ -227,7 +227,7 @@ module riscv_lsu_ref( input logic mem_ready_i ); -import riscv_pkg::*; +import decoder_pkg::*; logic enable; logic [32:0] cursed_numbers; diff --git a/Labs/Made-up modules/lab_07.ext_mem.sv b/Labs/Made-up modules/lab_06.data_mem.sv similarity index 99% rename from Labs/Made-up modules/lab_07.ext_mem.sv rename to Labs/Made-up modules/lab_06.data_mem.sv index 3a8ebd3..02a9f2a 100644 --- a/Labs/Made-up modules/lab_07.ext_mem.sv +++ b/Labs/Made-up modules/lab_06.data_mem.sv @@ -9,7 +9,7 @@ See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details. * ------------------------------------------------------------------------------ */ -module ext_mem( +module data_mem( input logic clk_i, input logic mem_req_i, input logic write_enable_i, diff --git a/Labs/Made-up modules/lab_08.lsu.sv b/Labs/Made-up modules/lab_08.lsu.sv index 89401a4..7024da9 100644 --- a/Labs/Made-up modules/lab_08.lsu.sv +++ b/Labs/Made-up modules/lab_08.lsu.sv @@ -27,7 +27,7 @@ module riscv_lsu( input logic mem_ready_i ); -import riscv_pkg::*; +import decoder_pkg::*; logic enable; logic [32:0] cursed_numbers; diff --git a/Labs/README.md b/Labs/README.md index f87c8cd..f5df57c 100644 --- a/Labs/README.md +++ b/Labs/README.md @@ -15,8 +15,8 @@ - [3. Регистровый файл и внешняя память (RF)](#3-регистровый-файл-и-внешняя-память-rf) - [4. Простейшее программируемое устройство (PPD)](#4-простейшее-программируемое-устройство-ppd) - [5. Основной дешифратор команд (MD)](#5-основной-дешифратор-команд-md) - - [6. Тракт данных (DP)](#6-тракт-данных-dp) - - [7. Внешняя память](#7-внешняя-память) + - [6. Основная память](#6-основная-память) + - [7. Тракт данных (DP)](#7-тракт-данных-dp) - [8. Блог загрузки и сохранения данных (LSU)](#8-блог-загрузки-и-сохранения-данных-lsu) - [9 Интеграция LSU](#9-интеграция-lsu) - [10. Подсистема прерывания (IC)](#10-подсистема-прерывания-ic) @@ -53,7 +53,7 @@ 4. Простейшее программируемое устройство ([04. Primitive programmable device](04.%20Primitive%20programmable%20device)) 5. Основной дешифратор ([05. Main decoder](05.%20Main%20decoder)) 6. - 1. Тракт данных ([06. Datapath](06.%20Datapath)) + 1. Тракт данных ([07. Datapath](07.%20Datapath)) 2. Интеграция блока загрузки и сохранения ([09. LSU Integration](09.%20LSU%20Integration)) 3. Интеграция подсистемы прерываний ([11. Interrupt Integration](11.%20Interrupt%20integration)) 7. Периферийные устройства ([13. Peripheral units](13.%20Peripheral%20units)) @@ -66,7 +66,7 @@ 1. Память ([03. Register file and memory](03.%20Register%20file%20and%20memory)), 2. Простейшее программируемое устройство ([04. Primitive programmable device](04.%20Primitive%20programmable%20device)) 3. Основной дешифратор ([05. Main decoder](05.%20Main%20decoder)) -4. Тракт данных ([06. Datapath](06.%20Datapath)) +4. Тракт данных ([07. Datapath](07.%20Datapath)) 5. 1. Модуль загрузки и сохранения ([08. Load-store unit](08.%20Load-store%20unit)) 2. Интеграция блока загрузки и сохранения ([09. LSU Integration](09.%20LSU%20Integration)) @@ -131,17 +131,17 @@ https://github.com/MPSU/APS/assets/17159587/4daac01f-dc9a-4ec8-8d3f-c5dc1ef97119 ![../.pic/Labs/lab_05_md.drawio.svg](../.pic/Labs/lab_05_md.drawio.svg) Пятая лабораторная посвящена разработке устройства управления – основному дешифратору команд. Функция основного дешифратора — получать на вход коды выполняемых операций и преобразовывать их в управляющие сигналы для всех блоков процессора (АЛУ, память, регистровый файл, мультиплексоры). Работа требует внимательности в реализации, а ее результат проверяется заранее подготовленными автоматическими тестами. -## 6. Тракт данных (DP) - -![../.pic/Labs/lab_06_datapath.drawio.svg](../.pic/Labs/lab_06_datapath.drawio.svg) -Разработанные блоки объединяются, образуя тракт данных, управляемый основным дешифратором команд. Результатом шестой лабораторной работы является однотактный процессор, с архитектурой RISC-V, поддерживающий стандартный набор целочисленных инструкций RV32I. В качестве проверки на процессоре запускаются программы, заранее написанные на языке ассемблера RISC-V. Сравнивается результат полученный на симуляторе и на разработанном процессоре. - -## 7. Внешняя память +## 6. Основная память Недостатком реализации процессора из предыдущей лабораторной работы была его неспособность выполнять операции `LB`, `LBU`, `SB`, `LH`, `LHU`, `SH`. Отчасти это связано с ограничением реализованной ранее памяти (в этой памяти не было возможности обновить отдельный байт в ячейке памяти). Данная вспомогательная лабораторная работа позволяет реализовать память без этого ограничения. +## 7. Тракт данных (DP) + +![../.pic/Labs/lab_07_datapath.drawio.svg](../.pic/Labs/lab_07_datapath.drawio.svg) +Разработанные блоки объединяются, образуя тракт данных, управляемый основным дешифратором команд. Результатом шестой лабораторной работы является однотактный процессор, с архитектурой RISC-V, поддерживающий стандартный набор целочисленных инструкций RV32I. В качестве проверки на процессоре запускаются программы, заранее написанные на языке ассемблера RISC-V. Сравнивается результат полученный на симуляторе и на разработанном процессоре. + ## 8. Блог загрузки и сохранения данных (LSU) ![../.pic/Labs/lab_08_lsu.drawio.svg](../.pic/Labs/lab_08_lsu.drawio.svg)