Skip to content

Commit a6aa3c3

Browse files
committed
Done fifo initialization
1 parent 66ff427 commit a6aa3c3

10 files changed

+452
-243
lines changed

fifo_single_clock_ram.sv

Lines changed: 112 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//------------------------------------------------------------------------------
22
// fifo_single_clock_ram.sv
3+
// published as part of https://github.com/pConst/basic_verilog
34
// Konstantin Pavlov, pavlovconst@gmail.com
45
//------------------------------------------------------------------------------
56

@@ -15,15 +16,23 @@
1516
// - configurable depth and data width
1617
// - only "normal" mode is supported here, no FWFT mode
1718
// - protected against overflow and underflow
19+
// - simultaneous read and write operations supported BUT:
20+
// only read will happen if simultaneous rw from full fifo
21+
// only write will happen if simultaneous rw from empty fifo
22+
// Always honor empty and full flags!
1823
// - provides fifo contents initialization (!)
19-
//
24+
// - CAUTION! block RAMs do NOT support fifo contents REinitialization after reset
2025

2126

2227
/* --- INSTANTIATION TEMPLATE BEGIN ---
2328
2429
fifo_single_clock_ram #(
2530
.DEPTH( 8 ),
26-
.DATA_W( 32 )
31+
.DATA_W( 32 ),
32+
33+
// optional initialization
34+
.INIT_FILE( "fifo_single_clock_ram_init.mem" ),
35+
.INIT_CNT( 10 )
2736
) FF1 (
2837
.clk( clk ),
2938
.nrst( 1'b1 ),
@@ -43,19 +52,23 @@ fifo_single_clock_ram #(
4352

4453
module fifo_single_clock_ram #( parameter
4554

46-
//FWFT_MODE = "TRUE", // "TRUE" - first word fall-trrough" mode
47-
// "FALSE" - normal fifo mode
55+
FWFT_MODE = "TRUE", // "TRUE" - first word fall-trrough" mode
56+
// "FALSE" - normal fifo mode
57+
DEPTH = 8, // max elements count == DEPTH, DEPTH MUST be power of 2
58+
DEPTH_W = clogb2(DEPTH)+1, // elements counter width, extra bit to store
59+
// "fifo full" state, see cnt[] variable comments
60+
61+
DATA_W = 32, // data field width
4862

49-
DEPTH = 8, // max elements count == DEPTH, DEPTH MUST be power of 2
50-
DEPTH_W = $clog2(DEPTH)+1, // elements counter width, extra bit to store
51-
// "fifo full" state, see cnt[] variable comments
63+
RAM_STYLE = "", // "block","register","M10K","logic",...
5264

53-
DATA_W = 32, // data field width
54-
INIT_FILE = ""
65+
// optional initialization
66+
INIT_FILE = "", // .HEX or .MEM file to initialize fifo contents
67+
INIT_CNT = '0 // sets desired initial cnt[]
5568
)(
5669

5770
input clk,
58-
input nrst, // inverted reset
71+
input nrst, // inverted reset
5972

6073
// input port
6174
input w_req,
@@ -66,91 +79,107 @@ module fifo_single_clock_ram #( parameter
6679
output [DATA_W-1:0] r_data,
6780

6881
// helper ports
69-
output logic [DEPTH_W-1:0] cnt = '0,
82+
output logic [DEPTH_W-1:0] cnt = INIT_CNT[DEPTH_W-1:0],
7083
output logic empty,
7184
output logic full,
7285

7386
output logic fail
7487
);
7588

7689

77-
// read and write pointers
78-
logic [DEPTH_W-1:0] w_ptr = '0;
79-
logic [DEPTH_W-1:0] r_ptr = '0;
80-
81-
// filtered requests
82-
logic w_req_f;
83-
assign w_req_f = w_req && ~full;
84-
85-
logic r_req_f;
86-
assign r_req_f = r_req && ~empty;
87-
88-
89-
true_dual_port_write_first_2_clock_ram #(
90-
.RAM_WIDTH( DATA_W ),
91-
.RAM_DEPTH( DEPTH ),
92-
.INIT_FILE( INIT_FILE )
93-
) data_ram (
94-
.clka( clk ),
95-
.addra( w_ptr[DEPTH_W-1:0] ),
96-
.ena( w_req_f ),
97-
.wea( 1'b1 ),
98-
.dina( w_data[DATA_W-1:0] ),
99-
.douta( ),
100-
101-
.clkb( clk ),
102-
.addrb( r_ptr[DEPTH_W-1:0] ),
103-
.enb( r_req_f ),
104-
.web( 1'b0 ),
105-
.dinb( '0 ),
106-
.doutb( r_data[DATA_W-1:0] )
107-
);
108-
109-
110-
function [DEPTH_W-1:0] inc_ptr (
111-
input [DEPTH_W-1:0] ptr
112-
);
113-
114-
if( ptr[DEPTH_W-1:0] == DEPTH-1 ) begin
115-
inc_ptr[DEPTH_W-1:0] = '0;
116-
end else begin
117-
inc_ptr[DEPTH_W-1:0] = ptr[DEPTH_W-1:0] + 1'b1;
118-
end
119-
endfunction
120-
121-
122-
always_ff @(posedge clk) begin
123-
if ( ~nrst ) begin
124-
w_ptr[DEPTH_W-1:0] <= '0;
125-
r_ptr[DEPTH_W-1:0] <= '0;
126-
127-
cnt[DEPTH_W-1:0] <= '0;
128-
end else begin
129-
130-
if( w_req_f ) begin
131-
w_ptr[DEPTH_W-1:0] <= inc_ptr(w_ptr[DEPTH_W-1:0]);
132-
end
133-
134-
if( r_req_f ) begin
135-
r_ptr[DEPTH_W-1:0] <= inc_ptr(r_ptr[DEPTH_W-1:0]);
90+
// read and write pointers
91+
logic [DEPTH_W-1:0] w_ptr = INIT_CNT[DEPTH_W-1:0];
92+
logic [DEPTH_W-1:0] r_ptr = '0;
93+
94+
// filtered requests
95+
logic w_req_f;
96+
assign w_req_f = w_req && ~full;
97+
98+
logic r_req_f;
99+
assign r_req_f = r_req && ~empty;
100+
101+
102+
true_dual_port_write_first_2_clock_ram #(
103+
.RAM_WIDTH( DATA_W ),
104+
.RAM_DEPTH( DEPTH ),
105+
.RAM_STYLE( RAM_STYLE ), // "block","register","M10K","logic",...
106+
.INIT_FILE( INIT_FILE )
107+
) data_ram (
108+
.clka( clk ),
109+
.addra( w_ptr[DEPTH_W-1:0] ),
110+
.ena( w_req_f ),
111+
.wea( 1'b1 ),
112+
.dina( w_data[DATA_W-1:0] ),
113+
.douta( ),
114+
115+
.clkb( clk ),
116+
.addrb( r_ptr[DEPTH_W-1:0] ),
117+
.enb( r_req_f ),
118+
.web( 1'b0 ),
119+
.dinb( '0 ),
120+
.doutb( r_data[DATA_W-1:0] )
121+
);
122+
123+
124+
always_ff @(posedge clk) begin
125+
if ( ~nrst ) begin
126+
w_ptr[DEPTH_W-1:0] <= '0;
127+
r_ptr[DEPTH_W-1:0] <= '0;
128+
129+
cnt[DEPTH_W-1:0] <= '0;
130+
end else begin
131+
unique case ({w_req, r_req})
132+
2'b00: ; // nothing
133+
134+
2'b01: begin // reading out
135+
if( ~empty ) begin
136+
r_ptr[DEPTH_W-1:0] <= inc_ptr(r_ptr[DEPTH_W-1:0]);
137+
cnt[DEPTH_W-1:0] <= cnt[DEPTH_W-1:0] - 1'b1;
138+
end
139+
end
140+
141+
2'b10: begin // writing in
142+
if( ~full ) begin
143+
w_ptr[DEPTH_W-1:0] <= inc_ptr(w_ptr[DEPTH_W-1:0]);
144+
cnt[DEPTH_W-1:0] <= cnt[DEPTH_W-1:0] + 1'b1;
145+
end
146+
end
147+
148+
2'b11: begin // simultaneously reading and writing
149+
if( empty ) begin
150+
w_ptr[DEPTH_W-1:0] <= inc_ptr(w_ptr[DEPTH_W-1:0]);
151+
cnt[DEPTH_W-1:0] <= cnt[DEPTH_W-1:0] + 1'b1;
152+
end else if( full ) begin
153+
r_ptr[DEPTH_W-1:0] <= inc_ptr(r_ptr[DEPTH_W-1:0]);
154+
cnt[DEPTH_W-1:0] <= cnt[DEPTH_W-1:0] - 1'b1;
155+
end else begin
156+
w_ptr[DEPTH_W-1:0] <= inc_ptr(w_ptr[DEPTH_W-1:0]);
157+
r_ptr[DEPTH_W-1:0] <= inc_ptr(r_ptr[DEPTH_W-1:0]);
158+
//cnt[DEPTH_W-1:0] <= // data counter does not change here
159+
end
160+
end
161+
endcase
136162
end
163+
end
137164

138-
if( w_req_f && ~r_req_f ) begin
139-
cnt[DEPTH_W-1:0] <= cnt[DEPTH_W-1:0] + 1'b1;
140-
end else if( ~w_req_f && r_req_f ) begin
141-
cnt[DEPTH_W-1:0] <= cnt[DEPTH_W-1:0] - 1'b1;
142-
end
165+
always_comb begin
166+
empty = ( cnt[DEPTH_W-1:0] == '0 );
167+
full = ( cnt[DEPTH_W-1:0] == DEPTH );
143168

169+
fail = ( empty && r_req ) ||
170+
( full && w_req );
144171
end
145-
end
146172

147-
always_comb begin
148-
empty = ( cnt[DEPTH_W-1:0] == '0 );
149-
full = ( cnt[DEPTH_W-1:0] == DEPTH );
173+
function [DEPTH_W-1:0] inc_ptr (
174+
input [DEPTH_W-1:0] ptr
175+
);
176+
if( ptr[DEPTH_W-1:0] == DEPTH-1 ) begin
177+
inc_ptr[DEPTH_W-1:0] = '0;
178+
end else begin
179+
inc_ptr[DEPTH_W-1:0] = ptr[DEPTH_W-1:0] + 1'b1;
180+
end
181+
endfunction
150182

151-
fail = ( empty && r_req ) ||
152-
( full && w_req );
153-
end
183+
`include "clogb2.svh"
154184

155185
endmodule
156-

fifo_single_clock_ram_init.mem

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
ABCD
2+
A001
3+
A002
4+
A003
5+
A004
6+
A005
7+
A006
8+
A007
9+
A008
10+
A009
11+
A00A
12+
A00B
13+
A00C
14+
A00D
15+
A00E
16+
A00F
17+
A001
18+
A002
19+
A001
20+
A002
21+
A001
22+
A002
23+
A001
24+
A002
25+
A001
26+
A002
27+
A001
28+
A002
29+
A001
30+
A002
31+
A001
32+
A002

0 commit comments

Comments
 (0)