diff --git a/examples/simple_system/rtl/ibex_simple_system.sv b/examples/simple_system/rtl/ibex_simple_system.sv index 33b93e7e..d1882d6c 100644 --- a/examples/simple_system/rtl/ibex_simple_system.sv +++ b/examples/simple_system/rtl/ibex_simple_system.sv @@ -24,8 +24,7 @@ module ibex_simple_system ( logic clk_sys = 1'b0, rst_sys_n; typedef enum { - CoreD, - CoreI + CoreD } bus_host_e; typedef enum { @@ -35,7 +34,7 @@ module ibex_simple_system ( } bus_device_e; localparam NrDevices = 3; - localparam NrHosts = 2; + localparam NrHosts = 1; // interrupts logic timer_irq; @@ -71,6 +70,16 @@ module ibex_simple_system ( assign cfg_device_addr_base[Timer] = 32'h30000; assign cfg_device_addr_mask[Timer] = ~32'h3FF; // 1 kB + // Instruction fetch signals + logic instr_req; + logic instr_gnt; + logic instr_rvalid; + logic [31:0] instr_addr; + logic [31:0] instr_rdata; + logic instr_err; + + assign instr_gnt = instr_req; + assign instr_err = '0; `ifdef VERILATOR assign clk_sys = IO_CLK; @@ -123,10 +132,6 @@ module ibex_simple_system ( .cfg_device_addr_mask ); - assign host_we[CoreI] = 1'b0; - assign host_be[CoreI] = 4'b1111; - assign host_wdata[CoreI] = 32'b0; - ibex_core_tracing #( .MHPMCounterNum(29), .DmHaltAddr(32'h00100000), @@ -143,12 +148,12 @@ module ibex_simple_system ( // First instruction executed is at 0x0 + 0x80 .boot_addr_i (32'h00100000), - .instr_req_o (host_req[CoreI]), - .instr_gnt_i (host_gnt[CoreI]), - .instr_rvalid_i (host_rvalid[CoreI]), - .instr_addr_o (host_addr[CoreI]), - .instr_rdata_i (host_rdata[CoreI]), - .instr_err_i (host_err[CoreI]), + .instr_req_o (instr_req), + .instr_gnt_i (instr_gnt), + .instr_rvalid_i (instr_rvalid), + .instr_addr_o (instr_addr), + .instr_rdata_i (instr_rdata), + .instr_err_i (instr_err), .data_req_o (host_req[CoreD]), .data_gnt_i (host_gnt[CoreD]), @@ -173,18 +178,27 @@ module ibex_simple_system ( ); // SRAM block for instruction and data storage - ram_1p #( + ram_2p #( .Depth(1024*1024/4) ) u_ram ( - .clk_i (clk_sys), - .rst_ni (rst_sys_n), - .req_i (device_req[Ram]), - .we_i (device_we[Ram]), - .be_i (device_be[Ram]), - .addr_i (device_addr[Ram]), - .wdata_i (device_wdata[Ram]), - .rvalid_o (device_rvalid[Ram]), - .rdata_o (device_rdata[Ram]) + .clk_i (clk_sys), + .rst_ni (rst_sys_n), + + .a_req_i (device_req[Ram]), + .a_we_i (device_we[Ram]), + .a_be_i (device_be[Ram]), + .a_addr_i (device_addr[Ram]), + .a_wdata_i (device_wdata[Ram]), + .a_rvalid_o (device_rvalid[Ram]), + .a_rdata_o (device_rdata[Ram]), + + .b_req_i (instr_req), + .b_we_i (1'b0), + .b_be_i (4'b0), + .b_addr_i (instr_addr), + .b_wdata_i (32'b0), + .b_rvalid_o (instr_rvalid), + .b_rdata_o (instr_rdata) ); simulator_ctrl #( diff --git a/shared/rtl/bus.sv b/shared/rtl/bus.sv index 188a2b83..d25abb3b 100644 --- a/shared/rtl/bus.sv +++ b/shared/rtl/bus.sv @@ -51,14 +51,17 @@ module bus #( input [AddressWidth-1:0] cfg_device_addr_mask [NrDevices] ); - logic [$clog2(NrHosts)-1:0] host_sel_req, host_sel_resp; - logic [$clog2(NrDevices)-1:0] device_sel_req, device_sel_resp; + localparam int unsigned NumBitsHostSel = NrHosts > 1 ? $clog2(NrHosts) : 1; + localparam int unsigned NumBitsDeviceSel = NrDevices > 1 ? $clog2(NrDevices) : 1; + + logic [NumBitsHostSel-1:0] host_sel_req, host_sel_resp; + logic [NumBitsDeviceSel-1:0] device_sel_req, device_sel_resp; // Master select prio arbiter always_comb begin for (integer host = NrHosts - 1; host >= 0; host = host - 1) begin if (host_req_i[host]) begin - host_sel_req = $clog2(NrHosts)'(host); + host_sel_req = NumBitsHostSel'(host); end end end @@ -68,7 +71,7 @@ module bus #( for (integer device = 0; device < NrDevices; device = device + 1) begin if ((host_addr_i[host_sel_req] & cfg_device_addr_mask[device]) == cfg_device_addr_base[device]) begin - device_sel_req = $clog2(NrDevices)'(device); + device_sel_req = NumBitsDeviceSel'(device); end end end @@ -86,7 +89,7 @@ module bus #( always_comb begin for (integer device = 0; device < NrDevices; device = device + 1) begin - if ($clog2(NrDevices)'(device) == device_sel_req) begin + if (NumBitsDeviceSel'(device) == device_sel_req) begin device_req_o[device] = host_req_i[host_sel_req]; device_we_o[device] = host_we_i[host_sel_req]; device_addr_o[device] = host_addr_i[host_sel_req]; @@ -105,8 +108,7 @@ module bus #( always_comb begin for (integer host = 0; host < NrHosts; host = host + 1) begin host_gnt_o[host] = 1'b0; - - if ($clog2(NrHosts)'(host) == host_sel_resp) begin + if (NumBitsHostSel'(host) == host_sel_resp) begin host_rvalid_o[host] = device_rvalid_i[device_sel_resp]; host_err_o[host] = device_err_i[device_sel_resp]; host_rdata_o[host] = device_rdata_i[device_sel_resp]; diff --git a/shared/rtl/ram_2p.sv b/shared/rtl/ram_2p.sv new file mode 100644 index 00000000..d583fb4f --- /dev/null +++ b/shared/rtl/ram_2p.sv @@ -0,0 +1,125 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +/** + * Dual-port RAM with 1 cycle read/write delay, 32 bit words. + * + * The two ports are in Read-First Mode: when reading from and writing to the same address + * simultaneously, the old content is returned, before the new content is written. New content + * is made available to both ports with one cycle delay. + * + * Simultaneous write operations by both ports to the same address are to be avoided: The data + * written to memory is not determined. + */ +module ram_2p #( + parameter int Depth = 128 +) ( + input clk_i, + input rst_ni, + + input a_req_i, + input a_we_i, + input [ 3:0] a_be_i, + input [31:0] a_addr_i, + input [31:0] a_wdata_i, + output logic a_rvalid_o, + output logic [31:0] a_rdata_o, + + input b_req_i, + input b_we_i, + input [ 3:0] b_be_i, + input [31:0] b_addr_i, + input [31:0] b_wdata_i, + output logic b_rvalid_o, + output logic [31:0] b_rdata_o +); + + localparam int Aw = $clog2(Depth); + + logic [31:0] mem [Depth]; + + logic [Aw-1:0] a_addr_idx; + assign a_addr_idx = a_addr_i[Aw-1+2:2]; + logic [31-Aw:0] unused_a_addr_parts; + assign unused_a_addr_parts = {a_addr_i[31:Aw+2], a_addr_i[1:0]}; + + logic [Aw-1:0] b_addr_idx; + assign b_addr_idx = b_addr_i[Aw-1+2:2]; + logic [31-Aw:0] unused_b_addr_parts; + assign unused_b_addr_parts = {b_addr_i[31:Aw+2], b_addr_i[1:0]}; + + always @(posedge clk_i) begin + if (a_req_i) begin + if (a_we_i) begin + for (int i = 0; i < 4; i = i + 1) begin + if (a_be_i[i] == 1'b1) begin + mem[a_addr_idx][i*8 +: 8] <= a_wdata_i[i*8 +: 8]; + end + end + end + a_rdata_o <= mem[a_addr_idx]; + end + end + + always @(posedge clk_i) begin + if (b_req_i) begin + if (b_we_i) begin + for (int i = 0; i < 4; i = i + 1) begin + if (b_be_i[i] == 1'b1) begin + mem[b_addr_idx][i*8 +: 8] <= b_wdata_i[i*8 +: 8]; + end + end + end + b_rdata_o <= mem[b_addr_idx]; + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + a_rvalid_o <= '0; + end else begin + a_rvalid_o <= a_req_i; + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + b_rvalid_o <= '0; + end else begin + b_rvalid_o <= b_req_i; + end + end + + `ifdef VERILATOR + // Task for loading 'mem' with SystemVerilog system task $readmemh() + export "DPI-C" task simutil_verilator_memload; + // Function for setting a specific 32 bit element in |mem| + // Returns 1 (true) for success, 0 (false) for errors. + export "DPI-C" function simutil_verilator_set_mem; + + task simutil_verilator_memload; + input string file; + $readmemh(file, mem); + endtask + + // TODO: Allow 'val' to have other widths than 32 bit + function int simutil_verilator_set_mem(input int index, + input logic[31:0] val); + if (index >= Depth) begin + return 0; + end + + mem[index] = val; + return 1; + endfunction + `endif + + `ifdef SRAM_INIT_FILE + localparam MEM_FILE = `"`SRAM_INIT_FILE`"; + initial begin + $display("Initializing SRAM from %s", MEM_FILE); + $readmemh(MEM_FILE, mem); + end + `endif +endmodule diff --git a/shared/sim_shared.core b/shared/sim_shared.core index 42fea450..02ff4d4d 100644 --- a/shared/sim_shared.core +++ b/shared/sim_shared.core @@ -11,6 +11,7 @@ filesets: files: - ./rtl/prim_clock_gating.sv - ./rtl/ram_1p.sv + - ./rtl/ram_2p.sv - ./rtl/bus.sv - ./rtl/sim/simulator_ctrl.sv - ./rtl/timer.sv