diff --git a/.pic/Basic Verilog structures/controllers/fig_08.drawio.png b/.pic/Basic Verilog structures/controllers/fig_08.drawio.png index c9ae2e3..a5db2b0 100644 Binary files a/.pic/Basic Verilog structures/controllers/fig_08.drawio.png and b/.pic/Basic Verilog structures/controllers/fig_08.drawio.png differ diff --git a/.pic/Basic Verilog structures/controllers/fig_09.drawio.png b/.pic/Basic Verilog structures/controllers/fig_09.drawio.png index 8ebe3e6..8bac8d0 100644 Binary files a/.pic/Basic Verilog structures/controllers/fig_09.drawio.png and b/.pic/Basic Verilog structures/controllers/fig_09.drawio.png differ diff --git a/Basic Verilog structures/Controllers.md b/Basic Verilog structures/Controllers.md index a5666c7..9880f6b 100644 --- a/Basic Verilog structures/Controllers.md +++ b/Basic Verilog structures/Controllers.md @@ -26,9 +26,9 @@ * W — доступ **только на запись**; * RW — доступ на **чтение и запись**. -В случае отсутствия **запроса на чтения**, на выход `read_data_o` должно подаваться значение `32'hfa11_1eaf`. Это никак не повлияет на работу процессора, но будет удобно в процессе отладки на временной диаграмме (тоже самое было сделано в процессе разработки памяти данных). +В случае отсутствия **запроса на чтение**, на выходе `read_data_o` не должно меняться значение (тоже самое было сделано в процессе разработки памяти данных). -Если пришел **запрос на запись** или **чтение**, это еще не значит, что контроллер должен его выполнить. В случае, если запрос происходит по адресу, не поддерживающему этот запрос (например **запрос на запись** по адресу поддерживающему только чтение), данный запрос должен игнорироваться. В случае **запроса на чтение** по недоступному адресу, на выходе `read_data_o` должно появиться значение `32'hdead_beef`. +Если пришел **запрос на запись** или **чтение**, это еще не значит, что контроллер должен его выполнить. В случае, если запрос происходит по адресу, не поддерживающему этот запрос (например **запрос на запись** по адресу поддерживающему только чтение), данный запрос должен игнорироваться. В случае **запроса на чтение** по недоступному адресу, на выходе `read_data_o` должно остаться прежнее значение. К примеру, в случае запроса на чтение по адресу `0x0100004` (четвертый байт в адресном пространстве периферийного устройства "переключатели"), на выходе `read_data_o` должно оказаться значение `32'hdead_beef`. В случае отсутствия запроса на чтение (`req_i == 0` или `write_enable_i == 1`), на выходе `read_data_o` контроллера переключателей должно оказаться значение `32'hfa11_1eaf`. @@ -147,9 +147,10 @@ endmodule На управление этим сигналом наложены следующие требования: * изменения этого сигнала должны быть **синхронными** (значит перед выходным сигналом должен стоять регистр); -* в случае отсутствия **запроса на чтение**, данный сигнал должен принять значение `32'hfa11_1eaf`; -* в случае **запроса на чтение** по неподдерживаемому адресу, данный сигнал должен принять значение `32'hdead_beef`; * в случае **запроса на чтение** по поддерживаемому адресу, данный сигнал должен принять значение ассоциированного с этим адресом регистра (дополнив это значение нулями в старших разрядах). +* в случае отсутствия **запроса на чтение**, или запроса на чтение по неподдерживаемому адресу, регистр должен сохранить значение + +Чтобы регистр сохранял значение между **запросами на чтение** по поддерживаемому адресу, добавим ему сигнал enable, а на вход данных подадим выход с мультиплексора, выбирающего между доступными источниками данных для чтения. Таким образом, итоговая схема примет вид: diff --git a/Labs/03. Register file and memory/README.md b/Labs/03. Register file and memory/README.md index 8eff492..8e2862a 100644 --- a/Labs/03. Register file and memory/README.md +++ b/Labs/03. Register file and memory/README.md @@ -226,19 +226,13 @@ mоdulе instr_mеm( ); ``` -Не смотря на разрядность адреса, на практике, внутри данного модуля вы должны будете реализовать память с 1024-мя 32-битными ячейками (в ПЛИС попросту не хватит ресурсов на реализации памяти с 232 ячеек). +Не смотря на разрядность адреса, на практике, внутри данного модуля вы должны будете реализовать память с 1024-мя 32-битными ячейками (в ПЛИС попросту не хватит ресурсов на реализации памяти с 232 ячеек). Таким образом, реально будет использоваться только 10 бит адреса. При этом по спецификации процессор RISC-V использует память с побайтовой адресацией. Байтовая адресация означает, что процессор способен обращаться к отдельным байтам в памяти (за каждым байтом памяти закреплен свой индивидуальный адрес). Однако, если у памяти будут 32-рязрядные ячейки, доступ к конкретному байту будет осложнен, ведь каждая ячейка — это 4 байта. Как получить данные третьего байта памяти? Если обратиться к третьей ячейке в массиве — придут данные 12-15-ых байт (поскольку каждая ячейка содержит по 4 байта). Чтобы получить данные третьего байта, необходимо **разделить значение пришедшего адреса на 4** (отбросив остаток от деления). `3 / 4 = 0` — и действительно, если обратиться к нулевой ячейке памяти — будут получены данные 3-го, 2-го, 1-го и 0-го байт. То что помимо значения третьего байта есть еще данные других байт нас в данный момент не интересует, важна только сама возможность указать адрес конкретного байта. -Деление на 2n можно осуществить отбросив `n` младших бит числа. Таким образом на выход память инструкций должна выдавать данные, расположенные по адресу addr_i[31:2]; - -Обращение в память по адресам, превышающим `4095` должно выдавать значение `32'd0`. Почему именно `4095`? `4095 / 4 = 1023` — индекс последней ячейки памяти. - -Как реализовать подобный функционал? Разумеется, с помощью [мультиплексора](../../Basic%20Verilog%20structures/Multiplexors.md). - -В данном случае, вы можете либо воспользоваться конструкцией `if-else` в блоке `always_comb`, либо **тернарным условным оператором** во время реализации **непрерывного присваивания**. В любом из случаев, вам нужно будет реализовать условие того, что пришедшее значение на шине адреса попадает в диапазон допустимых адресов. Если это так, вернуть склейку данных из памяти, начинающихся с этого адреса, в противном случае — вернуть 0. +Деление на 2n можно осуществить отбросив `n` младших бит числа. Учитывая то, что для адресации 1024 ячеек памяти мы будем использовать 10 бит адреса, память инструкций должна выдавать на выход данные, расположенные по адресу `addr_i[11:2]`. ### 2. Память данных @@ -263,23 +257,11 @@ mоdulе data_mеm( ``` -Как и память инструкций, память данных будет состоять из 32-разрядных ячеек (только теперь их будет 4096), и при обращении к этим ячейкам будет необходимо делить адрес на 4. +Как и память инструкций, память данных будет состоять из 32-разрядных ячеек. Только теперь их будет 4096, а значит при обращении к ячейкам памяти нужно использовать не 10 бит адреса, а 12. При этом по-прежнему необходимо разделить пришедший адрес на 4, т.е. нужно отбросить два младших бита. Таким образом, обращение к ячейкам памяти (для записи и чтения) должно осуществляться по адресу `addr_i[13:2]`. -Однако в отличие от памяти инструкций, в память данных добавлено два управляющих сигнала (`mem_req_i`и `write_enable_i`). Сигнал `mem_req_i` является сигналом запроса на работу с памятью. Без этого сигнала память не должна выполнять операции чтения/записи (вне зависимости от сигнала `write_enable`, определяющего происходит сейчас запись или чтение). Как сделать так, чтобы не происходило чтение без запроса? Например возвращать на шину чтения специальное "магическое число". +Однако в отличие от памяти инструкций, в память данных добавлено два управляющих сигнала (`mem_req_i`и `write_enable_i`). Сигнал `mem_req_i` является сигналом запроса на работу с памятью. Без этого сигнала память не должна выполнять операции чтения/записи (вне зависимости от сигнала `write_enable`, определяющего происходит сейчас запись или чтение). Как сделать так, чтобы не происходило чтение без запроса? Например не обновлять значение, считанное во время предыдущей операции чтения. -- В случае `mem_req_i == 0` или `write_enable_i == 1` (т.е. когда не выполняется операция чтения), на выходе `read_data_o` должно оказаться значение `32'hfa11_1eaf` (поскольку `1` схожа с латинским символом `l`, это выражение можно прочесть как `fall_leaf`). -- В случае, если `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`. - -Зачем нужны эти магические числа `32'hfa11_1eaf` и `32'hdead_beef`? У этих чисел легко узнаваемая сигнатура, позволяющая обратить на них внимание. В случае, если при чтении из памяти в регистровый файл попадут эти значения, увидев их вы сможете почувствовать что "что-то не то", и проверить: а было ли в памяти по указанному адресу действительно такое значение (в отличие от значения `32'h0000_0000`, которое не вызовет у вас никаких вопросов). Вероятность того, что такие числа возникнут в естественном ходе работы программы достаточно мала, а значит скорее всего если вы встретите эти числа — это сигнал того, что что-то в вашем процессоре работает неправильно (например, произошло обращение за пределы памяти, или неправильно формируется сигнал `mem_req_i`). - -Если `mem_req_i == 1` и `write_enable_i == 1` происходит запрос на запись в память. В этом случае, необходимо по положительному фронту `clk_i` записать в значение `write_data_i` в ячейку по адресу в 4 раза меньшему `addr_i`. Во всех других случаях (любой из сигналов `mem_req_i`, `write_enable_i` равен нулю), запись в память не производится. - -Поскольку мы описываем память с синхронным чтением, было бы неплохо, чтобы в результате мы получили блочную память (см. [теорию про память](#теория-про-память)). Однако блочная память — это заранее созданный аппаратный блок памяти, в котором нет места придуманным нами магическим числам, поэтому описывая порт на чтение, сперва лучше описать регистр, в который по запросу на работу с памятью всегда будет записываться значение из соответствующей ячейки. А уже после можно описать выход `rеаd_dаtа_o` перед которым будет стоять мультиплексор с тремя входами: константами `32'hfa11_1eaf`, `32'hdead_beaf` и значением с выхода описанного вами регистра: - -![../../.pic/Labs/lab_03_memory/fig_03.drawio.png](../../.pic/Labs/lab_03_memory/fig_03.drawio.png) +Если `mem_req_i == 1` и `write_enable_i == 1`, то происходит запрос на запись в память. В этом случае, необходимо записать значение `write_data_i` в ячейку по адресу `addr_i[13:2]`. Во всех других случаях (любой из сигналов `mem_req_i`, `write_enable_i` равен нулю), запись в память не производится. ### 3. Регистровый файл @@ -327,7 +309,7 @@ mоdulе rf_r𝚒sсv( 1. Сперва необходимо создать память (массив регистров). Как это сделать, сказано в разделе [описание памяти на языке SystemVerilog](#описание-памяти-на-языке-systemverilog). Разрядность ячеек памяти должна быть 32 бита, количество ячеек — 1024. 2. Добавить в проект [`файл с содержимым памяти инструкций`](program.txt)([`как добавить файл, инициализирующий память`](../../Vivado%20Basics/How%20to%20add%20a%20mem-file.md)). Данный файл будет использоваться при вызове системной функции `$readmemh` в описании памяти инструкций. 3. К созданной памяти необходимо подключить выход модуля `read_data_o`. При подключении должен быть использован вход модуля `addr_i`, значение которого должно быть уменьшено в 4 раза (побайтовая адресация). - 4. При подключении выхода `read_data_o` помните, что чтение по адресам, превышающим `4095` должно возвращать `0`. + 4. При реализации выхода `read_data_o` помните, что обращаясь к ячейке памяти, вам необходимо использовать `[11:2]` биты адреса. 3. После описания памяти инструкций, её необходимо проверить с помощью тестового окружения. 1. Тестовое окружение находится [`здесь`](tb_instr_mem.sv). 2. Для запуска симуляции воспользуйтесь [`этой инструкцией`](../../Vivado%20Basics/Run%20Simulation.md). @@ -338,10 +320,8 @@ mоdulе rf_r𝚒sсv( 2. Опишите в нем модуль памяти данных с таким же именем и портами, как указано в задании. 1. Описание модуля будет схожим с описанием модуля памяти инструкций, однако порт чтения в этот раз будет **синхронным** (запись в него будет происходить в блоке `always_ff`). Кроме того необходимо будет описать логику записи данных в память. 2. Запись в ячейки памяти описывается подобно записи данных в [регистры](../../Basic%20Verilog%20structures/Registers.md), только при этом, происходит доступ к конкретной ячейке памяти с помощью входа `addr_i` (как осуществляется доступ к ячейкам памяти сказано в разделе [описание памяти на языке SystemVerilog](#описание-памяти-на-языке-systemverilog)). - 3. Необходимо помнить, что запись будет вестись в ячейку с индексом в 4 раза меньшим пришедшего адреса. - 4. Обратите внимание что работа с памятью должна осуществляться только когда сигнал `mem_req_i == 1`, в противном случае запись не должна производиться, а на шину `read_data_o` должно возвращаться магическое число `32'hfall_leaf`. - 5. При чтении по адресам вне допустимого диапазона (старше адреса `16383`), на шине `read_data_o` должно выставляться значение `32'hdead_beaf`. - 6. Проверка условий перед записью значения в `read_data_o` должно идти в указанном в задании порядке: сперва проверяются значения сигналов `mem_req_i` и `write_enable_i`, и только после этого значение адреса. Реализация логики приоритетов осуществляется в цепочке блоков `if-else-if-else`. + 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). diff --git a/Labs/03. Register file and memory/tb_data_mem.sv b/Labs/03. Register file and memory/tb_data_mem.sv index 6430370..b679bfd 100644 --- a/Labs/03. Register file and memory/tb_data_mem.sv +++ b/Labs/03. Register file and memory/tb_data_mem.sv @@ -63,32 +63,17 @@ parameter STEP = 8; end end for (i = 0; i < (ADDR_SIZE+STEP); i = i + 1 + $urandom() % STEP) begin - if (i < (ADDR_SIZE)) begin - REQ = |($urandom %10); - WE = 0; - #TIME_OPERATION; - RDa = RD; - WD = $urandom; - #TIME_OPERATION; - WE = $urandom % 2; - #TIME_OPERATION; - if ((WE && REQ || !REQ) && RD !== 32'd4195425967) begin - $error("When writing (write_enable_i = %h) read_data_o should be equal to fa11_1eaf, your data: %h_%h, time: %t", WE, RD[31:16],RD[15:0], $time); - err_count = err_count + 1; - end - 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 - end - else begin - WE = 0; - REQ = 1; - #TIME_OPERATION; - if (RD !== 32'd3735928559) begin - $error("When reading (write_enable_i = %h) at address greater than 16383 (current addr = %d), it should return dead_beef, but your data: %h_%h, time: %t", WE, A, RD[31:16],RD[15:0], $time); - err_count = err_count + 1; - end + 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 @@ -96,9 +81,9 @@ parameter STEP = 8; REQ = 1; WE = 0; #TIME_OPERATION; - for (i = 0; i < 4; i = i + 1) begin - if(i==0) begin - repeat(2)@(posedge CLK); + 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 @@ -118,12 +103,6 @@ parameter STEP = 8; err_count = err_count + 1; end @(posedge CLK); - i = {14{1'b1}}; - repeat(2) @(posedge CLK); - if (RD === 'd3735928559) begin - $error("incorrect reading from address = %d, data = %h", A, RD); - err_count = err_count + 1; - end $display("Number of errors: %d", err_count); if( !err_count ) $display("\ndata_mem SUCCESS!!!\n"); $finish(); diff --git a/Labs/07. External memory/README.md b/Labs/07. External memory/README.md index eac3798..fb75d68 100644 --- a/Labs/07. External memory/README.md +++ b/Labs/07. External memory/README.md @@ -55,15 +55,9 @@ module ext_mem( ); ``` -Как и память данных из лабораторной работы №3, память данных в данной лабораторной состоит из 4096-и 32-разрядных ячеек и обладает портом синхронного чтения, выдающим данные по следующим правилам: +Как и память данных из лабораторной работы №3, память данных в данной лабораторной состоит из 4096-и 32-разрядных ячеек и обладает портом синхронного чтения, обновляющим данные только по запросу на чтение (`mem_req_i & !write_enable_i`). -- В случае `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 (можно скопировать эту логику). +Иными словами, логика реализации порта на чтение повторяет логику памяти данных лабораторной работы №3 (можно скопировать эту логику). Если `mem_req_i == 1` и `write_enable_i == 1` (т.е. если происходит запрос на запись в память), то необходимо обновить данные в тех байтах `addr_i / 4`-ой ячейки памяти, которые соответствуют единичным битам сигнала `byte_enable_i`. diff --git a/Labs/12. Peripheral units/README.md b/Labs/12. Peripheral units/README.md index 68b40fd..2161aeb 100644 --- a/Labs/12. Peripheral units/README.md +++ b/Labs/12. Peripheral units/README.md @@ -184,11 +184,9 @@ sys_clk_rst_gen divider(.ex_clk_i(clk_i),.ex_areset_n_i(resetn_i),.div_i(10),.sy * W — доступ **только на запись**; * RW — доступ на **чтение и запись**. -В случае отсутствия **запроса на чтения**, на выход `read_data_o` должно подаваться значение `32'hfa11_1eaf`. Это никак не повлияет на работу процессора, но будет удобно в процессе отладки на временной диаграмме (тоже самое было сделано в процессе разработки памяти данных). +В случае отсутствия **запроса на чтение**, на выходе `read_data_o` не должно меняться значение (тоже самое было сделано в процессе разработки памяти данных). -Если пришел **запрос на запись** или **чтение**, это еще не значит, что контроллер должен его выполнить. В случае, если запрос происходит по адресу, не поддерживающему этот запрос (например **запрос на запись** по адресу поддерживающему только чтение), данный запрос должен игнорироваться. В случае **запроса на чтение** по недоступному адресу, на выходе `read_data_o` должно появиться значение `32'hdead_beef`. - -К примеру, в случае запроса на чтение по адресу `0x0100004` (четвертый байт в адресном пространстве периферийного устройства "переключатели"), на выходе `read_data_o` должно оказаться значение `32'hdead_beef`. В случае отсутствия запроса на чтение (`req_i == 0` или `write_enable_i == 1`), на выходе `read_data_o` контроллера переключателей должно оказаться значение `32'hfa11_1eaf`. +Если пришел **запрос на запись** или **чтение**, это еще не значит, что контроллер должен его выполнить. В случае, если запрос происходит по адресу, не поддерживающему этот запрос (например **запрос на запись** по адресу поддерживающему только чтение), данный запрос должен игнорироваться. В случае **запроса на чтение** по недоступному адресу, на выходе `read_data_o` должно остаться прежнее значение. В случае осуществления записи по принятому запросу, необходимо записать данные с сигнала `write_data_i` в регистр, ассоциированный с адресом `addr_i` (если разрядность регистра меньше разрядности сигнала `write_data_i`, старшие биты записываемых данных отбрасываются). diff --git a/Labs/Made-up modules/lab_03.data_mem.sv b/Labs/Made-up modules/lab_03.data_mem.sv index 31ac535..732f06a 100644 --- a/Labs/Made-up modules/lab_03.data_mem.sv +++ b/Labs/Made-up modules/lab_03.data_mem.sv @@ -17,29 +17,28 @@ logic [31:0] addr; assign addr = {2'b0, addr_i[31:2]}; always_ff @(posedge clk_i) begin - if(write_enable_i&mem_req_i) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{5{1'b1}}:{3'd7,2'b00}] <= write_data_i['h1f:'h1c]; - if(write_enable_i&mem_req_i) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][19:{1'b1,4'h0}] <= write_data_i[42-23-:`asdasdhkjasdsadat]; - if(write_enable_i&mem_req_i) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{3{1'b1}}:{1'b1,2'h0}] <= write_data_i[`akjsdnnaskjdndat-:`asdasdhkjasdsadat]; - if(write_enable_i&mem_req_i) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][23:{{2{2'b10}},1'b0}] <= write_data_i[42-19-:`asdasdhkjasdsadat]; - if(write_enable_i&mem_req_i) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][27:{2'b11,3'b000}] <= write_data_i['h1b:'h18]; - if(write_enable_i&mem_req_i) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][11:{1'b1,{3{1'b0}}}] <= write_data_i[`akjsdnnaskjdndat+`asdasdhkjasdsadat:(`akjsdnnaskjdndat+`asdasdhkjasdsadat)-`cdyfguvhbjnmkdat]; - if(write_enable_i&mem_req_i) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{2{1'b1}}:{3{1'b0}}] <= write_data_i[`akjsdnnaskjdndat-`asdasdhkjasdsadat-:`asdasdhkjasdsadat]; - if(write_enable_i&mem_req_i) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{4{1'b1}}:4'b1100] <= write_data_i[(`akjsdnnaskjdndat<<(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat)) + (`asdasdhkjasdsadat-`cdyfguvhbjnmkdat):12]; + if(write_enable_i&mem_req_i) RAM[addr[13'o10+13'b101:'hBA & 'h45]][{5{1'b1}}:{3'd7,2'b00}] <= write_data_i['h1f:'h1c]; + if(write_enable_i&mem_req_i) RAM[addr[13'o10+13'b101:'hBA & 'h45]][19:{1'b1,4'h0}] <= write_data_i[42-23-:`asdasdhkjasdsadat]; + if(write_enable_i&mem_req_i) RAM[addr[13'o10+13'b101:'hBA & 'h45]][{3{1'b1}}:{1'b1,2'h0}] <= write_data_i[`akjsdnnaskjdndat-:`asdasdhkjasdsadat]; + if(write_enable_i&mem_req_i) RAM[addr[13'o10+13'b101:'hBA & 'h45]][23:{{2{2'b10}},1'b0}] <= write_data_i[42-19-:`asdasdhkjasdsadat]; + if(write_enable_i&mem_req_i) RAM[addr[13'o10+13'b101:'hBA & 'h45]][27:{2'b11,3'b000}] <= write_data_i['h1b:'h18]; + if(write_enable_i&mem_req_i) RAM[addr[13'o10+13'b101:'hBA & 'h45]][11:{1'b1,{3{1'b0}}}] <= write_data_i[`akjsdnnaskjdndat+`asdasdhkjasdsadat:(`akjsdnnaskjdndat+`asdasdhkjasdsadat)-`cdyfguvhbjnmkdat]; + if(write_enable_i&mem_req_i) RAM[addr[13'o10+13'b101:'hBA & 'h45]][{2{1'b1}}:{3{1'b0}}] <= write_data_i[`akjsdnnaskjdndat-`asdasdhkjasdsadat-:`asdasdhkjasdsadat]; + if(write_enable_i&mem_req_i) RAM[addr[13'o10+13'b101:'hBA & 'h45]][{4{1'b1}}:4'b1100] <= write_data_i[(`akjsdnnaskjdndat<<(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat)) + (`asdasdhkjasdsadat-`cdyfguvhbjnmkdat):12]; end always_ff@(posedge clk_i) begin case(1) - !mem_req_i||write_enable_i: read_data_o <= 'd4195425967; - mem_req_i&&(addr_i<={14{1'b1}}): begin - read_data_o['h1f:'h1c]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{5{1'b1}}:{3'd7,2'b00}]; - read_data_o[42-23-:`asdasdhkjasdsadat]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][19:{1'b1,4'h0}]; - read_data_o[`akjsdnnaskjdndat-:`asdasdhkjasdsadat]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{3{1'b1}}:{1'b1,2'h0}]; - read_data_o[42-19-:`asdasdhkjasdsadat]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][23:{{2{2'b10}},1'b0}]; - read_data_o['h1b:'h18]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][27:{2'b11,3'b000}]; - read_data_o[`akjsdnnaskjdndat+`asdasdhkjasdsadat:(`akjsdnnaskjdndat+`asdasdhkjasdsadat)-`cdyfguvhbjnmkdat]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][11:8]; - read_data_o[`akjsdnnaskjdndat-`asdasdhkjasdsadat-:`asdasdhkjasdsadat]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][3:0]; - read_data_o[(`akjsdnnaskjdndat<<(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat))+(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat):12]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{4{1'b1}}:12]; + mem_req_i&&!write_enable_i: begin + read_data_o['h1f:'h1c]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][{5{1'b1}}:{3'd7,2'b00}]; + read_data_o[42-23-:`asdasdhkjasdsadat]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][19:{1'b1,4'h0}]; + read_data_o[`akjsdnnaskjdndat-:`asdasdhkjasdsadat]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][{3{1'b1}}:{1'b1,2'h0}]; + read_data_o[42-19-:`asdasdhkjasdsadat]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][23:{{2{2'b10}},1'b0}]; + read_data_o['h1b:'h18]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][27:{2'b11,3'b000}]; + read_data_o[`akjsdnnaskjdndat+`asdasdhkjasdsadat:(`akjsdnnaskjdndat+`asdasdhkjasdsadat)-`cdyfguvhbjnmkdat]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][11:8]; + read_data_o[`akjsdnnaskjdndat-`asdasdhkjasdsadat-:`asdasdhkjasdsadat]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][3:0]; + read_data_o[(`akjsdnnaskjdndat<<(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat))+(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat):12]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][{4{1'b1}}:12]; end - default: read_data_o <= 'd3735928559; + default: read_data_o <= read_data_o; endcase end endmodule diff --git a/Labs/Made-up modules/lab_03.instr_mem.sv b/Labs/Made-up modules/lab_03.instr_mem.sv index 6aa6b89..502639b 100644 --- a/Labs/Made-up modules/lab_03.instr_mem.sv +++ b/Labs/Made-up modules/lab_03.instr_mem.sv @@ -12,18 +12,13 @@ reg [31:0] RAM [0:1023]; initial $readmemh("program.txt", RAM); always_comb begin - case(addr_i > {12{1'b1}}) - 0: begin - read_data_o['h1f:'h1c]=RAM[{2'b00, addr_i[{5{1'b1}}:2]}][{5{1'b1}}:{3'd7,2'b00}]; - read_data_o[42-23-:`asdasdhkjasdsa]=RAM[{2'b00, addr_i[{5{1'b1}}:2]}][19:{1'b1,4'h0}]; - read_data_o[`akjsdnnaskjdn-:`asdasdhkjasdsa]=RAM[{2'b00, addr_i[{5{1'b1}}:2]}][{3{1'b1}}:{1'b1,2'h0}]; - read_data_o[42-19-:`asdasdhkjasdsa]=RAM[{2'b00, addr_i[{5{1'b1}}:2]}][23:{{2{2'b10}},1'b0}]; - read_data_o['h1b:'h18]=RAM[{2'b00, addr_i[{5{1'b1}}:2]}][27:{2'b11,3'b000}]; - read_data_o[`akjsdnnaskjdn+`asdasdhkjasdsa:(`akjsdnnaskjdn+`asdasdhkjasdsa)-`cdyfguvhbjnmk]=RAM[{2'b00, addr_i[{5{1'b1}}:2]}][11:8]; - read_data_o[`akjsdnnaskjdn-`asdasdhkjasdsa-:`asdasdhkjasdsa]=RAM[{2'b00, addr_i[{5{1'b1}}:2]}][3:0]; - read_data_o[(`akjsdnnaskjdn<<(`asdasdhkjasdsa-`cdyfguvhbjnmk)) + (`asdasdhkjasdsa-`cdyfguvhbjnmk):12 ]=RAM[{2'b00, addr_i[{5{1'b1}}:2]}][{4{1'b1}}:12]; - end - default: read_data_o = 'hBA & 'h45; - endcase + 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/Made-up modules/lab_07.ext_mem.sv b/Labs/Made-up modules/lab_07.ext_mem.sv index 7eab6d3..c5cba59 100644 --- a/Labs/Made-up modules/lab_07.ext_mem.sv +++ b/Labs/Made-up modules/lab_07.ext_mem.sv @@ -40,28 +40,28 @@ always_ff@(posedge clk_i) begin case(1) !mem_req_i||write_enable_i: read_data_o <= 'd4195425967; mem_req_i&&(addr_i<={14{1'b1}}): begin - read_data_o['h1f:'h1c]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{5{1'b1}}:{3'd7,2'b00}]; - read_data_o[42-23-:`asdasdhkjasdsadat]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][19:{1'b1,4'h0}]; - read_data_o[`akjsdnnaskjdndat-:`asdasdhkjasdsadat]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{3{1'b1}}:{1'b1,2'h0}]; - read_data_o[42-19-:`asdasdhkjasdsadat]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][23:{{2{2'b10}},1'b0}]; - read_data_o['h1b:'h18]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][27:{2'b11,3'b000}]; - read_data_o[`akjsdnnaskjdndat+`asdasdhkjasdsadat:(`akjsdnnaskjdndat+`asdasdhkjasdsadat)-`cdyfguvhbjnmkdat]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][11:8]; - read_data_o[`akjsdnnaskjdndat-`asdasdhkjasdsadat-:`asdasdhkjasdsadat]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][3:0]; - read_data_o[(`akjsdnnaskjdndat<<(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat))+(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat):12]<=RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{4{1'b1}}:12]; + read_data_o['h1f:'h1c]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][{5{1'b1}}:{3'd7,2'b00}]; + read_data_o[42-23-:`asdasdhkjasdsadat]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][19:{1'b1,4'h0}]; + read_data_o[`akjsdnnaskjdndat-:`asdasdhkjasdsadat]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][{3{1'b1}}:{1'b1,2'h0}]; + read_data_o[42-19-:`asdasdhkjasdsadat]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][23:{{2{2'b10}},1'b0}]; + read_data_o['h1b:'h18]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][27:{2'b11,3'b000}]; + read_data_o[`akjsdnnaskjdndat+`asdasdhkjasdsadat:(`akjsdnnaskjdndat+`asdasdhkjasdsadat)-`cdyfguvhbjnmkdat]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][11:8]; + read_data_o[`akjsdnnaskjdndat-`asdasdhkjasdsadat-:`asdasdhkjasdsadat]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][3:0]; + read_data_o[(`akjsdnnaskjdndat<<(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat))+(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat):12]<=RAM[addr[13'o10+13'b101:'hBA & 'h45]][{4{1'b1}}:12]; end default: read_data_o <= 'd3735928559; endcase end always_ff @(posedge clk_i) begin - if(write_enable_i&mem_req_i&be[4'o14>>2]) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{5{1'b1}}:{3'd7,2'b00}] <= write_data_i['h1f:'h1c]; - if(write_enable_i&mem_req_i&be[7'd5>>1]) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][19:{1'b1,4'h0}] <= write_data_i[42-23-:`asdasdhkjasdsadat]; - if(write_enable_i&mem_req_i&be[16'haaaa&16'h5555]) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{3{1'b1}}:{1'b1,2'h0}] <= write_data_i[`akjsdnnaskjdndat-:`asdasdhkjasdsadat]; - if(write_enable_i&mem_req_i&be[7'd2-$clog2(1)]) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][23:{{2{2'b10}},1'b0}] <= write_data_i[42-19-:`asdasdhkjasdsadat]; - if(write_enable_i&mem_req_i&be[4'o17&(4'o14>>2)]) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][27:{2'b11,3'b000}] <= write_data_i['h1b:'h18]; - if(write_enable_i&mem_req_i&be[3'sb111>>8]) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][11:{1'b1,{3{1'b0}}}] <= write_data_i[`akjsdnnaskjdndat+`asdasdhkjasdsadat:(`akjsdnnaskjdndat+`asdasdhkjasdsadat)-`cdyfguvhbjnmkdat]; - if(write_enable_i&mem_req_i&be[$clog2(1)]) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{2{1'b1}}:{3{1'b0}}] <= write_data_i[`akjsdnnaskjdndat-`asdasdhkjasdsadat-:`asdasdhkjasdsadat]; - if(write_enable_i&mem_req_i&be[4'o13&4'o25]) RAM[addr[{1'b1,2'b0}:'hBA & 'h45]][{4{1'b1}}:4'b1100] <= write_data_i[(`akjsdnnaskjdndat<<(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat)) + (`asdasdhkjasdsadat-`cdyfguvhbjnmkdat):12]; + if(write_enable_i&mem_req_i&be[4'o14>>2]) RAM[addr[13'o10+13'b101:'hBA & 'h45]][{5{1'b1}}:{3'd7,2'b00}] <= write_data_i['h1f:'h1c]; + if(write_enable_i&mem_req_i&be[7'd5>>1]) RAM[addr[13'o10+13'b101:'hBA & 'h45]][19:{1'b1,4'h0}] <= write_data_i[42-23-:`asdasdhkjasdsadat]; + if(write_enable_i&mem_req_i&be[16'haaaa&16'h5555]) RAM[addr[13'o10+13'b101:'hBA & 'h45]][{3{1'b1}}:{1'b1,2'h0}] <= write_data_i[`akjsdnnaskjdndat-:`asdasdhkjasdsadat]; + if(write_enable_i&mem_req_i&be[7'd2-$clog2(1)]) RAM[addr[13'o10+13'b101:'hBA & 'h45]][23:{{2{2'b10}},1'b0}] <= write_data_i[42-19-:`asdasdhkjasdsadat]; + if(write_enable_i&mem_req_i&be[4'o17&(4'o14>>2)]) RAM[addr[13'o10+13'b101:'hBA & 'h45]][27:{2'b11,3'b000}] <= write_data_i['h1b:'h18]; + if(write_enable_i&mem_req_i&be[3'sb111>>8]) RAM[addr[13'o10+13'b101:'hBA & 'h45]][11:{1'b1,{3{1'b0}}}] <= write_data_i[`akjsdnnaskjdndat+`asdasdhkjasdsadat:(`akjsdnnaskjdndat+`asdasdhkjasdsadat)-`cdyfguvhbjnmkdat]; + if(write_enable_i&mem_req_i&be[$clog2(1)]) RAM[addr[13'o10+13'b101:'hBA & 'h45]][{2{1'b1}}:{3{1'b0}}] <= write_data_i[`akjsdnnaskjdndat-`asdasdhkjasdsadat-:`asdasdhkjasdsadat]; + if(write_enable_i&mem_req_i&be[4'o13&4'o25]) RAM[addr[13'o10+13'b101:'hBA & 'h45]][{4{1'b1}}:4'b1100] <= write_data_i[(`akjsdnnaskjdndat<<(`asdasdhkjasdsadat-`cdyfguvhbjnmkdat)) + (`asdasdhkjasdsadat-`cdyfguvhbjnmkdat):12]; end endmodule