Added storage area standalone rtl
diff --git a/verilog/dv/wb_utests/storage_wb/Makefile b/verilog/dv/wb_utests/storage_wb/Makefile
new file mode 100644
index 0000000..4ff890f
--- /dev/null
+++ b/verilog/dv/wb_utests/storage_wb/Makefile
@@ -0,0 +1,17 @@
+.SUFFIXES:
+
+PATTERN = storage_wb
+
+all:  ${PATTERN:=.vcd}
+
+%.vvp: %_tb.v
+	iverilog  -I ../../../rtl \
+	$< -o $@
+
+%.vcd: %.vvp
+	vvp $<
+
+clean:
+	rm -f *.vvp *.vcd *.log
+
+.PHONY: clean all
\ No newline at end of file
diff --git a/verilog/dv/wb_utests/storage_wb/storage_wb_tb.v b/verilog/dv/wb_utests/storage_wb/storage_wb_tb.v
new file mode 100644
index 0000000..ccfdf95
--- /dev/null
+++ b/verilog/dv/wb_utests/storage_wb/storage_wb_tb.v
@@ -0,0 +1,330 @@
+
+`define MGMT_BLOCKS 2
+`define USER_BLOCKS 4
+
+`define BASE_ADR { \
+    {8'h07, {24{1'b0}} }, \   
+    {8'h06, {24{1'b0}} }, \     
+    {8'h05, {24{1'b0}} }, \    
+    {8'h04, {24{1'b0}} }, \    
+    {8'h03, {24{1'b0}} }, \    
+    {8'h02, {24{1'b0}} }, \
+    {8'h01, {24{1'b0}} }  \
+}\
+
+
+// `define DBG
+`include "sram_1rw1r_32_256_8_sky130.v"
+`include "storage.v"
+`include "storage_bridge_wb.v"
+
+module storage_tb;
+
+    reg wb_clk_i;
+    reg wb_rst_i;
+
+    reg [31:0] wb_adr_i;
+    reg [31:0] wb_dat_i;
+    reg [3:0]  wb_sel_i;
+    reg wb_we_i;
+    reg wb_cyc_i;
+    reg  [1:0] wb_stb_i;
+    wire [1:0] wb_ack_o;
+    wire [31:0] wb_mgmt_dat_o;
+
+    // MGMT_AREA RO WB Interface (USER_BLOCKS)  
+    wire [31:0] wb_user_dat_o;
+
+    wire [`MGMT_BLOCKS-1:0] mgmt_ena;
+    wire [(`MGMT_BLOCKS*4)-1:0] mgmt_wen_mask;
+    wire [`MGMT_BLOCKS-1:0] mgmt_wen;
+    wire [31:0] mgmt_wdata;
+    wire [7:0] mgmt_addr;
+    wire [(`MGMT_BLOCKS*32)-1:0] mgmt_rdata;
+    wire [`USER_BLOCKS-1:0] mgmt_user_ena;
+    wire [7:0] mgmt_user_addr;
+    wire [(`USER_BLOCKS*32)-1:0] mgmt_user_rdata;
+
+    // USER_AREA R/W Interface (USER_BLOCKS)
+    reg user_clk;
+    reg [`USER_BLOCKS-1:0] user_ena;
+    reg [`USER_BLOCKS-1:0] user_wen;
+    reg [(`USER_BLOCKS*4)-1:0] user_wen_mask;
+    reg [7:0] user_addr;
+    reg [31:0] user_wdata;
+    wire [(`USER_BLOCKS*32)-1:0] user_rdata;
+
+    // USER_AREA RO Interface (MGMT_BLOCS)
+    reg [`MGMT_BLOCKS-1:0] user_mgmt_ena;
+    reg [7:0] user_mgmt_addr;
+    wire [(`MGMT_BLOCKS*32)-1:0] user_mgmt_rdata;
+
+    initial begin
+        // MGMT Ports
+        wb_clk_i = 0;
+        wb_rst_i = 0;
+        wb_stb_i = 0; 
+        wb_cyc_i = 0;  
+        wb_sel_i = 0;  
+        wb_we_i  = 0;  
+        wb_dat_i = 0; 
+        wb_adr_i = 0; 
+        // User Ports
+        user_clk = 0;
+        user_ena = {`USER_BLOCKS{1'b1}};
+        user_wen = {`USER_BLOCKS{1'b1}};
+        user_addr = 0;
+        user_wdata = 0;
+        user_mgmt_ena = {`MGMT_BLOCKS{1'b1}};
+        user_mgmt_addr = 0;
+    end
+
+    always #1 wb_clk_i = ~wb_clk_i;
+    always #1 user_clk = ~user_clk;
+
+    initial begin
+        $dumpfile("storage_tb.vcd");
+        $dumpvars(0, storage_tb);
+        repeat (100) begin
+            repeat (1000) @(posedge wb_clk_i);
+        end
+        $display("%c[1;31m",27);
+        $display ("Monitor: Timeout, Test Storage Area Failed");
+        $display("%c[0m",27);
+        $finish;
+    end
+
+    reg [31:0] ref_data [255: 0];
+    reg [32*(`MGMT_BLOCKS+`USER_BLOCKS)-1:0] base_adr = `BASE_ADR;
+    reg [31:0] block_adr;
+    integer i,j;
+
+    initial begin
+        // Reset Operation
+        wb_rst_i = 1;
+        #2;
+        wb_rst_i = 0;
+        #2;
+
+        // Test MGMT R/W port and user RO port
+        for (i = 0; i< `MGMT_BLOCKS; i = i +1) begin
+            for ( j = 0; j < 100; j = j + 1) begin 
+                if (i == 0) begin
+                    ref_data[j] = $urandom_range(0, 2**30);
+                end
+                block_adr = base_adr[32*i+:32] + j;
+                mgmt_write(block_adr, ref_data[j]);
+                #2;
+            end
+        end
+        
+        for (i = 0; i< `MGMT_BLOCKS; i = i +1) begin
+            for ( j = 0; j < 100; j = j + 1) begin 
+                block_adr = base_adr[32*i+:32] + j;
+                mgmt_read(block_adr, 0);
+                if (wb_mgmt_dat_o !== ref_data[j]) begin
+                    $display("Monitor: MGMT R/W Operation Failed");
+                    $finish;
+                end
+                
+                user_mgmt_read(j,i);
+                if (user_mgmt_rdata[32*i+:32] !== ref_data[j]) begin
+                    $display("Monitor: User RO Operation Failed");
+                    $finish;
+                end
+                #2;
+            end
+        end
+
+        // Test user R/W port & MGMT RO port
+        for (i = 0; i<`USER_BLOCKS; i = i +1) begin
+            for ( j = 0; j < 100; j = j + 1) begin 
+                if (i == 0) begin
+                    ref_data[j] = $urandom_range(0, 2**30);
+                end
+                user_write(j, ref_data[j], i);
+                #2;
+            end
+        end
+
+        for (i = 0; i< `USER_BLOCKS; i = i +1) begin
+            for ( j = 0; j < 100; j = j + 1) begin 
+                user_read(j,i);
+                if (user_rdata[32*i+:32] !== ref_data[j]) begin
+                    $display("Monitor: User R/W Operation Failed");
+                    $finish;
+                end
+
+                block_adr = base_adr[32*(i+`MGMT_BLOCKS)+:32] + j;
+                mgmt_read(block_adr,1);
+                if(wb_user_dat_o !== ref_data[j])begin
+                    $display("Monitor: MGMT RO Operation Failed");
+                    $finish;
+                end
+                #2;
+            end
+        end
+
+        $display("Success");
+        $finish;
+    end
+    
+    task user_write;
+        input [32:0] addr;
+        input [32:0] data;
+        input integer block;
+        begin
+            @(posedge user_clk) begin
+                user_ena[block] = 0;
+                user_wen[block] = 0;
+                user_wen_mask[(block*4)+:4] = 4'b1111;
+                user_wdata = data;
+                user_addr = addr[7:0];
+                $display("Write Cycle Started.");
+            end
+            #4;
+            user_ena[block] = 1;
+            user_wen_mask[(block*4)+:4] = 4'b0000;
+            user_wen[block] = 1;
+            $display("Write Cycle Ended.");
+        end
+    endtask
+
+    task user_read;
+        input [32:0] addr;
+        input integer block;
+        begin
+            @(posedge user_clk) begin
+                user_ena[block] = 0;
+                user_addr = addr[7:0];
+                $display("Read Cycle Started.");
+            end
+            #8;
+            user_ena[block] = 1;
+            $display("Read Cycle Ended.");
+        end
+    endtask
+
+    task user_mgmt_read;
+        input [32:0] addr;
+        input integer block;
+        begin
+            @(posedge user_clk) begin
+                user_mgmt_ena[block] = 0;
+                user_mgmt_addr = addr[7:0];
+                $display("Read Cycle Started.");
+            end
+            #8;
+            $display("Read Cycle Ended.");
+        end
+    endtask
+
+    task mgmt_write;
+        input [32:0] addr;
+        input [32:0] data;
+        begin 
+            @(posedge wb_clk_i) begin
+                wb_stb_i[0] = 1;
+                wb_cyc_i = 1;
+                wb_sel_i = 4'hF; 
+                wb_we_i = 1;     
+                wb_adr_i = addr;
+                wb_dat_i = data;
+                $display("Write Cycle Started.");
+            end
+            // Wait for an ACK
+            wait(wb_ack_o[0] == 1);
+            wait(wb_ack_o[0] == 0);
+            wb_cyc_i = 0;
+            wb_stb_i[0] = 0;
+            $display("Write Cycle Ended.");
+        end
+    endtask
+    
+    task mgmt_read;
+        input [32:0] addr;
+        input integer block;
+        begin 
+            @(posedge wb_clk_i) begin
+                wb_stb_i[block] = 1;
+                wb_cyc_i = 1;
+                wb_we_i = 0;
+                wb_adr_i = addr;
+                $display("Read Cycle Started.");
+            end
+            // Wait for an ACK
+            wait(wb_ack_o[block] == 1);
+            wait(wb_ack_o[block] == 0);
+            wb_cyc_i = 0;
+            wb_stb_i[block] = 0;
+            $display("Read Cycle Ended.");
+        end
+    endtask
+
+    storage_bridge_wb #(
+        .USER_BLOCKS(`USER_BLOCKS),
+        .MGMT_BLOCKS(`MGMT_BLOCKS),
+        .BASE_ADDR(`BASE_ADR)
+    ) wb_bridge (
+        .wb_clk_i(wb_clk_i),
+        .wb_rst_i(wb_rst_i),
+
+        .wb_adr_i(wb_adr_i),
+        .wb_dat_i(wb_dat_i),
+        .wb_sel_i(wb_sel_i),
+        .wb_we_i(wb_we_i),
+        .wb_cyc_i(wb_cyc_i),
+        .wb_stb_i(wb_stb_i),
+        .wb_ack_o(wb_ack_o),
+        .wb_mgmt_dat_o(wb_mgmt_dat_o),
+
+    // MGMT_AREA RO WB Interface (USER_BLOCKS)  
+        .wb_user_dat_o(wb_user_dat_o),
+
+    // MGMT Area native memory interface
+        .mgmt_ena(mgmt_ena), 
+        .mgmt_wen_mask(mgmt_wen_mask),
+        .mgmt_wen(mgmt_wen),
+        .mgmt_addr(mgmt_addr),
+        .mgmt_wdata(mgmt_wdata),
+        .mgmt_rdata(mgmt_rdata),
+
+    // MGMT_AREA RO Interface (USER_BLOCKS)
+        .mgmt_user_ena(mgmt_user_ena),
+        .mgmt_user_addr(mgmt_user_addr),
+        .mgmt_user_rdata(mgmt_user_rdata)
+    );
+
+
+    storage  #(
+        .MGMT_BLOCKS(`MGMT_BLOCKS),
+        .USER_BLOCKS(`USER_BLOCKS)  
+    ) uut (
+        // Management R/W WB interface
+        .mgmt_clk(wb_clk_i),
+        .mgmt_ena(mgmt_ena),
+        .mgmt_wen(mgmt_wen),
+        .mgmt_wen_mask(mgmt_wen_mask),
+        .mgmt_addr(mgmt_addr),
+        .mgmt_wdata(mgmt_wdata),
+        .mgmt_rdata(mgmt_rdata),
+        // Management RO interface  
+        .mgmt_user_ena(mgmt_user_ena),
+        .mgmt_user_addr(mgmt_user_addr),
+        .mgmt_user_rdata(mgmt_user_rdata),
+        // User R/W interface
+        .user_clk(user_clk),
+        .user_ena(user_ena),
+        .user_wen(user_wen),
+        .user_wen_mask(user_wen_mask),
+        .user_addr(user_addr), 
+        .user_wdata(user_wdata),
+        .user_rdata(user_rdata),
+        // User RO interface
+        .user_mgmt_ena(user_mgmt_ena),
+        .user_mgmt_addr(user_mgmt_addr),
+        .user_mgmt_rdata(user_mgmt_rdata)
+    );
+
+
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/storage.v b/verilog/rtl/storage.v
new file mode 100644
index 0000000..b773158
--- /dev/null
+++ b/verilog/rtl/storage.v
@@ -0,0 +1,70 @@
+ 
+/* User area has R/W access for USER_BLOCKS and RO access for MGMT_BLOCKS 
+   Management area has R/W access for MGMT_BLOCKS and RO access for USER_BLOCKS */
+
+module storage #(
+    parameter USER_BLOCKS = 4,  // R/W access
+    parameter MGMT_BLOCKS = 2   // R/W access
+) (
+    // MGMT_AREA R/W Interface (MGMT_BLOCKS)
+    input mgmt_clk,
+    input [MGMT_BLOCKS-1:0] mgmt_ena, 
+    input [MGMT_BLOCKS-1:0] mgmt_wen, // not shared 
+    input [(MGMT_BLOCKS*4)-1:0] mgmt_wen_mask, // not shared 
+    input [7:0] mgmt_addr,
+    input [31:0] mgmt_wdata,
+    output [(MGMT_BLOCKS*32)-1:0] mgmt_rdata,
+
+    // MGMT_AREA RO Interface (USER_BLOCKS)
+    input [USER_BLOCKS-1:0] mgmt_user_ena,
+    input [7:0] mgmt_user_addr,
+    output [(USER_BLOCKS*32)-1:0] mgmt_user_rdata,
+    
+    // USER_AREA R/W Interface (USER_BLOCKS)
+    input user_clk,
+    input [USER_BLOCKS-1:0] user_ena, 
+    input [USER_BLOCKS-1:0] user_wen,
+    input [(USER_BLOCKS*4)-1:0] user_wen_mask,
+    input [7:0] user_addr,
+    input [31:0] user_wdata,
+    output [(USER_BLOCKS*32)-1:0] user_rdata,
+
+    // USER_AREA RO Interface (MGMT_BLOCS)
+    input [MGMT_BLOCKS-1:0] user_mgmt_ena,
+    input [7:0] user_mgmt_addr,
+    output  [(MGMT_BLOCKS*32)-1:0] user_mgmt_rdata
+);
+
+    sram_1rw1r_32_256_8_sky130 SRAM_0 [MGMT_BLOCKS-1:0] (
+        // MGMT R/W port
+        .clk0(mgmt_clk), 
+        .csb0(mgmt_ena),   
+        .web0(mgmt_wen),  
+        .wmask0(mgmt_wen_mask),
+        .addr0(mgmt_addr[7:0]),
+        .din0(mgmt_wdata),
+        .dout0(mgmt_rdata),
+        // User RO port
+        .clk1(user_clk),
+        .csb1(user_mgmt_ena), 
+        .addr1(user_mgmt_addr),
+        .dout1(user_mgmt_rdata)
+    );    
+
+    sram_1rw1r_32_256_8_sky130 SRAM_1 [USER_BLOCKS-1:0](
+        // User R/W port
+        .clk0(user_clk), 
+        .csb0(user_ena), 
+        .web0(user_wen),
+        .wmask0(user_wen_mask),
+        .addr0(user_addr),
+        .din0(user_wdata),
+        .dout0(user_rdata),
+        // MGMT RO port
+        .clk1(mgmt_clk),
+        .csb1(mgmt_user_ena),
+        .addr1(mgmt_user_addr),
+        .dout1(mgmt_user_rdata)
+    );
+    
+endmodule
\ No newline at end of file
diff --git a/verilog/rtl/storage_bridge_wb.v b/verilog/rtl/storage_bridge_wb.v
new file mode 100644
index 0000000..1c89ca5
--- /dev/null
+++ b/verilog/rtl/storage_bridge_wb.v
@@ -0,0 +1,109 @@
+module storage_bridge_wb #(
+    parameter USER_BLOCKS = 4, 
+    parameter MGMT_BLOCKS = 2
+) (
+    // MGMT_AREA R/W WB Interface (#of WB Slaves = MGMT_BLOCKS )
+    input wb_clk_i,
+    input wb_rst_i,
+
+    input [31:0] wb_adr_i,
+    input [31:0] wb_dat_i,
+    input [3:0]  wb_sel_i,
+    input wb_we_i,
+    input wb_cyc_i,
+    input [1:0] wb_stb_i,
+    output reg [1:0] wb_ack_o,
+    output reg [31:0] wb_mgmt_dat_o,
+
+    // MGMT_AREA RO WB Interface (USER_BLOCKS)  
+    output reg [31:0] wb_user_dat_o,
+
+    // MGMT Area native memory interface
+    output [MGMT_BLOCKS-1:0] mgmt_ena, 
+    output [(MGMT_BLOCKS*4)-1:0] mgmt_wen_mask,
+    output [MGMT_BLOCKS-1:0] mgmt_wen,
+    output [7:0] mgmt_addr,
+    output [31:0] mgmt_wdata,
+    input  [(MGMT_BLOCKS*32)-1:0] mgmt_rdata,
+
+    // MGMT_AREA RO Interface (USER_BLOCKS)
+    output [USER_BLOCKS-1:0] mgmt_user_ena,
+    output [7:0] mgmt_user_addr,
+    input  [(USER_BLOCKS*32)-1:0] mgmt_user_rdata
+);
+
+    localparam RAM_BLOCKS = USER_BLOCKS + MGMT_BLOCKS; 
+    parameter [(RAM_BLOCKS*32)-1:0] BASE_ADDR = {
+        // User partition
+        {32'h 0700_0000},
+        {32'h 0600_0000},
+        {32'h 0500_0000},
+        {32'h 0400_0000},
+        {32'h 0300_0000},
+        // MGMT partition
+        {32'h 0200_0000},
+        {32'h 0100_0000}
+    };
+    parameter ADR_MASK = 32'h FF00_0000;
+
+    wire [1:0] valid;
+    wire [1:0] wen;
+    wire [7:0] wen_mask;
+
+    assign valid = {2{wb_cyc_i}} & wb_stb_i;
+    assign wen   = wb_we_i & valid;    
+    assign wen_mask = wb_sel_i & {{4{wen[1]}}, {4{wen[0]}}};
+
+    // Ack generation
+    reg [1:0] wb_ack_read;
+
+    always @(posedge wb_clk_i) begin
+        if (wb_rst_i == 1'b 1) begin
+            wb_ack_read <= 2'b0;
+            wb_ack_o <= 2'b0;
+        end else begin
+            wb_ack_o <= wb_we_i? (valid & ~wb_ack_o): wb_ack_read;
+            wb_ack_read <= (valid & ~wb_ack_o) & ~wb_ack_read;
+        end
+    end
+    
+    // Address decoding
+    wire [RAM_BLOCKS-1: 0] ram_sel;
+    genvar iS;
+    generate
+        for (iS = 0; iS < RAM_BLOCKS; iS = iS + 1) begin
+            assign ram_sel[iS] = 
+                ((wb_adr_i & ADR_MASK) == BASE_ADDR[(iS+1)*32-1:iS*32]);
+        end
+    endgenerate
+
+    // Management SoC interface
+    assign mgmt_ena = valid[0] ? ~ram_sel[1:0] : {MGMT_BLOCKS{1'b1}}; 
+    assign mgmt_wen = ~{MGMT_BLOCKS{wen[0]}};
+    assign mgmt_wen_mask = {MGMT_BLOCKS{wen_mask[3:0]}};
+    assign mgmt_addr = wb_adr_i[7:0];
+    assign mgmt_wdata = wb_dat_i[31:0];
+
+    wire [1:0] mgmt_sel = ram_sel[1:0];
+
+    integer i;
+    always @(*) begin
+        wb_mgmt_dat_o = {32{1'b0}};
+        for (i=0; i<(MGMT_BLOCKS*32); i=i+1)
+            wb_mgmt_dat_o[i%32] = wb_mgmt_dat_o[i%32] | (mgmt_sel[i/32] & mgmt_rdata[i]);
+    end
+
+    // User Interface
+    assign mgmt_user_ena = valid[1] ? ~ram_sel[5:2] : {USER_BLOCKS{1'b1}}; 
+    assign mgmt_user_addr = wb_adr_i[7:0];
+    
+    wire [3:0] user_sel = ram_sel [5:2];
+
+    integer j;
+    always @(*) begin
+        wb_user_dat_o = {32{1'b0}};
+        for (j=0; j<(USER_BLOCKS*32); j=j+1)
+            wb_user_dat_o[j%32] = wb_user_dat_o[j%32] | (user_sel[j/32] & mgmt_user_rdata[j]);
+    end
+
+endmodule
\ No newline at end of file