From ddfc4d6f362f27176c1042ab49b2a33dcae7c9d6 Mon Sep 17 00:00:00 2001 From: Andrei Solodovnikov Date: Sat, 27 Jul 2024 19:46:27 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9B=D0=A03.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=D0=B4=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=B5=D0=B9=20=D0=BA=20=D0=BB=D0=B8=D1=81=D1=82=D0=B8?= =?UTF-8?q?=D0=BD=D0=B3=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Labs/03. Register file and memory/README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Labs/03. Register file and memory/README.md b/Labs/03. Register file and memory/README.md index d9ec956..90b3549 100644 --- a/Labs/03. Register file and memory/README.md +++ b/Labs/03. Register file and memory/README.md @@ -111,6 +111,8 @@ logic [19:0] memory3 [1:16]; // А вот memory3 хоть и совпадае // особенность. ``` +_Листинг 1. Пример создания массива ячеек._ + В приведенном листинге `logic [19:0] memory1 [16];` создается память с шестнадцатью (от 0-го до 15-го адреса) 20-битными ячейками памяти. В таком случае говорят, что ширина памяти 20 бит, а глубина 16. Для адресации такой памяти потребуется адрес с разрядностью ceil(log2(16)) = 4 бита (`ceil` — операция округления вверх). Это однопортовая память. Для обращения к конкретной ячейке памяти используются квадратные скобки с указанием нужного адреса `memory[addr]`. Грубо говоря, то, что указывается в квадратных скобках будет подключено ко входу адреса памяти `memory`. @@ -158,6 +160,8 @@ module mem16_20 ( // создать блок с именем endmodule ``` +_Листинг 2. Пример описания портов памяти._ + В случае реализации ПЗУ нет необходимости в описании входов для записи, поэтому описание памяти занимает всего пару строк. Чтобы проинициализировать такую память (то есть поместить в нее начальные значения, которые можно было бы из нее читать), требуемое содержимое нужно добавить к прошивке, вместе с которой данные попадут в ПЛИС. Для этого в проект добавляется текстовый файл формата `.mem` с содержимым памяти. Для того, чтобы отметить данный файл в качестве инициализирующего память, можно использовать системную функцию `$readmemh`. У данной функции есть два обязательных аргумента: @@ -195,12 +199,14 @@ module rom16_8 ( end // файла rom_data.mem - assign read_data1 = R0M[addr1]; // реализация первого порта на чтение - assign read_data2 = R0M[addr2] // реализация второго порта на чтение + assign read_data1 = ROM[addr1]; // реализация первого порта на чтение + assign read_data2 = ROM[addr2] // реализация второго порта на чтение endmodule ``` +_Листинг 3. Пример использования инициализирующей функции $readmemh._ + Содержимое файла `rom_data.mem`, к примеру может быть таким (каждая строка соответствует значению отдельной ячейки памяти, начиная со стартового адреса): ```hex @@ -285,6 +291,8 @@ import memory_pkg::INSTR_MEM_SIZE_WORDS; endmodule ``` +_Листинг 4. SystemVerilog-описание памяти инструкций._ + ### 3. Регистровый файл На языке SystemVerilog необходимо реализовать модуль регистрового файла (`rf_r𝚒sсv`) для процессора с архитектурой RISC-V, представляющего собой трехпортовое ОЗУ с двумя портами на чтение и одним портом на запись и состоящей из 32-х 32-битных регистров, объединенных в массив с именем `rf_mem`. @@ -329,7 +337,7 @@ mоdulе rf_r𝚒sсv( 2. Добавьте в проект файл [`memory_pkg.sv`](memory_pkg.sv). Этот файл содержит объявление пакета `memory_pkg`, в котором прописаны размеры памяти инструкций и памяти данных (реализуется позднее). 3. Реализуйте память инструкций. Для этого: 1. В `Design Sources` проекта с предыдущих лаб, создайте `SystemVerilog`-файл `instr_mem.sv`. - 2. Опишите в нем модуль памяти инструкций по предоставленному коду. + 2. Опишите в нем модуль памяти инструкций по предоставленному в _листинге 4_ коду. 4. Реализуйте регистровый файл. Для этого: 1. В `Design Sources` проекта создайте `SystemVerilog`-файл `rf_riscv.sv`. 2. Опишите в нем модуль регистрового файла с таким же именем и портами, как указано в задании.