initial versions
diff --git a/verilog/rtl/sram/sky130_sram_1kbyte_1rw1r_32x256_8.v b/verilog/rtl/sram/sky130_sram_1kbyte_1rw1r_32x256_8.v new file mode 100644 index 0000000..d9444fe --- /dev/null +++ b/verilog/rtl/sram/sky130_sram_1kbyte_1rw1r_32x256_8.v
@@ -0,0 +1,114 @@ +// OpenRAM SRAM model +// Words: 256 +// Word size: 32 +// Write size: 8 + +module sky130_sram_1kbyte_1rw1r_32x256_8( +`ifdef USE_POWER_PINS + vccd1, + vssd1, +`endif +// Port 0: RW + clk0,csb0,web0,wmask0,addr0,din0,dout0, +// Port 1: R + clk1,csb1,addr1,dout1 + ); + + parameter NUM_WMASKS = 4 ; + parameter DATA_WIDTH = 32 ; + parameter ADDR_WIDTH = 8 ; + parameter RAM_DEPTH = 1 << ADDR_WIDTH; + // FIXME: This delay is arbitrary. + parameter DELAY = 3 ; + parameter VERBOSE = 0 ; //Set to 0 to only display warnings + parameter T_HOLD = 1 ; //Delay to hold dout value after posedge. Value is arbitrary + +`ifdef USE_POWER_PINS + inout vccd1; + inout vssd1; +`endif + input clk0; // clock + input csb0; // active low chip select + input web0; // active low write control + input [NUM_WMASKS-1:0] wmask0; // write mask + input [ADDR_WIDTH-1:0] addr0; + input [DATA_WIDTH-1:0] din0; + output [DATA_WIDTH-1:0] dout0; + input clk1; // clock + input csb1; // active low chip select + input [ADDR_WIDTH-1:0] addr1; + output [DATA_WIDTH-1:0] dout1; + + reg csb0_reg; + reg web0_reg; + reg [NUM_WMASKS-1:0] wmask0_reg; + reg [ADDR_WIDTH-1:0] addr0_reg; + reg [DATA_WIDTH-1:0] din0_reg; + reg [DATA_WIDTH-1:0] dout0; + + // All inputs are registers + always @(posedge clk0) + begin + csb0_reg = csb0; + web0_reg = web0; + wmask0_reg = wmask0; + addr0_reg = addr0; + din0_reg = din0; + #(T_HOLD) dout0 = 32'bx; + if ( !csb0_reg && web0_reg && VERBOSE ) + $display($time," Reading %m addr0=%b dout0=%b",addr0_reg,mem[addr0_reg]); + if ( !csb0_reg && !web0_reg && VERBOSE ) + $display($time," Writing %m addr0=%b din0=%b wmask0=%b",addr0_reg,din0_reg,wmask0_reg); + end + + reg csb1_reg; + reg [ADDR_WIDTH-1:0] addr1_reg; + reg [DATA_WIDTH-1:0] dout1; + + // All inputs are registers + always @(posedge clk1) + begin + csb1_reg = csb1; + addr1_reg = addr1; + if (!csb0 && !web0 && !csb1 && (addr0 == addr1)) + $display($time," WARNING: Writing and reading addr0=%b and addr1=%b simultaneously!",addr0,addr1); + #(T_HOLD) dout1 = 32'bx; + if ( !csb1_reg && VERBOSE ) + $display($time," Reading %m addr1=%b dout1=%b",addr1_reg,mem[addr1_reg]); + end + +reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; + + // Memory Write Block Port 0 + // Write Operation : When web0 = 0, csb0 = 0 + always @ (negedge clk0) + begin : MEM_WRITE0 + if ( !csb0_reg && !web0_reg ) begin + if (wmask0_reg[0]) + mem[addr0_reg][7:0] = din0_reg[7:0]; + if (wmask0_reg[1]) + mem[addr0_reg][15:8] = din0_reg[15:8]; + if (wmask0_reg[2]) + mem[addr0_reg][23:16] = din0_reg[23:16]; + if (wmask0_reg[3]) + mem[addr0_reg][31:24] = din0_reg[31:24]; + end + end + + // Memory Read Block Port 0 + // Read Operation : When web0 = 1, csb0 = 0 + always @ (negedge clk0) + begin : MEM_READ0 + if (!csb0_reg && web0_reg) + dout0 <= #(DELAY) mem[addr0_reg]; + end + + // Memory Read Block Port 1 + // Read Operation : When web1 = 1, csb1 = 0 + always @ (negedge clk1) + begin : MEM_READ1 + if (!csb1_reg) + dout1 <= #(DELAY) mem[addr1_reg]; + end + +endmodule
diff --git a/verilog/rtl/sram/sky130_sram_2kbyte_1rw1r_32x512_8.v b/verilog/rtl/sram/sky130_sram_2kbyte_1rw1r_32x512_8.v new file mode 100644 index 0000000..289a770 --- /dev/null +++ b/verilog/rtl/sram/sky130_sram_2kbyte_1rw1r_32x512_8.v
@@ -0,0 +1,114 @@ +// OpenRAM SRAM model +// Words: 512 +// Word size: 32 +// Write size: 8 + +module sky130_sram_2kbyte_1rw1r_32x512_8( +`ifdef USE_POWER_PINS + vccd1, + vssd1, +`endif +// Port 0: RW + clk0,csb0,web0,wmask0,addr0,din0,dout0, +// Port 1: R + clk1,csb1,addr1,dout1 + ); + + parameter NUM_WMASKS = 4 ; + parameter DATA_WIDTH = 32 ; + parameter ADDR_WIDTH = 9 ; + parameter RAM_DEPTH = 1 << ADDR_WIDTH; + // FIXME: This delay is arbitrary. + parameter DELAY = 3 ; + parameter VERBOSE = 0 ; //Set to 0 to only display warnings + parameter T_HOLD = 1 ; //Delay to hold dout value after posedge. Value is arbitrary + +`ifdef USE_POWER_PINS + inout vccd1; + inout vssd1; +`endif + input clk0; // clock + input csb0; // active low chip select + input web0; // active low write control + input [NUM_WMASKS-1:0] wmask0; // write mask + input [ADDR_WIDTH-1:0] addr0; + input [DATA_WIDTH-1:0] din0; + output [DATA_WIDTH-1:0] dout0; + input clk1; // clock + input csb1; // active low chip select + input [ADDR_WIDTH-1:0] addr1; + output [DATA_WIDTH-1:0] dout1; + + reg csb0_reg; + reg web0_reg; + reg [NUM_WMASKS-1:0] wmask0_reg; + reg [ADDR_WIDTH-1:0] addr0_reg; + reg [DATA_WIDTH-1:0] din0_reg; + reg [DATA_WIDTH-1:0] dout0; + + // All inputs are registers + always @(posedge clk0) + begin + csb0_reg = csb0; + web0_reg = web0; + wmask0_reg = wmask0; + addr0_reg = addr0; + din0_reg = din0; + #(T_HOLD) dout0 = 32'bx; + if ( !csb0_reg && web0_reg && VERBOSE ) + $display($time," Reading %m addr0=%b dout0=%b",addr0_reg,mem[addr0_reg]); + if ( !csb0_reg && !web0_reg && VERBOSE ) + $display($time," Writing %m addr0=%b din0=%b wmask0=%b",addr0_reg,din0_reg,wmask0_reg); + end + + reg csb1_reg; + reg [ADDR_WIDTH-1:0] addr1_reg; + reg [DATA_WIDTH-1:0] dout1; + + // All inputs are registers + always @(posedge clk1) + begin + csb1_reg = csb1; + addr1_reg = addr1; + if (!csb0 && !web0 && !csb1 && (addr0 == addr1)) + $display($time," WARNING: Writing and reading addr0=%b and addr1=%b simultaneously!",addr0,addr1); + #(T_HOLD) dout1 = 32'bx; + if ( !csb1_reg && VERBOSE ) + $display($time," Reading %m addr1=%b dout1=%b",addr1_reg,mem[addr1_reg]); + end + +reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; + + // Memory Write Block Port 0 + // Write Operation : When web0 = 0, csb0 = 0 + always @ (negedge clk0) + begin : MEM_WRITE0 + if ( !csb0_reg && !web0_reg ) begin + if (wmask0_reg[0]) + mem[addr0_reg][7:0] = din0_reg[7:0]; + if (wmask0_reg[1]) + mem[addr0_reg][15:8] = din0_reg[15:8]; + if (wmask0_reg[2]) + mem[addr0_reg][23:16] = din0_reg[23:16]; + if (wmask0_reg[3]) + mem[addr0_reg][31:24] = din0_reg[31:24]; + end + end + + // Memory Read Block Port 0 + // Read Operation : When web0 = 1, csb0 = 0 + always @ (negedge clk0) + begin : MEM_READ0 + if (!csb0_reg && web0_reg) + dout0 <= #(DELAY) mem[addr0_reg]; + end + + // Memory Read Block Port 1 + // Read Operation : When web1 = 1, csb1 = 0 + always @ (negedge clk1) + begin : MEM_READ1 + if (!csb1_reg) + dout1 <= #(DELAY) mem[addr1_reg]; + end + +endmodule
diff --git a/verilog/rtl/sram/sram_wb_wrapper.sv b/verilog/rtl/sram/sram_wb_wrapper.sv new file mode 100644 index 0000000..58ec2d3 --- /dev/null +++ b/verilog/rtl/sram/sram_wb_wrapper.sv
@@ -0,0 +1,101 @@ +//----------------------------------------------------------------------------- +// @file sram_wb_wrapper.vhd +// +// @brief This block is a wishbone wrapper for SRAM signal mapping +// +// @details This wrapper gets signal from master if it is selected +// and convey to the SRAM module and vice versa. +// +// @author Sukru Uzun <sukru.uzun@procenne.com> +// @date 10.03.2022 +// +// @todo SRAM signalization should be checked +// @warning SRAM signalization +// +// @project https://github.com/Procenne-Digital-Design/secure-memory.git +// +// @revision : +// 0.1 - 10 March 2022, Sukru Uzun +// initial version +//----------------------------------------------------------------------------- + +module sram_wb_wrapper #( + parameter SRAM_ADDR_WD = 9, + parameter SRAM_DATA_WD = 32, + parameter SRAM_ADDR_START = 9'h000, + parameter SRAM_ADDR_END = 9'h1F8) + ( + input logic rst_n, + // Wishbone Interface + input logic wb_clk_i, // System clock + input logic wb_cyc_i, // strobe/request + input logic wb_stb_i, // strobe/request + input logic [SRAM_ADDR_WD-1:0] wb_adr_i, // address + input logic wb_we_i, // write + input logic [SRAM_DATA_WD-1:0] wb_dat_i, // data output + input logic [SRAM_DATA_WD/8-1:0] wb_sel_i, // byte enable + output logic [SRAM_DATA_WD-1:0] wb_dat_o, // data input + output logic wb_ack_o // acknowlegement +); + +// Port A +logic sram_clk_a; +logic sram_csb_a; +logic [SRAM_ADDR_WD-1:0] sram_addr_a; +logic [SRAM_DATA_WD-1:0] sram_dout_a; + +// Port B +logic sram_clk_b; +logic sram_csb_b; +logic sram_web_b; +logic [SRAM_DATA_WD/8-1:0] sram_mask_b; +logic [SRAM_ADDR_WD-1:0] sram_addr_b; +logic [SRAM_DATA_WD-1:0] sram_din_b; + +// Memory Write Port +assign sram_clk_b = wb_clk_i; +assign sram_csb_b = !wb_stb_i; +assign sram_web_b = !wb_we_i; +assign sram_mask_b = wb_sel_i; +assign sram_addr_b = wb_adr_i; +assign sram_din_b = wb_dat_i; + +// Memory Read Port +assign sram_clk_a = wb_clk_i; +assign sram_csb_a = (wb_stb_i == 1'b1 && wb_we_i == 1'b0 && wb_ack_o == 0) ? 1'b0 : 1'b1; +assign sram_addr_a = wb_adr_i; + +assign wb_dat_o = sram_dout_a; + +sky130_sram_2kbyte_1rw1r_32x512_8 u_sram1_2kb( +`ifdef USE_POWER_PINS + .vccd1 (vccd1), // User area 1 1.8V supply + .vssd1 (vssd1), // User area 1 digital ground +`endif + // Port 0: RW + .clk0 (sram_clk_b), + .csb0 (sram_csb_b), + .web0 (sram_web_b), + .wmask0 (sram_mask_b), + .addr0 (sram_addr_b), + .din0 (sram_din_b), + .dout0 (), // dont read from Port B + // Port 1: R + .clk1 (sram_clk_a), + .csb1 (sram_csb_a), + .addr1 (sram_addr_a), + .dout1 (sram_dout_a) +); + +// Generate once cycle delayed ACK to get the data from SRAM +always_ff @(posedge wb_clk_i) begin + if ( rst_n == 1'b0 ) + begin + wb_ack_o <= 'h0; + end else + begin + wb_ack_o <= (wb_stb_i == 1'b1) & (wb_ack_o == 0); + end +end + +endmodule
diff --git a/verilog/rtl/user_proj_example.v b/verilog/rtl/user_proj_example.v index 26081e9..d898a39 100644 --- a/verilog/rtl/user_proj_example.v +++ b/verilog/rtl/user_proj_example.v
@@ -68,98 +68,116 @@ // IRQ output [2:0] irq ); - wire clk; - wire rst; - wire [`MPRJ_IO_PADS-1:0] io_in; - wire [`MPRJ_IO_PADS-1:0] io_out; - wire [`MPRJ_IO_PADS-1:0] io_oeb; +parameter WB_WIDTH = 32; // WB ADDRESS/DARA WIDTH +parameter SRAM_ADDR_WD = 9; +parameter SRAM_DATA_WD = 32; +parameter SRAM_ADDR_START = 9'h000; +parameter SRAM_ADDR_END = 9'h1F8; - wire [31:0] rdata; - wire [31:0] wdata; - wire [BITS-1:0] count; +//--------------------------------------------------------------------- +// WB Master Interface +//--------------------------------------------------------------------- +wire clk; +wire rst; +wire [`MPRJ_IO_PADS-1:0] io_in; +wire [`MPRJ_IO_PADS-1:0] io_out; +wire [`MPRJ_IO_PADS-1:0] io_oeb; - wire valid; - wire [3:0] wstrb; - wire [31:0] la_write; +//--------------------------------------------------------------------- +// SRAM +//--------------------------------------------------------------------- +wire s0_wb_cyc_i; +wire s0_wb_stb_i; +wire [SRAM_ADDR_WD-1:0] s0_wb_adr_i; +wire s0_wb_we_i; +wire [SRAM_DATA_WD-1:0] s0_wb_dat_i; +wire [SRAM_DATA_WD/8-1:0] s0_wb_sel_i; +wire [SRAM_DATA_WD-1:0] s0_wb_dat_o; +wire s0_wb_ack_o; - // WB MI A - assign valid = wbs_cyc_i && wbs_stb_i; - assign wstrb = wbs_sel_i & {4{wbs_we_i}}; - assign wbs_dat_o = rdata; - assign wdata = wbs_dat_i; +wb_interconnect interconnect +( +`ifdef USE_POWER_PINS + .vccd1(vccd1), // User area 1 1.8V supply + .vssd1(vssd1), // User area 1 digital ground +`endif + .clk_i(wb_clk_i), + .rst_n(wb_rst_i), - // IO - assign io_out = count; - assign io_oeb = {(`MPRJ_IO_PADS-1){rst}}; + // Master 0 Interface + .m0_wb_dat_i(wbs_dat_i), + .m0_wb_adr_i(wbs_adr_i), + .m0_wb_sel_i(wbs_sel_i), + .m0_wb_we_i (wbs_we_i), + .m0_wb_cyc_i(wbs_cyc_i), + .m0_wb_stb_i(wbs_stb_i), + .m0_wb_dat_o(wbs_dat_o), + .m0_wb_ack_o(wbs_ack_o), + .m0_wb_err_o(), - // IRQ - assign irq = 3'b000; // Unused + // Slave 0 Interface + .s0_wb_dat_i(s0_wb_dat_i), + .s0_wb_ack_i(s0_wb_ack_o), + .s0_wb_dat_o(s0_wb_dat_i), + .s0_wb_adr_o(s0_wb_adr_i), + .s0_wb_sel_o(s0_wb_sel_i), + .s0_wb_we_o (s0_wb_we_i), + .s0_wb_cyc_o(s0_wb_cyc_i), + .s0_wb_stb_o(s0_wb_stb_i), - // LA - assign la_data_out = {{(127-BITS){1'b0}}, count}; - // Assuming LA probes [63:32] are for controlling the count register - assign la_write = ~la_oenb[63:32] & ~{BITS{valid}}; - // Assuming LA probes [65:64] are for controlling the count clk & reset - assign clk = (~la_oenb[64]) ? la_data_in[64]: wb_clk_i; - assign rst = (~la_oenb[65]) ? la_data_in[65]: wb_rst_i; + // Slave 1 Interface + .s1_wb_dat_i(), + .s1_wb_ack_i(), + .s1_wb_dat_o(), + .s1_wb_adr_o(), + .s1_wb_sel_o(), + .s1_wb_we_o (), + .s1_wb_cyc_o(), + .s1_wb_stb_o(), - counter #( - .BITS(BITS) - ) counter( - .clk(clk), - .reset(rst), - .ready(wbs_ack_o), - .valid(valid), - .rdata(rdata), - .wdata(wbs_dat_i), - .wstrb(wstrb), - .la_write(la_write), - .la_input(la_data_in[63:32]), - .count(count) - ); + // Slave 2 Interface + .s2_wb_dat_i(), + .s2_wb_ack_i(), + .s2_wb_dat_o(), + .s2_wb_adr_o(), + .s2_wb_sel_o(), + .s2_wb_we_o (), + .s2_wb_cyc_o(), + .s2_wb_stb_o(), -endmodule - -module counter #( - parameter BITS = 32 -)( - input clk, - input reset, - input valid, - input [3:0] wstrb, - input [BITS-1:0] wdata, - input [BITS-1:0] la_write, - input [BITS-1:0] la_input, - output ready, - output [BITS-1:0] rdata, - output [BITS-1:0] count + // Slave 3 Interface + .s3_wb_dat_i(), + .s3_wb_ack_i(), + .s3_wb_dat_o(), + .s3_wb_adr_o(), + .s3_wb_sel_o(), + .s3_wb_we_o (), + .s3_wb_cyc_o(), + .s3_wb_stb_o() ); - reg ready; - reg [BITS-1:0] count; - reg [BITS-1:0] rdata; - always @(posedge clk) begin - if (reset) begin - count <= 0; - ready <= 0; - end else begin - ready <= 1'b0; - if (~|la_write) begin - count <= count + 1; - end - if (valid && !ready) begin - ready <= 1'b1; - rdata <= count; - if (wstrb[0]) count[7:0] <= wdata[7:0]; - if (wstrb[1]) count[15:8] <= wdata[15:8]; - if (wstrb[2]) count[23:16] <= wdata[23:16]; - if (wstrb[3]) count[31:24] <= wdata[31:24]; - end else if (|la_write) begin - count <= la_write & la_input; - end - end - end +sram_wb_wrapper #( +`ifndef SYNTHESIS + .SRAM_ADDR_WD (SRAM_ADDR_WD ), + .SRAM_DATA_WD (SRAM_DATA_WD ), + .SRAM_ADDR_START(SRAM_ADDR_START), + .SRAM_ADDR_END (SRAM_ADDR_END ) +`endif + ) + wb_wrapper0 ( + .rst_n(wb_rst_i), + // Wishbone Interface + .wb_clk_i(wb_clk_i), // System clock + .wb_cyc_i(s0_wb_cyc_i), // cycle enable + .wb_stb_i(s0_wb_stb_i), // strobe + .wb_adr_i(s0_wb_adr_i), // address + .wb_we_i (s0_wb_we_i), // write + .wb_dat_i(s0_wb_dat_i), // data output + .wb_sel_i(s0_wb_sel_i), // byte enable + .wb_dat_o(s0_wb_dat_o), // data input + .wb_ack_o(s0_wb_ack_o) // acknowlegement +); endmodule `default_nettype wire
diff --git a/verilog/rtl/wb_interconnect/wb_interconnect.sv b/verilog/rtl/wb_interconnect/wb_interconnect.sv new file mode 100644 index 0000000..4631887 --- /dev/null +++ b/verilog/rtl/wb_interconnect/wb_interconnect.sv
@@ -0,0 +1,249 @@ +//----------------------------------------------------------------------------- +// @file wb_interconnect.vhd +// +// @brief Convey wishbone signals to corresponding module. +// +// @details 1 masters and 4 slaves share bus Wishbone connection +// M0 - WB_PORT +// S0 - SRAM +// S1 - UART +// S2 - TRNG +// S3 - SPI +// +// @author Sukru Uzun <sukru.uzun@procenne.com> +// @date 10.03.2022 +// +// @todo add other modules +// @warning be careful about chip select +// +// @project https://github.com/Procenne-Digital-Design/secure-memory.git +// +// @revision : +// 0.1 - 10 March 2022, Sukru Uzun +// initial version +//----------------------------------------------------------------------------- + +module wb_interconnect +( +`ifdef USE_POWER_PINS + input logic vccd1, // User area 1 1.8V supply + input logic vssd1, // User area 1 digital ground +`endif + input logic clk_i, + input logic rst_n, + + // Master 0 Interface + input logic [31:0] m0_wb_dat_i, + input logic [31:0] m0_wb_adr_i, + input logic [3:0] m0_wb_sel_i, + input logic m0_wb_we_i, + input logic m0_wb_cyc_i, + input logic m0_wb_stb_i, + output logic [31:0] m0_wb_dat_o, + output logic m0_wb_ack_o, + output logic m0_wb_err_o, + + // Slave 0 Interface + input logic [31:0] s0_wb_dat_i, + input logic s0_wb_ack_i, + output logic [31:0] s0_wb_dat_o, + output logic [7:0] s0_wb_adr_o, + output logic [3:0] s0_wb_sel_o, + output logic s0_wb_we_o, + output logic s0_wb_cyc_o, + output logic s0_wb_stb_o, + + // Slave 1 Interface + input logic [31:0] s1_wb_dat_i, + input logic s1_wb_ack_i, + output logic [31:0] s1_wb_dat_o, + output logic [10:0] s1_wb_adr_o, + output logic [3:0] s1_wb_sel_o, + output logic s1_wb_we_o, + output logic s1_wb_cyc_o, + output logic s1_wb_stb_o, + + // Slave 2 Interface + input logic [31:0] s2_wb_dat_i, + input logic s2_wb_ack_i, + output logic [31:0] s2_wb_dat_o, + output logic [10:0] s2_wb_adr_o, + output logic [3:0] s2_wb_sel_o, + output logic s2_wb_we_o, + output logic s2_wb_cyc_o, + output logic s2_wb_stb_o, + + // Slave 3 Interface + input logic [31:0] s3_wb_dat_i, + input logic s3_wb_ack_i, + output logic [31:0] s3_wb_dat_o, + output logic [10:0] s3_wb_adr_o, + output logic [3:0] s3_wb_sel_o, + output logic s3_wb_we_o, + output logic s3_wb_cyc_o, + output logic s3_wb_stb_o +); + +// WishBone Wr Interface +typedef struct packed { + logic [31:0] wb_dat; + logic [31:0] wb_adr; + logic [3:0] wb_sel; + logic wb_we; + logic wb_cyc; + logic wb_stb; + logic [1:0] wb_tid; // target id +} type_wb_wr_intf; + +// WishBone Rd Interface +typedef struct packed { + logic [31:0] wb_dat; + logic wb_ack; + logic wb_err; +} type_wb_rd_intf; + +// Master Write Interface +type_wb_wr_intf m0_wb_wr; + +// Master Read Interface +type_wb_rd_intf m0_wb_rd; + +// Slave Write Interface +type_wb_wr_intf s0_wb_wr; +type_wb_wr_intf s1_wb_wr; +type_wb_wr_intf s2_wb_wr; +type_wb_wr_intf s3_wb_wr; + +// Slave Read Interface +type_wb_rd_intf s0_wb_rd; +type_wb_rd_intf s1_wb_rd; +type_wb_rd_intf s2_wb_rd; +type_wb_rd_intf s3_wb_rd; + +type_wb_wr_intf s_bus_wr; // Multiplexed Master I/F +type_wb_rd_intf s_bus_rd; // Multiplexed Slave I/F + +//------------------------------------------------------------------- +// EXTERNAL MEMORY MAP +// 0x0000_0000 to 0x0000_0FFF - SRAM +// 0x0000_1000 to 0x0000_1FFF - UART +// 0x0000_2000 to 0x0000_2FFF - TRNG +// 0x0000_3000 to 0x0000_3FFF - SPI +// ------------------------------------------------------------------ +wire [1:0] m0_wb_tid_i = m0_wb_adr_i[13:12]; + +//---------------------------------------- +// Master Mapping +// --------------------------------------- +assign m0_wb_wr.wb_dat = m0_wb_dat_i; +assign m0_wb_wr.wb_adr = {m0_wb_adr_i[31:2],2'b00}; +assign m0_wb_wr.wb_sel = m0_wb_sel_i; +assign m0_wb_wr.wb_we = m0_wb_we_i; +assign m0_wb_wr.wb_cyc = m0_wb_cyc_i; +assign m0_wb_wr.wb_stb = m0_wb_stb_i; +assign m0_wb_wr.wb_tid = m0_wb_tid_i; + +assign m0_wb_dat_o = m0_wb_rd.wb_dat; +assign m0_wb_ack_o = m0_wb_rd.wb_ack; +assign m0_wb_err_o = m0_wb_rd.wb_err; + +//---------------------------------------- +// Slave Mapping +// ------------------------------------- +// 2KB SRAM +assign s0_wb_dat_o = s0_wb_wr.wb_dat; +assign s0_wb_adr_o = s0_wb_wr.wb_adr[8:0]; +assign s0_wb_sel_o = s0_wb_wr.wb_sel; +assign s0_wb_we_o = s0_wb_wr.wb_we; +assign s0_wb_cyc_o = s0_wb_wr.wb_cyc; +assign s0_wb_stb_o = s0_wb_wr.wb_stb; + +assign s0_wb_rd.wb_dat = s0_wb_dat_i; +assign s0_wb_rd.wb_ack = s0_wb_ack_i; +assign s0_wb_rd.wb_err = 1'b0; + +// UART +assign s1_wb_dat_o = s1_wb_wr.wb_dat; +assign s1_wb_adr_o = s1_wb_wr.wb_adr[10:0]; +assign s1_wb_sel_o = s1_wb_wr.wb_sel; +assign s1_wb_we_o = s1_wb_wr.wb_we; +assign s1_wb_cyc_o = s1_wb_wr.wb_cyc; +assign s1_wb_stb_o = s1_wb_wr.wb_stb; + +assign s1_wb_rd.wb_dat = s1_wb_dat_i; +assign s1_wb_rd.wb_ack = s1_wb_ack_i; +assign s1_wb_rd.wb_err = 1'b0; + +// TRNG +assign s2_wb_dat_o = s2_wb_wr.wb_dat; +assign s2_wb_adr_o = s2_wb_wr.wb_adr[10:0]; +assign s2_wb_sel_o = s2_wb_wr.wb_sel; +assign s2_wb_we_o = s2_wb_wr.wb_we; +assign s2_wb_cyc_o = s2_wb_wr.wb_cyc; +assign s2_wb_stb_o = s2_wb_wr.wb_stb; + +assign s2_wb_rd.wb_dat = s2_wb_dat_i; +assign s2_wb_rd.wb_ack = s2_wb_ack_i; +assign s2_wb_rd.wb_err = 1'b0; + +// SPI +assign s3_wb_dat_o = s3_wb_wr.wb_dat; +assign s3_wb_adr_o = s3_wb_wr.wb_adr[10:0]; +assign s3_wb_sel_o = s3_wb_wr.wb_sel; +assign s3_wb_we_o = s3_wb_wr.wb_we; +assign s3_wb_cyc_o = s3_wb_wr.wb_cyc; +assign s3_wb_stb_o = s3_wb_wr.wb_stb; + +assign s3_wb_rd.wb_dat = s3_wb_dat_i; +assign s3_wb_rd.wb_ack = s3_wb_ack_i; +assign s3_wb_rd.wb_err = 1'b0; + +// Generate Multiplexed Slave Interface based on target Id +wire [3:0] s_wb_tid = s_bus_wr.wb_tid; // to fix iverilog warning + +always_comb begin + case(s_wb_tid) + 2'b00: s_bus_rd = s0_wb_rd; + 2'b01: s_bus_rd = s1_wb_rd; + 2'b10: s_bus_rd = s2_wb_rd; + 2'b11: s_bus_rd = s3_wb_rd; + endcase +end + +// Connect Master => Slave +assign s0_wb_wr = (s_wb_tid == 2'b00) ? s_bus_wr : 2'b00; +assign s1_wb_wr = (s_wb_tid == 2'b01) ? s_bus_wr : 2'b00; +assign s2_wb_wr = (s_wb_tid == 2'b10) ? s_bus_wr : 2'b00; +assign s3_wb_wr = (s_wb_tid == 2'b11) ? s_bus_wr : 2'b00; + +// Stagging FF to break write and read timing path +wb_stagging u_m_wb_stage( + .clk_i (clk_i), + .rst_n (rst_n), + + // WishBone Input master I/P + .m_wb_dat_i (m0_wb_wr.wb_dat), + .m_wb_adr_i (m0_wb_wr.wb_adr), + .m_wb_sel_i (m0_wb_wr.wb_sel), + .m_wb_we_i (m0_wb_wr.wb_we ), + .m_wb_cyc_i (m0_wb_wr.wb_cyc), + .m_wb_stb_i (m0_wb_wr.wb_stb), + .m_wb_tid_i (m0_wb_wr.wb_tid), + .m_wb_dat_o (m0_wb_rd.wb_dat), + .m_wb_ack_o (m0_wb_rd.wb_ack), + .m_wb_err_o (m0_wb_rd.wb_err), + + // Slave Interface + .s_wb_dat_i (s_bus_rd.wb_dat), + .s_wb_ack_i (s_bus_rd.wb_ack), + .s_wb_err_i (s_bus_rd.wb_err), + .s_wb_dat_o (s_bus_wr.wb_dat), + .s_wb_adr_o (s_bus_wr.wb_adr), + .s_wb_sel_o (s_bus_wr.wb_sel), + .s_wb_we_o (s_bus_wr.wb_we ), + .s_wb_cyc_o (s_bus_wr.wb_cyc), + .s_wb_stb_o (s_bus_wr.wb_stb), + .s_wb_tid_o (s_bus_wr.wb_tid) +); + +endmodule
diff --git a/verilog/rtl/wb_interconnect/wb_stagging.sv b/verilog/rtl/wb_interconnect/wb_stagging.sv new file mode 100644 index 0000000..2d0121e --- /dev/null +++ b/verilog/rtl/wb_interconnect/wb_stagging.sv
@@ -0,0 +1,116 @@ +//----------------------------------------------------------------------------- +// @file wb_staging.vhd +// +// @brief Register wishbone signals. +// +// @details This logic create a holding FF for Wishbone interface. +// This is usefull to break timing issue at interconnect +// +// @author Sukru Uzun <sukru.uzun@procenne.com> +// @date 10.03.2022 +// +// @todo +// @warning +// +// @project https://github.com/Procenne-Digital-Design/secure-memory.git +// +// @revision : +// 0.1 - 10 March 2022, Sukru Uzun +// initial version +//----------------------------------------------------------------------------- + +module wb_stagging ( + input logic clk_i, + input logic rst_n, + + // WishBone Input master I/P + input logic [31:0] m_wbd_dat_i, + input logic [31:0] m_wbd_adr_i, + input logic [3:0] m_wbd_sel_i, + input logic m_wbd_we_i, + input logic m_wbd_cyc_i, + input logic m_wbd_stb_i, + input logic [3:0] m_wbd_tid_i, + output logic [31:0] m_wbd_dat_o, + output logic m_wbd_ack_o, + output logic m_wbd_err_o, + + // Slave Interface + input logic [31:0] s_wbd_dat_i, + input logic s_wbd_ack_i, + input logic s_wbd_err_i, + output logic [31:0] s_wbd_dat_o, + output logic [31:0] s_wbd_adr_o, + output logic [3:0] s_wbd_sel_o, + output logic s_wbd_we_o, + output logic s_wbd_cyc_o, + output logic s_wbd_stb_o, + output logic [3:0] s_wbd_tid_o +); + +logic holding_busy ; // Indicate Stagging for Free or not +logic [31:0] m_wbd_dat_i_ff ; // Flopped vesion of m_wbd_dat_i +logic [31:0] m_wbd_adr_i_ff ; // Flopped vesion of m_wbd_adr_i +logic [3:0] m_wbd_sel_i_ff ; // Flopped vesion of m_wbd_sel_i +logic m_wbd_we_i_ff ; // Flopped vesion of m_wbd_we_i +logic m_wbd_cyc_i_ff ; // Flopped vesion of m_wbd_cyc_i +logic m_wbd_stb_i_ff ; // Flopped vesion of m_wbd_stb_i +logic [3:0] m_wbd_tid_i_ff ; // Flopped vesion of m_wbd_tid_i +logic [31:0] s_wbd_dat_i_ff ; // Flopped vesion of s_wbd_dat_i +logic s_wbd_ack_i_ff ; // Flopped vesion of s_wbd_ack_i +logic s_wbd_err_i_ff ; // Flopped vesion of s_wbd_err_i + +assign s_wbd_dat_o = m_wbd_dat_i_ff; +assign s_wbd_adr_o = m_wbd_adr_i_ff; +assign s_wbd_sel_o = m_wbd_sel_i_ff; +assign s_wbd_we_o = m_wbd_we_i_ff; +assign s_wbd_cyc_o = m_wbd_cyc_i_ff; +assign s_wbd_stb_o = m_wbd_stb_i_ff; +assign s_wbd_tid_o = m_wbd_tid_i_ff; + +assign m_wbd_dat_o = s_wbd_dat_i_ff; +assign m_wbd_ack_o = s_wbd_ack_i_ff; +assign m_wbd_err_o = s_wbd_err_i_ff; + +always @(negedge rst_n or posedge clk_i) +begin + if(rst_n == 1'b0) begin + holding_busy <= 1'b0; + m_wbd_dat_i_ff <= 'h0; + m_wbd_adr_i_ff <= 'h0; + m_wbd_sel_i_ff <= 'h0; + m_wbd_we_i_ff <= 'h0; + m_wbd_cyc_i_ff <= 'h0; + m_wbd_stb_i_ff <= 'h0; + m_wbd_tid_i_ff <= 'h0; + s_wbd_dat_i_ff <= 'h0; + s_wbd_ack_i_ff <= 'h0; + s_wbd_err_i_ff <= 'h0; + end else begin + s_wbd_dat_i_ff <= s_wbd_dat_i; + s_wbd_ack_i_ff <= s_wbd_ack_i; + s_wbd_err_i_ff <= s_wbd_err_i; + if(m_wbd_stb_i && holding_busy == 0 && m_wbd_ack_o == 0) begin + holding_busy <= 1'b1; + m_wbd_dat_i_ff <= m_wbd_dat_i; + m_wbd_adr_i_ff <= m_wbd_adr_i; + m_wbd_sel_i_ff <= m_wbd_sel_i; + m_wbd_we_i_ff <= m_wbd_we_i; + m_wbd_cyc_i_ff <= m_wbd_cyc_i; + m_wbd_stb_i_ff <= m_wbd_stb_i; + m_wbd_tid_i_ff <= m_wbd_tid_i; + end + else if (holding_busy && s_wbd_ack_i) begin + holding_busy <= 1'b0; + m_wbd_dat_i_ff <= 'h0; + m_wbd_adr_i_ff <= 'h0; + m_wbd_sel_i_ff <= 'h0; + m_wbd_we_i_ff <= 'h0; + m_wbd_cyc_i_ff <= 'h0; + m_wbd_stb_i_ff <= 'h0; + m_wbd_tid_i_ff <= 'h0; + end + end +end + +endmodule