Skip to content

Commit 6a43980

Browse files
authored
1r1w enhancements (#542)
* Adding banked 1r1w * Adding latch last read * Fixing review comments * Defaulting to 1 for verbose * Fixing bank index * Adding latch last read in generator * Update bsg_mem_1r1w_sync_banked.v * Update bsg_mem_1r1w_sync_banked.v
1 parent 7ace0d7 commit 6a43980

8 files changed

+447
-3
lines changed

bsg_mem/bsg_mem_1r1w_sync.v

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
module bsg_mem_1r1w_sync #(parameter `BSG_INV_PARAM(width_p)
1616
, parameter `BSG_INV_PARAM(els_p)
1717
, parameter read_write_same_addr_p=0
18+
, parameter latch_last_read_p=0
1819
, parameter addr_width_lp=`BSG_SAFE_CLOG2(els_p)
1920
, parameter harden_p=0
2021
, parameter disable_collision_warning_p=0
2122
, parameter enable_clock_gating_p=0
23+
, parameter verbose_if_synth_p=1
2224
)
2325
(input clk_i
2426
, input reset_i
@@ -54,6 +56,9 @@ module bsg_mem_1r1w_sync #(parameter `BSG_INV_PARAM(width_p)
5456
#(.width_p(width_p)
5557
,.els_p(els_p)
5658
,.read_write_same_addr_p(read_write_same_addr_p)
59+
,.latch_last_read_p(latch_last_read_p)
60+
,.verbose_p(verbose_if_synth_p) // disables reprinting out a masked synth ram
61+
// that has been split into many synth rams
5762
) synth
5863
(.clk_i( clk_lo )
5964
,.reset_i

bsg_mem/bsg_mem_1r1w_sync_banked.v

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/**
2+
* bsg_mem_1r1w_sync_banked.v
3+
*
4+
* This module has the same interface/functionality as
5+
* bsg_mem_1r1w_sync.
6+
*
7+
* This module can be used for breaking a big SRAM block into
8+
* smaller blocks. This might be useful, if the SRAM generator does not
9+
* support sizes of SRAM that are too wide or too deep.
10+
* It is also useful for power and delay perspective, since only one depth
11+
* bank is activated while reading or writing.
12+
*
13+
* If the desired banking is decided by node-specific (e.g. TSMC 28) SRAM
14+
* generator characteristics then the preferred methodology is to invoke this
15+
* from the /hard SRAM macro, rather than to instantiate it in the RTL.
16+
* However, in some cases, for example, for research infrastructures exploring
17+
* a pareto design space, it may be desirable to directly use this interface.
18+
*
19+
* - width_p : width of the total memory
20+
* - els_p : depth of the total memory
21+
*
22+
* - num_width_bank_p : Number of banks for the memory's width. width_p has
23+
* to be a multiple of this number.
24+
* - num_depth_bank_p : Number of banks for the memory's depth. els_p has to
25+
* be a multiple of this number.
26+
*
27+
*/
28+
29+
30+
`include "bsg_defines.v"
31+
32+
module bsg_mem_1r1w_sync_banked
33+
#(parameter `BSG_INV_PARAM(width_p)
34+
, parameter `BSG_INV_PARAM(els_p)
35+
, parameter read_write_same_addr_p=0
36+
, parameter latch_last_read_p=0
37+
38+
, parameter num_width_bank_p=1
39+
, parameter num_depth_bank_p=1
40+
41+
, parameter addr_width_lp=`BSG_SAFE_CLOG2(els_p)
42+
43+
, parameter bank_depth_lp=(els_p/num_depth_bank_p)
44+
, parameter bank_addr_width_lp=`BSG_SAFE_CLOG2(bank_depth_lp)
45+
, parameter depth_bank_idx_width_lp=`BSG_SAFE_CLOG2(num_depth_bank_p)
46+
, parameter bank_width_lp=(width_p/num_width_bank_p)
47+
)
48+
(
49+
input clk_i
50+
, input reset_i
51+
52+
, input w_v_i
53+
, input [addr_width_lp-1:0] w_addr_i
54+
, input [width_p-1:0] w_data_i
55+
56+
, input r_v_i
57+
, input [addr_width_lp-1:0] r_addr_i
58+
, output logic [width_p-1:0] r_data_o
59+
);
60+
61+
62+
if (num_depth_bank_p==1) begin: db1
63+
64+
for (genvar i = 0; i < num_width_bank_p; i++) begin: wb
65+
66+
bsg_mem_1r1w_sync #(
67+
.width_p(bank_width_lp)
68+
,.els_p(bank_depth_lp)
69+
,.read_write_same_addr_p(read_write_same_addr_p)
70+
) bank (
71+
.clk_i(clk_i)
72+
,.reset_i(reset_i)
73+
,.w_v_i(w_v_i)
74+
,.w_addr_i(w_addr_i)
75+
,.w_data_i(w_data_i[bank_width_lp*i+:bank_width_lp])
76+
,.r_v_i(r_v_i)
77+
,.r_addr_i(r_addr_i)
78+
,.r_data_o(r_data_o[bank_width_lp*i+:bank_width_lp])
79+
);
80+
81+
end
82+
83+
end
84+
else begin: dbn
85+
86+
logic [num_depth_bank_p-1:0] bank_r_v_li, bank_w_v_li;
87+
logic [num_depth_bank_p-1:0][width_p-1:0] bank_r_data_lo;
88+
89+
wire [depth_bank_idx_width_lp-1:0] depth_bank_r_idx_li = r_addr_i[0+:depth_bank_idx_width_lp];
90+
wire [bank_addr_width_lp-1:0] bank_r_addr_li = r_addr_i[depth_bank_idx_width_lp+:bank_addr_width_lp];
91+
92+
wire [depth_bank_idx_width_lp-1:0] depth_bank_w_idx_li = w_addr_i[0+:depth_bank_idx_width_lp];
93+
wire [bank_addr_width_lp-1:0] bank_w_addr_li = w_addr_i[depth_bank_idx_width_lp+:bank_addr_width_lp];
94+
95+
bsg_decode_with_v #(
96+
.num_out_p(num_depth_bank_p)
97+
) demux_r_v (
98+
.i(depth_bank_r_idx_li)
99+
,.v_i(r_v_i)
100+
,.o(bank_r_v_li)
101+
);
102+
103+
bsg_decode_with_v #(
104+
.num_out_p(num_depth_bank_p)
105+
) demux_w_v (
106+
.i(depth_bank_w_idx_li)
107+
,.v_i(w_v_i)
108+
,.o(bank_w_v_li)
109+
);
110+
111+
for (genvar i = 0; i < num_width_bank_p; i++) begin: wb
112+
for (genvar j = 0; j < num_depth_bank_p; j++) begin: db
113+
114+
bsg_mem_1r1w_sync #(
115+
.width_p(bank_width_lp)
116+
,.els_p(bank_depth_lp)
117+
,.read_write_same_addr_p(read_write_same_addr_p)
118+
,.latch_last_read_p(latch_last_read_p)
119+
) bank (
120+
.clk_i(clk_i)
121+
,.reset_i(reset_i)
122+
123+
,.w_v_i(bank_w_v_li[j])
124+
,.w_addr_i(bank_w_addr_li)
125+
,.w_data_i(w_data_i[i*bank_width_lp+:bank_width_lp])
126+
,.r_v_i(bank_r_v_li[j])
127+
,.r_addr_i(bank_r_addr_li)
128+
,.r_data_o(bank_r_data_lo[j][i*bank_width_lp+:bank_width_lp])
129+
);
130+
131+
end
132+
end
133+
134+
logic [depth_bank_idx_width_lp-1:0] depth_bank_r_idx_r;
135+
136+
bsg_dff_en #(
137+
.width_p(depth_bank_idx_width_lp)
138+
) depth_bank_idx_dff (
139+
.clk_i(clk_i)
140+
,.en_i(r_v_i)
141+
,.data_i(depth_bank_r_idx_li)
142+
,.data_o(depth_bank_r_idx_r)
143+
);
144+
145+
bsg_mux #(
146+
.els_p(num_depth_bank_p)
147+
,.width_p(width_p)
148+
) data_out_mux (
149+
.data_i(bank_r_data_lo)
150+
,.sel_i(depth_bank_r_idx_r)
151+
,.data_o(r_data_o)
152+
);
153+
154+
end
155+
156+
157+
// synopsys translate_off
158+
159+
initial begin
160+
assert(els_p % num_depth_bank_p == 0)
161+
else $error("[BSG_ERROR] num_depth_bank_p does not divide even with els_p. %m");
162+
163+
assert(width_p % num_width_bank_p == 0)
164+
else $error("[BSG_ERROR] num_width_bank_p does not divide even with width_p. %m");
165+
end
166+
167+
// synopsys translate_on
168+
169+
170+
171+
endmodule
172+
173+
`BSG_ABSTRACT_MODULE(bsg_mem_1r1w_sync_banked)

bsg_mem/bsg_mem_1r1w_sync_mask_write_bit.v

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module bsg_mem_1r1w_sync_mask_write_bit #(parameter `BSG_INV_PARAM(width_p)
1313
// 1r1w SRAM without changing timing.
1414
// fixme: change to write_then_read_same_addr_p
1515
, parameter read_write_same_addr_p=0
16+
, parameter latch_last_read_p=0
1617
, parameter addr_width_lp=`BSG_SAFE_CLOG2(els_p)
1718
, parameter harden_p=0
1819
, parameter disable_collision_warning_p=0
@@ -52,6 +53,7 @@ module bsg_mem_1r1w_sync_mask_write_bit #(parameter `BSG_INV_PARAM(width_p)
5253
#(.width_p(width_p)
5354
,.els_p (els_p )
5455
,.read_write_same_addr_p(read_write_same_addr_p)
56+
,.latch_last_read_p(latch_last_read_p)
5557
,.disable_collision_warning_p(disable_collision_warning_p)
5658
) synth
5759
(.clk_i(clk_lo)

bsg_mem/bsg_mem_1r1w_sync_mask_write_bit_synth.v

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module bsg_mem_1r1w_sync_mask_write_bit_synth #(parameter `BSG_INV_PARAM(width_p
1414
, parameter `BSG_INV_PARAM(els_p)
1515
, parameter read_write_same_addr_p=0
1616
, parameter addr_width_lp=`BSG_SAFE_CLOG2(els_p)
17+
, parameter latch_last_read_p=0
1718
, parameter disable_collision_warning_p=1
1819
)
1920
(input clk_i
@@ -42,6 +43,8 @@ module bsg_mem_1r1w_sync_mask_write_bit_synth #(parameter `BSG_INV_PARAM(width_p
4243
begin: nz
4344

4445
logic [width_p-1:0] mem [els_p-1:0];
46+
logic read_en;
47+
logic [width_p-1:0] data_out;
4548

4649
// this treats the ram as an array of registers for which the
4750
// read addr is latched on the clock, the write
@@ -64,6 +67,10 @@ module bsg_mem_1r1w_sync_mask_write_bit_synth #(parameter `BSG_INV_PARAM(width_p
6467

6568
logic [addr_width_lp-1:0] r_addr_r;
6669

70+
assign read_en = r_v_i;
71+
assign data_out = mem[r_addr_r];
72+
73+
6774
always_ff @(posedge clk_i)
6875
begin
6976
if (r_v_i)
@@ -87,8 +94,31 @@ module bsg_mem_1r1w_sync_mask_write_bit_synth #(parameter `BSG_INV_PARAM(width_p
8794

8895
end
8996

90-
assign r_data_o = mem[r_addr_r];
91-
97+
if (latch_last_read_p)
98+
begin: llr
99+
logic read_en_r;
100+
101+
bsg_dff #(
102+
.width_p(1)
103+
) read_en_dff (
104+
.clk_i(clk_i)
105+
,.data_i(read_en)
106+
,.data_o(read_en_r)
107+
);
108+
109+
bsg_dff_en_bypass #(
110+
.width_p(width_p)
111+
) dff_bypass (
112+
.clk_i(clk_i)
113+
,.en_i(read_en_r)
114+
,.data_i(data_out)
115+
,.data_o(r_data_o)
116+
);
117+
end
118+
else
119+
begin: no_llr
120+
assign r_data_o = data_out;
121+
end
92122

93123
genvar i;
94124
for (i = 0; i < width_p; i=i+1)
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// MBT 7/7/2016
2+
//
3+
// 1 read-port, 1 write-port ram
4+
//
5+
// reads are synchronous
6+
7+
`include "bsg_defines.v"
8+
9+
module bsg_mem_1r1w_sync_mask_write_byte #(parameter `BSG_INV_PARAM(width_p)
10+
, parameter `BSG_INV_PARAM(els_p)
11+
// semantics of "1" are write occurs, then read
12+
// the other semantics cannot be simulated on a hardened, non-simultaneous
13+
// 1r1w SRAM without changing timing.
14+
// fixme: change to write_then_read_same_addr_p
15+
, parameter read_write_same_addr_p=0
16+
, parameter latch_last_read_p=0
17+
, parameter addr_width_lp=`BSG_SAFE_CLOG2(els_p)
18+
, parameter harden_p=0
19+
, parameter disable_collision_warning_p=0
20+
, parameter write_mask_width_lp = width_p>>3
21+
, parameter enable_clock_gating_p=0
22+
)
23+
(input clk_i
24+
, input reset_i
25+
26+
, input w_v_i
27+
// for each bit set in the mask, a byte is written
28+
,input [`BSG_SAFE_MINUS(write_mask_width_lp, 1):0] w_mask_i
29+
, input [addr_width_lp-1:0] w_addr_i
30+
, input [`BSG_SAFE_MINUS(width_p, 1):0] w_data_i
31+
32+
, input r_v_i
33+
, input [addr_width_lp-1:0] r_addr_i
34+
35+
, output logic [`BSG_SAFE_MINUS(width_p, 1):0] r_data_o
36+
);
37+
38+
wire clk_lo;
39+
40+
if (enable_clock_gating_p)
41+
begin
42+
bsg_clkgate_optional icg
43+
(.clk_i( clk_i )
44+
,.en_i( w_v_i | r_v_i )
45+
,.bypass_i( 1'b0 )
46+
,.gated_clock_o( clk_lo )
47+
);
48+
end
49+
else
50+
begin
51+
assign clk_lo = clk_i;
52+
end
53+
54+
bsg_mem_1r1w_sync_mask_write_byte_synth
55+
#(.width_p(width_p)
56+
,.els_p (els_p )
57+
,.read_write_same_addr_p(read_write_same_addr_p)
58+
,.latch_last_read_p(latch_last_read_p)
59+
,.harden_p(harden_p)
60+
,.disable_collision_warning_p(disable_collision_warning_p)
61+
) synth
62+
(.clk_i(clk_lo)
63+
,.reset_i
64+
,.w_v_i
65+
,.w_mask_i
66+
,.w_addr_i
67+
,.w_data_i
68+
,.r_v_i
69+
,.r_addr_i
70+
,.r_data_o
71+
);
72+
73+
//synopsys translate_off
74+
75+
/*
76+
always_ff @(negedge clk_lo)
77+
begin
78+
if (reset_i!==1'b1 & (r_v_i | w_v_i))
79+
$display("@@ w=%b w_addr=%x w_data=%x w_mask=%x r=%b r_addr=%x (%m)",w_v_i,w_addr_i,w_data_i,w_mask_i,r_v_i,r_addr_i);
80+
end
81+
*/
82+
83+
always_ff @(posedge clk_lo)
84+
if (w_v_i===1)
85+
begin
86+
assert ((reset_i === 'X) || (reset_i === 1'b1) || (w_addr_i < els_p))
87+
else $error("Invalid address %x to %m of size %x (reset_i = %b, w_v_i = %b, clk_lo = %b)\n", w_addr_i, els_p, reset_i, w_v_i, clk_lo);
88+
89+
assert ((reset_i === 'X) || (reset_i === 1'b1) || (~(r_addr_i == w_addr_i && w_v_i && r_v_i && !read_write_same_addr_p && !disable_collision_warning_p)))
90+
else
91+
begin
92+
$error("%m: Attempt to read and write same address reset_i %b, %x <= %x (mask %x)",reset_i, w_addr_i,w_data_i,w_mask_i);
93+
//$finish();
94+
end
95+
end
96+
97+
initial
98+
begin
99+
$display("## %L: instantiating width_p=%d, els_p=%d, read_write_same_addr_p=%d harden_p=%d (%m)",width_p,els_p,read_write_same_addr_p, harden_p);
100+
101+
if (disable_collision_warning_p)
102+
$display("## %m %L: disable_collision_warning_p is set; you should not have this on unless you have broken code. fix it!\n");
103+
end
104+
105+
//synopsys translate_on
106+
107+
108+
endmodule
109+
110+
`BSG_ABSTRACT_MODULE(bsg_mem_1r1w_sync_mask_write_byte)
111+

0 commit comments

Comments
 (0)