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