Skip to content

Commit 9804067

Browse files
committed
Added fifo initialization
1 parent 68b33a1 commit 9804067

3 files changed

+154
-63
lines changed

fifo_single_clock_reg_v1.sv

+96-61
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
//------------------------------------------------------------------------------
22
// fifo_single_clock_reg_v1.sv
3+
// published as part of https://github.com/pConst/basic_verilog
34
// Konstantin Pavlov, [email protected]
45
//------------------------------------------------------------------------------
56

67
// INFO ------------------------------------------------------------------------
78
// Single-clock FIFO buffer implementation, also known as "queue"
89
//
10+
// I`ve made two variants of fifo_single_clock_reg module - v1 and v2
11+
// Both variants are valid, both operate identically from an outside observer`s
12+
// view. Only internal r/w pointers operation is different.
13+
//
914
// Features:
1015
// - single clock operation
1116
// - configurable depth and data width
@@ -14,6 +19,7 @@
1419
// - simultaneous read and write operations supported if not full and not empty
1520
// - only read operation is performed when (full && r_req && w_req)
1621
// - only write operation is performed when (empty && r_req && w_req)
22+
// - (new!) optional fifo contents initialization
1723
//
1824
// See also "lifo.sv" module for similar LIFO buffer implementation
1925

@@ -23,7 +29,11 @@
2329
fifo_single_clock_reg_v1 #(
2430
.FWFT_MODE( "TRUE" ),
2531
.DEPTH( 8 ),
26-
.DATA_W( 32 )
32+
.DATA_W( 32 ),
33+
34+
// optional initialization
35+
.INIT_FILE( "fifo_single_clock_reg_v1_init.svh" ),
36+
.INIT_CNT( 10 )
2737
) FF1 (
2838
.clk( clk ),
2939
.nrst( 1'b1 ),
@@ -45,16 +55,19 @@ module fifo_single_clock_reg_v1 #( parameter
4555

4656
FWFT_MODE = "TRUE", // "TRUE" - first word fall-trrough" mode
4757
// "FALSE" - normal fifo mode
48-
4958
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
59+
DEPTH_W = clogb2(DEPTH)+1, // elements counter width, extra bit to store
5160
// "fifo full" state, see cnt[] variable comments
5261

53-
DATA_W = 32 // data field width
54-
)(
62+
DATA_W = 32, // data field width
5563

64+
// optional initialization
65+
USE_INIT_FILE = "FALSE", // "TRUE" - uses special filethat provides init data
66+
// "FALSE" - initializes with '0
67+
INIT_CNT = '0 // sets desired initial cnt[]
68+
)(
5669
input clk,
57-
input nrst, // inverted reset
70+
input nrst, // inverted reset
5871

5972
// input port
6073
input w_req,
@@ -65,86 +78,108 @@ module fifo_single_clock_reg_v1 #( parameter
6578
output logic [DATA_W-1:0] r_data,
6679

6780
// helper ports
68-
output logic [DEPTH_W-1:0] cnt = '0,
81+
output logic [DEPTH_W-1:0] cnt,
6982
output logic empty,
7083
output logic full,
7184

7285
output logic fail
7386
);
7487

75-
// fifo data
76-
logic [DEPTH-1:0][DATA_W-1:0] data = '0;
88+
// fifo data
89+
logic [DEPTH-1:0][DATA_W-1:0] data;
90+
91+
// fofo initialization
92+
// Modelsim gives suppressable error here
93+
// "(vlog-7061) Variable 'data' driven in an always_ff block, may not be driven by any other process"
94+
generate
95+
initial begin
96+
if( USE_INIT_FILE ) begin
97+
`include "fifo_single_clock_reg_v1_init.svh"
98+
cnt[DEPTH_W-1:0] <= INIT_CNT[DEPTH_W-1:0];
99+
end else begin
100+
data <= '0;
101+
cnt[DEPTH_W-1:0] <= '0;
102+
end
103+
end // initial
104+
endgenerate
77105

78-
// data output buffer for normal fifo mode
79-
logic [DATA_W-1:0] data_buf = '0;
80106

81-
// cnt[] vector always holds fifo elements count
82-
// data[cnt[]] points to the first empty fifo slot
83-
// when fifo is full data[cnt[]] points "outside" of data[]
107+
// data output buffer for normal fifo mode
108+
logic [DATA_W-1:0] data_buf = '0;
84109

85-
// filtered requests
86-
logic w_req_f;
87-
assign w_req_f = w_req && ~full;
110+
// cnt[] vector always holds fifo elements count
111+
// data[cnt[]] points to the first empty fifo slot
112+
// when fifo is full data[cnt[]] points "outside" of data[]
88113

89-
logic r_req_f;
90-
assign r_req_f = r_req && ~empty;
114+
// filtered requests
115+
logic w_req_f;
116+
assign w_req_f = w_req && ~full;
91117

118+
logic r_req_f;
119+
assign r_req_f = r_req && ~empty;
92120

93-
integer i;
94-
always_ff @(posedge clk) begin
95-
if ( ~nrst ) begin
96-
data <= '0;
97-
cnt[DEPTH_W-1:0] <= '0;
98-
data_buf[DATA_W-1:0] <= '0;
99-
end else begin
100-
unique case ({w_req_f, r_req_f})
101-
2'b00: ; // nothing
102121

103-
2'b01: begin // reading out
104-
for ( i = (DEPTH-1); i > 0; i-- ) begin
105-
data[i-1] <= data[i];
106-
end
107-
cnt[DEPTH_W-1:0] <= cnt[DEPTH_W-1:0] - 1'b1;
122+
always_ff @(posedge clk) begin
123+
integer i;
124+
if ( ~nrst ) begin
125+
if( USE_INIT_FILE ) begin
126+
`include "fifo_single_clock_reg_v1_init.svh"
127+
cnt[DEPTH_W-1:0] <= INIT_CNT[DEPTH_W-1:0];
128+
end else begin
129+
data <= '0;
130+
cnt[DEPTH_W-1:0] <= '0;
108131
end
132+
data_buf[DATA_W-1:0] <= '0;
133+
end else begin
134+
unique case ({w_req_f, r_req_f})
135+
2'b00: ; // nothing
136+
137+
2'b01: begin // reading out
138+
for ( i = (DEPTH-1); i > 0; i=i-1 ) begin
139+
data[i-1] <= data[i];
140+
end
141+
cnt[DEPTH_W-1:0] <= cnt[DEPTH_W-1:0] - 1'b1;
142+
end
109143

110-
2'b10: begin // writing in
111-
data[cnt[DEPTH_W-1:0]] <= w_data[DATA_W-1:0];
112-
cnt[DEPTH_W-1:0] <= cnt[DEPTH_W-1:0] + 1'b1;
113-
end
144+
2'b10: begin // writing in
145+
data[cnt[DEPTH_W-1:0]] <= w_data[DATA_W-1:0];
146+
cnt[DEPTH_W-1:0] <= cnt[DEPTH_W-1:0] + 1'b1;
147+
end
114148

115-
2'b11: begin // simultaneously reading and writing
116-
for ( i = (DEPTH-1); i > 0; i-- ) begin
117-
data[i-1] <= data[i];
149+
2'b11: begin // simultaneously reading and writing
150+
for ( i = (DEPTH-1); i > 0; i=i-1 ) begin
151+
data[i-1] <= data[i];
152+
end
153+
data[cnt[DEPTH_W-1:0]-1] <= w_data[DATA_W-1:0];
154+
// data counter does not change here
118155
end
119-
data[cnt[DEPTH_W-1:0]-1] <= w_data[DATA_W-1:0];
120-
// data counter does not change here
121-
end
122-
endcase
156+
endcase
123157

124-
// data buffer works only for normal fifo mode
125-
if( r_req_f ) begin
126-
data_buf[DATA_W-1:0] <= data[0];
158+
// data buffer works only for normal fifo mode
159+
if( r_req_f ) begin
160+
data_buf[DATA_W-1:0] <= data[0];
161+
end
127162
end
128163
end
129-
end
130-
131164

132-
always_comb begin
133-
empty = ( cnt[DEPTH_W-1:0] == '0 );
134-
full = ( cnt[DEPTH_W-1:0] == DEPTH );
165+
always_comb begin
166+
empty = ( cnt[DEPTH_W-1:0] == '0 );
167+
full = ( cnt[DEPTH_W-1:0] == DEPTH );
135168

136-
if( FWFT_MODE == "TRUE" ) begin
137-
if (~empty) begin
138-
r_data[DATA_W-1:0] = data[0]; // first-word fall-through mode
169+
if( FWFT_MODE == "TRUE" ) begin
170+
if( ~empty ) begin
171+
r_data[DATA_W-1:0] = data[0]; // first-word fall-through mode
172+
end else begin
173+
r_data[DATA_W-1:0] = '0;
174+
end
139175
end else begin
140-
r_data[DATA_W-1:0] = '0;
176+
r_data[DATA_W-1:0] = data_buf[DATA_W-1:0]; // normal mode
141177
end
142-
end else begin
143-
r_data[DATA_W-1:0] = data_buf[DATA_W-1:0]; // normal mode
178+
179+
fail = ( empty && r_req ) ||
180+
( full && w_req );
144181
end
145182

146-
fail = ( empty && r_req ) ||
147-
( full && w_req );
148-
end
183+
`include "clogb2.svh"
149184

150185
endmodule

fifo_single_clock_reg_v1_init.svh

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//------------------------------------------------------------------------------
2+
// fifo_single_clock_reg_v1_init.svh
3+
// published as part of https://github.com/pConst/basic_verilog
4+
// Konstantin Pavlov, [email protected]
5+
//------------------------------------------------------------------------------
6+
7+
// INFO ------------------------------------------------------------------------
8+
// Initialization statements example for fifo_single_clock_reg_v1 fifo
9+
//
10+
11+
data[0] <= 32'hAAAA;
12+
data[1] <= 32'h0001;
13+
data[2] <= 32'h0002;
14+
data[3] <= 32'h0003;
15+
data[4] <= 32'h0004;
16+
data[5] <= 32'h0005;
17+
data[6] <= 32'h0006;
18+
data[7] <= 32'h0007;
19+
data[8] <= 32'hBBBB;
20+
data[9] <= 32'h0001;
21+
data[10] <= 32'h0002;
22+
data[11] <= 32'h0003;
23+
data[12] <= 32'h0004;
24+
data[13] <= 32'h0005;
25+
data[14] <= 32'h0006;
26+
data[15] <= 32'h0007;
27+
data[16] <= 32'hCCCC;
28+
data[17] <= 32'h0001;
29+
data[18] <= 32'h0002;
30+
data[19] <= 32'h0003;
31+
data[20] <= 32'h0004;
32+
data[21] <= 32'h0005;
33+
data[22] <= 32'h0006;
34+
data[23] <= 32'h0007;
35+
data[24] <= 32'hDDDD;
36+
data[25] <= 32'h0001;
37+
data[26] <= 32'h0002;
38+
data[27] <= 32'h0003;
39+
data[28] <= 32'h0004;
40+
data[29] <= 32'h0005;
41+
data[30] <= 32'h0006;
42+
data[31] <= 32'h0007;
43+

fifo_single_clock_reg_v1_tb.sv

+15-2
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,14 @@ end
9494
//`define TEST_FWFT yes
9595

9696
// comment or uncomment to sweep-test or random test
97-
//`define TEST_SWEEP yes
97+
`define TEST_SWEEP yes
9898

9999
// comment or uncomment to use bare scfifo or quartus wizard-generated wrappers
100100
//`define BARE_SCFIFO yes
101101

102+
// initialization is not supported for Altera fifo
103+
`define TEST_INIT yes
104+
102105
logic full1, empty1;
103106
logic full1_d1, empty1_d1;
104107

@@ -131,10 +134,20 @@ fifo_single_clock_reg_v1 #(
131134
.FWFT_MODE( "FALSE" ),
132135
`endif
133136
.DEPTH( 8 ),
134-
.DATA_W( 16 )
137+
.DATA_W( 16 ),
138+
139+
`ifdef TEST_INIT
140+
// optional initialization
141+
.USE_INIT_FILE( "TRUE" ),
142+
.INIT_CNT( 10 )
143+
`endif
135144
) FF1 (
136145
.clk( clk200 ),
146+
`ifdef TEST_INIT
147+
.nrst( 1'b1 ),
148+
`else
137149
.nrst( nrst_once ),
150+
`endif
138151

139152
`ifdef TEST_SWEEP
140153
.w_req( ~direction1 && &RandomNumber1[10] ),

0 commit comments

Comments
 (0)