From 0209c0916003dc9872b0ba01ffde752883ca3031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Tue, 3 Sep 2024 17:57:47 +0100 Subject: [PATCH 01/12] feat(fifos): Add confs to FIFOs python modules --- .../fifo/iob_fifo_async/iob_fifo_async.py | 74 +++++++++++++++++++ .../fifo/iob_fifo_sync/iob_fifo_sync.py | 74 +++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/lib/hardware/fifo/iob_fifo_async/iob_fifo_async.py b/lib/hardware/fifo/iob_fifo_async/iob_fifo_async.py index afeba64ef..e5d32f9b6 100644 --- a/lib/hardware/fifo/iob_fifo_async/iob_fifo_async.py +++ b/lib/hardware/fifo/iob_fifo_async/iob_fifo_async.py @@ -4,6 +4,80 @@ def setup(py_params_dict): "name": "iob_fifo_async", "version": "0.1", "generate_hw": False, + "confs": [ + { + "name": "W_DATA_W", + "descr": "", + "type": "P", + "val": "21", + "min": "NA", + "max": "NA", + }, + { + "name": "R_DATA_W", + "descr": "", + "type": "P", + "val": "21", + "min": "NA", + "max": "NA", + }, + { + "name": "ADDR_W", + "descr": "Higher ADDR_W lower DATA_W", + "type": "P", + "val": "3", + "min": "NA", + "max": "NA", + }, + { + "name": "MAXDATA_W", + "descr": "", + "type": "F", + "val": "iob_max(W_DATA_W, R_DATA_W)", + "min": "NA", + "max": "NA", + }, + { + "name": "MINDATA_W", + "descr": "", + "type": "F", + "val": "iob_min(W_DATA_W, R_DATA_W)", + "min": "NA", + "max": "NA", + }, + { + "name": "R", + "descr": "", + "type": "F", + "val": "MAXDATA_W / MINDATA_W", + "min": "NA", + "max": "NA", + }, + { + "name": "MINADDR_W", + "descr": "Lower ADDR_W (higher DATA_W)", + "type": "F", + "val": "ADDR_W - $clog2(R)", + "min": "NA", + "max": "NA", + }, + { + "name": "W_ADDR_W", + "descr": "", + "type": "F", + "val": "(W_DATA_W == MAXDATA_W) ? MINADDR_W : ADDR_W", + "min": "NA", + "max": "NA", + }, + { + "name": "R_ADDR_W", + "descr": "", + "type": "F", + "val": "(R_DATA_W == MAXDATA_W) ? MINADDR_W : ADDR_W", + "min": "NA", + "max": "NA", + }, + ], "ports": [ { "name": "write", diff --git a/lib/hardware/fifo/iob_fifo_sync/iob_fifo_sync.py b/lib/hardware/fifo/iob_fifo_sync/iob_fifo_sync.py index 0d163acc4..d551419ff 100644 --- a/lib/hardware/fifo/iob_fifo_sync/iob_fifo_sync.py +++ b/lib/hardware/fifo/iob_fifo_sync/iob_fifo_sync.py @@ -4,6 +4,80 @@ def setup(py_params_dict): "name": "iob_fifo_sync", "version": "0.1", "generate_hw": False, + "confs": [ + { + "name": "W_DATA_W", + "descr": "", + "type": "P", + "val": "21", + "min": "NA", + "max": "NA", + }, + { + "name": "R_DATA_W", + "descr": "", + "type": "P", + "val": "21", + "min": "NA", + "max": "NA", + }, + { + "name": "ADDR_W", + "descr": "Higher ADDR_W lower DATA_W", + "type": "P", + "val": "21", + "min": "NA", + "max": "NA", + }, + { + "name": "MAXDATA_W", + "descr": "", + "type": "F", + "val": "iob_max(W_DATA_W, R_DATA_W)", + "min": "NA", + "max": "NA", + }, + { + "name": "MINDATA_W", + "descr": "", + "type": "F", + "val": "iob_min(W_DATA_W, R_DATA_W)", + "min": "NA", + "max": "NA", + }, + { + "name": "R", + "descr": "", + "type": "F", + "val": "MAXDATA_W / MINDATA_W", + "min": "NA", + "max": "NA", + }, + { + "name": "MINADDR_W", + "descr": "Lower ADDR_W (higher DATA_W)", + "type": "F", + "val": "ADDR_W - $clog2(R)", + "min": "NA", + "max": "NA", + }, + { + "name": "W_ADDR_W", + "descr": "", + "type": "F", + "val": "(W_DATA_W == MAXDATA_W) ? MINADDR_W : ADDR_W", + "min": "NA", + "max": "NA", + }, + { + "name": "R_ADDR_W", + "descr": "", + "type": "F", + "val": "(R_DATA_W == MAXDATA_W) ? MINADDR_W : ADDR_W", + "min": "NA", + "max": "NA", + }, + ], "ports": [ { "name": "clk_en_rst", From 83cdb0480118704b0f968fcad63ca2350a809139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Wed, 4 Sep 2024 20:50:53 +0100 Subject: [PATCH 02/12] feat(vex): Add VexRiscV CPU; Use single bootrom; Structure similar to iob_soc_opencryptolinux system. --- .gitmodules | 6 +- .../fpga/quartus/cyclonev_gt_dk/board.tcl | 8 +- .../quartus/cyclonev_gt_dk/cyclonev_gt_dk.py | 8 - .../vivado/aes_ku040_db_g/aes_ku040_db_g.py | 11 - .../modules/iob_soc_mwrap/iob_soc_mwrap.py | 2 +- .../iob_soc_sim_wrapper.py | 8 - hardware/simulation/src/iob_soc_tb.cpp | 7 - hardware/simulation/src/iob_soc_tb.v | 10 - iob_soc.py | 202 +++++++++--------- submodules/BOOTROM/iob_bootrom.py | 196 ++++++----------- submodules/CACHE | 1 - submodules/VEXRISCV | 1 + 12 files changed, 168 insertions(+), 292 deletions(-) delete mode 160000 submodules/CACHE create mode 160000 submodules/VEXRISCV diff --git a/.gitmodules b/.gitmodules index 754d95974..92a26f7fa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "submodules/CACHE"] - path = submodules/CACHE - url = git@github.com:IObundle/iob-cache.git +[submodule "submodules/VEXRISCV"] + path = submodules/VEXRISCV + url = git@github.com:IObundle/iob-vexriscv.git diff --git a/hardware/fpga/quartus/cyclonev_gt_dk/board.tcl b/hardware/fpga/quartus/cyclonev_gt_dk/board.tcl index 54bad4fb5..a78dfaba9 100644 --- a/hardware/fpga/quartus/cyclonev_gt_dk/board.tcl +++ b/hardware/fpga/quartus/cyclonev_gt_dk/board.tcl @@ -33,11 +33,11 @@ if {$IS_FPGA == "1"} { #set_location_assignment PIN_AM23 -to led #set_instance_assignment -name IO_STANDARD "2.5-V" -to led - set_location_assignment PIN_AE25 -to trap_o - set_instance_assignment -name IO_STANDARD "1.5-V" -to trap_o + #set_location_assignment PIN_AE25 -to trap_o + #set_instance_assignment -name IO_STANDARD "1.5-V" -to trap_o - set_instance_assignment -name SLEW_RATE 1 -to trap_o - set_instance_assignment -name CURRENT_STRENGTH_NEW DEFAULT -to trap_o + #set_instance_assignment -name SLEW_RATE 1 -to trap_o + #set_instance_assignment -name CURRENT_STRENGTH_NEW DEFAULT -to trap_o #Uart set_location_assignment PIN_F10 -to txd_o diff --git a/hardware/fpga/quartus/cyclonev_gt_dk/cyclonev_gt_dk.py b/hardware/fpga/quartus/cyclonev_gt_dk/cyclonev_gt_dk.py index 0ac336206..568e76746 100644 --- a/hardware/fpga/quartus/cyclonev_gt_dk/cyclonev_gt_dk.py +++ b/hardware/fpga/quartus/cyclonev_gt_dk/cyclonev_gt_dk.py @@ -52,13 +52,6 @@ def setup(py_params_dict): {"name": "resetn", "direction": "input", "width": "1"}, ], }, - { - "name": "trap", - "descr": "CPU trap output", - "signals": [ - {"name": "trap", "direction": "output", "width": "1"}, - ], - }, { "name": "rs232", "descr": "Serial port", @@ -263,7 +256,6 @@ def setup(py_params_dict): }, "connect": { "clk_en_rst": "clk_en_rst", - "cpu_trap": "trap", "rs232": "rs232_int", "axi": "axi", }, diff --git a/hardware/fpga/vivado/aes_ku040_db_g/aes_ku040_db_g.py b/hardware/fpga/vivado/aes_ku040_db_g/aes_ku040_db_g.py index f9727731e..a27eaa026 100644 --- a/hardware/fpga/vivado/aes_ku040_db_g/aes_ku040_db_g.py +++ b/hardware/fpga/vivado/aes_ku040_db_g/aes_ku040_db_g.py @@ -125,16 +125,6 @@ def setup(py_params_dict): "type": "clk_en_rst", }, }, - { - "name": "cpu_trap", - "descr": "CPU trap", - "signals": [ - { - "name": "trap", - "width": "1", - }, - ], - }, { "name": "rs232_int", "descr": "iob-soc uart interface", @@ -285,7 +275,6 @@ def setup(py_params_dict): }, "connect": { "clk_en_rst": "clk_en_rst", - "cpu_trap": "cpu_trap", "rs232": "rs232_int", "axi": "axi", }, diff --git a/hardware/modules/iob_soc_mwrap/iob_soc_mwrap.py b/hardware/modules/iob_soc_mwrap/iob_soc_mwrap.py index f991f0479..ad54f7b09 100644 --- a/hardware/modules/iob_soc_mwrap/iob_soc_mwrap.py +++ b/hardware/modules/iob_soc_mwrap/iob_soc_mwrap.py @@ -17,7 +17,7 @@ def setup(py_params_dict): "name": "BOOT_HEXFILE", "descr": "Bootloader file name", "type": "P", - "val": '"iob_soc_boot"', + "val": '"iob_soc_bootrom"', "min": "NA", "max": "NA", }, diff --git a/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py b/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py index c2d2f69e7..0c16bbfb4 100644 --- a/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py +++ b/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py @@ -52,13 +52,6 @@ def setup(py_params_dict): "subtype": "slave", }, }, - { - "name": "trap", - "descr": "CPU trap", - "signals": [ - {"name": "trap", "direction": "output", "width": "1"}, - ], - }, { "name": "uart", "descr": "Testbench uart csrs interface", @@ -194,7 +187,6 @@ def setup(py_params_dict): }, "connect": { "clk_en_rst": "clk_en_rst", - "cpu_trap": "trap", "rs232": "rs232", "axi": "axi", }, diff --git a/hardware/simulation/src/iob_soc_tb.cpp b/hardware/simulation/src/iob_soc_tb.cpp index 2da7495c2..3d26e5889 100644 --- a/hardware/simulation/src/iob_soc_tb.cpp +++ b/hardware/simulation/src/iob_soc_tb.cpp @@ -110,13 +110,6 @@ int main(int argc, char **argv, char **env) { #endif while (1) { - if (dut->trap_o > 0) { - printf("\nTESTBENCH: force cpu trap exit\n"); - cpu_char = 4; - fwrite(&cpu_char, sizeof(char), 1, soc2cnsl_fd); - fclose(soc2cnsl_fd); - break; - } while (!rxread_reg && !txread_reg) { rxread_reg = (char)iob_read(IOB_UART_RXREADY_ADDR, &uart_if); txread_reg = (char)iob_read(IOB_UART_TXREADY_ADDR, &uart_if); diff --git a/hardware/simulation/src/iob_soc_tb.v b/hardware/simulation/src/iob_soc_tb.v index 3d5c6b937..3db784fed 100644 --- a/hardware/simulation/src/iob_soc_tb.v +++ b/hardware/simulation/src/iob_soc_tb.v @@ -43,9 +43,6 @@ module iob_soc_tb; integer i = 0, n = 0; integer error, n_byte = 0; - //cpu trap signal - wire trap; - ///////////////////////////////////////////// // TEST PROCEDURE // @@ -144,7 +141,6 @@ module iob_soc_tb; .clk_i (clk), .cke_i (1'b1), .arst_i(arst), - .trap_o(trap), `ifdef IOB_SOC_USE_ETHERNET .ethernet_iob_valid_i (ethernet_valid), @@ -180,10 +176,4 @@ module iob_soc_tb; `include "iob_tasks.vs" - //finish simulation on trap - always @(posedge trap) begin - #10 $display("Found CPU trap condition"); - $finish(); - end - endmodule diff --git a/iob_soc.py b/iob_soc.py index dd9d94c17..c481ec0ae 100755 --- a/iob_soc.py +++ b/iob_soc.py @@ -16,9 +16,6 @@ def setup(py_params_dict): "data_w": 32, "mem_addr_w": 24, "bootrom_addr_w": 12, - "prebootrom_addr_w": 7, - "use_compressed": True, - "use_mul_div": True, "fw_addr": 0, "fw_addr_w": 15, } @@ -68,22 +65,6 @@ def setup(py_params_dict): "min": "0", "max": "1", }, - { # Needed for makefile - "name": "USE_MUL_DIV", - "descr": "Enable MUL and DIV CPU instructions", - "type": "M", - "val": params["use_mul_div"], - "min": "0", - "max": "1", - }, - { # Needed for makefile - "name": "USE_COMPRESSED", - "descr": "Use compressed CPU instructions", - "type": "M", - "val": params["use_compressed"], - "min": "0", - "max": "1", - }, { # Needed for software "name": "MEM_ADDR_W", "descr": "Memory bus address width", @@ -116,14 +97,6 @@ def setup(py_params_dict): "min": "0", "max": "1", }, - { # Needed for makefiles - "name": "PREBOOTROM_ADDR_W", - "descr": "Preboot ROM address width", - "type": "M", - "val": params["prebootrom_addr_w"], - "min": "1", - "max": "32", - }, { # Needed for software and makefiles "name": "BOOTROM_ADDR_W", "descr": "Bootloader ROM address width", @@ -176,17 +149,6 @@ def setup(py_params_dict): "subtype": "slave", }, }, - { - "name": "cpu_trap", - "descr": "CPU trap output", - "signals": [ - { - "name": "trap", - "direction": "output", - "width": "1", - }, - ], - }, { "name": "rom_bus", "descr": "Ports for connection with ROM memory", @@ -233,10 +195,17 @@ def setup(py_params_dict): attributes_dict["wires"] = [ { - "name": "cpu_general", - "descr": "", + "name": "clk", + "descr": "Clock signal", + "signals": [ + {"name": "clk"}, + ], + }, + { + "name": "rst", + "descr": "Reset signal", "signals": [ - {"name": "trap"}, + {"name": "arst"}, ], }, { @@ -259,6 +228,18 @@ def setup(py_params_dict): "ADDR_W": params["addr_w"], }, }, + { + "name": "periphs_axi", + "descr": "AXI bus for peripheral CSRs", + "interface": { + "type": "axi", + "subtype": "master", + "ID_W": "AXI_ID_W", + "ADDR_W": "AXI_ADDR_W", + "DATA_W": "AXI_DATA_W", + "LEN_W": "AXI_LEN_W", + }, + }, { "name": "periphs_cbus", "descr": "Bus for peripherals Control/Status Register interfaces", @@ -309,39 +290,66 @@ def setup(py_params_dict): "name": "bootrom_ibus", "descr": "iob-soc boot controller instruction interface", "interface": { - "type": "iob", + "type": "axi", "wire_prefix": "bootrom_i_", "DATA_W": params["data_w"], "ADDR_W": params["addr_w"] - 1, }, }, + { + "name": "bootrom_bus", + "descr": "iob-soc boot controller data interface", + "interface": { + "type": "axi", + "wire_prefix": "bootrom_d_", + "DATA_W": params["data_w"], + "ADDR_W": params["addr_w"] - 1, + }, + }, + { + "name": "interrupts", + "descr": "System interrupts", + "signals": [ + {"name": "interrupts", "width": 1}, + ], + }, # Peripheral wires { - "name": "uart_cbus", - "descr": "UART Control/Status Registers bus", + "name": "plic_cbus", + "descr": "PLIC Control/Status Registers bus", "interface": { - "type": "iob", - "wire_prefix": "uart_cbus_", + "type": "axil", + "wire_prefix": "plic_cbus_", "DATA_W": params["data_w"], "ADDR_W": params["addr_w"] - 3, }, }, { - "name": "timer_cbus", - "descr": "TIMER Control/Status Registers bus", + "name": "clint_cbus", + "descr": "CLINT Control/Status Registers bus", + "interface": { + "type": "axil", + "wire_prefix": "clint_cbus_", + "DATA_W": params["data_w"], + "ADDR_W": params["addr_w"] - 3, + }, + }, + { + "name": "uart_cbus", + "descr": "UART Control/Status Registers bus", "interface": { "type": "iob", - "wire_prefix": "timer_cbus_", + "wire_prefix": "uart_cbus_", "DATA_W": params["data_w"], "ADDR_W": params["addr_w"] - 3, }, }, { - "name": "bootrom_cbus", - "descr": "BOOTROM Control/Status Registers bus", + "name": "timer_cbus", + "descr": "TIMER Control/Status Registers bus", "interface": { "type": "iob", - "wire_prefix": "bootrom_cbus_", + "wire_prefix": "timer_cbus_", "DATA_W": params["data_w"], "ADDR_W": params["addr_w"] - 3, }, @@ -350,58 +358,56 @@ def setup(py_params_dict): ] attributes_dict["blocks"] = [ { - "core_name": "iob_picorv32", + "core_name": "iob_vexriscv", "instance_name": "cpu", "instance_description": "RISC-V CPU instance", "parameters": { "ADDR_W": params["addr_w"], "DATA_W": params["data_w"], - "USE_COMPRESSED": int(params["use_compressed"]), - "USE_MUL_DIV": int(params["use_mul_div"]), }, "connect": { "clk_en_rst": "clk_en_rst", - "general": "cpu_general", + "rst": "rst", "i_bus": "cpu_ibus", "d_bus": "cpu_dbus", + "plic_interrupts": "interrupts", + "plic_cbus": "plic_cbus", + "clint_cbus": "clint_cbus", }, }, { - "core_name": "iob_soc_cache_system", - "instance_name": "cache_system", + "core_name": "axi_interconnect_wrapper", + "instance_name": "axi_interconnect", + "instance_description": "Interconnect instance", "parameters": { - "FIRM_ADDR_W": params["mem_addr_w"], - "DDR_ADDR_W ": "`DDR_ADDR_W", - "DDR_DATA_W ": "`DDR_DATA_W", - "AXI_ID_W ": "AXI_ID_W", - "AXI_LEN_W ": "AXI_LEN_W", - "AXI_ADDR_W ": "AXI_ADDR_W", - "AXI_DATA_W ": "AXI_DATA_W", + "AXI_ID_W": "AXI_ID_W", + "AXI_ADDR_W": "AXI_ADDR_W", + "AXI_DATA_W": "AXI_DATA_W", }, "connect": { - "clk_en_rst": "mem_clk_en_rst", - "i_bus": "cache_ibus", - "d_bus": "cache_dbus", - "axi": "axi", - }, - "addr_w": params["addr_w"] - 1, - "data_w": params["data_w"], - "mem_addr_w": params["mem_addr_w"], + "clk": "clk", + "rst": "rst", + "s0_axi": "cpu_ibus", + "s1_axi": "cpu_dbus", + "m0_axi": "bootrom_bus", + "m1_axi": "axi", + "m2_axi": "periphs_axi", + "m3_axi": "clint_cbus", + "m4_axi": "plic_cbus", + }, + "num_slaves": 2, + "num_masters": 5, + # FIXME: Size of each output }, { - "core_name": "iob_split", - "name": "iob_data_split", - "instance_name": "iob_data_split", - "instance_description": "Split between cache and peripheral bus", + "core_name": "axil2iob", + "instance_name": "peripheral_axil2iob", + "instance_description": "Convert AXI interface to IOb for peripheral CSRs bus", "connect": { "clk_en_rst": "clk_en_rst", - "reset": "split_reset", - "input": "cpu_dbus", - "output_0": "cache_dbus", - "output_1": "periphs_cbus", + "axil": "periphs_axi", + "iob": "periphs_cbus", }, - "num_outputs": 2, - "addr_w": params["addr_w"], }, { "core_name": "iob_split", @@ -414,26 +420,10 @@ def setup(py_params_dict): "input": "periphs_cbus", "output_0": "uart_cbus", "output_1": "timer_cbus", - "output_2": "bootrom_cbus", # NOTE: Connect other peripherals here }, "num_outputs": num_peripherals, - "addr_w": params["addr_w"] - 1, - }, - { - "core_name": "iob_split", - "name": "iob_instr_split", - "instance_name": "iob_instr_split", - "instance_description": "Split between cache and bootrom bus", - "connect": { - "clk_en_rst": "clk_en_rst", - "reset": "split_reset", - "input": "cpu_ibus", - "output_0": "cache_ibus", - "output_1": "bootrom_ibus", - }, - "num_outputs": 2, - "addr_w": params["addr_w"], + "addr_w": params["addr_w"] - 1, # FIXME: }, ] peripherals = [ @@ -465,12 +455,10 @@ def setup(py_params_dict): "parameters": {}, "connect": { "clk_en_rst": "clk_en_rst", - "cbus": "bootrom_cbus", - "ibus": "bootrom_ibus", + "rom_bus": "bootrom_bus", "ext_rom_bus": "rom_bus", }, "bootrom_addr_w": params["bootrom_addr_w"], - "prebootrom_addr_w": params["prebootrom_addr_w"], }, # NOTE: Instantiate other peripherals here ] @@ -515,6 +503,14 @@ def setup(py_params_dict): "instance_name": "printf_inst", }, ] + attributes_dict["snippets"] = [ + { + "verilog_code": """ + //assign interrupts = {{30{1'b0}}, uart_interrupt_o, 1'b0}; + assign interrupts = {{30{1'b0}}, 1'b0, 1'b0}; +""" + } + ] iob_soc_scripts(attributes_dict, peripherals, params, py_params_dict) diff --git a/submodules/BOOTROM/iob_bootrom.py b/submodules/BOOTROM/iob_bootrom.py index 88e48b92f..b705b14fb 100644 --- a/submodules/BOOTROM/iob_bootrom.py +++ b/submodules/BOOTROM/iob_bootrom.py @@ -3,11 +3,6 @@ def setup(py_params_dict): BOOTROM_ADDR_W = ( py_params_dict["bootrom_addr_w"] if "bootrom_addr_w" in py_params_dict else 12 ) - PREBOOTROM_ADDR_W = ( - py_params_dict["prebootrom_addr_w"] - if "prebootrom_addr_w" in py_params_dict - else 7 - ) attributes_dict = { "original_name": "iob_bootrom", @@ -19,18 +14,49 @@ def setup(py_params_dict): "descr": "Data bus width", "type": "F", "val": "32", - "min": "?", + "min": "0", "max": "32", }, { "name": "ADDR_W", "descr": "Address bus width", "type": "F", - # "val": "`IOB_BOOTROM_CSRS_ADDR_W", - "val": 13, - "min": "?", + "val": BOOTROM_ADDR_W - 2, + "min": "0", "max": "32", }, + { + "name": "AXI_ID_W", + "descr": "AXI ID bus width", + "type": "P", + "val": "0", + "min": "1", + "max": "32", + }, + { + "name": "AXI_ADDR_W", + "descr": "AXI address bus width", + "type": "P", + "val": "0", + "min": "1", + "max": "32", + }, + { + "name": "AXI_DATA_W", + "descr": "AXI data bus width", + "type": "P", + "val": "0", + "min": "1", + "max": "32", + }, + { + "name": "AXI_LEN_W", + "descr": "AXI burst length width", + "type": "P", + "val": "0", + "min": "1", + "max": "4", + }, ], # # Ports @@ -45,29 +71,15 @@ def setup(py_params_dict): }, }, { - "name": "cbus", - "descr": "Front-end control interface", + "name": "rom_bus", + "descr": "Boot ROM bus", "interface": { - "type": "iob", + "type": "axi", "subtype": "slave", - "port_prefix": "cbus_", - # "ADDR_W": "`IOB_BOOTROM_CSRS_ADDR_W", - "ADDR_W": 13, + "ADDR_W": BOOTROM_ADDR_W - 2, "DATA_W": "DATA_W", }, }, - { - "name": "ibus", - "descr": "Instruction bus", - "interface": { - "type": "iob", - "subtype": "slave", - "port_prefix": "ibus_", - "DATA_W": "DATA_W", - # "ADDR_W": "`IOB_BOOTROM_CSRS_ADDR_W", - "ADDR_W": 13, - }, - }, { "name": "ext_rom_bus", "descr": "External ROM signals", @@ -95,57 +107,17 @@ def setup(py_params_dict): # "wires": [ { - "name": "rom", - "descr": "'rom' register interface", - "signals": [ - {"name": "rom_rdata_rd", "width": "DATA_W"}, - {"name": "rom_rvalid_rd", "width": 1}, - {"name": "rom_ren_rd", "width": 1}, - {"name": "rom_rready_rd", "width": 1}, - ], - }, - { - "name": "preboot_rom_clk", - "descr": "Pre-bootloader ROM clock input", - "signals": [ - {"name": "clk"}, - ], - }, - { - "name": "preboot_rom_if", - "descr": "Pre-bootloader Memory interface", - "signals": [ - {"name": "ibus_iob_valid"}, - {"name": "prebootrom_addr_i", "width": PREBOOTROM_ADDR_W - 2}, - {"name": "ibus_iob_rdata"}, - ], - }, - { - "name": "ibus_rvalid_data_i", + "name": "rom_rvalid_i", "descr": "Register input", "signals": [ - {"name": "ibus_iob_valid"}, + {"name": "rom_ren", "width": 1}, ], }, { - "name": "ibus_rvalid_data_o", + "name": "rom_rvalid_o", "descr": "Register output", "signals": [ - {"name": "ibus_iob_rvalid"}, - ], - }, - { - "name": "rom_rvalid_data_i", - "descr": "Register input", - "signals": [ - {"name": "rom_ren_rd"}, - ], - }, - { - "name": "rom_rvalid_data_o", - "descr": "Register output", - "signals": [ - {"name": "rom_rvalid_rd"}, + {"name": "axi_rvalid"}, ], }, ], @@ -153,63 +125,6 @@ def setup(py_params_dict): # Blocks # "blocks": [ - { - "core_name": "csrs", - "instance_name": "csrs_inst", - "version": VERSION, - "csrs": [ - { - "name": "rom", - "descr": "ROM access.", - "regs": [ - { - "name": "rom", - "descr": "Bootloader ROM (read).", - "type": "R", - "n_bits": "DATA_W", - "rst_val": 0, - "addr": -1, - "log2n_items": BOOTROM_ADDR_W - 2, - "autoreg": False, - }, - ], - } - ], - "connect": { - "clk_en_rst": "clk_en_rst", - "control_if": "cbus", - # Register interfaces - "rom": "rom", - }, - }, - { - "core_name": "iob_rom_sp", - "instance_name": "preboot_rom", - "instance_description": "Pre-bootloader ROM", - "parameters": { - "ADDR_W": PREBOOTROM_ADDR_W - 2, - "DATA_W": "DATA_W", - "HEXFILE": '"iob_soc_preboot.hex"', - }, - "connect": { - "clk": "preboot_rom_clk", - "rom_if": "preboot_rom_if", - }, - }, - { - "core_name": "iob_reg", - "instance_name": "ibus_rvalid_r", - "instance_description": "Instruction bus rvalid register", - "parameters": { - "DATA_W": 1, - "RST_VAL": "1'b0", - }, - "connect": { - "clk_en_rst": "clk_en_rst", - "data_i": "ibus_rvalid_data_i", - "data_o": "ibus_rvalid_data_o", - }, - }, { "core_name": "iob_reg", "instance_name": "rom_rvalid_r", @@ -220,8 +135,8 @@ def setup(py_params_dict): }, "connect": { "clk_en_rst": "clk_en_rst", - "data_i": "rom_rvalid_data_i", - "data_o": "rom_rvalid_data_o", + "data_i": "rom_rvalid_i", + "data_o": "rom_rvalid_o", }, }, ], @@ -231,12 +146,21 @@ def setup(py_params_dict): "snippets": [ { "verilog_code": f""" - assign prebootrom_addr_i = ibus_iob_addr_i[{PREBOOTROM_ADDR_W}:2]; - assign ibus_iob_ready_o = 1'b1; - assign ext_rom_en_o = rom_ren_rd; - assign ext_rom_addr_o = cbus_iob_addr_i[{BOOTROM_ADDR_W}:2]; - assign rom_rdata_rd = ext_rom_rdata_i; - assign rom_rready_rd = 1'b1; // ROM is always ready + assing rom_ren = axi_arvalid_i; + assign ext_rom_en_o = rom_ren; + assign ext_rom_addr_o = axi_arddr_i[{BOOTROM_ADDR_W}:2]; + assign axi_rdata_o = ext_rom_rdata_i; + assign axi_arready_o = 1'b1; // ROM is always ready + + // Unused outputs + assign axi_awready_o = 1'b0; + assign axi_wready_o = 1'b0; + assign axi_bid_o = {{AXI_ID{{1'b0}}}}; + assign axi_bresp_o = 2'b0; + assign axi_bvalid_o = 1'b0; + assign axi_rid_o = {{AXI_ID{{1'b0}}}}; + assign axi_rresp_o = 2'b0; + assign axi_rlast_o = 1'b0; """, }, ], diff --git a/submodules/CACHE b/submodules/CACHE deleted file mode 160000 index fc91e5830..000000000 --- a/submodules/CACHE +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fc91e58308f0dc37a9b8e23ca88a03b091260fe5 diff --git a/submodules/VEXRISCV b/submodules/VEXRISCV new file mode 160000 index 000000000..23363e58d --- /dev/null +++ b/submodules/VEXRISCV @@ -0,0 +1 @@ +Subproject commit 23363e58d32f3c86e3dd788edfe8215cbd5b8a06 From fd6d7a3b6170c2fa3ca7c080e3c7bc49b9a30c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Fri, 6 Sep 2024 04:33:11 +0100 Subject: [PATCH 03/12] fix(setup): Fix setup issues WIP: Simulation is stuck before boot. Likely due to wrong address ranges. There are also a lot of warnings about AXI_ADDR_W of signals. This is because interconnect expects 24 bits (configurable via AXI_ADDR_W parameter) and the peripherals/cpu dont use the same width. --- hardware/simulation/sim_build.mk | 2 +- iob_soc.py | 134 ++- lib/hardware/buses/axi2axil/axi2axil.py | 124 +++ lib/hardware/buses/axi2iob/axi2iob.py | 65 ++ .../buses/axi2iob/hardware/src/axi2iob.v | 965 +++++++++--------- software/sw_build.mk | 8 +- submodules/BOOTROM/iob_bootrom.py | 11 +- .../BOOTROM/software/src/iob_soc_boot.c | 6 - submodules/VEXRISCV | 2 +- 9 files changed, 744 insertions(+), 573 deletions(-) create mode 100644 lib/hardware/buses/axi2axil/axi2axil.py diff --git a/hardware/simulation/sim_build.mk b/hardware/simulation/sim_build.mk index 6a94695f3..dc86748d3 100644 --- a/hardware/simulation/sim_build.mk +++ b/hardware/simulation/sim_build.mk @@ -1,7 +1,7 @@ include auto_sim_build.mk # Add iob-soc software as a build dependency -HEX+=iob_soc_preboot.hex iob_soc_boot.hex iob_soc_firmware.hex +HEX+=iob_soc_bootrom.hex iob_soc_firmware.hex ROOT_DIR :=../.. include $(ROOT_DIR)/software/sw_build.mk diff --git a/iob_soc.py b/iob_soc.py index c481ec0ae..95d05683d 100755 --- a/iob_soc.py +++ b/iob_soc.py @@ -99,7 +99,7 @@ def setup(py_params_dict): }, { # Needed for software and makefiles "name": "BOOTROM_ADDR_W", - "descr": "Bootloader ROM address width", + "descr": "Bootloader ROM address width (byte addressable). Includes a pre-bootloader that uses the first 128 bytes. Bootloader starts at address 0x80 of this ROM.", "type": "M", "val": params["bootrom_addr_w"], "min": "1", @@ -188,6 +188,7 @@ def setup(py_params_dict): "ADDR_W": "AXI_ADDR_W", "DATA_W": "AXI_DATA_W", "LEN_W": "AXI_LEN_W", + "LOCK_W": "AXI_LEN_W", }, }, # NOTE: Add ports for peripherals here @@ -212,20 +213,26 @@ def setup(py_params_dict): "name": "cpu_ibus", "descr": "CPU instruction bus", "interface": { - "type": "iob", + "type": "axi", "wire_prefix": "cpu_i_", - "DATA_W": params["data_w"], + "ID_W": "AXI_ID_W", "ADDR_W": params["addr_w"], + "DATA_W": params["data_w"], + "LEN_W": "AXI_LEN_W", + "LOCK_W": "1", }, }, { "name": "cpu_dbus", "descr": "CPU data bus", "interface": { - "type": "iob", + "type": "axi", "wire_prefix": "cpu_d_", - "DATA_W": params["data_w"], + "ID_W": "AXI_ID_W", "ADDR_W": params["addr_w"], + "DATA_W": params["data_w"], + "LEN_W": "AXI_LEN_W", + "LOCK_W": "1", }, }, { @@ -233,7 +240,7 @@ def setup(py_params_dict): "descr": "AXI bus for peripheral CSRs", "interface": { "type": "axi", - "subtype": "master", + "wire_prefix": "periphs_", "ID_W": "AXI_ID_W", "ADDR_W": "AXI_ADDR_W", "DATA_W": "AXI_DATA_W", @@ -258,80 +265,53 @@ def setup(py_params_dict): ], }, { - "name": "cache_ibus", - "descr": "iob-soc cache instruction interface", - "interface": { - "type": "iob", - "wire_prefix": "cache_system_i_", - "DATA_W": params["data_w"], - "ADDR_W": params["addr_w"] - 1, - }, - }, - { - "name": "cache_dbus", - "descr": "iob-soc cache data interface", - "interface": { - "type": "iob", - "wire_prefix": "cache_system_d_", - "DATA_W": params["data_w"], - "ADDR_W": params["addr_w"] - 1, - }, - }, - { - "name": "mem_clk_en_rst", - "descr": "", - "signals": [ - {"name": "clk"}, - {"name": "cke"}, - {"name": "arst"}, - ], - }, - { - "name": "bootrom_ibus", - "descr": "iob-soc boot controller instruction interface", - "interface": { - "type": "axi", - "wire_prefix": "bootrom_i_", - "DATA_W": params["data_w"], - "ADDR_W": params["addr_w"] - 1, - }, - }, - { - "name": "bootrom_bus", + "name": "bootrom_axi", "descr": "iob-soc boot controller data interface", "interface": { "type": "axi", - "wire_prefix": "bootrom_d_", - "DATA_W": params["data_w"], - "ADDR_W": params["addr_w"] - 1, + "wire_prefix": "bootrom_", + # "DATA_W": params["data_w"], + # "ADDR_W": params["addr_w"] - 1, + "ID_W": "AXI_ID_W", + "ADDR_W": "AXI_ADDR_W", + "DATA_W": "AXI_DATA_W", + "LEN_W": "AXI_LEN_W", }, }, { "name": "interrupts", "descr": "System interrupts", "signals": [ - {"name": "interrupts", "width": 1}, + {"name": "interrupts", "width": 32}, ], }, # Peripheral wires { - "name": "plic_cbus", - "descr": "PLIC Control/Status Registers bus", + "name": "clint_cbus", + "descr": "CLINT Control/Status Registers bus", "interface": { - "type": "axil", - "wire_prefix": "plic_cbus_", - "DATA_W": params["data_w"], - "ADDR_W": params["addr_w"] - 3, + "type": "axi", + "wire_prefix": "clint_cbus_", + # "DATA_W": params["data_w"], + # "ADDR_W": params["addr_w"] - 3, + "ID_W": "AXI_ID_W", + "ADDR_W": "AXI_ADDR_W", + "DATA_W": "AXI_DATA_W", + "LEN_W": "AXI_LEN_W", }, }, { - "name": "clint_cbus", - "descr": "CLINT Control/Status Registers bus", + "name": "plic_cbus", + "descr": "PLIC Control/Status Registers bus", "interface": { - "type": "axil", - "wire_prefix": "clint_cbus_", - "DATA_W": params["data_w"], - "ADDR_W": params["addr_w"] - 3, + "type": "axi", + "wire_prefix": "plic_cbus_", + # "DATA_W": params["data_w"], + # "ADDR_W": params["addr_w"] - 3, + "ID_W": "AXI_ID_W", + "ADDR_W": "AXI_ADDR_W", + "DATA_W": "AXI_DATA_W", + "LEN_W": "AXI_LEN_W", }, }, { @@ -362,8 +342,10 @@ def setup(py_params_dict): "instance_name": "cpu", "instance_description": "RISC-V CPU instance", "parameters": { - "ADDR_W": params["addr_w"], - "DATA_W": params["data_w"], + "AXI_ID_W": "1", + "AXI_ADDR_W": params["addr_w"], + "AXI_DATA_W": params["data_w"], + "AXI_LEN_W": "AXI_LEN_W", }, "connect": { "clk_en_rst": "clk_en_rst", @@ -389,7 +371,7 @@ def setup(py_params_dict): "rst": "rst", "s0_axi": "cpu_ibus", "s1_axi": "cpu_dbus", - "m0_axi": "bootrom_bus", + "m0_axi": "bootrom_axi", "m1_axi": "axi", "m2_axi": "periphs_axi", "m3_axi": "clint_cbus", @@ -400,12 +382,15 @@ def setup(py_params_dict): # FIXME: Size of each output }, { - "core_name": "axil2iob", - "instance_name": "peripheral_axil2iob", + "core_name": "axi2iob", + "instance_name": "peripheral_axi2iob", "instance_description": "Convert AXI interface to IOb for peripheral CSRs bus", + "parameters": { + "ADDR_WIDTH": params["addr_w"] - 1, + }, "connect": { "clk_en_rst": "clk_en_rst", - "axil": "periphs_axi", + "axi": "periphs_axi", "iob": "periphs_cbus", }, }, @@ -422,8 +407,8 @@ def setup(py_params_dict): "output_1": "timer_cbus", # NOTE: Connect other peripherals here }, - "num_outputs": num_peripherals, - "addr_w": params["addr_w"] - 1, # FIXME: + "num_outputs": num_peripherals - 1, # Don't count bootloader + "addr_w": params["addr_w"] - 2, # FIXME: }, ] peripherals = [ @@ -452,10 +437,15 @@ def setup(py_params_dict): "core_name": "iob_bootrom", "instance_name": "BOOTROM0", "instance_description": "Boot ROM peripheral", - "parameters": {}, + "parameters": { + "AXI_ID_W": "AXI_ID_W", + "AXI_ADDR_W": "AXI_ADDR_W", + "AXI_DATA_W": "AXI_DATA_W", + "AXI_LEN_W": "AXI_LEN_W", + }, "connect": { "clk_en_rst": "clk_en_rst", - "rom_bus": "bootrom_bus", + "rom_bus": "bootrom_axi", "ext_rom_bus": "rom_bus", }, "bootrom_addr_w": params["bootrom_addr_w"], diff --git a/lib/hardware/buses/axi2axil/axi2axil.py b/lib/hardware/buses/axi2axil/axi2axil.py new file mode 100644 index 000000000..8294fdd88 --- /dev/null +++ b/lib/hardware/buses/axi2axil/axi2axil.py @@ -0,0 +1,124 @@ +def setup(py_params_dict): + """AXI to AXI-Lite converter + This converter has the same limitations as AXI-Lite: + - No Burst Support: burst-related signals (like AWLEN, AWSIZE, ARBURST, etc.) are ignored. + """ + attributes_dict = { + "original_name": "axi2axil", + "name": "axi2axil", + "version": "0.1", + "confs": [ + { + "name": "AXI_ID_W", + "descr": "AXI ID bus width", + "type": "P", + "val": "4", + "min": "1", + "max": "32", + }, + { + "name": "AXI_LEN_W", + "descr": "AXI burst length width", + "type": "P", + "val": "4", + "min": "1", + "max": "4", + }, + { + "name": "AXI_ADDR_W", + "descr": "AXI address bus width", + "type": "P", + "val": "32", + "min": "1", + "max": "32", + }, + { + "name": "AXI_DATA_W", + "descr": "AXI data bus width", + "type": "P", + "val": "32", + "min": "1", + "max": "32", + }, + ], + "ports": [ + { + "name": "axi", + "descr": "AXI slave interface to connect to external master", + "interface": { + "type": "axi", + "subtype": "slave", + "ID_W": "AXI_ID_W", + "ADDR_W": "AXI_ADDR_W", + "DATA_W": "AXI_DATA_W", + "LEN_W": "AXI_LEN_W", + }, + }, + { + "name": "axil", + "descr": "AXI Lite master interface to connect to external slave", + "interface": { + "type": "axil", + "subtype": "master", + "ID_W": "AXI_ID_W", + "ADDR_W": "AXI_ADDR_W", + "DATA_W": "AXI_DATA_W", + "LEN_W": "AXI_LEN_W", + }, + }, + ], + "snippets": [ + { + "verilog_code": """ + // Write Address Channel + assign axil_awaddr_o = axi_awaddr_i; + assign axil_awprot_o = axi_awprot_i; + assign axil_awvalid_o = axi_awvalid_i; + assign axi_awready_o = axil_awready_i; + // Write Data Channel + assign axil_wdata_o = axi_wdata_i; + assign axil_wstrb_o = axi_wstrb_i; + assign axil_wvalid_o = axi_wvalid_i; + assign axi_wready_o = axil_wready_i; + // Write Response Channel + assign axi_bresp_o = axil_bresp_i; + assign axi_bvalid_o = axil_bvalid_i; + assign axil_bready_o = axi_bready_i; + // Read Address Channel + assign axil_araddr_o = axi_araddr_i; + assign axil_arprot_o = axi_arprot_i; + assign axil_arvalid_o = axi_arvalid_i; + assign axi_arready_o = axil_arready_i; + // Read Data Channel + assign axi_rdata_o = axil_rdata_i; + assign axi_rresp_o = axil_rresp_i; + assign axi_rvalid_o = axil_rvalid_i; + assign axil_rready_o = axi_rready_i; + + // Unused axi outputs + assign axi_bid_o = 'b0; + assign axi_rid_o = 'b0; + assign axi_rlast_o = 'b0; + + // Unused axi inputs + // axi_awid_i + // axi_awlen_i + // axi_awsize_i + // axi_awburst_i + // axi_awlock_i + // axi_awcache_i + // axi_awqos_i + // axi_wlast_i + // axi_arid_i + // axi_arlen_i + // axi_arsize_i + // axi_arburst_i + // axi_arlock_i + // axi_arcache_i + // axi_arqos_i +""" + } + ], + } + + return attributes_dict diff --git a/lib/hardware/buses/axi2iob/axi2iob.py b/lib/hardware/buses/axi2iob/axi2iob.py index e9c049f05..65b352879 100644 --- a/lib/hardware/buses/axi2iob/axi2iob.py +++ b/lib/hardware/buses/axi2iob/axi2iob.py @@ -4,6 +4,71 @@ def setup(py_params_dict): "name": "axi2iob", "version": "0.1", "generate_hw": False, + "confs": [ + { + "name": "ADDR_WIDTH", + "descr": "", + "type": "P", + "val": "32", + "min": "1", + "max": "32", + }, + { + "name": "DATA_WIDTH", + "descr": "", + "type": "P", + "val": "32", + "min": "1", + "max": "32", + }, + { + "name": "STRB_WIDTH", + "descr": "", + "type": "P", + "val": "(DATA_WIDTH / 8)", + "min": "1", + "max": "32", + }, + { + "name": "AXI_ID_WIDTH", + "descr": "", + "type": "P", + "val": "8", + "min": "1", + "max": "32", + }, + ], + "ports": [ + { + "name": "clk_en_rst", + "interface": { + "type": "clk_en_rst", + "subtype": "slave", + }, + "descr": "Clock, clock enable and reset", + }, + { + "name": "axi", + "descr": "Slave AXI interface", + "interface": { + "type": "axi", + "subtype": "slave", + "port_prefix": "s_", + "ADDR_W": "ADDR_WIDTH", + "DATA_W": "DATA_WIDTH", + }, + }, + { + "name": "iob", + "descr": "Master IOb interface", + "interface": { + "type": "iob", + "subtype": "master", + "ADDR_W": "ADDR_WIDTH", + "DATA_W": "DATA_WIDTH", + }, + }, + ], "blocks": [ { "core_name": "iob_reg_re", diff --git a/lib/hardware/buses/axi2iob/hardware/src/axi2iob.v b/lib/hardware/buses/axi2iob/hardware/src/axi2iob.v index db9866469..2e2230bfd 100644 --- a/lib/hardware/buses/axi2iob/hardware/src/axi2iob.v +++ b/lib/hardware/buses/axi2iob/hardware/src/axi2iob.v @@ -5,526 +5,529 @@ * AXI4 to IOb adapter */ module axi2iob #( - // Width of address bus in bits - parameter ADDR_WIDTH = 32, - // Width of input (slave/master) AXI/IOb interface data bus in bits - parameter DATA_WIDTH = 32, - // Width of input (slave/master) AXI/IOb interface wstrb (width of data bus in words) - parameter STRB_WIDTH = (DATA_WIDTH / 8), - // Width of AXI ID signal - parameter AXI_ID_WIDTH = 8 + // Width of address bus in bits + parameter ADDR_WIDTH = 32, + // Width of input (slave/master) AXI/IOb interface data bus in bits + parameter DATA_WIDTH = 32, + // Width of input (slave/master) AXI/IOb interface wstrb (width of data bus in words) + parameter STRB_WIDTH = (DATA_WIDTH / 8), + // Width of AXI ID signal + parameter AXI_ID_WIDTH = 8 ) ( - input wire clk_i, - input wire arst_i, + input wire clk_i, + input wire cke_i, + input wire arst_i, - /* + /* * AXI slave interface */ - input wire [AXI_ID_WIDTH-1:0] s_axi_awid_i, - input wire [ ADDR_WIDTH-1:0] s_axi_awaddr_i, - input wire [ 7:0] s_axi_awlen_i, - input wire [ 2:0] s_axi_awsize_i, - input wire [ 1:0] s_axi_awburst_i, - input wire s_axi_awlock_i, - input wire [ 3:0] s_axi_awcache_i, - input wire [ 2:0] s_axi_awprot_i, - input wire s_axi_awvalid_i, - output wire s_axi_awready_o, - input wire [ DATA_WIDTH-1:0] s_axi_wdata_i, - input wire [ STRB_WIDTH-1:0] s_axi_wstrb_i, - input wire s_axi_wlast_i, - input wire s_axi_wvalid_i, - output wire s_axi_wready_o, - output wire [AXI_ID_WIDTH-1:0] s_axi_bid_o, - output wire [ 1:0] s_axi_bresp_o, - output wire s_axi_bvalid_o, - input wire s_axi_bready_i, - input wire [AXI_ID_WIDTH-1:0] s_axi_arid_i, - input wire [ ADDR_WIDTH-1:0] s_axi_araddr_i, - input wire [ 7:0] s_axi_arlen_i, - input wire [ 2:0] s_axi_arsize_i, - input wire [ 1:0] s_axi_arburst_i, - input wire s_axi_arlock_i, - input wire [ 3:0] s_axi_arcache_i, - input wire [ 2:0] s_axi_arprot_i, - input wire s_axi_arvalid_i, - output wire s_axi_arready_o, - output wire [AXI_ID_WIDTH-1:0] s_axi_rid_o, - output wire [ DATA_WIDTH-1:0] s_axi_rdata_o, - output wire [ 1:0] s_axi_rresp_o, - output wire s_axi_rlast_o, - output wire s_axi_rvalid_o, - input wire s_axi_rready_i, - - /* + input wire [AXI_ID_WIDTH-1:0] s_axi_awid_i, + input wire [ ADDR_WIDTH-1:0] s_axi_awaddr_i, + input wire [ 7:0] s_axi_awlen_i, + input wire [ 2:0] s_axi_awsize_i, + input wire [ 1:0] s_axi_awburst_i, + input wire s_axi_awlock_i, + input wire [ 3:0] s_axi_awcache_i, + input wire [ 3:0] s_axi_awqos_i, + input wire [ 2:0] s_axi_awprot_i, + input wire s_axi_awvalid_i, + output wire s_axi_awready_o, + input wire [ DATA_WIDTH-1:0] s_axi_wdata_i, + input wire [ STRB_WIDTH-1:0] s_axi_wstrb_i, + input wire s_axi_wlast_i, + input wire s_axi_wvalid_i, + output wire s_axi_wready_o, + output wire [AXI_ID_WIDTH-1:0] s_axi_bid_o, + output wire [ 1:0] s_axi_bresp_o, + output wire s_axi_bvalid_o, + input wire s_axi_bready_i, + input wire [AXI_ID_WIDTH-1:0] s_axi_arid_i, + input wire [ ADDR_WIDTH-1:0] s_axi_araddr_i, + input wire [ 7:0] s_axi_arlen_i, + input wire [ 2:0] s_axi_arsize_i, + input wire [ 1:0] s_axi_arburst_i, + input wire s_axi_arlock_i, + input wire [ 3:0] s_axi_arcache_i, + input wire [ 3:0] s_axi_arqos_i, + input wire [ 2:0] s_axi_arprot_i, + input wire s_axi_arvalid_i, + output wire s_axi_arready_o, + output wire [AXI_ID_WIDTH-1:0] s_axi_rid_o, + output wire [ DATA_WIDTH-1:0] s_axi_rdata_o, + output wire [ 1:0] s_axi_rresp_o, + output wire s_axi_rlast_o, + output wire s_axi_rvalid_o, + input wire s_axi_rready_i, + + /* * IOb-bus master interface */ - output wire iob_valid_o, - output wire [ADDR_WIDTH-1:0] iob_addr_o, - output wire [DATA_WIDTH-1:0] iob_wdata_o, - output wire [STRB_WIDTH-1:0] iob_wstrb_o, - input wire iob_rvalid_i, - input wire [DATA_WIDTH-1:0] iob_rdata_i, - input wire iob_ready_i + output wire iob_valid_o, + output wire [ADDR_WIDTH-1:0] iob_addr_o, + output wire [DATA_WIDTH-1:0] iob_wdata_o, + output wire [STRB_WIDTH-1:0] iob_wstrb_o, + input wire iob_rvalid_i, + input wire [DATA_WIDTH-1:0] iob_rdata_i, + input wire iob_ready_i ); - localparam [1:0] STATE_IDLE = 2'd0, STATE_DATA = 2'd1, STATE_RESP = 2'd2; + localparam [1:0] STATE_IDLE = 2'd0, STATE_DATA = 2'd1, STATE_RESP = 2'd2; - /* + /* * AXI lite master interface (used as a middle ground from AXI4 to IOb) */ - wire [ADDR_WIDTH-1:0] m_axil_awaddr; - wire [ 2:0] m_axil_awprot; - wire m_axil_awvalid; - wire m_axil_awready; - wire [DATA_WIDTH-1:0] m_axil_wdata; - wire [STRB_WIDTH-1:0] m_axil_wstrb; - wire m_axil_wvalid; - wire m_axil_wready; - wire [ 1:0] m_axil_bresp; - wire m_axil_bvalid; - wire m_axil_bready; - wire [ADDR_WIDTH-1:0] m_axil_araddr; - wire [ 2:0] m_axil_arprot; - wire m_axil_arvalid; - wire m_axil_arready; - wire [DATA_WIDTH-1:0] m_axil_rdata; - wire [ 1:0] m_axil_rresp; - wire m_axil_rvalid; - wire m_axil_rready; - - // - // AXI4-Lite interface to IOb - // - wire iob_rvalid_q; - wire iob_rvalid_e; - wire write_enable; - wire [ADDR_WIDTH-1:0] m_axil_awaddr_q; - wire m_axil_bvalid_n; - wire m_axil_bvalid_e; - - assign write_enable = |m_axil_wstrb; - assign m_axil_bvalid_n = m_axil_wvalid; - assign m_axil_bvalid_e = m_axil_bvalid_n | m_axil_bready; - assign iob_rvalid_e = iob_rvalid_i | m_axil_rready; - - // COMPUTE AXIL OUTPUTS - // // write address - assign m_axil_awready = iob_ready_i; - // // write - assign m_axil_wready = iob_ready_i; - // // write response - assign m_axil_bresp = 2'b0; - // // read address - assign m_axil_arready = iob_ready_i; - // // read - assign m_axil_rdata = iob_rdata_i; - assign m_axil_rresp = 2'b0; - assign m_axil_rvalid = iob_rvalid_i ? 1'b1 : iob_rvalid_q; - - // COMPUTE IOb OUTPUTS - assign iob_valid_o = (m_axil_bvalid_n & write_enable) | m_axil_arvalid; - assign iob_addr_o = m_axil_arvalid ? m_axil_araddr : (m_axil_awvalid ? m_axil_awaddr : m_axil_awaddr_q); - assign iob_wdata_o = m_axil_wdata; - assign iob_wstrb_o = m_axil_arvalid ? {STRB_WIDTH{1'b0}} : m_axil_wstrb; - - iob_reg_re #( + wire [ADDR_WIDTH-1:0] m_axil_awaddr; + wire [ 2:0] m_axil_awprot; + wire m_axil_awvalid; + wire m_axil_awready; + wire [DATA_WIDTH-1:0] m_axil_wdata; + wire [STRB_WIDTH-1:0] m_axil_wstrb; + wire m_axil_wvalid; + wire m_axil_wready; + wire [ 1:0] m_axil_bresp; + wire m_axil_bvalid; + wire m_axil_bready; + wire [ADDR_WIDTH-1:0] m_axil_araddr; + wire [ 2:0] m_axil_arprot; + wire m_axil_arvalid; + wire m_axil_arready; + wire [DATA_WIDTH-1:0] m_axil_rdata; + wire [ 1:0] m_axil_rresp; + wire m_axil_rvalid; + wire m_axil_rready; + + // + // AXI4-Lite interface to IOb + // + wire iob_rvalid_q; + wire iob_rvalid_e; + wire write_enable; + wire [ADDR_WIDTH-1:0] m_axil_awaddr_q; + wire m_axil_bvalid_n; + wire m_axil_bvalid_e; + + assign write_enable = |m_axil_wstrb; + assign m_axil_bvalid_n = m_axil_wvalid; + assign m_axil_bvalid_e = m_axil_bvalid_n | m_axil_bready; + assign iob_rvalid_e = iob_rvalid_i | m_axil_rready; + + // COMPUTE AXIL OUTPUTS + // // write address + assign m_axil_awready = iob_ready_i; + // // write + assign m_axil_wready = iob_ready_i; + // // write response + assign m_axil_bresp = 2'b0; + // // read address + assign m_axil_arready = iob_ready_i; + // // read + assign m_axil_rdata = iob_rdata_i; + assign m_axil_rresp = 2'b0; + assign m_axil_rvalid = iob_rvalid_i ? 1'b1 : iob_rvalid_q; + + // COMPUTE IOb OUTPUTS + assign iob_valid_o = (m_axil_bvalid_n & write_enable) | m_axil_arvalid; + assign iob_addr_o = m_axil_arvalid ? m_axil_araddr : (m_axil_awvalid ? m_axil_awaddr : m_axil_awaddr_q); + assign iob_wdata_o = m_axil_wdata; + assign iob_wstrb_o = m_axil_arvalid ? {STRB_WIDTH{1'b0}} : m_axil_wstrb; + + iob_reg_re #( .DATA_W (ADDR_WIDTH), .RST_VAL(0) - ) iob_reg_awaddr ( + ) iob_reg_awaddr ( .clk_i (clk_i), .arst_i(arst_i), - .cke_i (1'b1), + .cke_i (cke_i), .rst_i (1'b0), .en_i (m_axil_awvalid), .data_i(m_axil_awaddr), .data_o(m_axil_awaddr_q) - ); + ); - iob_reg_re #( + iob_reg_re #( .DATA_W (1), .RST_VAL(0) - ) iob_reg_rvalid ( + ) iob_reg_rvalid ( .clk_i (clk_i), .arst_i(arst_i), - .cke_i (1'b1), + .cke_i (cke_i), .rst_i (1'b0), .en_i (iob_rvalid_e), .data_i(iob_rvalid_i), .data_o(iob_rvalid_q) - ); + ); - iob_reg_re #( + iob_reg_re #( .DATA_W (1), .RST_VAL(0) - ) iob_reg_bvalid ( + ) iob_reg_bvalid ( .clk_i (clk_i), .arst_i(arst_i), - .cke_i (1'b1), + .cke_i (cke_i), .rst_i (1'b0), .en_i (m_axil_bvalid_e), .data_i(m_axil_bvalid_n), .data_o(m_axil_bvalid) - ); - - // - // AXI4 write interface conversion to AXI4-Lite - // - reg [1:0] w_state_reg, w_state_next; - - reg [AXI_ID_WIDTH-1:0] w_id_reg, w_id_next; - reg [ADDR_WIDTH-1:0] w_addr_reg, w_addr_next; - reg [DATA_WIDTH-1:0] w_data_reg, w_data_next; - reg [STRB_WIDTH-1:0] w_strb_reg, w_strb_next; - reg [7:0] w_burst_reg, w_burst_next; - reg [2:0] w_burst_size_reg, w_burst_size_next; - reg [2:0] w_master_burst_size_reg, w_master_burst_size_next; - reg w_burst_active_reg, w_burst_active_next; - reg w_first_transfer_reg, w_first_transfer_next; - reg w_last_segment_reg, w_last_segment_next; - - reg s_axi_awready_reg, s_axi_awready_next; - reg s_axi_wready_reg, s_axi_wready_next; - reg [AXI_ID_WIDTH-1:0] s_axi_bid_reg, s_axi_bid_next; - reg [1:0] s_axi_bresp_reg, s_axi_bresp_next; - reg s_axi_bvalid_reg, s_axi_bvalid_next; - - reg [ADDR_WIDTH-1:0] m_axil_awaddr_reg, m_axil_awaddr_next; - reg [2:0] m_axil_awprot_reg, m_axil_awprot_next; - reg m_axil_awvalid_reg, m_axil_awvalid_next; - reg [DATA_WIDTH-1:0] m_axil_wdata_reg, m_axil_wdata_next; - reg [STRB_WIDTH-1:0] m_axil_wstrb_reg, m_axil_wstrb_next; - reg m_axil_wvalid_reg, m_axil_wvalid_next; - reg m_axil_bready_reg, m_axil_bready_next; - - assign s_axi_awready_o = s_axi_awready_reg; - assign s_axi_wready_o = s_axi_wready_reg; - assign s_axi_bid_o = s_axi_bid_reg; - assign s_axi_bresp_o = s_axi_bresp_reg; - assign s_axi_bvalid_o = s_axi_bvalid_reg; - - assign m_axil_awaddr = m_axil_awaddr_reg; - assign m_axil_awprot = m_axil_awprot_reg; - assign m_axil_awvalid = m_axil_awvalid_reg; - assign m_axil_wdata = m_axil_wdata_reg; - assign m_axil_wstrb = m_axil_wstrb_reg; - assign m_axil_wvalid = m_axil_wvalid_reg; - assign m_axil_bready = m_axil_bready_reg; - - integer i; - - always @* begin - w_state_next = STATE_IDLE; - - w_id_next = w_id_reg; - w_addr_next = w_addr_reg; - w_data_next = w_data_reg; - w_strb_next = w_strb_reg; - w_burst_next = w_burst_reg; - w_burst_size_next = w_burst_size_reg; - w_master_burst_size_next = w_master_burst_size_reg; - w_burst_active_next = w_burst_active_reg; - w_first_transfer_next = w_first_transfer_reg; - w_last_segment_next = w_last_segment_reg; - - s_axi_awready_next = 1'b0; - s_axi_wready_next = 1'b0; - s_axi_bid_next = s_axi_bid_reg; - s_axi_bresp_next = s_axi_bresp_reg; - s_axi_bvalid_next = s_axi_bvalid_reg & ~s_axi_bready_i; - m_axil_awaddr_next = m_axil_awaddr_reg; - m_axil_awprot_next = m_axil_awprot_reg; - m_axil_awvalid_next = m_axil_awvalid_reg & ~m_axil_awready; - m_axil_wdata_next = m_axil_wdata_reg; - m_axil_wstrb_next = m_axil_wstrb_reg; - m_axil_wvalid_next = m_axil_wvalid_reg & ~m_axil_wready; - m_axil_bready_next = 1'b0; - - case (w_state_reg) - default: begin // STATE_IDLE - // idle state; wait for new burst - s_axi_awready_next = ~m_axil_awvalid; - w_first_transfer_next = 1'b1; - - if (s_axi_awready_o & s_axi_awvalid_i) begin - s_axi_awready_next = 1'b0; - w_id_next = s_axi_awid_i; - m_axil_awaddr_next = s_axi_awaddr_i; - w_addr_next = s_axi_awaddr_i; - w_burst_next = s_axi_awlen_i; - w_burst_size_next = s_axi_awsize; - w_burst_active_next = 1'b1; - m_axil_awprot_next = s_axi_awprot_i; - m_axil_awvalid_next = 1'b1; - s_axi_wready_next = ~m_axil_wvalid; - w_state_next = STATE_DATA; - end else begin - w_state_next = STATE_IDLE; - end + ); + + // + // AXI4 write interface conversion to AXI4-Lite + // + reg [1:0] w_state_reg, w_state_next; + + reg [AXI_ID_WIDTH-1:0] w_id_reg, w_id_next; + reg [ADDR_WIDTH-1:0] w_addr_reg, w_addr_next; + reg [DATA_WIDTH-1:0] w_data_reg, w_data_next; + reg [STRB_WIDTH-1:0] w_strb_reg, w_strb_next; + reg [7:0] w_burst_reg, w_burst_next; + reg [2:0] w_burst_size_reg, w_burst_size_next; + reg [2:0] w_master_burst_size_reg, w_master_burst_size_next; + reg w_burst_active_reg, w_burst_active_next; + reg w_first_transfer_reg, w_first_transfer_next; + reg w_last_segment_reg, w_last_segment_next; + + reg s_axi_awready_reg, s_axi_awready_next; + reg s_axi_wready_reg, s_axi_wready_next; + reg [AXI_ID_WIDTH-1:0] s_axi_bid_reg, s_axi_bid_next; + reg [1:0] s_axi_bresp_reg, s_axi_bresp_next; + reg s_axi_bvalid_reg, s_axi_bvalid_next; + + reg [ADDR_WIDTH-1:0] m_axil_awaddr_reg, m_axil_awaddr_next; + reg [2:0] m_axil_awprot_reg, m_axil_awprot_next; + reg m_axil_awvalid_reg, m_axil_awvalid_next; + reg [DATA_WIDTH-1:0] m_axil_wdata_reg, m_axil_wdata_next; + reg [STRB_WIDTH-1:0] m_axil_wstrb_reg, m_axil_wstrb_next; + reg m_axil_wvalid_reg, m_axil_wvalid_next; + reg m_axil_bready_reg, m_axil_bready_next; + + assign s_axi_awready_o = s_axi_awready_reg; + assign s_axi_wready_o = s_axi_wready_reg; + assign s_axi_bid_o = s_axi_bid_reg; + assign s_axi_bresp_o = s_axi_bresp_reg; + assign s_axi_bvalid_o = s_axi_bvalid_reg; + + assign m_axil_awaddr = m_axil_awaddr_reg; + assign m_axil_awprot = m_axil_awprot_reg; + assign m_axil_awvalid = m_axil_awvalid_reg; + assign m_axil_wdata = m_axil_wdata_reg; + assign m_axil_wstrb = m_axil_wstrb_reg; + assign m_axil_wvalid = m_axil_wvalid_reg; + assign m_axil_bready = m_axil_bready_reg; + + integer i; + + always @* begin + w_state_next = STATE_IDLE; + + w_id_next = w_id_reg; + w_addr_next = w_addr_reg; + w_data_next = w_data_reg; + w_strb_next = w_strb_reg; + w_burst_next = w_burst_reg; + w_burst_size_next = w_burst_size_reg; + w_master_burst_size_next = w_master_burst_size_reg; + w_burst_active_next = w_burst_active_reg; + w_first_transfer_next = w_first_transfer_reg; + w_last_segment_next = w_last_segment_reg; + + s_axi_awready_next = 1'b0; + s_axi_wready_next = 1'b0; + s_axi_bid_next = s_axi_bid_reg; + s_axi_bresp_next = s_axi_bresp_reg; + s_axi_bvalid_next = s_axi_bvalid_reg & ~s_axi_bready_i; + m_axil_awaddr_next = m_axil_awaddr_reg; + m_axil_awprot_next = m_axil_awprot_reg; + m_axil_awvalid_next = m_axil_awvalid_reg & ~m_axil_awready; + m_axil_wdata_next = m_axil_wdata_reg; + m_axil_wstrb_next = m_axil_wstrb_reg; + m_axil_wvalid_next = m_axil_wvalid_reg & ~m_axil_wready; + m_axil_bready_next = 1'b0; + + case (w_state_reg) + default: begin // STATE_IDLE + // idle state; wait for new burst + s_axi_awready_next = ~m_axil_awvalid; + w_first_transfer_next = 1'b1; + + if (s_axi_awready_o & s_axi_awvalid_i) begin + s_axi_awready_next = 1'b0; + w_id_next = s_axi_awid_i; + m_axil_awaddr_next = s_axi_awaddr_i; + w_addr_next = s_axi_awaddr_i; + w_burst_next = s_axi_awlen_i; + w_burst_size_next = s_axi_awsize_i; + w_burst_active_next = 1'b1; + m_axil_awprot_next = s_axi_awprot_i; + m_axil_awvalid_next = 1'b1; + s_axi_wready_next = ~m_axil_wvalid; + w_state_next = STATE_DATA; + end else begin + w_state_next = STATE_IDLE; + end + end + STATE_DATA: begin + // data state; transfer write data + s_axi_wready_next = ~m_axil_wvalid; + + if (s_axi_wready_o & s_axi_wvalid_i) begin + m_axil_wdata_next = s_axi_wdata_i; + m_axil_wstrb_next = s_axi_wstrb_i; + m_axil_wvalid_next = 1'b1; + w_burst_next = w_burst_reg - 1; + w_burst_active_next = w_burst_reg != 0; + w_addr_next = w_addr_reg + (1 << w_burst_size_reg); + s_axi_wready_next = 1'b0; + m_axil_bready_next = ~s_axi_bvalid_o & ~m_axil_awvalid; + w_state_next = STATE_RESP; + end else begin + w_state_next = STATE_DATA; + end + end + STATE_RESP: begin + // resp state; transfer write response + m_axil_bready_next = ~s_axi_bvalid_o & ~m_axil_awvalid; + + if (m_axil_bready & m_axil_bvalid) begin + m_axil_bready_next = 1'b0; + s_axi_bid_next = w_id_reg; + w_first_transfer_next = 1'b0; + if (w_first_transfer_reg | (m_axil_bresp != 0)) begin + s_axi_bresp_next = m_axil_bresp; + end + if (w_burst_active_reg) begin + // burst on slave interface still active; start new AXI lite write + m_axil_awaddr_next = w_addr_reg; + m_axil_awvalid_next = 1'b1; + s_axi_wready_next = ~m_axil_wvalid; + w_state_next = STATE_DATA; + end else begin + // burst on slave interface finished; return to idle + s_axi_bvalid_next = 1'b1; + s_axi_awready_next = ~m_axil_awvalid; + w_state_next = STATE_IDLE; + end + end else begin + w_state_next = STATE_RESP; + end + end + endcase + end + + always @(posedge clk_i, posedge arst_i) begin + if (arst_i) begin + w_state_reg <= STATE_IDLE; + s_axi_awready_reg <= 1'b0; + s_axi_wready_reg <= 1'b0; + s_axi_bvalid_reg <= 1'b0; + m_axil_awvalid_reg <= 1'b0; + m_axil_wvalid_reg <= 1'b0; + m_axil_bready_reg <= 1'b0; + + w_id_reg <= {AXI_ID_WIDTH{1'b0}}; + w_addr_reg <= {ADDR_WIDTH{1'b0}}; + w_data_reg <= {DATA_WIDTH{1'b0}}; + w_strb_reg <= {STRB_WIDTH{1'b0}}; + w_burst_reg <= 8'd0; + w_burst_size_reg <= 3'd0; + w_master_burst_size_reg <= 3'd0; + w_burst_active_reg <= 1'b0; + w_first_transfer_reg <= 1'b0; + w_last_segment_reg <= 1'b0; + + s_axi_bid_reg <= {AXI_ID_WIDTH{1'b0}}; + s_axi_bresp_reg <= 2'd0; + m_axil_awaddr_reg <= {ADDR_WIDTH{1'b0}}; + m_axil_awprot_reg <= 3'd0; + m_axil_wdata_reg <= {DATA_WIDTH{1'b0}}; + m_axil_wstrb_reg <= {STRB_WIDTH{1'b0}}; + end else begin + w_state_reg <= w_state_next; + s_axi_awready_reg <= s_axi_awready_next; + s_axi_wready_reg <= s_axi_wready_next; + s_axi_bvalid_reg <= s_axi_bvalid_next; + m_axil_awvalid_reg <= m_axil_awvalid_next; + m_axil_wvalid_reg <= m_axil_wvalid_next; + m_axil_bready_reg <= m_axil_bready_next; + + w_id_reg <= w_id_next; + w_addr_reg <= w_addr_next; + w_data_reg <= w_data_next; + w_strb_reg <= w_strb_next; + w_burst_reg <= w_burst_next; + w_burst_size_reg <= w_burst_size_next; + w_master_burst_size_reg <= w_master_burst_size_next; + w_burst_active_reg <= w_burst_active_next; + w_first_transfer_reg <= w_first_transfer_next; + w_last_segment_reg <= w_last_segment_next; + + s_axi_bid_reg <= s_axi_bid_next; + s_axi_bresp_reg <= s_axi_bresp_next; + m_axil_awaddr_reg <= m_axil_awaddr_next; + m_axil_awprot_reg <= m_axil_awprot_next; + m_axil_wdata_reg <= m_axil_wdata_next; + m_axil_wstrb_reg <= m_axil_wstrb_next; end - STATE_DATA: begin - // data state; transfer write data - s_axi_wready_next = ~m_axil_wvalid; - - if (s_axi_wready_o & s_axi_wvalid_i) begin - m_axil_wdata_next = s_axi_wdata_i; - m_axil_wstrb_next = s_axi_wstrb_i; - m_axil_wvalid_next = 1'b1; - w_burst_next = w_burst_reg - 1; - w_burst_active_next = w_burst_reg != 0; - w_addr_next = w_addr_reg + (1 << w_burst_size_reg); - s_axi_wready_next = 1'b0; - m_axil_bready_next = ~s_axi_bvalid_o & ~m_axil_awvalid; - w_state_next = STATE_RESP; - end else begin - w_state_next = STATE_DATA; - end - end - STATE_RESP: begin - // resp state; transfer write response - m_axil_bready_next = ~s_axi_bvalid_o & ~m_axil_awvalid; - - if (m_axil_bready & m_axil_bvalid) begin - m_axil_bready_next = 1'b0; - s_axi_bid_next = w_id_reg; - w_first_transfer_next = 1'b0; - if (w_first_transfer_reg | (m_axil_bresp != 0)) begin - s_axi_bresp_next = m_axil_bresp; - end - if (w_burst_active_reg) begin - // burst on slave interface still active; start new AXI lite write - m_axil_awaddr_next = w_addr_reg; - m_axil_awvalid_next = 1'b1; - s_axi_wready_next = ~m_axil_wvalid; - w_state_next = STATE_DATA; - end else begin - // burst on slave interface finished; return to idle - s_axi_bvalid_next = 1'b1; - s_axi_awready_next = ~m_axil_awvalid; - w_state_next = STATE_IDLE; - end - end else begin - w_state_next = STATE_RESP; - end - end - endcase - end - - always @(posedge clk_i, posedge arst_i) begin - if (arst_i) begin - w_state_reg <= STATE_IDLE; - s_axi_awready_reg <= 1'b0; - s_axi_wready_reg <= 1'b0; - s_axi_bvalid_reg <= 1'b0; - m_axil_awvalid_reg <= 1'b0; - m_axil_wvalid_reg <= 1'b0; - m_axil_bready_reg <= 1'b0; - - w_id_reg <= {AXI_ID_WIDTH{1'b0}}; - w_addr_reg <= {ADDR_WIDTH{1'b0}}; - w_data_reg <= {DATA_WIDTH{1'b0}}; - w_strb_reg <= {STRB_WIDTH{1'b0}}; - w_burst_reg <= 8'd0; - w_burst_size_reg <= 3'd0; - w_master_burst_size_reg <= 3'd0; - w_burst_active_reg <= 1'b0; - w_first_transfer_reg <= 1'b0; - w_last_segment_reg <= 1'b0; - - s_axi_bid_reg <= {AXI_ID_WIDTH{1'b0}}; - s_axi_bresp_reg <= 2'd0; - m_axil_awaddr_reg <= {ADDR_WIDTH{1'b0}}; - m_axil_awprot_reg <= 3'd0; - m_axil_wdata_reg <= {DATA_WIDTH{1'b0}}; - m_axil_wstrb_reg <= {STRB_WIDTH{1'b0}}; - end else begin - w_state_reg <= w_state_next; - s_axi_awready_reg <= s_axi_awready_next; - s_axi_wready_reg <= s_axi_wready_next; - s_axi_bvalid_reg <= s_axi_bvalid_next; - m_axil_awvalid_reg <= m_axil_awvalid_next; - m_axil_wvalid_reg <= m_axil_wvalid_next; - m_axil_bready_reg <= m_axil_bready_next; - - w_id_reg <= w_id_next; - w_addr_reg <= w_addr_next; - w_data_reg <= w_data_next; - w_strb_reg <= w_strb_next; - w_burst_reg <= w_burst_next; - w_burst_size_reg <= w_burst_size_next; - w_master_burst_size_reg <= w_master_burst_size_next; - w_burst_active_reg <= w_burst_active_next; - w_first_transfer_reg <= w_first_transfer_next; - w_last_segment_reg <= w_last_segment_next; - - s_axi_bid_reg <= s_axi_bid_next; - s_axi_bresp_reg <= s_axi_bresp_next; - m_axil_awaddr_reg <= m_axil_awaddr_next; - m_axil_awprot_reg <= m_axil_awprot_next; - m_axil_wdata_reg <= m_axil_wdata_next; - m_axil_wstrb_reg <= m_axil_wstrb_next; - end - end - - // - // AXI4 read interface conversion to AXI4-Lite - // - reg [1:0] r_state_reg, r_state_next; - - reg [AXI_ID_WIDTH-1:0] r_id_reg, r_id_next; - reg [ADDR_WIDTH-1:0] r_addr_reg, r_addr_next; - reg [DATA_WIDTH-1:0] r_data_reg, r_data_next; - reg [1:0] r_resp_reg, r_resp_next; - reg [7:0] r_burst_reg, r_burst_next; - reg [2:0] r_burst_size_reg, r_burst_size_next; - reg [7:0] r_master_burst_reg, r_master_burst_next; - reg [2:0] r_master_burst_size_reg, r_master_burst_size_next; - - reg s_axi_arready_reg, s_axi_arready_next; - reg [AXI_ID_WIDTH-1:0] s_axi_rid_reg, s_axi_rid_next; - reg [DATA_WIDTH-1:0] s_axi_rdata_reg, s_axi_rdata_next; - reg [1:0] s_axi_rresp_reg, s_axi_rresp_next; - reg s_axi_rlast_reg, s_axi_rlast_next; - reg s_axi_rvalid_reg, s_axi_rvalid_next; - - reg [ADDR_WIDTH-1:0] m_axil_araddr_reg, m_axil_araddr_next; - reg [2:0] m_axil_arprot_reg, m_axil_arprot_next; - reg m_axil_arvalid_reg, m_axil_arvalid_next; - reg m_axil_rready_reg, m_axil_rready_next; - - assign s_axi_arready_o = s_axi_arready_reg; - assign s_axi_rid_o = s_axi_rid_reg; - assign s_axi_rdata_o = s_axi_rdata_reg; - assign s_axi_rresp_o = s_axi_rresp_reg; - assign s_axi_rlast_o = s_axi_rlast_reg; - assign s_axi_rvalid_o = s_axi_rvalid_reg; - - assign m_axil_araddr = m_axil_araddr_reg; - assign m_axil_arprot = m_axil_arprot_reg; - assign m_axil_arvalid = m_axil_arvalid_reg; - assign m_axil_rready = m_axil_rready_reg; - - always @* begin - r_state_next = STATE_IDLE; - - r_id_next = r_id_reg; - r_addr_next = r_addr_reg; - r_data_next = r_data_reg; - r_resp_next = r_resp_reg; - r_burst_next = r_burst_reg; - r_burst_size_next = r_burst_size_reg; - r_master_burst_next = r_master_burst_reg; - r_master_burst_size_next = r_master_burst_size_reg; - - s_axi_arready_next = 1'b0; - s_axi_rid_next = s_axi_rid_reg; - s_axi_rdata_next = s_axi_rdata_reg; - s_axi_rresp_next = s_axi_rresp_reg; - s_axi_rlast_next = s_axi_rlast_reg; - s_axi_rvalid_next = s_axi_rvalid_reg & ~s_axi_rready_i; - m_axil_araddr_next = m_axil_araddr_reg; - m_axil_arprot_next = m_axil_arprot_reg; - m_axil_arvalid_next = m_axil_arvalid_reg & ~m_axil_arready; - m_axil_rready_next = 1'b0; - - case (r_state_reg) - default: begin // STATE_IDLE - // idle state; wait for new burst - s_axi_arready_next = ~m_axil_arvalid; - - if (s_axi_arready_o & s_axi_arvalid_i) begin - s_axi_arready_next = 1'b0; - r_id_next = s_axi_arid_i; - m_axil_araddr_next = s_axi_araddr_i; - r_addr_next = s_axi_araddr_i; - r_burst_next = s_axi_arlen_i; - r_burst_size_next = s_axi_arsize_i; - m_axil_arprot_next = s_axi_arprot_i; - m_axil_arvalid_next = 1'b1; - m_axil_rready_next = 1'b0; - r_state_next = STATE_DATA; - end else begin - r_state_next = STATE_IDLE; - end - end - STATE_DATA: begin - // data state; transfer read data - m_axil_rready_next = ~s_axi_rvalid_o & ~m_axil_arvalid; - - if (m_axil_rready & m_axil_rvalid) begin - s_axi_rid_next = r_id_reg; - s_axi_rdata_next = m_axil_rdata; - s_axi_rresp_next = m_axil_rresp; - s_axi_rlast_next = 1'b0; - s_axi_rvalid_next = 1'b1; - r_burst_next = r_burst_reg - 1; - r_addr_next = r_addr_reg + (1 << r_burst_size_reg); - if (r_burst_reg == 0) begin - // last data word, return to idle - m_axil_rready_next = 1'b0; - s_axi_rlast_next = 1'b1; + end + + // + // AXI4 read interface conversion to AXI4-Lite + // + reg [1:0] r_state_reg, r_state_next; + + reg [AXI_ID_WIDTH-1:0] r_id_reg, r_id_next; + reg [ADDR_WIDTH-1:0] r_addr_reg, r_addr_next; + reg [DATA_WIDTH-1:0] r_data_reg, r_data_next; + reg [1:0] r_resp_reg, r_resp_next; + reg [7:0] r_burst_reg, r_burst_next; + reg [2:0] r_burst_size_reg, r_burst_size_next; + reg [7:0] r_master_burst_reg, r_master_burst_next; + reg [2:0] r_master_burst_size_reg, r_master_burst_size_next; + + reg s_axi_arready_reg, s_axi_arready_next; + reg [AXI_ID_WIDTH-1:0] s_axi_rid_reg, s_axi_rid_next; + reg [DATA_WIDTH-1:0] s_axi_rdata_reg, s_axi_rdata_next; + reg [1:0] s_axi_rresp_reg, s_axi_rresp_next; + reg s_axi_rlast_reg, s_axi_rlast_next; + reg s_axi_rvalid_reg, s_axi_rvalid_next; + + reg [ADDR_WIDTH-1:0] m_axil_araddr_reg, m_axil_araddr_next; + reg [2:0] m_axil_arprot_reg, m_axil_arprot_next; + reg m_axil_arvalid_reg, m_axil_arvalid_next; + reg m_axil_rready_reg, m_axil_rready_next; + + assign s_axi_arready_o = s_axi_arready_reg; + assign s_axi_rid_o = s_axi_rid_reg; + assign s_axi_rdata_o = s_axi_rdata_reg; + assign s_axi_rresp_o = s_axi_rresp_reg; + assign s_axi_rlast_o = s_axi_rlast_reg; + assign s_axi_rvalid_o = s_axi_rvalid_reg; + + assign m_axil_araddr = m_axil_araddr_reg; + assign m_axil_arprot = m_axil_arprot_reg; + assign m_axil_arvalid = m_axil_arvalid_reg; + assign m_axil_rready = m_axil_rready_reg; + + always @* begin + r_state_next = STATE_IDLE; + + r_id_next = r_id_reg; + r_addr_next = r_addr_reg; + r_data_next = r_data_reg; + r_resp_next = r_resp_reg; + r_burst_next = r_burst_reg; + r_burst_size_next = r_burst_size_reg; + r_master_burst_next = r_master_burst_reg; + r_master_burst_size_next = r_master_burst_size_reg; + + s_axi_arready_next = 1'b0; + s_axi_rid_next = s_axi_rid_reg; + s_axi_rdata_next = s_axi_rdata_reg; + s_axi_rresp_next = s_axi_rresp_reg; + s_axi_rlast_next = s_axi_rlast_reg; + s_axi_rvalid_next = s_axi_rvalid_reg & ~s_axi_rready_i; + m_axil_araddr_next = m_axil_araddr_reg; + m_axil_arprot_next = m_axil_arprot_reg; + m_axil_arvalid_next = m_axil_arvalid_reg & ~m_axil_arready; + m_axil_rready_next = 1'b0; + + case (r_state_reg) + default: begin // STATE_IDLE + // idle state; wait for new burst s_axi_arready_next = ~m_axil_arvalid; - r_state_next = STATE_IDLE; - end else begin - // start new AXI lite read - m_axil_araddr_next = r_addr_next; - m_axil_arvalid_next = 1'b1; - m_axil_rready_next = 1'b0; - r_state_next = STATE_DATA; - end - end else begin - r_state_next = STATE_DATA; - end + + if (s_axi_arready_o & s_axi_arvalid_i) begin + s_axi_arready_next = 1'b0; + r_id_next = s_axi_arid_i; + m_axil_araddr_next = s_axi_araddr_i; + r_addr_next = s_axi_araddr_i; + r_burst_next = s_axi_arlen_i; + r_burst_size_next = s_axi_arsize_i; + m_axil_arprot_next = s_axi_arprot_i; + m_axil_arvalid_next = 1'b1; + m_axil_rready_next = 1'b0; + r_state_next = STATE_DATA; + end else begin + r_state_next = STATE_IDLE; + end + end + STATE_DATA: begin + // data state; transfer read data + m_axil_rready_next = ~s_axi_rvalid_o & ~m_axil_arvalid; + + if (m_axil_rready & m_axil_rvalid) begin + s_axi_rid_next = r_id_reg; + s_axi_rdata_next = m_axil_rdata; + s_axi_rresp_next = m_axil_rresp; + s_axi_rlast_next = 1'b0; + s_axi_rvalid_next = 1'b1; + r_burst_next = r_burst_reg - 1; + r_addr_next = r_addr_reg + (1 << r_burst_size_reg); + if (r_burst_reg == 0) begin + // last data word, return to idle + m_axil_rready_next = 1'b0; + s_axi_rlast_next = 1'b1; + s_axi_arready_next = ~m_axil_arvalid; + r_state_next = STATE_IDLE; + end else begin + // start new AXI lite read + m_axil_araddr_next = r_addr_next; + m_axil_arvalid_next = 1'b1; + m_axil_rready_next = 1'b0; + r_state_next = STATE_DATA; + end + end else begin + r_state_next = STATE_DATA; + end + end + endcase + end + + always @(posedge clk_i, posedge arst_i) begin + if (arst_i) begin + r_state_reg <= STATE_IDLE; + s_axi_arready_reg <= 1'b0; + s_axi_rvalid_reg <= 1'b0; + m_axil_arvalid_reg <= 1'b0; + m_axil_rready_reg <= 1'b0; + + r_id_reg <= {AXI_ID_WIDTH{1'b0}}; + r_addr_reg <= {ADDR_WIDTH{1'b0}}; + r_data_reg <= {DATA_WIDTH{1'b0}}; + r_resp_reg <= 2'd0; + r_burst_reg <= 8'd0; + r_burst_size_reg <= 3'd0; + r_master_burst_reg <= 8'd0; + r_master_burst_size_reg <= 3'd0; + + s_axi_rid_reg <= {AXI_ID_WIDTH{1'b0}}; + s_axi_rdata_reg <= {DATA_WIDTH{1'b0}}; + s_axi_rresp_reg <= 2'd0; + s_axi_rlast_reg <= 1'b0; + m_axil_araddr_reg <= {ADDR_WIDTH{1'b0}}; + m_axil_arprot_reg <= 3'd0; + end else begin + r_state_reg <= r_state_next; + s_axi_arready_reg <= s_axi_arready_next; + s_axi_rvalid_reg <= s_axi_rvalid_next; + m_axil_arvalid_reg <= m_axil_arvalid_next; + m_axil_rready_reg <= m_axil_rready_next; + + r_id_reg <= r_id_next; + r_addr_reg <= r_addr_next; + r_data_reg <= r_data_next; + r_resp_reg <= r_resp_next; + r_burst_reg <= r_burst_next; + r_burst_size_reg <= r_burst_size_next; + r_master_burst_reg <= r_master_burst_next; + r_master_burst_size_reg <= r_master_burst_size_next; + + s_axi_rid_reg <= s_axi_rid_next; + s_axi_rdata_reg <= s_axi_rdata_next; + s_axi_rresp_reg <= s_axi_rresp_next; + s_axi_rlast_reg <= s_axi_rlast_next; + m_axil_araddr_reg <= m_axil_araddr_next; + m_axil_arprot_reg <= m_axil_arprot_next; end - endcase - end - - always @(posedge clk_i, posedge arst_i) begin - if (arst_i) begin - r_state_reg <= STATE_IDLE; - s_axi_arready_reg <= 1'b0; - s_axi_rvalid_reg <= 1'b0; - m_axil_arvalid_reg <= 1'b0; - m_axil_rready_reg <= 1'b0; - - r_id_reg <= {AXI_ID_WIDTH{1'b0}}; - r_addr_reg <= {ADDR_WIDTH{1'b0}}; - r_data_reg <= {DATA_WIDTH{1'b0}}; - r_resp_reg <= 2'd0; - r_burst_reg <= 8'd0; - r_burst_size_reg <= 3'd0; - r_master_burst_reg <= 8'd0; - r_master_burst_size_reg <= 3'd0; - - s_axi_rid_reg <= {AXI_ID_WIDTH{1'b0}}; - s_axi_rdata_reg <= {DATA_WIDTH{1'b0}}; - s_axi_rresp_reg <= 2'd0; - s_axi_rlast_reg <= 1'b0; - m_axil_araddr_reg <= {ADDR_WIDTH{1'b0}}; - m_axil_arprot_reg <= 3'd0; - end else begin - r_state_reg <= r_state_next; - s_axi_arready_reg <= s_axi_arready_next; - s_axi_rvalid_reg <= s_axi_rvalid_next; - m_axil_arvalid_reg <= m_axil_arvalid_next; - m_axil_rready_reg <= m_axil_rready_next; - - r_id_reg <= r_id_next; - r_addr_reg <= r_addr_next; - r_data_reg <= r_data_next; - r_resp_reg <= r_resp_next; - r_burst_reg <= r_burst_next; - r_burst_size_reg <= r_burst_size_next; - r_master_burst_reg <= r_master_burst_next; - r_master_burst_size_reg <= r_master_burst_size_next; - - s_axi_rid_reg <= s_axi_rid_next; - s_axi_rdata_reg <= s_axi_rdata_next; - s_axi_rresp_reg <= s_axi_rresp_next; - s_axi_rlast_reg <= s_axi_rlast_next; - m_axil_araddr_reg <= m_axil_araddr_next; - m_axil_arprot_reg <= m_axil_arprot_next; - end - end + end endmodule diff --git a/software/sw_build.mk b/software/sw_build.mk index c54aa9410..992bc937a 100644 --- a/software/sw_build.mk +++ b/software/sw_build.mk @@ -14,11 +14,8 @@ GET_MACRO = $(shell grep "define $(1)" $(2) | rev | cut -d" " -f1 | rev) #Function to obtain parameter named $(1) from iob_soc_conf.vh GET_IOB_SOC_CONF_MACRO = $(call GET_MACRO,IOB_SOC_$(1),../src/iob_soc_conf.vh) -iob_soc_preboot.hex: ../../software/iob_soc_preboot.bin - ../../scripts/makehex.py $< $(call GET_IOB_SOC_CONF_MACRO,PREBOOTROM_ADDR_W) > $@ - -iob_soc_boot.hex: ../../software/iob_soc_boot.bin - ../../scripts/makehex.py $< $(call GET_IOB_SOC_CONF_MACRO,BOOTROM_ADDR_W) > $@ +iob_soc_bootrom.hex: ../../software/iob_soc_preboot.bin ../../software/iob_soc_boot.bin + ../../scripts/makehex.py $^ 00000080 $(call GET_IOB_SOC_CONF_MACRO,BOOTROM_ADDR_W) > $@ iob_soc_firmware.hex: iob_soc_firmware.bin ../../scripts/makehex.py $< $(call GET_IOB_SOC_CONF_MACRO,MEM_ADDR_W) > $@ @@ -50,7 +47,6 @@ IOB_SOC_FW_SRC+=$(filter-out %_emul.c, $(wildcard src/*csrs*.c)) IOB_SOC_BOOT_SRC+=src/iob_soc_boot.S IOB_SOC_BOOT_SRC+=src/iob_soc_boot.c IOB_SOC_BOOT_SRC+=$(filter-out %_emul.c, $(wildcard src/iob*uart*.c)) -IOB_SOC_BOOT_SRC+=$(filter-out %_emul.c, $(wildcard src/iob*cache*.c)) # PREBOOT SOURCES IOB_SOC_PREBOOT_SRC=src/iob_soc_preboot.S diff --git a/submodules/BOOTROM/iob_bootrom.py b/submodules/BOOTROM/iob_bootrom.py index b705b14fb..88cfae087 100644 --- a/submodules/BOOTROM/iob_bootrom.py +++ b/submodules/BOOTROM/iob_bootrom.py @@ -110,7 +110,7 @@ def setup(py_params_dict): "name": "rom_rvalid_i", "descr": "Register input", "signals": [ - {"name": "rom_ren", "width": 1}, + {"name": "axi_arvalid", "width": 1}, ], }, { @@ -146,19 +146,18 @@ def setup(py_params_dict): "snippets": [ { "verilog_code": f""" - assing rom_ren = axi_arvalid_i; - assign ext_rom_en_o = rom_ren; - assign ext_rom_addr_o = axi_arddr_i[{BOOTROM_ADDR_W}:2]; + assign ext_rom_en_o = axi_arvalid_i; + assign ext_rom_addr_o = axi_araddr_i[{BOOTROM_ADDR_W}:2]; assign axi_rdata_o = ext_rom_rdata_i; assign axi_arready_o = 1'b1; // ROM is always ready // Unused outputs assign axi_awready_o = 1'b0; assign axi_wready_o = 1'b0; - assign axi_bid_o = {{AXI_ID{{1'b0}}}}; + assign axi_bid_o = {{AXI_ID_W{{1'b0}}}}; assign axi_bresp_o = 2'b0; assign axi_bvalid_o = 1'b0; - assign axi_rid_o = {{AXI_ID{{1'b0}}}}; + assign axi_rid_o = {{AXI_ID_W{{1'b0}}}}; assign axi_rresp_o = 2'b0; assign axi_rlast_o = 1'b0; """, diff --git a/submodules/BOOTROM/software/src/iob_soc_boot.c b/submodules/BOOTROM/software/src/iob_soc_boot.c index 18903c63b..600f1cd68 100644 --- a/submodules/BOOTROM/software/src/iob_soc_boot.c +++ b/submodules/BOOTROM/software/src/iob_soc_boot.c @@ -1,6 +1,5 @@ #include "bsp.h" #include "iob-uart.h" -#include "iob_cache_csrs.h" #include "iob_soc_conf.h" #include "iob_soc_periphs.h" #include "iob_soc_system.h" @@ -12,8 +11,6 @@ int main() { // init uart uart_init(UART0_BASE, FREQ / BAUD); - IOB_CACHE_INIT_BASEADDR(1 << IOB_SOC_MEM_ADDR_W); - // connect with console do { if (IOB_UART_GET_TXREADY()) @@ -60,7 +57,4 @@ int main() { uart_puts(PROGNAME); uart_puts(": Restart CPU to run user program...\n"); uart_txwait(); - - while (!IOB_CACHE_GET_WTB_EMPTY()) - ; } diff --git a/submodules/VEXRISCV b/submodules/VEXRISCV index 23363e58d..dc1971cf0 160000 --- a/submodules/VEXRISCV +++ b/submodules/VEXRISCV @@ -1 +1 @@ -Subproject commit 23363e58d32f3c86e3dd788edfe8215cbd5b8a06 +Subproject commit dc1971cf07a99e1776042a382b778f3c7f449ddb From dbc8f290c269da390568b14dd7ab41bf28a711c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Fri, 6 Sep 2024 05:33:08 +0100 Subject: [PATCH 04/12] wip(interconnect): Add support for interconnect master interfaces with different address widths. --- .../quartus/cyclonev_gt_dk/cyclonev_gt_dk.py | 1 + .../iob_soc_sim_wrapper.py | 1 + iob_soc.py | 25 ++++++---- .../axi_interconnect_wrapper.py | 48 +++++++++++++------ 4 files changed, 51 insertions(+), 24 deletions(-) diff --git a/hardware/fpga/quartus/cyclonev_gt_dk/cyclonev_gt_dk.py b/hardware/fpga/quartus/cyclonev_gt_dk/cyclonev_gt_dk.py index 568e76746..853abf3df 100644 --- a/hardware/fpga/quartus/cyclonev_gt_dk/cyclonev_gt_dk.py +++ b/hardware/fpga/quartus/cyclonev_gt_dk/cyclonev_gt_dk.py @@ -297,6 +297,7 @@ def setup(py_params_dict): attributes_dict["blocks"] += [ { "core_name": "axi_interconnect_wrapper", + "name": "fpga_axi_interconnect_wrapper", "instance_name": "axi_interconnect", "instance_description": "Interconnect instance", "parameters": { diff --git a/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py b/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py index 0c16bbfb4..29b00084c 100644 --- a/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py +++ b/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py @@ -205,6 +205,7 @@ def setup(py_params_dict): }, { "core_name": "axi_interconnect_wrapper", + "name": "sim_axi_interconnect_wrapper", "instance_name": "axi_interconnect", "instance_description": "Interconnect instance", "parameters": { diff --git a/iob_soc.py b/iob_soc.py index 95d05683d..07deb139f 100755 --- a/iob_soc.py +++ b/iob_soc.py @@ -273,7 +273,7 @@ def setup(py_params_dict): # "DATA_W": params["data_w"], # "ADDR_W": params["addr_w"] - 1, "ID_W": "AXI_ID_W", - "ADDR_W": "AXI_ADDR_W", + "ADDR_W": params["bootrom_addr_w"] - 2, "DATA_W": "AXI_DATA_W", "LEN_W": "AXI_LEN_W", }, @@ -295,7 +295,7 @@ def setup(py_params_dict): # "DATA_W": params["data_w"], # "ADDR_W": params["addr_w"] - 3, "ID_W": "AXI_ID_W", - "ADDR_W": "AXI_ADDR_W", + "ADDR_W": "16", "DATA_W": "AXI_DATA_W", "LEN_W": "AXI_LEN_W", }, @@ -309,7 +309,7 @@ def setup(py_params_dict): # "DATA_W": params["data_w"], # "ADDR_W": params["addr_w"] - 3, "ID_W": "AXI_ID_W", - "ADDR_W": "AXI_ADDR_W", + "ADDR_W": "22", "DATA_W": "AXI_DATA_W", "LEN_W": "AXI_LEN_W", }, @@ -359,6 +359,7 @@ def setup(py_params_dict): }, { "core_name": "axi_interconnect_wrapper", + "name": "soc_axi_interconnect_wrapper", "instance_name": "axi_interconnect", "instance_description": "Interconnect instance", "parameters": { @@ -371,14 +372,20 @@ def setup(py_params_dict): "rst": "rst", "s0_axi": "cpu_ibus", "s1_axi": "cpu_dbus", - "m0_axi": "bootrom_axi", - "m1_axi": "axi", - "m2_axi": "periphs_axi", - "m3_axi": "clint_cbus", - "m4_axi": "plic_cbus", + "bootrom_axi": "bootrom_axi", + "mem_axi": "axi", + "periphs_axi": "periphs_axi", + "clint_axi": "clint_cbus", + "plic_axi": "plic_cbus", }, "num_slaves": 2, - "num_masters": 5, + "masters": { + "bootrom": params["bootrom_addr_w"] - 2, + "mem": "AXI_ADDR_W", + "periphs": 24, + "clint": 16, + "plic": 22, + }, # FIXME: Size of each output }, { diff --git a/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py b/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py index 2d3565c43..02e2249e2 100644 --- a/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py +++ b/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py @@ -43,18 +43,29 @@ def setup(py_params_dict): + """Wrapper for `axi_interconnect` core. + Python parameters: + - num_slaves: number of slave interfaces + - masters: dictionary with name and address width of each master + """ + # Each generated wrapper must have a unique name (can't have two verilog modules with same name). + assert "name" in py_params_dict, print( + "Error: Missing name for generated interconnect wrapper module." + ) # Number of slave interfaces (number of masters to connect to) N_SLAVES = ( int(py_params_dict["num_slaves"]) if "num_slaves" in py_params_dict else 1 ) - # Number of master interfaces (number of slaves to connect to) - N_MASTERS = ( - int(py_params_dict["num_masters"]) if "num_masters" in py_params_dict else 1 + # Dictionary with name and address width of each master + MASTERS = ( + py_params_dict["masters"] + if "masters" in py_params_dict + else {"m0": "AXI_ADDR_W"} ) attributes_dict = { "original_name": "axi_interconnect_wrapper", - "name": "axi_interconnect_wrapper", + "name": py_params_dict["name"], "version": "0.1", # # AXI Parameters @@ -68,7 +79,7 @@ def setup(py_params_dict): "max": "32", "descr": "AXI ID bus width", }, - { + { # FIXME: Somehow make this parameter be 32 bits. This will allow passing 32'd... as a range "name": "AXI_ADDR_W", "type": "P", "val": "0", @@ -131,22 +142,29 @@ def setup(py_params_dict): }, ] master_axi_ports = [] - for i in range(N_MASTERS): + master_addr_w_parameter = "" + for name, width in MASTERS.items(): master_axi_ports += [ { - "name": f"m{i}_axi", - "descr": f"Master {i} axi interface", + "name": f"{name}_axi", + "descr": f"Master '{name}' axi interface", "interface": { "type": "axi", "subtype": "master", - "port_prefix": f"m{i}_", + "port_prefix": f"{name}_", "ID_W": "AXI_ID_W", - "ADDR_W": "AXI_ADDR_W", + "ADDR_W": width, "DATA_W": "AXI_DATA_W", "LOCK_W": 1, }, }, ] + try: + width_str = "32'd" + str(int(width)) + except ValueError: + width_str = width + master_addr_w_parameter = f"{width_str}," + master_addr_w_parameter + master_addr_w_parameter = "{" + master_addr_w_parameter[:-1] + "}" attributes_dict["ports"] += slave_axi_ports + master_axi_ports # # Wires @@ -176,15 +194,15 @@ def setup(py_params_dict): "interface": { "type": "axi", "wire_prefix": "intercon_m_", - "mult": N_MASTERS, + "mult": len(MASTERS), "ID_W": "AXI_ID_W", "ADDR_W": "AXI_ADDR_W", "DATA_W": "AXI_DATA_W", "LOCK_W": 1, }, "signals": [ - {"name": "intercon_m_axi_buser", "width": N_MASTERS}, - {"name": "intercon_m_axi_ruser", "width": N_MASTERS}, + {"name": "intercon_m_axi_buser", "width": len(MASTERS)}, + {"name": "intercon_m_axi_ruser", "width": len(MASTERS)}, ], }, ] @@ -200,9 +218,9 @@ def setup(py_params_dict): "ID_WIDTH": "AXI_ID_W", "DATA_WIDTH": "AXI_DATA_W", "ADDR_WIDTH": "AXI_ADDR_W", - "M_ADDR_WIDTH": "AXI_ADDR_W", "S_COUNT": N_SLAVES, - "M_COUNT": N_MASTERS, + "M_COUNT": len(MASTERS), + "M_ADDR_WIDTH": master_addr_w_parameter, }, "connect": { "clk": "clk", From 0a9d463e8158252fe1df648e8a71b99274e17964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Fri, 6 Sep 2024 15:07:33 +0100 Subject: [PATCH 05/12] fix(iob-soc): Remove pbus split; Fix address ranges. WIP: CPU reads first prebootloader instruction and gets stuck. Likely because ROM does not yet support burst transfers. --- iob_soc.py | 239 +++++++++--------- .../axi_interconnect_wrapper.py | 24 +- submodules/BOOTROM/iob_bootrom.py | 6 +- 3 files changed, 139 insertions(+), 130 deletions(-) diff --git a/iob_soc.py b/iob_soc.py index 07deb139f..94a40f492 100755 --- a/iob_soc.py +++ b/iob_soc.py @@ -23,7 +23,50 @@ def setup(py_params_dict): update_params(params, py_params_dict) # Number of peripherals - num_peripherals = 3 + peripherals = [ + { + "core_name": "iob_bootrom", + "instance_name": "BOOTROM0", + "instance_description": "Boot ROM peripheral", + "parameters": { + "AXI_ID_W": "AXI_ID_W", + "AXI_ADDR_W": "AXI_ADDR_W", + "AXI_DATA_W": "AXI_DATA_W", + "AXI_LEN_W": "AXI_LEN_W", + }, + "connect": { + "clk_en_rst": "clk_en_rst", + "rom_bus": "bootrom_axi", + "ext_rom_bus": "rom_bus", + }, + "bootrom_addr_w": params["bootrom_addr_w"], + }, + { + "core_name": "iob_uart", + "instance_name": "UART0", + "instance_description": "UART peripheral", + "parameters": {}, + "connect": { + "clk_en_rst": "clk_en_rst", + "cbus": "uart0_cbus", + "rs232": "rs232", + }, + }, + { + "core_name": "iob_timer", + "instance_name": "TIMER0", + "instance_description": "Timer peripheral", + "parameters": {}, + "connect": { + "clk_en_rst": "clk_en_rst", + "cbus": "timer0_cbus", + }, + }, + # NOTE: Instantiate other peripherals here + ] + # Number of peripherals = peripherals + CLINT + PLIC + num_peripherals = len(peripherals) + 2 + peripheral_addr_w = params["addr_w"] - 1 - (num_peripherals - 1).bit_length() attributes_dict = { "original_name": "iob_soc", @@ -170,17 +213,9 @@ def setup(py_params_dict): }, ], }, - # Peripheral IO ports - { - "name": "rs232", - "descr": "iob-soc uart interface", - "interface": { - "type": "rs232", - }, - }, { "name": "axi", - "descr": "AXI master interface for external memory", + "descr": "AXI master interface for memory", "interface": { "type": "axi", "subtype": "master", @@ -191,6 +226,14 @@ def setup(py_params_dict): "LOCK_W": "AXI_LEN_W", }, }, + # Peripheral IO ports + { + "name": "rs232", + "descr": "iob-soc uart interface", + "interface": { + "type": "rs232", + }, + }, # NOTE: Add ports for peripherals here ] @@ -236,56 +279,25 @@ def setup(py_params_dict): }, }, { - "name": "periphs_axi", - "descr": "AXI bus for peripheral CSRs", - "interface": { - "type": "axi", - "wire_prefix": "periphs_", - "ID_W": "AXI_ID_W", - "ADDR_W": "AXI_ADDR_W", - "DATA_W": "AXI_DATA_W", - "LEN_W": "AXI_LEN_W", - }, - }, - { - "name": "periphs_cbus", - "descr": "Bus for peripherals Control/Status Register interfaces", - "interface": { - "type": "iob", - "wire_prefix": "cpu_pbus_", - "DATA_W": params["data_w"], - "ADDR_W": params["addr_w"] - 1, - }, - }, - { - "name": "split_reset", - "descr": "Reset signal for iob_split components", + "name": "interrupts", + "descr": "System interrupts", "signals": [ - {"name": "arst"}, + {"name": "interrupts", "width": 32}, ], }, + # Peripheral wires { "name": "bootrom_axi", "descr": "iob-soc boot controller data interface", "interface": { "type": "axi", "wire_prefix": "bootrom_", - # "DATA_W": params["data_w"], - # "ADDR_W": params["addr_w"] - 1, "ID_W": "AXI_ID_W", - "ADDR_W": params["bootrom_addr_w"] - 2, + "ADDR_W": peripheral_addr_w, "DATA_W": "AXI_DATA_W", "LEN_W": "AXI_LEN_W", }, }, - { - "name": "interrupts", - "descr": "System interrupts", - "signals": [ - {"name": "interrupts", "width": 32}, - ], - }, - # Peripheral wires { "name": "clint_cbus", "descr": "CLINT Control/Status Registers bus", @@ -295,7 +307,7 @@ def setup(py_params_dict): # "DATA_W": params["data_w"], # "ADDR_W": params["addr_w"] - 3, "ID_W": "AXI_ID_W", - "ADDR_W": "16", + "ADDR_W": peripheral_addr_w, "DATA_W": "AXI_DATA_W", "LEN_W": "AXI_LEN_W", }, @@ -309,29 +321,55 @@ def setup(py_params_dict): # "DATA_W": params["data_w"], # "ADDR_W": params["addr_w"] - 3, "ID_W": "AXI_ID_W", - "ADDR_W": "22", + "ADDR_W": peripheral_addr_w, "DATA_W": "AXI_DATA_W", "LEN_W": "AXI_LEN_W", }, }, + # Uart { - "name": "uart_cbus", - "descr": "UART Control/Status Registers bus", + "name": "uart0_axi", + "descr": "AXI bus for uart0 CSRs", + "interface": { + "type": "axi", + "wire_prefix": "uart0_", + "ID_W": "AXI_ID_W", + "ADDR_W": peripheral_addr_w, + "DATA_W": "AXI_DATA_W", + "LEN_W": "AXI_LEN_W", + }, + }, + { + "name": "uart0_cbus", + "descr": "UART0 Control/Status Registers bus", "interface": { "type": "iob", - "wire_prefix": "uart_cbus_", + "wire_prefix": "uart0_cbus_", "DATA_W": params["data_w"], - "ADDR_W": params["addr_w"] - 3, + "ADDR_W": peripheral_addr_w, }, }, + # Timer { - "name": "timer_cbus", - "descr": "TIMER Control/Status Registers bus", + "name": "timer0_axi", + "descr": "AXI bus for timer0 CSRs", + "interface": { + "type": "axi", + "wire_prefix": "timer0_", + "ID_W": "AXI_ID_W", + "ADDR_W": peripheral_addr_w, + "DATA_W": "AXI_DATA_W", + "LEN_W": "AXI_LEN_W", + }, + }, + { + "name": "timer0_cbus", + "descr": "TIMER0 Control/Status Registers bus", "interface": { "type": "iob", - "wire_prefix": "timer_cbus_", + "wire_prefix": "timer0_cbus_", "DATA_W": params["data_w"], - "ADDR_W": params["addr_w"] - 3, + "ADDR_W": peripheral_addr_w, }, }, # NOTE: Add peripheral wires here @@ -364,7 +402,7 @@ def setup(py_params_dict): "instance_description": "Interconnect instance", "parameters": { "AXI_ID_W": "AXI_ID_W", - "AXI_ADDR_W": "AXI_ADDR_W", + "AXI_ADDR_W": params["addr_w"], "AXI_DATA_W": "AXI_DATA_W", }, "connect": { @@ -372,92 +410,53 @@ def setup(py_params_dict): "rst": "rst", "s0_axi": "cpu_ibus", "s1_axi": "cpu_dbus", - "bootrom_axi": "bootrom_axi", "mem_axi": "axi", - "periphs_axi": "periphs_axi", + "bootrom_axi": "bootrom_axi", + "uart0_axi": "uart0_axi", + "timer0_axi": "timer0_axi", + # NOTE: Add other peripherals here (before clint and plic) "clint_axi": "clint_cbus", "plic_axi": "plic_cbus", }, "num_slaves": 2, "masters": { - "bootrom": params["bootrom_addr_w"] - 2, - "mem": "AXI_ADDR_W", - "periphs": 24, - "clint": 16, - "plic": 22, + "mem": params["addr_w"] - 1, + "bootrom": peripheral_addr_w, + "uart0": peripheral_addr_w, + "timer0": peripheral_addr_w, + # NOTE: Add other peripherals here (before clint and plic) + "clint": peripheral_addr_w, + "plic": peripheral_addr_w, }, - # FIXME: Size of each output }, + # Uart { "core_name": "axi2iob", - "instance_name": "peripheral_axi2iob", - "instance_description": "Convert AXI interface to IOb for peripheral CSRs bus", + "instance_name": "uart0_axi2iob", + "instance_description": "Convert AXI interface to IOb for uart0 CSRs bus", "parameters": { - "ADDR_WIDTH": params["addr_w"] - 1, - }, - "connect": { - "clk_en_rst": "clk_en_rst", - "axi": "periphs_axi", - "iob": "periphs_cbus", + "ADDR_WIDTH": peripheral_addr_w, }, - }, - { - "core_name": "iob_split", - "name": "iob_pbus_split", - "instance_name": "iob_pbus_split", - "instance_description": "Split between peripherals", - "connect": { - "clk_en_rst": "clk_en_rst", - "reset": "split_reset", - "input": "periphs_cbus", - "output_0": "uart_cbus", - "output_1": "timer_cbus", - # NOTE: Connect other peripherals here - }, - "num_outputs": num_peripherals - 1, # Don't count bootloader - "addr_w": params["addr_w"] - 2, # FIXME: - }, - ] - peripherals = [ - { - "core_name": "iob_uart", - "instance_name": "UART0", - "instance_description": "UART peripheral", - "parameters": {}, "connect": { "clk_en_rst": "clk_en_rst", - "cbus": "uart_cbus", - "rs232": "rs232", + "axi": "uart0_axi", + "iob": "uart0_cbus", }, }, + # Timer { - "core_name": "iob_timer", - "instance_name": "TIMER0", - "instance_description": "Timer peripheral", - "parameters": {}, - "connect": { - "clk_en_rst": "clk_en_rst", - "cbus": "timer_cbus", - }, - }, - { - "core_name": "iob_bootrom", - "instance_name": "BOOTROM0", - "instance_description": "Boot ROM peripheral", + "core_name": "axi2iob", + "instance_name": "timer0_axi2iob", + "instance_description": "Convert AXI interface to IOb for timer0 CSRs bus", "parameters": { - "AXI_ID_W": "AXI_ID_W", - "AXI_ADDR_W": "AXI_ADDR_W", - "AXI_DATA_W": "AXI_DATA_W", - "AXI_LEN_W": "AXI_LEN_W", + "ADDR_WIDTH": peripheral_addr_w, }, "connect": { "clk_en_rst": "clk_en_rst", - "rom_bus": "bootrom_axi", - "ext_rom_bus": "rom_bus", + "axi": "timer0_axi", + "iob": "timer0_cbus", }, - "bootrom_addr_w": params["bootrom_addr_w"], }, - # NOTE: Instantiate other peripherals here ] attributes_dict["blocks"] += peripherals + [ # Modules that need to be setup, but are not instantiated directly inside diff --git a/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py b/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py index 02e2249e2..303bb2b8f 100644 --- a/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py +++ b/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py @@ -79,7 +79,7 @@ def setup(py_params_dict): "max": "32", "descr": "AXI ID bus width", }, - { # FIXME: Somehow make this parameter be 32 bits. This will allow passing 32'd... as a range + { "name": "AXI_ADDR_W", "type": "P", "val": "0", @@ -234,13 +234,16 @@ def setup(py_params_dict): # Connect all Slave AXI interfaces to interconnect verilog_code = " // Connect all slave AXI interfaces to interconnect\n" for sig_name, _ in AXI_IN_SIGNAL_NAMES: - verilog_code += f" assign intercon_s_axi_{sig_name} = {{" + assign_str = "" for port in slave_axi_ports: prefix = "" if "port_prefix" in port["interface"]: prefix = port["interface"]["port_prefix"] - verilog_code += f"{prefix}axi_{sig_name}_i, " - verilog_code = verilog_code[:-2] + "};\n" + assign_str = f"{prefix}axi_{sig_name}_i, " + assign_str + assign_str = assign_str[:-2] + verilog_code += ( + f" assign intercon_s_axi_{sig_name} = {{" + assign_str + "};\n" + ) for sig_name, sig_size in AXI_OUT_SIGNAL_NAMES: for idx, port in enumerate(slave_axi_ports): @@ -250,18 +253,23 @@ def setup(py_params_dict): bit_select = "" if type(sig_size) is not int or sig_size > 1: bit_select = f"[{idx}*{sig_size}+:{sig_size}]" + elif len(slave_axi_ports) > 1: + bit_select = f"[{idx}]" verilog_code += f" assign {prefix}axi_{sig_name}_o = intercon_s_axi_{sig_name}{bit_select}; \n" # Connect all Master AXI interfaces to interconnect verilog_code += " // Connect all master AXI interfaces to interconnect\n" for sig_name, _ in AXI_OUT_SIGNAL_NAMES: - verilog_code += f" assign intercon_m_axi_{sig_name} = {{" + assign_str = "" for port in master_axi_ports: prefix = "" if "port_prefix" in port["interface"]: prefix = port["interface"]["port_prefix"] - verilog_code += f"{prefix}axi_{sig_name}_i, " - verilog_code = verilog_code[:-2] + "};\n" + assign_str = f"{prefix}axi_{sig_name}_i, " + assign_str + assign_str = assign_str[:-2] + verilog_code += ( + f" assign intercon_m_axi_{sig_name} = {{" + assign_str + "};\n" + ) for sig_name, sig_size in AXI_IN_SIGNAL_NAMES: for idx, port in enumerate(master_axi_ports): @@ -271,6 +279,8 @@ def setup(py_params_dict): bit_select = "" if type(sig_size) is not int or sig_size > 1: bit_select = f"[{idx}*{sig_size}+:{sig_size}]" + elif len(master_axi_ports) > 1: + bit_select = f"[{idx}]" verilog_code += f" assign {prefix}axi_{sig_name}_o = intercon_m_axi_{sig_name}{bit_select}; \n" attributes_dict["snippets"] = [ diff --git a/submodules/BOOTROM/iob_bootrom.py b/submodules/BOOTROM/iob_bootrom.py index 88cfae087..b5f9f98d5 100644 --- a/submodules/BOOTROM/iob_bootrom.py +++ b/submodules/BOOTROM/iob_bootrom.py @@ -76,7 +76,7 @@ def setup(py_params_dict): "interface": { "type": "axi", "subtype": "slave", - "ADDR_W": BOOTROM_ADDR_W - 2, + "ADDR_W": BOOTROM_ADDR_W, "DATA_W": "DATA_W", }, }, @@ -156,10 +156,10 @@ def setup(py_params_dict): assign axi_wready_o = 1'b0; assign axi_bid_o = {{AXI_ID_W{{1'b0}}}}; assign axi_bresp_o = 2'b0; - assign axi_bvalid_o = 1'b0; + assign axi_bvalid_o = 1'b1; assign axi_rid_o = {{AXI_ID_W{{1'b0}}}}; assign axi_rresp_o = 2'b0; - assign axi_rlast_o = 1'b0; + assign axi_rlast_o = axi_rvalid_o; """, }, ], From 86d02acb68d5652783f0a3aaae8965764638c4aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Fri, 6 Sep 2024 17:42:19 +0100 Subject: [PATCH 06/12] feat(axi): Remove axi2iob converters; Use all peripherals with AXI cbus. Rename software sources to use underscores; Re-add csrs to bootrom. Allows csrs generator to handle AXI to iob conversion. TODO: Update py2hwsw to fix AXI interface of generated csrs. --- document/tsrc/presentation.tex | 4 +- .../iob_soc_sim_wrapper.py | 2 + iob_soc.py | 64 ++-------------- .../iob_nco/software/example_firmware.c | 4 +- .../software/src/{iob-nco.c => iob_nco.c} | 2 +- .../software/src/{iob-nco.h => iob_nco.h} | 0 lib/hardware/iob_timer/iob_timer.py | 3 +- .../iob_timer/software/example_firmware.c | 4 +- .../software/src/{iob-timer.c => iob_timer.c} | 2 +- .../software/src/{iob-timer.h => iob_timer.h} | 0 lib/hardware/iob_uart/iob_uart.py | 7 +- .../software/src/{iob-uart.c => iob_uart.c} | 2 +- .../software/src/{iob-uart.h => iob_uart.h} | 0 scripts/iob_soc_utils.py | 6 ++ software/src/iob_soc_firmware.c | 4 +- software/sw_build.mk | 7 +- submodules/BOOTROM/iob_bootrom.py | 75 +++++++++++++------ .../BOOTROM/software/src/iob_soc_boot.c | 2 +- 18 files changed, 91 insertions(+), 97 deletions(-) rename lib/hardware/clocks_resets/iob_nco/software/src/{iob-nco.c => iob_nco.c} (96%) rename lib/hardware/clocks_resets/iob_nco/software/src/{iob-nco.h => iob_nco.h} (100%) rename lib/hardware/iob_timer/software/src/{iob-timer.c => iob_timer.c} (95%) rename lib/hardware/iob_timer/software/src/{iob-timer.h => iob_timer.h} (100%) rename lib/hardware/iob_uart/software/src/{iob-uart.c => iob_uart.c} (99%) rename lib/hardware/iob_uart/software/src/{iob-uart.h => iob_uart.h} (100%) diff --git a/document/tsrc/presentation.tex b/document/tsrc/presentation.tex index 573ac8ab2..89f2aa6d2 100644 --- a/document/tsrc/presentation.tex +++ b/document/tsrc/presentation.tex @@ -134,10 +134,10 @@ \begin{lstlisting} #include "system.h" #include "periphs.h" -#include "iob-uart.h" +#include "iob_uart.h" #include "printf.h" -#include "iob-timer.h" +#include "iob_timer.h" int main() { diff --git a/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py b/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py index 29b00084c..a6622b635 100644 --- a/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py +++ b/hardware/modules/iob_soc_sim_wrapper/iob_soc_sim_wrapper.py @@ -195,8 +195,10 @@ def setup(py_params_dict): }, { "core_name": "iob_uart", + "name": "iob_uart_iob", "instance_name": "uart_tb", "instance_description": "Testbench uart core", + "csr_if": "iob", "connect": { "clk_en_rst": "clk_en_rst", "cbus": "uart", diff --git a/iob_soc.py b/iob_soc.py index 94a40f492..090e392e9 100755 --- a/iob_soc.py +++ b/iob_soc.py @@ -36,7 +36,7 @@ def setup(py_params_dict): }, "connect": { "clk_en_rst": "clk_en_rst", - "rom_bus": "bootrom_axi", + "cbus": "bootrom_cbus", "ext_rom_bus": "rom_bus", }, "bootrom_addr_w": params["bootrom_addr_w"], @@ -287,7 +287,7 @@ def setup(py_params_dict): }, # Peripheral wires { - "name": "bootrom_axi", + "name": "bootrom_cbus", "descr": "iob-soc boot controller data interface", "interface": { "type": "axi", @@ -326,9 +326,8 @@ def setup(py_params_dict): "LEN_W": "AXI_LEN_W", }, }, - # Uart { - "name": "uart0_axi", + "name": "uart0_cbus", "descr": "AXI bus for uart0 CSRs", "interface": { "type": "axi", @@ -340,18 +339,7 @@ def setup(py_params_dict): }, }, { - "name": "uart0_cbus", - "descr": "UART0 Control/Status Registers bus", - "interface": { - "type": "iob", - "wire_prefix": "uart0_cbus_", - "DATA_W": params["data_w"], - "ADDR_W": peripheral_addr_w, - }, - }, - # Timer - { - "name": "timer0_axi", + "name": "timer0_cbus", "descr": "AXI bus for timer0 CSRs", "interface": { "type": "axi", @@ -362,16 +350,6 @@ def setup(py_params_dict): "LEN_W": "AXI_LEN_W", }, }, - { - "name": "timer0_cbus", - "descr": "TIMER0 Control/Status Registers bus", - "interface": { - "type": "iob", - "wire_prefix": "timer0_cbus_", - "DATA_W": params["data_w"], - "ADDR_W": peripheral_addr_w, - }, - }, # NOTE: Add peripheral wires here ] attributes_dict["blocks"] = [ @@ -411,9 +389,9 @@ def setup(py_params_dict): "s0_axi": "cpu_ibus", "s1_axi": "cpu_dbus", "mem_axi": "axi", - "bootrom_axi": "bootrom_axi", - "uart0_axi": "uart0_axi", - "timer0_axi": "timer0_axi", + "bootrom_axi": "bootrom_cbus", + "uart0_axi": "uart0_cbus", + "timer0_axi": "timer0_cbus", # NOTE: Add other peripherals here (before clint and plic) "clint_axi": "clint_cbus", "plic_axi": "plic_cbus", @@ -429,34 +407,6 @@ def setup(py_params_dict): "plic": peripheral_addr_w, }, }, - # Uart - { - "core_name": "axi2iob", - "instance_name": "uart0_axi2iob", - "instance_description": "Convert AXI interface to IOb for uart0 CSRs bus", - "parameters": { - "ADDR_WIDTH": peripheral_addr_w, - }, - "connect": { - "clk_en_rst": "clk_en_rst", - "axi": "uart0_axi", - "iob": "uart0_cbus", - }, - }, - # Timer - { - "core_name": "axi2iob", - "instance_name": "timer0_axi2iob", - "instance_description": "Convert AXI interface to IOb for timer0 CSRs bus", - "parameters": { - "ADDR_WIDTH": peripheral_addr_w, - }, - "connect": { - "clk_en_rst": "clk_en_rst", - "axi": "timer0_axi", - "iob": "timer0_cbus", - }, - }, ] attributes_dict["blocks"] += peripherals + [ # Modules that need to be setup, but are not instantiated directly inside diff --git a/lib/hardware/clocks_resets/iob_nco/software/example_firmware.c b/lib/hardware/clocks_resets/iob_nco/software/example_firmware.c index c1de125d1..76b1f2280 100644 --- a/lib/hardware/clocks_resets/iob_nco/software/example_firmware.c +++ b/lib/hardware/clocks_resets/iob_nco/software/example_firmware.c @@ -1,6 +1,6 @@ #include "bsp.h" -#include "iob-nco.h" -#include "iob-uart.h" +#include "iob_nco.h" +#include "iob_uart.h" #include "periphs.h" #include "printf.h" #include "system.h" diff --git a/lib/hardware/clocks_resets/iob_nco/software/src/iob-nco.c b/lib/hardware/clocks_resets/iob_nco/software/src/iob_nco.c similarity index 96% rename from lib/hardware/clocks_resets/iob_nco/software/src/iob-nco.c rename to lib/hardware/clocks_resets/iob_nco/software/src/iob_nco.c index cd162ff22..20292cfe9 100644 --- a/lib/hardware/clocks_resets/iob_nco/software/src/iob-nco.c +++ b/lib/hardware/clocks_resets/iob_nco/software/src/iob_nco.c @@ -1,4 +1,4 @@ -#include "iob-nco.h" +#include "iob_nco.h" // Base Address static uint32_t base; diff --git a/lib/hardware/clocks_resets/iob_nco/software/src/iob-nco.h b/lib/hardware/clocks_resets/iob_nco/software/src/iob_nco.h similarity index 100% rename from lib/hardware/clocks_resets/iob_nco/software/src/iob-nco.h rename to lib/hardware/clocks_resets/iob_nco/software/src/iob_nco.h diff --git a/lib/hardware/iob_timer/iob_timer.py b/lib/hardware/iob_timer/iob_timer.py index 4d1a49404..497d73215 100755 --- a/lib/hardware/iob_timer/iob_timer.py +++ b/lib/hardware/iob_timer/iob_timer.py @@ -41,7 +41,7 @@ def setup(py_params_dict): { "name": "cbus", "interface": { - "type": "iob", + "type": "axi", "subtype": "slave", "ADDR_W": "4", # Same as `IOB_TIMER_CSRS_ADDR_W "DATA_W": "DATA_W", @@ -164,6 +164,7 @@ def setup(py_params_dict): ], }, ], + "csr_if": "axi", "connect": { "clk_en_rst": "clk_en_rst", "control_if": "cbus", diff --git a/lib/hardware/iob_timer/software/example_firmware.c b/lib/hardware/iob_timer/software/example_firmware.c index 811b45d21..4e54c4dc3 100644 --- a/lib/hardware/iob_timer/software/example_firmware.c +++ b/lib/hardware/iob_timer/software/example_firmware.c @@ -1,6 +1,6 @@ #include "bsp.h" -#include "iob-timer.h" -#include "iob-uart.h" +#include "iob_timer.h" +#include "iob_uart.h" #include "periphs.h" #include "printf.h" #include "system.h" diff --git a/lib/hardware/iob_timer/software/src/iob-timer.c b/lib/hardware/iob_timer/software/src/iob_timer.c similarity index 95% rename from lib/hardware/iob_timer/software/src/iob-timer.c rename to lib/hardware/iob_timer/software/src/iob_timer.c index cb4caf94e..41217d9bf 100644 --- a/lib/hardware/iob_timer/software/src/iob-timer.c +++ b/lib/hardware/iob_timer/software/src/iob_timer.c @@ -1,4 +1,4 @@ -#include "iob-timer.h" +#include "iob_timer.h" // Base Address static uint32_t base; diff --git a/lib/hardware/iob_timer/software/src/iob-timer.h b/lib/hardware/iob_timer/software/src/iob_timer.h similarity index 100% rename from lib/hardware/iob_timer/software/src/iob-timer.h rename to lib/hardware/iob_timer/software/src/iob_timer.h diff --git a/lib/hardware/iob_uart/iob_uart.py b/lib/hardware/iob_uart/iob_uart.py index 943905d8b..d0c8328e6 100755 --- a/lib/hardware/iob_uart/iob_uart.py +++ b/lib/hardware/iob_uart/iob_uart.py @@ -1,7 +1,9 @@ def setup(py_params_dict): + CSR_IF = py_params_dict["csr_if"] if "csr_if" in py_params_dict else "axi" + NAME = py_params_dict["name"] if "name" in py_params_dict else "iob_uart" attributes_dict = { "original_name": "iob_uart", - "name": "iob_uart", + "name": NAME, "version": "0.1", "board_list": ["cyclonev_gt_dk", "aes_ku040_db_g"], "confs": [ @@ -42,7 +44,7 @@ def setup(py_params_dict): { "name": "cbus", "interface": { - "type": "iob", + "type": CSR_IF, "subtype": "slave", "ADDR_W": "3", # Same as `IOB_UART_CSRS_ADDR_W "DATA_W": "DATA_W", @@ -257,6 +259,7 @@ def setup(py_params_dict): ], } ], + "csr_if": CSR_IF, "connect": { "clk_en_rst": "clk_en_rst", "control_if": "cbus", diff --git a/lib/hardware/iob_uart/software/src/iob-uart.c b/lib/hardware/iob_uart/software/src/iob_uart.c similarity index 99% rename from lib/hardware/iob_uart/software/src/iob-uart.c rename to lib/hardware/iob_uart/software/src/iob_uart.c index ae31ac6ab..35721efa0 100644 --- a/lib/hardware/iob_uart/software/src/iob-uart.c +++ b/lib/hardware/iob_uart/software/src/iob_uart.c @@ -1,4 +1,4 @@ -#include "iob-uart.h" +#include "iob_uart.h" #include // TX FUNCTIONS diff --git a/lib/hardware/iob_uart/software/src/iob-uart.h b/lib/hardware/iob_uart/software/src/iob_uart.h similarity index 100% rename from lib/hardware/iob_uart/software/src/iob-uart.h rename to lib/hardware/iob_uart/software/src/iob_uart.h diff --git a/scripts/iob_soc_utils.py b/scripts/iob_soc_utils.py index b036f821f..333ed8f79 100644 --- a/scripts/iob_soc_utils.py +++ b/scripts/iob_soc_utils.py @@ -100,6 +100,12 @@ def generate_makefile_segments(attributes_dict, peripherals, params, py_params): os.makedirs(f"{build_dir}/software", exist_ok=True) with open(f"{build_dir}/software/auto_sw_build.mk", "w") as file: file.write("#This file was auto generated by iob_soc_utils.py\n") + # Create a list with every peripheral name, except bootrom, clint, and plic + file.write( + "PERIPHERALS ?=" + + " ".join(peripheral["core_name"] for peripheral in peripherals[1:]) + + "\n", + ) if params["use_ethernet"]: # Set custom ethernet CONSOLE_CMD file.write( diff --git a/software/src/iob_soc_firmware.c b/software/src/iob_soc_firmware.c index c03595317..6aa3dc497 100644 --- a/software/src/iob_soc_firmware.c +++ b/software/src/iob_soc_firmware.c @@ -1,9 +1,9 @@ #include "bsp.h" -#include "iob-timer.h" -#include "iob-uart.h" #include "iob_soc_conf.h" #include "iob_soc_periphs.h" #include "iob_soc_system.h" +#include "iob_timer.h" +#include "iob_uart.h" #include "printf.h" #include diff --git a/software/sw_build.mk b/software/sw_build.mk index 992bc937a..989935262 100644 --- a/software/sw_build.mk +++ b/software/sw_build.mk @@ -40,13 +40,14 @@ IOB_SOC_FW_SRC=src/iob_soc_firmware.S IOB_SOC_FW_SRC+=src/iob_soc_firmware.c IOB_SOC_FW_SRC+=src/printf.c # PERIPHERAL SOURCES -IOB_SOC_FW_SRC+=$(wildcard src/iob-*.c) -IOB_SOC_FW_SRC+=$(filter-out %_emul.c, $(wildcard src/*csrs*.c)) +IOB_SOC_FW_SRC+=$(addprefix src/,$(addsuffix .c,$(PERIPHERALS))) +IOB_SOC_FW_SRC+=$(addprefix src/,$(addsuffix _csrs_emb.c,$(PERIPHERALS))) # BOOTLOADER SOURCES IOB_SOC_BOOT_SRC+=src/iob_soc_boot.S IOB_SOC_BOOT_SRC+=src/iob_soc_boot.c -IOB_SOC_BOOT_SRC+=$(filter-out %_emul.c, $(wildcard src/iob*uart*.c)) +IOB_SOC_BOOT_SRC+=src/iob_uart.c +IOB_SOC_BOOT_SRC+=src/iob_uart_csrs_emb.c # PREBOOT SOURCES IOB_SOC_PREBOOT_SRC=src/iob_soc_preboot.S diff --git a/submodules/BOOTROM/iob_bootrom.py b/submodules/BOOTROM/iob_bootrom.py index b5f9f98d5..9c84650f7 100644 --- a/submodules/BOOTROM/iob_bootrom.py +++ b/submodules/BOOTROM/iob_bootrom.py @@ -71,11 +71,12 @@ def setup(py_params_dict): }, }, { - "name": "rom_bus", - "descr": "Boot ROM bus", + "name": "cbus", + "descr": "Front-end control interface", "interface": { "type": "axi", "subtype": "slave", + "port_prefix": "cbus_", "ADDR_W": BOOTROM_ADDR_W, "DATA_W": "DATA_W", }, @@ -107,17 +108,27 @@ def setup(py_params_dict): # "wires": [ { - "name": "rom_rvalid_i", + "name": "rom", + "descr": "'rom' register interface", + "signals": [ + {"name": "rom_rdata_rd", "width": "DATA_W"}, + {"name": "rom_rvalid_rd", "width": 1}, + {"name": "rom_ren_rd", "width": 1}, + {"name": "rom_rready_rd", "width": 1}, + ], + }, + { + "name": "rom_rvalid_data_i", "descr": "Register input", "signals": [ - {"name": "axi_arvalid", "width": 1}, + {"name": "rom_ren_rd"}, ], }, { - "name": "rom_rvalid_o", + "name": "rom_rvalid_data_o", "descr": "Register output", "signals": [ - {"name": "axi_rvalid"}, + {"name": "rom_rvalid_rd"}, ], }, ], @@ -125,6 +136,36 @@ def setup(py_params_dict): # Blocks # "blocks": [ + { + "core_name": "csrs", + "instance_name": "csrs_inst", + "version": VERSION, + "csrs": [ + { + "name": "rom", + "descr": "ROM access.", + "regs": [ + { + "name": "rom", + "descr": "Bootloader ROM (read).", + "type": "R", + "n_bits": "DATA_W", + "rst_val": 0, + "addr": -1, + "log2n_items": BOOTROM_ADDR_W - 2, + "autoreg": False, + }, + ], + } + ], + "csr_if": "axi", + "connect": { + "clk_en_rst": "clk_en_rst", + "control_if": "cbus", + # Register interfaces + "rom": "rom", + }, + }, { "core_name": "iob_reg", "instance_name": "rom_rvalid_r", @@ -135,8 +176,8 @@ def setup(py_params_dict): }, "connect": { "clk_en_rst": "clk_en_rst", - "data_i": "rom_rvalid_i", - "data_o": "rom_rvalid_o", + "data_i": "rom_rvalid_data_i", + "data_o": "rom_rvalid_data_o", }, }, ], @@ -146,20 +187,10 @@ def setup(py_params_dict): "snippets": [ { "verilog_code": f""" - assign ext_rom_en_o = axi_arvalid_i; - assign ext_rom_addr_o = axi_araddr_i[{BOOTROM_ADDR_W}:2]; - assign axi_rdata_o = ext_rom_rdata_i; - assign axi_arready_o = 1'b1; // ROM is always ready - - // Unused outputs - assign axi_awready_o = 1'b0; - assign axi_wready_o = 1'b0; - assign axi_bid_o = {{AXI_ID_W{{1'b0}}}}; - assign axi_bresp_o = 2'b0; - assign axi_bvalid_o = 1'b1; - assign axi_rid_o = {{AXI_ID_W{{1'b0}}}}; - assign axi_rresp_o = 2'b0; - assign axi_rlast_o = axi_rvalid_o; + assign ext_rom_en_o = rom_ren_rd; + assign ext_rom_addr_o = cbus_iob_addr_i[{BOOTROM_ADDR_W}:2]; + assign rom_rdata_rd = ext_rom_rdata_i; + assign rom_rready_rd = 1'b1; // ROM is always ready """, }, ], diff --git a/submodules/BOOTROM/software/src/iob_soc_boot.c b/submodules/BOOTROM/software/src/iob_soc_boot.c index 600f1cd68..a652b58ea 100644 --- a/submodules/BOOTROM/software/src/iob_soc_boot.c +++ b/submodules/BOOTROM/software/src/iob_soc_boot.c @@ -1,8 +1,8 @@ #include "bsp.h" -#include "iob-uart.h" #include "iob_soc_conf.h" #include "iob_soc_periphs.h" #include "iob_soc_system.h" +#include "iob_uart.h" #define PROGNAME "IOb-Bootloader" From 7a59187fc83132856f449eeda998702d6d804541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Sun, 8 Sep 2024 03:10:33 +0100 Subject: [PATCH 07/12] feat(csrs): Add wires for new csrs "IOb" output interface; Update py2hwsw version. Pre-Bootloader seems to run, but not bootloader. Seems to keep resetting back to pre-bootloader. --- .../iob_axistream_in/iob_axistream_in.py | 11 ++++++++ .../iob_axistream_out/iob_axistream_out.py | 11 ++++++++ lib/hardware/clocks_resets/iob_nco/iob_nco.py | 11 ++++++++ lib/hardware/iob_gpio/iob_gpio.py | 11 ++++++++ lib/hardware/iob_regfileif/iob_regfileif.py | 26 ++++++++++++++++++- lib/hardware/iob_timer/iob_timer.py | 11 ++++++++ lib/hardware/iob_uart/iob_uart.py | 13 +++++++++- lib/scripts/default.nix | 4 +-- submodules/BOOTROM/iob_bootrom.py | 13 +++++++++- 9 files changed, 106 insertions(+), 5 deletions(-) diff --git a/lib/hardware/buses/iob_axistream_in/iob_axistream_in.py b/lib/hardware/buses/iob_axistream_in/iob_axistream_in.py index 79fd93104..0b96a617f 100755 --- a/lib/hardware/buses/iob_axistream_in/iob_axistream_in.py +++ b/lib/hardware/buses/iob_axistream_in/iob_axistream_in.py @@ -144,6 +144,16 @@ def setup(py_params_dict): }, ], "wires": [ + { + "name": "csrs_iob", + "descr": "Internal CSRs IOb interface", + "interface": { + "type": "iob", + "wire_prefix": "csrs_", + "ADDR_W": "ADDR_W", + "DATA_W": "DATA_W", + }, + }, { "name": "soft_reset", "descr": "", @@ -334,6 +344,7 @@ def setup(py_params_dict): "connect": { "clk_en_rst": "clk_en_rst", "control_if": "iob", + "csrs_iob_output": "csrs_iob", # Register interfaces "soft_reset": "soft_reset", "enable": "enable", diff --git a/lib/hardware/buses/iob_axistream_out/iob_axistream_out.py b/lib/hardware/buses/iob_axistream_out/iob_axistream_out.py index c8a63e169..0d30c5348 100755 --- a/lib/hardware/buses/iob_axistream_out/iob_axistream_out.py +++ b/lib/hardware/buses/iob_axistream_out/iob_axistream_out.py @@ -144,6 +144,16 @@ def setup(py_params_dict): }, ], "wires": [ + { + "name": "csrs_iob", + "descr": "Internal CSRs IOb interface", + "interface": { + "type": "iob", + "wire_prefix": "csrs_", + "ADDR_W": "ADDR_W", + "DATA_W": "DATA_W", + }, + }, { "name": "soft_reset", "descr": "", @@ -313,6 +323,7 @@ def setup(py_params_dict): "connect": { "clk_en_rst": "clk_en_rst", "control_if": "iob", + "csrs_iob_output": "csrs_iob", # Register interfaces "soft_reset": "soft_reset", "enable": "enable", diff --git a/lib/hardware/clocks_resets/iob_nco/iob_nco.py b/lib/hardware/clocks_resets/iob_nco/iob_nco.py index ff862463b..457adc67c 100644 --- a/lib/hardware/clocks_resets/iob_nco/iob_nco.py +++ b/lib/hardware/clocks_resets/iob_nco/iob_nco.py @@ -74,6 +74,16 @@ def setup(py_params_dict): }, ], "wires": [ + { + "name": "csrs_iob", + "descr": "Internal CSRs IOb interface", + "interface": { + "type": "iob", + "wire_prefix": "csrs_", + "ADDR_W": "ADDR_W", + "DATA_W": "DATA_W", + }, + }, # Register wires { "name": "softreset", @@ -309,6 +319,7 @@ def setup(py_params_dict): "connect": { "clk_en_rst": "clk_en_rst", "control_if": "iob", + "csrs_iob_output": "csrs_iob", # Register interfaces "softreset": "softreset", "enable": "enable", diff --git a/lib/hardware/iob_gpio/iob_gpio.py b/lib/hardware/iob_gpio/iob_gpio.py index 25cf62367..66452bc45 100755 --- a/lib/hardware/iob_gpio/iob_gpio.py +++ b/lib/hardware/iob_gpio/iob_gpio.py @@ -73,6 +73,16 @@ def setup(py_params_dict): }, ], "wires": [ + { + "name": "csrs_iob", + "descr": "Internal iob interface", + "interface": { + "type": "iob", + "wire_prefix": "csrs_", + "ADDR_W": "ADDR_W", + "DATA_W": "DATA_W", + }, + }, { "name": "input_ports", "descr": "", @@ -138,6 +148,7 @@ def setup(py_params_dict): "connect": { "clk_en_rst": "clk_en_rst", "control_if": "iob", + "csrs_iob_output": "csrs_iob", # Register interfaces "gpio_input": "input_ports", "gpio_output": "output_ports", diff --git a/lib/hardware/iob_regfileif/iob_regfileif.py b/lib/hardware/iob_regfileif/iob_regfileif.py index 74f5b67db..93fa0f388 100755 --- a/lib/hardware/iob_regfileif/iob_regfileif.py +++ b/lib/hardware/iob_regfileif/iob_regfileif.py @@ -159,7 +159,29 @@ def setup(py_params_dict): "descr": "External CPU native interface.", }, ], - "wires": reg_wires, + "wires": reg_wires + + [ + { + "name": "csrs_iob", + "descr": "Internal CSRs iob interface", + "interface": { + "type": "iob", + "wire_prefix": "csrs_", + "ADDR_W": "ADDR_W", + "DATA_W": "DATA_W", + }, + }, + { + "name": "internal_iob2", + "descr": "Internal iob interface", + "interface": { + "type": "iob", + "wire_prefix": "internal2_", + "ADDR_W": "ADDR_W", + "DATA_W": "DATA_W", + }, + }, + ], "blocks": [ { "core_name": "csrs", @@ -169,6 +191,7 @@ def setup(py_params_dict): "connect": { "clk_en_rst": "clk_en_rst", "control_if": "external_control_if", + "csrs_iob_output": "csrs_iob", **external_reg_connections, }, "csr_if": params["external_csr_if"], @@ -185,6 +208,7 @@ def setup(py_params_dict): "connect": { "clk_en_rst": "clk_en_rst", "control_if": "internal_control_if", + "csrs_iob_output": "internal_iob2", **internal_reg_connections, }, "csr_if": params["internal_csr_if"], diff --git a/lib/hardware/iob_timer/iob_timer.py b/lib/hardware/iob_timer/iob_timer.py index 497d73215..8d55189ae 100755 --- a/lib/hardware/iob_timer/iob_timer.py +++ b/lib/hardware/iob_timer/iob_timer.py @@ -50,6 +50,16 @@ def setup(py_params_dict): }, ], "wires": [ + { + "name": "csrs_iob", + "descr": "Internal CSRs IOb interface", + "interface": { + "type": "iob", + "wire_prefix": "csrs_", + "ADDR_W": "ADDR_W", + "DATA_W": "DATA_W", + }, + }, # Register wires { "name": "reset", @@ -168,6 +178,7 @@ def setup(py_params_dict): "connect": { "clk_en_rst": "clk_en_rst", "control_if": "cbus", + "csrs_iob_output": "csrs_iob", # Register interfaces "reset": "reset", "enable": "enable", diff --git a/lib/hardware/iob_uart/iob_uart.py b/lib/hardware/iob_uart/iob_uart.py index d0c8328e6..a56330446 100755 --- a/lib/hardware/iob_uart/iob_uart.py +++ b/lib/hardware/iob_uart/iob_uart.py @@ -60,6 +60,16 @@ def setup(py_params_dict): }, ], "wires": [ + { + "name": "csrs_iob", + "descr": "Internal iob interface", + "interface": { + "type": "iob", + "wire_prefix": "csrs_", + "ADDR_W": "ADDR_W", + "DATA_W": "DATA_W", + }, + }, { "name": "softreset", "descr": "", @@ -263,6 +273,7 @@ def setup(py_params_dict): "connect": { "clk_en_rst": "clk_en_rst", "control_if": "cbus", + "csrs_iob_output": "csrs_iob", # Register interfaces "softreset": "softreset", "div": "div", @@ -309,7 +320,7 @@ def setup(py_params_dict): assign rxdata_rready_rd = 1'b1; // rxdata rvalid is iob_valid registered - assign rxdata_rvalid_nxt = iob_valid_i & rxdata_ren_rd; + assign rxdata_rvalid_nxt = csrs_iob_valid & rxdata_ren_rd; """, }, ], diff --git a/lib/scripts/default.nix b/lib/scripts/default.nix index 044ce71bb..99eba124f 100644 --- a/lib/scripts/default.nix +++ b/lib/scripts/default.nix @@ -1,8 +1,8 @@ { pkgs ? import {} }: let - py2hwsw_commit = "1fd33b3afe912faa44fb885bd86bea4174763177"; # Replace with the desired commit. - py2hwsw_sha256 = "vdlyRutfxq14an+QIHyK5OWwd+bheNCIN5LrrcUkWrI="; # Replace with the actual SHA256 hash. + py2hwsw_commit = "24f47ac357b6232df07a4adeb021202adde57278"; # Replace with the desired commit. + py2hwsw_sha256 = "qY/eg+CoEAri3KvMoLRJRaMvu66Ao5lDLigBNnQUgro="; # Replace with the actual SHA256 hash. py2hwsw = pkgs.python3.pkgs.buildPythonPackage rec { pname = "py2hwsw"; diff --git a/submodules/BOOTROM/iob_bootrom.py b/submodules/BOOTROM/iob_bootrom.py index 9c84650f7..e7c319ee9 100644 --- a/submodules/BOOTROM/iob_bootrom.py +++ b/submodules/BOOTROM/iob_bootrom.py @@ -107,6 +107,16 @@ def setup(py_params_dict): # Wires # "wires": [ + { + "name": "csrs_iob", + "descr": "Internal iob interface", + "interface": { + "type": "iob", + "wire_prefix": "csrs_", + "ADDR_W": BOOTROM_ADDR_W, + "DATA_W": "DATA_W", + }, + }, { "name": "rom", "descr": "'rom' register interface", @@ -162,6 +172,7 @@ def setup(py_params_dict): "connect": { "clk_en_rst": "clk_en_rst", "control_if": "cbus", + "csrs_iob_output": "csrs_iob", # Register interfaces "rom": "rom", }, @@ -188,7 +199,7 @@ def setup(py_params_dict): { "verilog_code": f""" assign ext_rom_en_o = rom_ren_rd; - assign ext_rom_addr_o = cbus_iob_addr_i[{BOOTROM_ADDR_W}:2]; + assign ext_rom_addr_o = csrs_iob_addr[{BOOTROM_ADDR_W}:2]; assign rom_rdata_rd = ext_rom_rdata_i; assign rom_rready_rd = 1'b1; // ROM is always ready """, From 390fcb6b6ec6c75facfc640dd994090049ed4a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Tue, 10 Sep 2024 00:46:48 +0100 Subject: [PATCH 08/12] fix(bugs): Fix iob-soc and depedencies. - Fix prebootloader copy size. - Fix interconnect wrapper for single master. - Fix iob-soc scripts. - Fix rdata timing bug in axi2iob module. - Update vexriscv submodule. --- .../buses/axi2iob/hardware/src/axi2iob.v | 16 +++++++++++++++- .../axi_interconnect_wrapper.py | 4 +++- scripts/iob_soc_utils.py | 16 +++++++++++++--- submodules/BOOTROM/iob_bootrom.py | 2 +- submodules/BOOTROM/software/src/iob_soc_boot.lds | 2 +- .../BOOTROM/software/src/iob_soc_preboot.S | 6 +++--- submodules/VEXRISCV | 2 +- 7 files changed, 37 insertions(+), 11 deletions(-) diff --git a/lib/hardware/buses/axi2iob/hardware/src/axi2iob.v b/lib/hardware/buses/axi2iob/hardware/src/axi2iob.v index 2e2230bfd..3a84df5e0 100644 --- a/lib/hardware/buses/axi2iob/hardware/src/axi2iob.v +++ b/lib/hardware/buses/axi2iob/hardware/src/axi2iob.v @@ -100,6 +100,7 @@ module axi2iob #( // AXI4-Lite interface to IOb // wire iob_rvalid_q; + wire [DATA_WIDTH-1:0] iob_rdata_q; wire iob_rvalid_e; wire write_enable; wire [ADDR_WIDTH-1:0] m_axil_awaddr_q; @@ -121,7 +122,7 @@ module axi2iob #( // // read address assign m_axil_arready = iob_ready_i; // // read - assign m_axil_rdata = iob_rdata_i; + assign m_axil_rdata = iob_rvalid_i ? iob_rdata_i : iob_rdata_q; assign m_axil_rresp = 2'b0; assign m_axil_rvalid = iob_rvalid_i ? 1'b1 : iob_rvalid_q; @@ -157,6 +158,19 @@ module axi2iob #( .data_o(iob_rvalid_q) ); + iob_reg_re #( + .DATA_W (DATA_WIDTH), + .RST_VAL(0) + ) iob_reg_rdata ( + .clk_i (clk_i), + .arst_i(arst_i), + .cke_i (cke_i), + .rst_i (1'b0), + .en_i (iob_rvalid_e), + .data_i(iob_rdata_i), + .data_o(iob_rdata_q) + ); + iob_reg_re #( .DATA_W (1), .RST_VAL(0) diff --git a/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py b/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py index 303bb2b8f..7764e9bc4 100644 --- a/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py +++ b/lib/hardware/buses/axi_interconnect_wrapper/axi_interconnect_wrapper.py @@ -164,7 +164,9 @@ def setup(py_params_dict): except ValueError: width_str = width master_addr_w_parameter = f"{width_str}," + master_addr_w_parameter - master_addr_w_parameter = "{" + master_addr_w_parameter[:-1] + "}" + master_addr_w_parameter = master_addr_w_parameter[:-1] + if len(MASTERS) > 1: + master_addr_w_parameter = "{" + master_addr_w_parameter + "}" attributes_dict["ports"] += slave_axi_ports + master_axi_ports # # Wires diff --git a/scripts/iob_soc_utils.py b/scripts/iob_soc_utils.py index 333ed8f79..232d76cd1 100644 --- a/scripts/iob_soc_utils.py +++ b/scripts/iob_soc_utils.py @@ -66,7 +66,12 @@ def generate_peripheral_base_addresses( if os.path.isfile(out_file): return - n_slaves_w = (len(peripherals_list) - 1).bit_length() + # Include CLINT and PLIC in peripherals list + complete_peripherals_list = peripherals_list + [ + {"instance_name": "CLINT0"}, + {"instance_name": "PLIC0"}, + ] + n_slaves_w = (len(complete_peripherals_list) - 1).bit_length() # Don't create files for other targets (like clean) if "py2hwsw_target" not in py_params or py_params["py2hwsw_target"] != "setup": @@ -74,7 +79,7 @@ def generate_peripheral_base_addresses( os.makedirs(os.path.dirname(out_file), exist_ok=True) with open(out_file, "w") as f: - for idx, instance in enumerate(peripherals_list): + for idx, instance in enumerate(complete_peripherals_list): instance_name = instance["instance_name"] f.write( f"#define {instance_name}_BASE (PBUS_BASE + ({idx}<<(P_BIT-{n_slaves_w})))\n" @@ -155,9 +160,14 @@ def generate_makefile_segments(attributes_dict, peripherals, params, py_params): ) # - # Create auto_iob_soc_firmware.lds + # Create auto_iob_soc_boot.lds and auto_iob_soc_firmware.lds # os.makedirs(f"{build_dir}/software", exist_ok=True) + with open(f"{build_dir}/software/auto_iob_soc_boot.lds", "w") as file: + file.write("/* This file was auto generated by iob_soc_utils.py */\n") + file.write( + f". = {hex((1 << params['mem_addr_w']) - (1 << params['bootrom_addr_w']))};\n" + ) with open(f"{build_dir}/software/auto_iob_soc_firmware.lds", "w") as file: file.write("/* This file was auto generated by iob_soc_utils.py */\n") file.write(f". = {params['fw_addr']};\n") diff --git a/submodules/BOOTROM/iob_bootrom.py b/submodules/BOOTROM/iob_bootrom.py index e7c319ee9..efd3cdb23 100644 --- a/submodules/BOOTROM/iob_bootrom.py +++ b/submodules/BOOTROM/iob_bootrom.py @@ -199,7 +199,7 @@ def setup(py_params_dict): { "verilog_code": f""" assign ext_rom_en_o = rom_ren_rd; - assign ext_rom_addr_o = csrs_iob_addr[{BOOTROM_ADDR_W}:2]; + assign ext_rom_addr_o = csrs_iob_addr[{BOOTROM_ADDR_W}-1:2]; assign rom_rdata_rd = ext_rom_rdata_i; assign rom_rready_rd = 1'b1; // ROM is always ready """, diff --git a/submodules/BOOTROM/software/src/iob_soc_boot.lds b/submodules/BOOTROM/software/src/iob_soc_boot.lds index 23428b27a..4dfdb41c0 100644 --- a/submodules/BOOTROM/software/src/iob_soc_boot.lds +++ b/submodules/BOOTROM/software/src/iob_soc_boot.lds @@ -1,6 +1,6 @@ SECTIONS { /* Program code */ - . = 0x00FFF000; + INCLUDE auto_iob_soc_boot.lds .init : { *(.init) } .text : { *(.text) } diff --git a/submodules/BOOTROM/software/src/iob_soc_preboot.S b/submodules/BOOTROM/software/src/iob_soc_preboot.S index 18b85c14a..6bb9f80ee 100644 --- a/submodules/BOOTROM/software/src/iob_soc_preboot.S +++ b/submodules/BOOTROM/software/src/iob_soc_preboot.S @@ -4,9 +4,9 @@ // Can't include iob_bootrom_swreg.h because the assembler doesn't recognize stdint.h, // so define the constants here instead (these are address offsets). -#define IOB_BOOTROM_ROM_ADDR 0 +#define IOB_BOOTROM_ROM_ADDR 0x80 -#define LENGTH (1 << IOB_SOC_BOOTROM_ADDR_W) +#define LENGTH ((1 << IOB_SOC_BOOTROM_ADDR_W) - IOB_BOOTROM_ROM_ADDR) #define BOOTROM (BOOTROM0_BASE + IOB_BOOTROM_ROM_ADDR) #define BOOTLDR_ADDR ((1 << IOB_SOC_MEM_ADDR_W) - (1 << IOB_SOC_BOOTROM_ADDR_W)) @@ -23,7 +23,7 @@ copy_loop: sw x4, 0(x3) addi x2, x2, 4 addi x3, x3, 4 - addi x1, x1, -1 + addi x1, x1, -4 bne x1, x0, copy_loop // Jump to the bootloader diff --git a/submodules/VEXRISCV b/submodules/VEXRISCV index dc1971cf0..cd04902c3 160000 --- a/submodules/VEXRISCV +++ b/submodules/VEXRISCV @@ -1 +1 @@ -Subproject commit dc1971cf07a99e1776042a382b778f3c7f449ddb +Subproject commit cd04902c3eba2426117140d61c0805151ccd190a From 7df9aadeb2b1870f588f1a1cb608ade1dcd1445a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Tue, 10 Sep 2024 01:41:04 +0100 Subject: [PATCH 09/12] feat(ci): Remove unused CACHE test. IOb-SoC no longer uses iob-cache. --- .github/workflows/ci.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef01f39a6..505d74fb9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,22 +99,6 @@ jobs: - name: run LIB test run: nix-shell --run "make -C lib sim-test" - cache: - runs-on: self-hosted - timeout-minutes: 20 - if: ${{ !cancelled() }} - needs: [ cyclonev ] - - steps: - - uses: actions/checkout@v4 - with: - submodules: 'recursive' - - name: Clean untracked files and directories (like old submodules) - run: git clean -ffdx - - name: run simulation test - run: make -C submodules/CACHE sim-test - - name: run fpga test - run: make -C submodules/CACHE fpga-test doc: runs-on: self-hosted timeout-minutes: 60 From d8d6abfcfeabdf82c6421686d435591423b49bb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Tue, 10 Sep 2024 01:57:54 +0100 Subject: [PATCH 10/12] fix(bugs): Fix fpga depedencies; pc-emul sources; axi_ram; Update py2hwsw. --- hardware/fpga/fpga_build.mk | 4 ++-- lib/hardware/memories/axi_ram/axi_ram.py | 5 +++++ lib/scripts/default.nix | 4 ++-- software/sw_build.mk | 3 ++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/hardware/fpga/fpga_build.mk b/hardware/fpga/fpga_build.mk index 3c65ddd7d..f3c07d33a 100644 --- a/hardware/fpga/fpga_build.mk +++ b/hardware/fpga/fpga_build.mk @@ -1,9 +1,9 @@ include auto_fpga_build.mk # Add iob-soc software as a build dependency -RUN_DEPS+=iob_soc_preboot.hex iob_soc_boot.hex iob_soc_firmware.hex +RUN_DEPS+=iob_soc_bootrom.hex iob_soc_firmware.hex # Don't add firmware to BUILD_DEPS if we are not initializing memory since we don't want to rebuild the bitstream when we modify it. -BUILD_DEPS+=iob_soc_preboot.hex iob_soc_boot.hex $(if $(filter $(INIT_MEM),1),iob_soc_firmware.hex) +BUILD_DEPS+=iob_soc_bootrom.hex $(if $(filter $(INIT_MEM),1),iob_soc_firmware.hex) QUARTUS_SEED ?=5 diff --git a/lib/hardware/memories/axi_ram/axi_ram.py b/lib/hardware/memories/axi_ram/axi_ram.py index f8edcd949..14407f84a 100644 --- a/lib/hardware/memories/axi_ram/axi_ram.py +++ b/lib/hardware/memories/axi_ram/axi_ram.py @@ -114,6 +114,11 @@ def setup(py_params_dict): "descr": "AXI interface", }, ], + "blocks": [ + { + "core_name": "iob_ram_sp", + }, + ], } return attributes_dict diff --git a/lib/scripts/default.nix b/lib/scripts/default.nix index 99eba124f..c622abca2 100644 --- a/lib/scripts/default.nix +++ b/lib/scripts/default.nix @@ -1,8 +1,8 @@ { pkgs ? import {} }: let - py2hwsw_commit = "24f47ac357b6232df07a4adeb021202adde57278"; # Replace with the desired commit. - py2hwsw_sha256 = "qY/eg+CoEAri3KvMoLRJRaMvu66Ao5lDLigBNnQUgro="; # Replace with the actual SHA256 hash. + py2hwsw_commit = "4d51b94283522d53f1c3c293efda1fc9c180ae3d"; # Replace with the desired commit. + py2hwsw_sha256 = "X5jjz014jxpOh0rK7rOrvpTIvIcdX2QgU6JEaKjWTsI="; # Replace with the actual SHA256 hash. py2hwsw = pkgs.python3.pkgs.buildPythonPackage rec { pname = "py2hwsw"; diff --git a/software/sw_build.mk b/software/sw_build.mk index 989935262..b4a642f6b 100644 --- a/software/sw_build.mk +++ b/software/sw_build.mk @@ -76,5 +76,6 @@ EMUL_SRC+=src/iob_soc_firmware.c EMUL_SRC+=src/printf.c # PERIPHERAL SOURCES -EMUL_SRC+=$(wildcard src/iob-*.c) +EMUL_SRC+=$(addprefix src/,$(addsuffix .c,$(PERIPHERALS))) +EMUL_SRC+=$(addprefix src/,$(addsuffix _csrs_pc_emul.c,$(PERIPHERALS))) From 265c1d9dea4557c5bb5ac2d16ee2a1b2c040e1a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Tue, 10 Sep 2024 02:17:56 +0100 Subject: [PATCH 11/12] fix(vivado): Add missing include for axi_ram.v source --- hardware/fpga/vivado/vivado_premap.tcl | 1 + 1 file changed, 1 insertion(+) diff --git a/hardware/fpga/vivado/vivado_premap.tcl b/hardware/fpga/vivado/vivado_premap.tcl index c6be31d5d..7a7785712 100644 --- a/hardware/fpga/vivado/vivado_premap.tcl +++ b/hardware/fpga/vivado/vivado_premap.tcl @@ -86,5 +86,6 @@ if { $USE_EXTMEM > 0 } { read_verilog vivado/$BOARD/clock_wizard.v read_verilog vivado/$BOARD/iob_reset_sync.v read_verilog vivado/$BOARD/iob_r.v + read_verilog vivado/$BOARD/axi_ram.v } From a9a91b14e77992e721045a7dad74d970ca81b953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20N=C3=B3brega?= Date: Tue, 10 Sep 2024 03:22:32 +0100 Subject: [PATCH 12/12] feat(axi_ram): Update axi_ram source to remove SystemVerilog syntax. --- .../memories/axi_ram/hardware/src/axi_ram.v | 722 +++++++++--------- 1 file changed, 363 insertions(+), 359 deletions(-) diff --git a/lib/hardware/memories/axi_ram/hardware/src/axi_ram.v b/lib/hardware/memories/axi_ram/hardware/src/axi_ram.v index ab0fff809..2473777ad 100644 --- a/lib/hardware/memories/axi_ram/hardware/src/axi_ram.v +++ b/lib/hardware/memories/axi_ram/hardware/src/axi_ram.v @@ -38,379 +38,383 @@ Changes made (2023 Pedro Antunes): * AXI4 RAM */ module axi_ram #( - parameter DATA_WIDTH = 32, - parameter ADDR_WIDTH = 16, - parameter STRB_WIDTH = (DATA_WIDTH / 8), - parameter READ_ON_WRITE = 1, - // Width of AXI signals - parameter ID_WIDTH = 8, - parameter LEN_WIDTH = 8, - // Extra pipeline register on output - parameter PIPELINE_OUTPUT = 0, - // File with which to preload RAM - parameter FILE = "none" + parameter DATA_WIDTH = 32, + parameter ADDR_WIDTH = 16, + parameter STRB_WIDTH = (DATA_WIDTH / 8), + parameter READ_ON_WRITE = 1, + // Width of AXI signals + parameter ID_WIDTH = 8, + parameter LEN_WIDTH = 8, + // Extra pipeline register on output + parameter PIPELINE_OUTPUT = 0, + // File with which to preload RAM + parameter FILE = "none" ) ( - input wire clk_i, - input wire rst_i, - - input wire [ ID_WIDTH-1:0] axi_awid_i, - input wire [ADDR_WIDTH-1:0] axi_awaddr_i, - input wire [ LEN_WIDTH-1:0] axi_awlen_i, - input wire [ 2:0] axi_awsize_i, - input wire [ 1:0] axi_awburst_i, - input wire [ 1:0] axi_awlock_i, - input wire [ 3:0] axi_awcache_i, - input wire [ 2:0] axi_awprot_i, - input wire [ 3:0] axi_awqos_i, - input wire axi_awvalid_i, - output wire axi_awready_o, - - input wire [DATA_WIDTH-1:0] axi_wdata_i, - input wire [STRB_WIDTH-1:0] axi_wstrb_i, - input wire axi_wlast_i, - input wire axi_wvalid_i, - output wire axi_wready_o, - - output wire [ ID_WIDTH-1:0] axi_bid_o, - output wire [ 1:0] axi_bresp_o, - output wire axi_bvalid_o, - input wire axi_bready_i, - input wire [ ID_WIDTH-1:0] axi_arid_i, - input wire [ADDR_WIDTH-1:0] axi_araddr_i, - input wire [ LEN_WIDTH-1:0] axi_arlen_i, - input wire [ 2:0] axi_arsize_i, - input wire [ 1:0] axi_arburst_i, - input wire [ 1:0] axi_arlock_i, - input wire [ 3:0] axi_arcache_i, - input wire [ 2:0] axi_arprot_i, - input wire [ 3:0] axi_arqos_i, - input wire axi_arvalid_i, - output wire axi_arready_o, - output wire [ ID_WIDTH-1:0] axi_rid_o, - output wire [DATA_WIDTH-1:0] axi_rdata_o, - output wire [ 1:0] axi_rresp_o, - output wire axi_rlast_o, - output wire axi_rvalid_o, - input wire axi_rready_i + input wire clk_i, + input wire rst_i, + + input wire [ ID_WIDTH-1:0] axi_awid_i, + input wire [ADDR_WIDTH-1:0] axi_awaddr_i, + input wire [ LEN_WIDTH-1:0] axi_awlen_i, + input wire [ 2:0] axi_awsize_i, + input wire [ 1:0] axi_awburst_i, + input wire [ 1:0] axi_awlock_i, + input wire [ 3:0] axi_awcache_i, + input wire [ 2:0] axi_awprot_i, + input wire [ 3:0] axi_awqos_i, + input wire axi_awvalid_i, + output wire axi_awready_o, + + input wire [DATA_WIDTH-1:0] axi_wdata_i, + input wire [STRB_WIDTH-1:0] axi_wstrb_i, + input wire axi_wlast_i, + input wire axi_wvalid_i, + output wire axi_wready_o, + + output wire [ ID_WIDTH-1:0] axi_bid_o, + output wire [ 1:0] axi_bresp_o, + output wire axi_bvalid_o, + input wire axi_bready_i, + input wire [ ID_WIDTH-1:0] axi_arid_i, + input wire [ADDR_WIDTH-1:0] axi_araddr_i, + input wire [ LEN_WIDTH-1:0] axi_arlen_i, + input wire [ 2:0] axi_arsize_i, + input wire [ 1:0] axi_arburst_i, + input wire [ 1:0] axi_arlock_i, + input wire [ 3:0] axi_arcache_i, + input wire [ 2:0] axi_arprot_i, + input wire [ 3:0] axi_arqos_i, + input wire axi_arvalid_i, + output wire axi_arready_o, + output wire [ ID_WIDTH-1:0] axi_rid_o, + output wire [DATA_WIDTH-1:0] axi_rdata_o, + output wire [ 1:0] axi_rresp_o, + output wire axi_rlast_o, + output wire axi_rvalid_o, + input wire axi_rready_i ); - localparam VALID_ADDR_WIDTH = ADDR_WIDTH - $clog2(STRB_WIDTH); - localparam WORD_WIDTH = STRB_WIDTH; - localparam WORD_SIZE = DATA_WIDTH / WORD_WIDTH; - - // bus width assertions - initial begin - if (WORD_SIZE * STRB_WIDTH != DATA_WIDTH) begin - $error("Error: AXI data width not evenly divisble (instance %m)"); - $finish(); - end - - if (2 ** $clog2(WORD_WIDTH) != WORD_WIDTH) begin - $error("Error: AXI word width must be even power of two (instance %m)"); - $finish(); - end - end - - localparam [0:0] READ_STATE_IDLE = 1'd0, READ_STATE_BURST = 1'd1; - - reg [0:0] read_state_reg, read_state_next; - - localparam [1:0] WRITE_STATE_IDLE = 2'd0, WRITE_STATE_BURST = 2'd1, WRITE_STATE_RESP = 2'd2; - - reg [1:0] write_state_reg, write_state_next; - - reg mem_wr_en; - - reg [ID_WIDTH-1:0] read_id_reg, read_id_next; - reg [ADDR_WIDTH-1:0] read_addr_reg, read_addr_next; - reg [LEN_WIDTH-1:0] read_count_reg, read_count_next; - reg [2:0] read_size_reg, read_size_next; - reg [1:0] read_burst_reg, read_burst_next; - reg [ID_WIDTH-1:0] write_id_reg, write_id_next; - reg [ADDR_WIDTH-1:0] write_addr_reg, write_addr_next; - reg [LEN_WIDTH-1:0] write_count_reg, write_count_next; - reg [2:0] write_size_reg, write_size_next; - reg [1:0] write_burst_reg, write_burst_next; - - reg axi_awready_reg, axi_awready_next; - reg axi_wready_reg, axi_wready_next; - reg [ID_WIDTH-1:0] axi_bid_reg, axi_bid_next; - reg axi_bvalid_reg, axi_bvalid_next; - reg axi_arready_reg, axi_arready_next; - reg [ID_WIDTH-1:0] axi_rid_reg, axi_rid_next; - reg [DATA_WIDTH-1:0] axi_rdata_reg, axi_rdata_next; - reg axi_rlast_reg, axi_rlast_next; - reg axi_rvalid_reg, axi_rvalid_next; - reg [ID_WIDTH-1:0] axi_rid_pipe_reg; - reg [DATA_WIDTH-1:0] axi_rdata_pipe_reg; - reg axi_rlast_pipe_reg; - reg axi_rvalid_pipe_reg; - - // (* RAM_STYLE="BLOCK" *) - reg [DATA_WIDTH-1:0] mem[2**VALID_ADDR_WIDTH]; - - wire [VALID_ADDR_WIDTH-1:0] axi_awaddr_valid = axi_awaddr_i >> (ADDR_WIDTH - VALID_ADDR_WIDTH); - wire [VALID_ADDR_WIDTH-1:0] axi_araddr_valid = axi_araddr_i >> (ADDR_WIDTH - VALID_ADDR_WIDTH); - wire [VALID_ADDR_WIDTH-1:0] read_addr_valid = read_addr_reg >> (ADDR_WIDTH - VALID_ADDR_WIDTH); - wire [VALID_ADDR_WIDTH-1:0] write_addr_valid = write_addr_reg >> (ADDR_WIDTH - VALID_ADDR_WIDTH); - - assign axi_awready_o = axi_awready_reg; - assign axi_wready_o = axi_wready_reg; - assign axi_bid_o = axi_bid_reg; - assign axi_bresp_o = 2'b00; - assign axi_bvalid_o = axi_bvalid_reg; - assign axi_arready_o = axi_arready_reg; - assign axi_rid_o = PIPELINE_OUTPUT ? axi_rid_pipe_reg : axi_rid_reg; - assign axi_rdata_o = PIPELINE_OUTPUT ? axi_rdata_pipe_reg : axi_rdata_reg; - assign axi_rresp_o = 2'b00; - assign axi_rlast_o = PIPELINE_OUTPUT ? axi_rlast_pipe_reg : axi_rlast_reg; - assign axi_rvalid_o = PIPELINE_OUTPUT ? axi_rvalid_pipe_reg : axi_rvalid_reg; - - generate - genvar i; - if (READ_ON_WRITE) begin : g_always_read - localparam mem_init_file_int = {FILE, ".hex"}; - initial begin - if (FILE != "none") begin - $readmemh(mem_init_file_int, mem, 0, 2 ** VALID_ADDR_WIDTH - 1); - end + localparam VALID_ADDR_WIDTH = ADDR_WIDTH - $clog2(STRB_WIDTH); + localparam WORD_WIDTH = STRB_WIDTH; + localparam WORD_SIZE = DATA_WIDTH / WORD_WIDTH; + + // bus width assertions + initial begin + if (WORD_SIZE * STRB_WIDTH != DATA_WIDTH) begin + $error("Error: AXI data width not evenly divisble (instance %m)"); + $finish(); end - for (i = 0; i < WORD_WIDTH; i = i + 1) begin : g_Bytes_in_word - always @(posedge clk_i) begin - if (mem_wr_en & axi_wstrb_i[i]) begin - mem[write_addr_valid][WORD_SIZE*i+:WORD_SIZE] <= axi_wdata_i[WORD_SIZE*i+:WORD_SIZE]; - end - axi_rdata_reg[WORD_SIZE*i+:WORD_SIZE] <= mem[read_addr_valid][WORD_SIZE*i+:WORD_SIZE]; - end + + if (2 ** $clog2(WORD_WIDTH) != WORD_WIDTH) begin + $error("Error: AXI word width must be even power of two (instance %m)"); + $finish(); end - end else begin : g_no_read_on_write - localparam file_suffix = {"7", "6", "5", "4", "3", "2", "1", "0"}; - wire [VALID_ADDR_WIDTH-1:0] ram_addr_valid; - wire [WORD_WIDTH-1:0] ram_en; - assign ram_addr_valid = mem_wr_en ? write_addr_valid : read_addr_valid; - for (i = 0; i < WORD_WIDTH; i = i + 1) begin : g_Bytes_in_word - localparam mem_init_file_int = (FILE != "none") ? + end + + localparam [0:0] READ_STATE_IDLE = 1'd0, READ_STATE_BURST = 1'd1; + + reg [0:0] read_state_reg, read_state_next; + + localparam [1:0] WRITE_STATE_IDLE = 2'd0, WRITE_STATE_BURST = 2'd1, WRITE_STATE_RESP = 2'd2; + + reg [1:0] write_state_reg, write_state_next; + + reg mem_wr_en; + + reg [ID_WIDTH-1:0] read_id_reg, read_id_next; + reg [ADDR_WIDTH-1:0] read_addr_reg, read_addr_next; + reg [LEN_WIDTH-1:0] read_count_reg, read_count_next; + reg [2:0] read_size_reg, read_size_next; + reg [1:0] read_burst_reg, read_burst_next; + reg [ID_WIDTH-1:0] write_id_reg, write_id_next; + reg [ADDR_WIDTH-1:0] write_addr_reg, write_addr_next; + reg [LEN_WIDTH-1:0] write_count_reg, write_count_next; + reg [2:0] write_size_reg, write_size_next; + reg [1:0] write_burst_reg, write_burst_next; + + reg axi_awready_reg, axi_awready_next; + reg axi_wready_reg, axi_wready_next; + reg [ID_WIDTH-1:0] axi_bid_reg, axi_bid_next; + reg axi_bvalid_reg, axi_bvalid_next; + reg axi_arready_reg, axi_arready_next; + reg [ID_WIDTH-1:0] axi_rid_reg, axi_rid_next; + reg [DATA_WIDTH-1:0] axi_rdata_reg, axi_rdata_next; + reg axi_rlast_reg, axi_rlast_next; + reg axi_rvalid_reg, axi_rvalid_next; + reg [ID_WIDTH-1:0] axi_rid_pipe_reg; + reg [DATA_WIDTH-1:0] axi_rdata_pipe_reg; + reg axi_rlast_pipe_reg; + reg axi_rvalid_pipe_reg; + + // (* RAM_STYLE="BLOCK" *) + reg [DATA_WIDTH-1:0] mem[2**VALID_ADDR_WIDTH-1:0]; + + wire [VALID_ADDR_WIDTH-1:0] axi_awaddr_valid = axi_awaddr_i >> (ADDR_WIDTH - VALID_ADDR_WIDTH); + wire [VALID_ADDR_WIDTH-1:0] axi_araddr_valid = axi_araddr_i >> (ADDR_WIDTH - VALID_ADDR_WIDTH); + wire [VALID_ADDR_WIDTH-1:0] read_addr_valid = read_addr_reg >> (ADDR_WIDTH - VALID_ADDR_WIDTH); + wire [VALID_ADDR_WIDTH-1:0] write_addr_valid = write_addr_reg >> (ADDR_WIDTH - VALID_ADDR_WIDTH); + + assign axi_awready_o = axi_awready_reg; + assign axi_wready_o = axi_wready_reg; + assign axi_bid_o = axi_bid_reg; + assign axi_bresp_o = 2'b00; + assign axi_bvalid_o = axi_bvalid_reg; + assign axi_arready_o = axi_arready_reg; + assign axi_rid_o = PIPELINE_OUTPUT ? axi_rid_pipe_reg : axi_rid_reg; + assign axi_rdata_o = PIPELINE_OUTPUT ? axi_rdata_pipe_reg : axi_rdata_reg; + assign axi_rresp_o = 2'b00; + assign axi_rlast_o = PIPELINE_OUTPUT ? axi_rlast_pipe_reg : axi_rlast_reg; + assign axi_rvalid_o = PIPELINE_OUTPUT ? axi_rvalid_pipe_reg : axi_rvalid_reg; + + generate + genvar i; + if (READ_ON_WRITE) begin : g_always_read + localparam mem_init_file_int = {FILE, ".hex"}; + initial begin + if (FILE != "none") begin + $readmemh(mem_init_file_int, mem, 0, 2 ** VALID_ADDR_WIDTH - 1); + end + end + for (i = 0; i < WORD_WIDTH; i = i + 1) begin : g_Bytes_in_word + always @(posedge clk_i) begin + if (mem_wr_en & axi_wstrb_i[i]) begin + mem[write_addr_valid][WORD_SIZE*i+:WORD_SIZE] <= axi_wdata_i[WORD_SIZE*i+:WORD_SIZE]; + end + axi_rdata_reg[WORD_SIZE*i+:WORD_SIZE] <= mem[read_addr_valid][WORD_SIZE*i+:WORD_SIZE]; + end + end + end else begin : g_no_read_on_write + localparam file_suffix = {"7", "6", "5", "4", "3", "2", "1", "0"}; + wire [VALID_ADDR_WIDTH-1:0] ram_addr_valid; + wire [ WORD_WIDTH-1:0] ram_en; + assign ram_addr_valid = mem_wr_en ? write_addr_valid : read_addr_valid; + for (i = 0; i < WORD_WIDTH; i = i + 1) begin : g_Bytes_in_word + localparam mem_init_file_int = (FILE != "none") ? {FILE, "_", file_suffix[8*(i+1)-1-:8], ".hex"} : "none"; - assign ram_en[i] = mem_wr_en ? axi_wstrb_i[i] : 1'b1; - - iob_ram_sp #( - .HEXFILE(mem_init_file_int), - .ADDR_W (VALID_ADDR_WIDTH), - .DATA_W (WORD_SIZE) - ) ram ( - .clk_i(clk_i), - - .en_i (ram_en[i]), - .addr_i(ram_addr_valid), - .d_i (axi_wdata_i[WORD_SIZE*i+:WORD_SIZE]), - .we_i (mem_wr_en), - .d_o (axi_rdata_reg[WORD_SIZE*i+:WORD_SIZE]) - ); - end - end - endgenerate - - always_comb begin - write_state_next = WRITE_STATE_IDLE; - - mem_wr_en = 1'b0; - - write_id_next = write_id_reg; - write_addr_next = write_addr_reg; - write_count_next = write_count_reg; - write_size_next = write_size_reg; - write_burst_next = write_burst_reg; - - axi_awready_next = 1'b0; - axi_wready_next = 1'b0; - axi_bid_next = axi_bid_reg; - axi_bvalid_next = axi_bvalid_reg && !axi_bready_i; - - case (write_state_reg) - WRITE_STATE_IDLE: begin - axi_awready_next = 1'b1; - - if (axi_awready_o && axi_awvalid_i) begin - write_id_next = axi_awid_i; - write_addr_next = axi_awaddr_i; - write_count_next = axi_awlen_i; - write_size_next = axi_awsize_i < $clog2(STRB_WIDTH) ? axi_awsize_i : $clog2(STRB_WIDTH); - write_burst_next = axi_awburst_i; - - axi_awready_next = 1'b0; - axi_wready_next = 1'b1; - write_state_next = WRITE_STATE_BURST; - end else begin - write_state_next = WRITE_STATE_IDLE; - end + assign ram_en[i] = mem_wr_en ? axi_wstrb_i[i] : 1'b1; + + iob_ram_sp #( + .HEXFILE(mem_init_file_int), + .ADDR_W (VALID_ADDR_WIDTH), + .DATA_W (WORD_SIZE) + ) ram ( + .clk_i(clk_i), + + .en_i (ram_en[i]), + .addr_i(ram_addr_valid), + .d_i (axi_wdata_i[WORD_SIZE*i+:WORD_SIZE]), + .we_i (mem_wr_en), + .d_o (axi_rdata_reg[WORD_SIZE*i+:WORD_SIZE]) + ); + end end - WRITE_STATE_BURST: begin - axi_wready_next = 1'b1; - - if (axi_wready_o && axi_wvalid_i) begin - mem_wr_en = 1'b1; - if (write_burst_reg != 2'b00) begin - write_addr_next = write_addr_reg + (1 << write_size_reg); - end - write_count_next = write_count_reg - 1; - if (write_count_reg > 0) begin - write_state_next = WRITE_STATE_BURST; - end else begin - axi_wready_next = 1'b0; + endgenerate + + // always_comb in SystemVerilog + always @(*) begin + write_state_next = WRITE_STATE_IDLE; + + mem_wr_en = 1'b0; + + write_id_next = write_id_reg; + write_addr_next = write_addr_reg; + write_count_next = write_count_reg; + write_size_next = write_size_reg; + write_burst_next = write_burst_reg; + + axi_awready_next = 1'b0; + axi_wready_next = 1'b0; + axi_bid_next = axi_bid_reg; + axi_bvalid_next = axi_bvalid_reg && !axi_bready_i; + + case (write_state_reg) + WRITE_STATE_IDLE: begin + axi_awready_next = 1'b1; + + if (axi_awready_o && axi_awvalid_i) begin + write_id_next = axi_awid_i; + write_addr_next = axi_awaddr_i; + write_count_next = axi_awlen_i; + write_size_next = axi_awsize_i < $clog2(STRB_WIDTH) ? axi_awsize_i : + $clog2(STRB_WIDTH); + write_burst_next = axi_awburst_i; + + axi_awready_next = 1'b0; + axi_wready_next = 1'b1; + write_state_next = WRITE_STATE_BURST; + end else begin + write_state_next = WRITE_STATE_IDLE; + end + end + WRITE_STATE_BURST: begin + axi_wready_next = 1'b1; + + if (axi_wready_o && axi_wvalid_i) begin + mem_wr_en = 1'b1; + if (write_burst_reg != 2'b00) begin + write_addr_next = write_addr_reg + (1 << write_size_reg); + end + write_count_next = write_count_reg - 1; + if (write_count_reg > 0) begin + write_state_next = WRITE_STATE_BURST; + end else begin + axi_wready_next = 1'b0; + if (axi_bready_i || !axi_bvalid_o) begin + axi_bid_next = write_id_reg; + axi_bvalid_next = 1'b1; + axi_awready_next = 1'b1; + write_state_next = WRITE_STATE_IDLE; + end else begin + write_state_next = WRITE_STATE_RESP; + end + end + end else begin + write_state_next = WRITE_STATE_BURST; + end + end + WRITE_STATE_RESP: begin if (axi_bready_i || !axi_bvalid_o) begin - axi_bid_next = write_id_reg; - axi_bvalid_next = 1'b1; - axi_awready_next = 1'b1; - write_state_next = WRITE_STATE_IDLE; + axi_bid_next = write_id_reg; + axi_bvalid_next = 1'b1; + axi_awready_next = 1'b1; + write_state_next = WRITE_STATE_IDLE; end else begin - write_state_next = WRITE_STATE_RESP; + write_state_next = WRITE_STATE_RESP; end - end - end else begin - write_state_next = WRITE_STATE_BURST; - end - end - WRITE_STATE_RESP: begin - if (axi_bready_i || !axi_bvalid_o) begin - axi_bid_next = write_id_reg; - axi_bvalid_next = 1'b1; - axi_awready_next = 1'b1; - write_state_next = WRITE_STATE_IDLE; - end else begin - write_state_next = WRITE_STATE_RESP; - end - end - default: ; - endcase - end - - always @(posedge clk_i, posedge rst_i) begin - if (rst_i) begin - write_state_reg <= WRITE_STATE_IDLE; - axi_awready_reg <= 1'b0; - axi_wready_reg <= 1'b0; - axi_bvalid_reg <= 1'b0; - - write_id_reg <= {ID_WIDTH{1'b0}}; - write_addr_reg <= {ADDR_WIDTH{1'b0}}; - write_count_reg <= {LEN_WIDTH{1'b0}}; - write_size_reg <= 3'd0; - write_burst_reg <= 2'd0; - - axi_bid_reg <= {ID_WIDTH{1'b0}}; - end else begin - write_state_reg <= write_state_next; - axi_awready_reg <= axi_awready_next; - axi_wready_reg <= axi_wready_next; - axi_bvalid_reg <= axi_bvalid_next; - - write_id_reg <= write_id_next; - write_addr_reg <= write_addr_next; - write_count_reg <= write_count_next; - write_size_reg <= write_size_next; - write_burst_reg <= write_burst_next; - - axi_bid_reg <= axi_bid_next; - end - end - - always_comb begin - read_state_next = READ_STATE_IDLE; - - axi_rid_next = axi_rid_reg; - axi_rlast_next = axi_rlast_reg; - axi_rvalid_next = axi_rvalid_reg && !(axi_rready_i || (PIPELINE_OUTPUT && !axi_rvalid_pipe_reg)); - - read_id_next = read_id_reg; - read_addr_next = read_addr_reg; - read_count_next = read_count_reg; - read_size_next = read_size_reg; - read_burst_next = read_burst_reg; - - axi_arready_next = 1'b0; - - case (read_state_reg) - READ_STATE_IDLE: begin - axi_arready_next = 1'b1; - - if (axi_arready_o && axi_arvalid_i) begin - read_id_next = axi_arid_i; - read_addr_next = axi_araddr_i; - read_count_next = axi_arlen_i; - read_size_next = axi_arsize_i < $clog2(STRB_WIDTH) ? axi_arsize_i : $clog2(STRB_WIDTH); - read_burst_next = axi_arburst_i; - - axi_arready_next = 1'b0; - read_state_next = READ_STATE_BURST; - end else begin - read_state_next = READ_STATE_IDLE; - end - end - READ_STATE_BURST: begin - if (axi_rready_i || (PIPELINE_OUTPUT && !axi_rvalid_pipe_reg) || !axi_rvalid_reg) begin - axi_rvalid_next = 1'b1; - axi_rid_next = read_id_reg; - axi_rlast_next = read_count_reg == 0; - if (read_burst_reg != 2'b00) begin - read_addr_next = read_addr_reg + (1 << read_size_reg); - end - read_count_next = read_count_reg - 1; - if (read_count_reg > 0) begin - read_state_next = READ_STATE_BURST; - end else begin - axi_arready_next = 1'b1; - read_state_next = READ_STATE_IDLE; - end - end else begin - read_state_next = READ_STATE_BURST; - end - end // case: READ_STATE_BURST - default: ; - endcase - end - - always @(posedge clk_i, posedge rst_i) begin - if (rst_i) begin - read_state_reg <= READ_STATE_IDLE; - axi_arready_reg <= 1'b0; - axi_rvalid_reg <= 1'b0; - axi_rvalid_pipe_reg <= 1'b0; - - read_id_reg <= {ID_WIDTH{1'b0}}; - read_addr_reg <= {ADDR_WIDTH{1'b0}}; - read_count_reg <= 0; - read_size_reg <= 3'd0; - read_burst_reg <= 2'd0; - - axi_rid_reg <= {ID_WIDTH{1'b0}}; - axi_rlast_reg <= 1'b0; - axi_rid_pipe_reg <= {ID_WIDTH{1'b0}}; - axi_rdata_pipe_reg <= {DATA_WIDTH{1'b0}}; - axi_rlast_pipe_reg <= 1'b0; - end else begin - read_state_reg <= read_state_next; - axi_arready_reg <= axi_arready_next; - axi_rvalid_reg <= axi_rvalid_next; - - if (!axi_rvalid_pipe_reg || axi_rready_i) begin - axi_rvalid_pipe_reg <= axi_rvalid_reg; + end + default: ; + endcase + end + + always @(posedge clk_i, posedge rst_i) begin + if (rst_i) begin + write_state_reg <= WRITE_STATE_IDLE; + axi_awready_reg <= 1'b0; + axi_wready_reg <= 1'b0; + axi_bvalid_reg <= 1'b0; + + write_id_reg <= {ID_WIDTH{1'b0}}; + write_addr_reg <= {ADDR_WIDTH{1'b0}}; + write_count_reg <= {LEN_WIDTH{1'b0}}; + write_size_reg <= 3'd0; + write_burst_reg <= 2'd0; + + axi_bid_reg <= {ID_WIDTH{1'b0}}; + end else begin + write_state_reg <= write_state_next; + axi_awready_reg <= axi_awready_next; + axi_wready_reg <= axi_wready_next; + axi_bvalid_reg <= axi_bvalid_next; + + write_id_reg <= write_id_next; + write_addr_reg <= write_addr_next; + write_count_reg <= write_count_next; + write_size_reg <= write_size_next; + write_burst_reg <= write_burst_next; + + axi_bid_reg <= axi_bid_next; end + end + + // always_comb in SystemVerilog + always @(*) begin + read_state_next = READ_STATE_IDLE; - read_id_reg <= read_id_next; - read_addr_reg <= read_addr_next; - read_count_reg <= read_count_next; - read_size_reg <= read_size_next; - read_burst_reg <= read_burst_next; + axi_rid_next = axi_rid_reg; + axi_rlast_next = axi_rlast_reg; + axi_rvalid_next = axi_rvalid_reg && !(axi_rready_i || (PIPELINE_OUTPUT && !axi_rvalid_pipe_reg)); - axi_rid_reg <= axi_rid_next; - axi_rlast_reg <= axi_rlast_next; + read_id_next = read_id_reg; + read_addr_next = read_addr_reg; + read_count_next = read_count_reg; + read_size_next = read_size_reg; + read_burst_next = read_burst_reg; + + axi_arready_next = 1'b0; + + case (read_state_reg) + READ_STATE_IDLE: begin + axi_arready_next = 1'b1; - if (!axi_rvalid_pipe_reg || axi_rready_i) begin - axi_rid_pipe_reg <= axi_rid_reg; - axi_rdata_pipe_reg <= axi_rdata_reg; - axi_rlast_pipe_reg <= axi_rlast_reg; + if (axi_arready_o && axi_arvalid_i) begin + read_id_next = axi_arid_i; + read_addr_next = axi_araddr_i; + read_count_next = axi_arlen_i; + read_size_next = axi_arsize_i < $clog2(STRB_WIDTH) ? axi_arsize_i : + $clog2(STRB_WIDTH); + read_burst_next = axi_arburst_i; + + axi_arready_next = 1'b0; + read_state_next = READ_STATE_BURST; + end else begin + read_state_next = READ_STATE_IDLE; + end + end + READ_STATE_BURST: begin + if (axi_rready_i || (PIPELINE_OUTPUT && !axi_rvalid_pipe_reg) || !axi_rvalid_reg) begin + axi_rvalid_next = 1'b1; + axi_rid_next = read_id_reg; + axi_rlast_next = read_count_reg == 0; + if (read_burst_reg != 2'b00) begin + read_addr_next = read_addr_reg + (1 << read_size_reg); + end + read_count_next = read_count_reg - 1; + if (read_count_reg > 0) begin + read_state_next = READ_STATE_BURST; + end else begin + axi_arready_next = 1'b1; + read_state_next = READ_STATE_IDLE; + end + end else begin + read_state_next = READ_STATE_BURST; + end + end // case: READ_STATE_BURST + default: ; + endcase + end + + always @(posedge clk_i, posedge rst_i) begin + if (rst_i) begin + read_state_reg <= READ_STATE_IDLE; + axi_arready_reg <= 1'b0; + axi_rvalid_reg <= 1'b0; + axi_rvalid_pipe_reg <= 1'b0; + + read_id_reg <= {ID_WIDTH{1'b0}}; + read_addr_reg <= {ADDR_WIDTH{1'b0}}; + read_count_reg <= 0; + read_size_reg <= 3'd0; + read_burst_reg <= 2'd0; + + axi_rid_reg <= {ID_WIDTH{1'b0}}; + axi_rlast_reg <= 1'b0; + axi_rid_pipe_reg <= {ID_WIDTH{1'b0}}; + axi_rdata_pipe_reg <= {DATA_WIDTH{1'b0}}; + axi_rlast_pipe_reg <= 1'b0; + end else begin + read_state_reg <= read_state_next; + axi_arready_reg <= axi_arready_next; + axi_rvalid_reg <= axi_rvalid_next; + + if (!axi_rvalid_pipe_reg || axi_rready_i) begin + axi_rvalid_pipe_reg <= axi_rvalid_reg; + end + + read_id_reg <= read_id_next; + read_addr_reg <= read_addr_next; + read_count_reg <= read_count_next; + read_size_reg <= read_size_next; + read_burst_reg <= read_burst_next; + + axi_rid_reg <= axi_rid_next; + axi_rlast_reg <= axi_rlast_next; + + if (!axi_rvalid_pipe_reg || axi_rready_i) begin + axi_rid_pipe_reg <= axi_rid_reg; + axi_rdata_pipe_reg <= axi_rdata_reg; + axi_rlast_pipe_reg <= axi_rlast_reg; + end end - end - end + end endmodule