Skip to content

Commit 2845a2a

Browse files
committed
Updated lifo module to support FWFT and normal modes
1 parent 452b357 commit 2845a2a

File tree

2 files changed

+141
-61
lines changed

2 files changed

+141
-61
lines changed

lifo.sv

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,29 @@
44
//------------------------------------------------------------------------------
55

66
// INFO ------------------------------------------------------------------------
7-
// Simple single-clock LIFO buffer implementation, also known as "stack"
8-
// Features one write- and one read- port in FWFT mode
9-
// See also "fifo.sv" module for similar FIFO buffer implementation
7+
// Single-clock LIFO buffer implementation, also known as "stack"
8+
//
9+
// Features:
10+
// - single clock operation
11+
// - configurable depth and data width
12+
// - one write- and one read- port in "FWFT" or "normal" mode
13+
// - protected against overflow and underflow
14+
// - simultaneous read and write operations supported if not full and not empty
15+
// - only read operation is performed when (full && r_req && w_req)
16+
// - only write operation is performed when (empty && r_req && w_req)
17+
//
18+
// See also "fifo_Single_clock_reg_*.sv" modules for similar FIFO buffer implementation
1019

1120

1221
/* --- INSTANTIATION TEMPLATE BEGIN ---
1322
1423
lifo #(
24+
.FWFT_MODE( "TRUE" ),
1525
.DEPTH( 8 ),
1626
.DATA_W( 32 )
17-
) FF1 (
27+
) LF1 (
1828
.clk( clk ),
19-
.rst( 1'b0 ),
29+
.nrst( 1'b1 ),
2030
2131
.w_req( ),
2232
.w_data( ),
@@ -33,15 +43,18 @@ lifo #(
3343

3444
module lifo #( parameter
3545

36-
DEPTH = 4, // max elements count == DEPTH, DEPTH MUST be power of 2
46+
FWFT_MODE = "TRUE", // "TRUE" - first word fall-trrough" mode
47+
// "FALSE" - normal fifo mode
48+
49+
DEPTH = 8, // max elements count == DEPTH, DEPTH MUST be power of 2
3750
DEPTH_W = $clog2(DEPTH)+1, // elements counter width, extra bit to store
3851
// "fifo full" state, see cnt[] variable comments
3952

4053
DATA_W = 32 // data field width
4154
)(
4255

4356
input clk,
44-
input rst, // non-inverted reset
57+
input nrst, // inverted reset
4558

4659
// input port
4760
input w_req,
@@ -52,59 +65,79 @@ module lifo #( parameter
5265
output logic [DATA_W-1:0] r_data,
5366

5467
// helper ports
55-
output logic [DATA_W-1:0] cnt = 0,
68+
output logic [DEPTH_W-1:0] cnt = '0,
5669
output logic empty,
5770
output logic full,
5871

5972
output logic fail
6073
);
6174

6275
// lifo data
63-
logic [DEPTH-1:0][DATA_W-1:0] data = 0;
76+
logic [DEPTH-1:0][DATA_W-1:0] data = '0;
77+
78+
// data output buffer for normal fifo mode
79+
logic [DATA_W-1:0] data_buf = '0;
6480

6581
// cnt[] vector always holds lifo elements count
6682
// data[cnt[]] points to the first empty lifo slot
6783
// when lifo is full data[cnt[]] points "outside" of data[]
6884

69-
// please take attention to the case when cnt[]==0 && r_req==1'b1 && w_req==1'b1
70-
// this case makes no read/write to the lifo and should be handled externally
85+
// filtered requests
86+
logic w_req_f;
87+
assign w_req_f = w_req && ~full;
88+
89+
logic r_req_f;
90+
assign r_req_f = r_req && ~empty;
7191

92+
93+
integer i;
7294
always_ff @(posedge clk) begin
73-
if ( rst ) begin
74-
data <= 0;
75-
cnt <= 0;
95+
if ( ~nrst ) begin
96+
data <= '0;
97+
cnt[DEPTH_W-1:0] <= '0;
98+
data_buf[DATA_W-1:0] <= '0;
7699
end else begin
77-
case ({w_req, r_req})
100+
unique case ({w_req_f, r_req_f})
101+
2'b00: ; // nothing
102+
78103
2'b01 : begin // reading out
79-
if ( cnt[DATA_W-1:0] > 1'b0 ) begin
80-
cnt[DATA_W-1:0] <= cnt[DATA_W-1:0] - 1'b1;
104+
for ( i = (DEPTH-1); i > 0; i-- ) begin
105+
data[i-1] <= data[i];
81106
end
107+
cnt[DEPTH_W-1:0] <= cnt[DEPTH_W-1:0] - 1'b1;
82108
end
109+
83110
2'b10 : begin // writing in
84-
if ( ~full ) begin
85-
data[cnt[DATA_W-1:0]] <= w_data;
86-
cnt[DATA_W-1:0] <= cnt[DATA_W-1:0] + 1'b1;
87-
end
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;
88113
end
114+
89115
2'b11 : begin // simultaneously reading and writing
90-
if ( cnt[DATA_W-1:0] > 1'b0 ) begin
91-
data[cnt[DATA_W-1:0]-1] <= w_data;
92-
end
93-
// cnt[DATA_W-1:0] <= cnt[DATA_W-1:0]; // data counter does not change
116+
data[cnt[DEPTH_W-1:0]-1] <= w_data[DATA_W-1:0];
117+
// data counter does not change here
94118
end
95-
default: ;
96119
endcase
120+
121+
// data buffer works only for normal lifo mode
122+
if( r_req_f ) begin
123+
data_buf[DATA_W-1:0] <= data[0];
124+
end
97125
end
98126
end
99127

100-
always_comb begin
101-
empty = ( cnt[DATA_W-1:0] == 0 );
102-
full = ( cnt[DATA_W-1:0] == DEPTH );
103128

104-
if (~empty) begin
105-
r_data[DATA_W-1:0] = data[cnt[DATA_W-1:0]]; // first-word fall-through mode
129+
always_comb begin
130+
empty = ( cnt[DEPTH_W-1:0] == '0 );
131+
full = ( cnt[DEPTH_W-1:0] == DEPTH );
132+
133+
if( FWFT_MODE == "TRUE" ) begin
134+
if (~empty) begin
135+
r_data[DATA_W-1:0] = data[0]; // first-word fall-through mode
136+
end else begin
137+
r_data[DATA_W-1:0] = '0;
138+
end
106139
end else begin
107-
r_data[DATA_W-1:0] = 0;
140+
r_data[DATA_W-1:0] = data_buf[DATA_W-1:0]; // normal mode
108141
end
109142

110143
fail = ( empty && r_req ) ||

lifo_tb.sv

Lines changed: 76 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,24 @@ module lifo_tb();
1313

1414
logic clk200;
1515
initial begin
16-
#0 clk200 = 1;
16+
#0 clk200 = 1'b0;
1717
forever
1818
#2.5 clk200 = ~clk200;
1919
end
2020

21+
// external device "asynchronous" clock
22+
logic clk33;
23+
initial begin
24+
#0 clk33 = 1'b0;
25+
forever
26+
#15.151 clk33 = ~clk33;
27+
end
28+
2129
logic rst;
2230
initial begin
23-
#10.2 rst = 1;
24-
#5 rst = 0;
31+
#0 rst = 1'b0;
32+
#10.2 rst = 1'b1;
33+
#5 rst = 1'b0;
2534
//#10000;
2635
forever begin
2736
#9985 rst = ~rst;
@@ -33,29 +42,27 @@ logic nrst;
3342
assign nrst = ~rst;
3443

3544
logic rst_once;
36-
initial begin // initializing non-X data before PLL starts
37-
#10.2 rst_once = 1;
38-
#5 rst_once = 0;
39-
end
4045
initial begin
41-
#510.2 rst_once = 1; // PLL starts at 500ns, clock appears, so doing the reset for modules
42-
#5 rst_once = 0;
46+
#0 rst_once = 1'b0;
47+
#10.2 rst_once = 1'b1;
48+
#5 rst_once = 1'b0;
4349
end
4450

4551
logic nrst_once;
4652
assign nrst_once = ~rst_once;
4753

4854
logic [31:0] DerivedClocks;
49-
ClkDivider #(
55+
clk_divider #(
5056
.WIDTH( 32 )
51-
) CD1 (
57+
) cd1 (
5258
.clk( clk200 ),
5359
.nrst( nrst_once ),
60+
.ena( 1'b1 ),
5461
.out( DerivedClocks[31:0] )
5562
);
5663

5764
logic [31:0] E_DerivedClocks;
58-
EdgeDetect ED1[31:0] (
65+
edge_detect ed1[31:0] (
5966
.clk( {32{clk200}} ),
6067
.nrst( {32{nrst_once}} ),
6168
.in( DerivedClocks[31:0] ),
@@ -65,44 +72,84 @@ EdgeDetect ED1[31:0] (
6572
);
6673

6774
logic [15:0] RandomNumber1;
68-
c_rand RNG1 (
75+
c_rand rng1 (
6976
.clk(clk200),
7077
.rst(rst_once),
7178
.reseed(1'b0),
7279
.seed_val(DerivedClocks[31:0]),
73-
.out(RandomNumber1[15:0]));
80+
.out( RandomNumber1[15:0] )
81+
);
7482

75-
/*logic start;
83+
logic start;
7684
initial begin
7785
#0 start = 1'b0;
78-
#100.2 start = 1'b1;
79-
#5 start = 1'b0;
80-
end*/
81-
82-
logic read;
83-
initial begin
84-
#0 read = 1'b0;
85-
#1000.2 read = 1'b1;
86+
#100 start = 1'b1;
87+
#20 start = 1'b0;
8688
end
8789

90+
// Module under test ==========================================================
91+
92+
93+
// comment or uncomment to test FWFT and normal fifo modes
94+
//`define TEST_FWFT yes
8895

96+
// comment or uncomment to sweep-test or random test
97+
`define TEST_SWEEP yes
8998

99+
logic full1, empty1;
100+
logic full1_d1, empty1_d1;
101+
102+
logic direction1 = 1'b0;
103+
always_ff @(posedge clk200) begin
104+
if( ~nrst ) begin
105+
direction1 <= 1'b0;
106+
end else begin
107+
// sweep logic
108+
if( full1_d1 ) begin
109+
direction1 <= 1'b1;
110+
end else if( empty1_d1 ) begin
111+
direction1 <= 1'b0;
112+
end
113+
114+
// these signals allow "erroring" requests testing:
115+
// - reads from the empty fifo
116+
// - writes to the filled fifo
117+
full1_d1 <= full1;
118+
empty1_d1 <= empty1;
119+
end
120+
end
121+
122+
logic [3:0] cnt1;
123+
logic [15:0] data_out1;
90124
lifo #(
125+
`ifdef TEST_FWFT
126+
.FWFT_MODE( "TRUE" ),
127+
`else
128+
.FWFT_MODE( "FALSE" ),
129+
`endif
91130
.DEPTH( 8 ),
92131
.DATA_W( 16 )
93132
) LF1 (
94133
.clk( clk200 ),
95-
.rst( rst_once ),
134+
.nrst( nrst_once ),
135+
136+
`ifdef TEST_SWEEP
137+
.w_req( ~direction1 && &RandomNumber1[10] ),
138+
.w_data( RandomNumber1[15:0] ),
96139

140+
.r_req( direction1 && &RandomNumber1[10] ),
141+
.r_data( data_out1[15:0] ),
142+
`else
97143
.w_req( &RandomNumber1[10:9] ),
98144
.w_data( RandomNumber1[15:0] ),
99145

100-
.r_req( read ),
101-
.r_data( ),
146+
.r_req( &RandomNumber1[8:7] ),
147+
.r_data( data_out1[15:0] ),
148+
`endif
102149

103-
.cnt( ),
104-
.empty( ),
105-
.full( )
150+
.cnt( cnt1[3:0] ),
151+
.empty( empty1 ),
152+
.full( full1 )
106153
);
107154

108155

0 commit comments

Comments
 (0)