4
4
// ------------------------------------------------------------------------------
5
5
6
6
// 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
10
19
11
20
12
21
/* --- INSTANTIATION TEMPLATE BEGIN ---
13
22
14
23
lifo #(
24
+ .FWFT_MODE( "TRUE" ),
15
25
.DEPTH( 8 ),
16
26
.DATA_W( 32 )
17
- ) FF1 (
27
+ ) LF1 (
18
28
.clk( clk ),
19
- .rst ( 1'b0 ),
29
+ .nrst ( 1'b1 ),
20
30
21
31
.w_req( ),
22
32
.w_data( ),
@@ -33,15 +43,18 @@ lifo #(
33
43
34
44
module lifo # ( parameter
35
45
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
37
50
DEPTH_W = $clog2(DEPTH )+ 1 , // elements counter width, extra bit to store
38
51
// "fifo full" state, see cnt[] variable comments
39
52
40
53
DATA_W = 32 // data field width
41
54
)(
42
55
43
56
input clk,
44
- input rst , // non- inverted reset
57
+ input nrst , // inverted reset
45
58
46
59
// input port
47
60
input w_req,
@@ -52,59 +65,79 @@ module lifo #( parameter
52
65
output logic [DATA_W - 1 : 0 ] r_data,
53
66
54
67
// helper ports
55
- output logic [DATA_W - 1 : 0 ] cnt = 0 ,
68
+ output logic [DEPTH_W - 1 : 0 ] cnt = ' 0 ,
56
69
output logic empty,
57
70
output logic full,
58
71
59
72
output logic fail
60
73
);
61
74
62
75
// 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 ;
64
80
65
81
// cnt[] vector always holds lifo elements count
66
82
// data[cnt[]] points to the first empty lifo slot
67
83
// when lifo is full data[cnt[]] points "outside" of data[]
68
84
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;
71
91
92
+
93
+ integer i;
72
94
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 ;
76
99
end else begin
77
- case ({ w_req, r_req} )
100
+ unique case ({ w_req_f, r_req_f} )
101
+ 2'b00 : ; // nothing
102
+
78
103
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] ;
81
106
end
107
+ cnt[DEPTH_W - 1 : 0 ] <= cnt[DEPTH_W - 1 : 0 ] - 1'b1 ;
82
108
end
109
+
83
110
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 ;
88
113
end
114
+
89
115
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
94
118
end
95
- default : ;
96
119
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
97
125
end
98
126
end
99
127
100
- always_comb begin
101
- empty = ( cnt[DATA_W - 1 : 0 ] == 0 );
102
- full = ( cnt[DATA_W - 1 : 0 ] == DEPTH );
103
128
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
106
139
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
108
141
end
109
142
110
143
fail = ( empty && r_req ) ||
0 commit comments