1
1
// ------------------------------------------------------------------------------
2
2
// fifo_single_clock_reg_v1.sv
3
+ // published as part of https://github.com/pConst/basic_verilog
3
4
// Konstantin Pavlov, [email protected]
4
5
// ------------------------------------------------------------------------------
5
6
6
7
// INFO ------------------------------------------------------------------------
7
8
// Single-clock FIFO buffer implementation, also known as "queue"
8
9
//
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
+ //
9
14
// Features:
10
15
// - single clock operation
11
16
// - configurable depth and data width
14
19
// - simultaneous read and write operations supported if not full and not empty
15
20
// - only read operation is performed when (full && r_req && w_req)
16
21
// - only write operation is performed when (empty && r_req && w_req)
22
+ // - (new!) optional fifo contents initialization
17
23
//
18
24
// See also "lifo.sv" module for similar LIFO buffer implementation
19
25
23
29
fifo_single_clock_reg_v1 #(
24
30
.FWFT_MODE( "TRUE" ),
25
31
.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 )
27
37
) FF1 (
28
38
.clk( clk ),
29
39
.nrst( 1'b1 ),
@@ -45,16 +55,19 @@ module fifo_single_clock_reg_v1 #( parameter
45
55
46
56
FWFT_MODE = " TRUE" , // "TRUE" - first word fall-trrough" mode
47
57
// "FALSE" - normal fifo mode
48
-
49
58
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
51
60
// "fifo full" state, see cnt[] variable comments
52
61
53
- DATA_W = 32 // data field width
54
- )(
62
+ DATA_W = 32 , // data field width
55
63
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
+ )(
56
69
input clk,
57
- input nrst, // inverted reset
70
+ input nrst, // inverted reset
58
71
59
72
// input port
60
73
input w_req,
@@ -65,86 +78,108 @@ module fifo_single_clock_reg_v1 #( parameter
65
78
output logic [DATA_W - 1 : 0 ] r_data,
66
79
67
80
// helper ports
68
- output logic [DEPTH_W - 1 : 0 ] cnt = '0 ,
81
+ output logic [DEPTH_W - 1 : 0 ] cnt,
69
82
output logic empty,
70
83
output logic full,
71
84
72
85
output logic fail
73
86
);
74
87
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
77
105
78
- // data output buffer for normal fifo mode
79
- logic [DATA_W - 1 : 0 ] data_buf = '0 ;
80
106
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 ;
84
109
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[]
88
113
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;
91
117
118
+ logic r_req_f;
119
+ assign r_req_f = r_req && ~ empty;
92
120
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
102
121
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 ;
108
131
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
109
143
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
114
148
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
118
155
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
123
157
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
127
162
end
128
163
end
129
- end
130
-
131
164
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 );
135
168
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
139
175
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
141
177
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 );
144
181
end
145
182
146
- fail = ( empty && r_req ) ||
147
- ( full && w_req );
148
- end
183
+ `include " clogb2.svh"
149
184
150
185
endmodule
0 commit comments