Skip to content

Commit d07d0ad

Browse files
committed
Added preview FIFO
1 parent bb246b3 commit d07d0ad

File tree

1 file changed

+207
-0
lines changed

1 file changed

+207
-0
lines changed

preview_fifo.sv

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
//------------------------------------------------------------------------------
2+
// preview_fifo.sv
3+
// Konstantin Pavlov, [email protected]
4+
//------------------------------------------------------------------------------
5+
6+
// INFO ------------------------------------------------------------------------
7+
// module performs just like an ordinany FIFO in show-ahead mode
8+
// the diffenence is that 0,1 or 2 words may be requested at once
9+
// reader can also "preview" future fifo elements without actually fetching it
10+
11+
12+
/* --- INSTANTIATION TEMPLATE BEGIN ---
13+
14+
preview_fifo #( parameter
15+
.WIDTH( 16 ),
16+
.DEPTH( 16 ),
17+
) pf (
18+
.clk( clk ),
19+
.nrst( nrst ),
20+
21+
// input port
22+
.wrreq( ),
23+
.ena( ),
24+
.id0( ),
25+
.id1( ),
26+
27+
// output port
28+
.valid( ),
29+
.shift_req_oh( ),
30+
.od( ),
31+
.od( )
32+
);
33+
34+
--- INSTANTIATION TEMPLATE END ---*/
35+
36+
37+
module preview_fifo #( parameter
38+
WIDTH = 32,
39+
DEPTH = 16, // should be power of 2
40+
41+
USED_W = $clog2(DEPTH)
42+
)(
43+
input clk,
44+
input nrst,
45+
46+
// input port
47+
output wrreq, // request to make a write
48+
input ena, // write data to fifo command
49+
input [WIDTH-1:0] id0, // preceding data word
50+
input [WIDTH-1:0] id1, // subsequent data word
51+
// both data words are written simultaneously
52+
53+
// output port
54+
output valid, // data outputs have valid data
55+
input [2:0] shift_req_oh, // 3'b001 - no shift
56+
// 3'b010 - shift one word
57+
// 3'b100 - shift two words at once
58+
output logic [WIDTH-1:0] od0, // first data word (preceding)
59+
output logic [WIDTH-1:0] od1, // seconfd dadta word (subsequent)
60+
61+
62+
// debug ports
63+
output logic fail = 1'b0
64+
);
65+
66+
67+
// pointer to the first data word
68+
logic ptr = 1'b0;
69+
70+
logic [WIDTH-1:0] fifo_d0;
71+
logic [WIDTH-1:0] fifo_d1;
72+
73+
logic rdreq0 = 1'b0;
74+
logic rdreq1 = 1'b0;
75+
76+
logic empty0;
77+
logic empty1;
78+
79+
logic full0;
80+
logic full1;
81+
82+
// usedw0[] == usedw1[] OR usedw0[] == (usedw1[]-1) combinations are possible
83+
logic [USED_W-1:0] usedw0;
84+
logic [USED_W-1:0] usedw1;
85+
86+
scfifo #(
87+
.LPM_WIDTH( WIDTH ),
88+
.LPM_NUMWORDS( DEPTH ),
89+
.LPM_WIDTHU( USED_W ),
90+
.LPM_SHOWAHEAD( "ON" ),
91+
.UNDERFLOW_CHECKING( "ON" ),
92+
.OVERFLOW_CHECKING( "ON" ),
93+
.ALMOST_FULL_VALUE( DEPTH-4 ),
94+
.ALMOST_EMPTY_VALUE( 0+4 ),
95+
.ENABLE_ECC( "FALSE" ),
96+
.ALLOW_RWCYCLE_WHEN_FULL( "ON" ),
97+
.USE_EAB( "ON" ),
98+
.MAXIMIZE_SPEED( 5 ),
99+
.DEVICE_FAMILY( "Cyclone V" )
100+
) internal_fifo0 (
101+
.clock( clk ),
102+
.aclr( 1'b0 ),
103+
.sclr( ~nrst ),
104+
105+
.data( id0[WIDTH-1:0] ),
106+
.wrreq( ena ),
107+
.rdreq( rdreq0 ),
108+
109+
.q( fifo_d0[WIDTH-1:0] ),
110+
.empty( empty0 ),
111+
.full( full0 ),
112+
.almost_full( ),
113+
.almost_empty( ),
114+
.usedw( usedw0[USED_W-1:0] ),
115+
.eccstatus( ) // [1:0]
116+
);
117+
118+
scfifo #(
119+
.LPM_WIDTH( WIDTH ),
120+
.LPM_NUMWORDS( DEPTH ),
121+
.LPM_WIDTHU( USED_W ),
122+
.LPM_SHOWAHEAD( "ON" ),
123+
.UNDERFLOW_CHECKING( "ON" ),
124+
.OVERFLOW_CHECKING( "ON" ),
125+
.ALMOST_FULL_VALUE( DEPTH-4 ),
126+
.ALMOST_EMPTY_VALUE( 0+4 ),
127+
.ENABLE_ECC( "FALSE" ),
128+
.ALLOW_RWCYCLE_WHEN_FULL( "ON" ),
129+
.USE_EAB( "ON" ),
130+
.MAXIMIZE_SPEED( 5 ),
131+
.DEVICE_FAMILY( "Cyclone V" )
132+
) internal_fifo1 (
133+
.clock( clk ),
134+
.aclr( 1'b0 ),
135+
.sclr( ~nrst ),
136+
137+
.data( id1[WIDTH-1:0] ),
138+
.wrreq( ena ),
139+
.rdreq( rdreq1 ),
140+
141+
.q( fifo_d1[WIDTH-1:0] ),
142+
.empty( empty1 ),
143+
.full( full1 ),
144+
.almost_full( ),
145+
.almost_empty( ),
146+
.usedw( usedw1[USED_W-1:0] ),
147+
.eccstatus( ) // [1:0]
148+
);
149+
150+
151+
always_ff @(posedge clk) begin
152+
if( ~nrst ) begin
153+
ptr <= 1'b0;
154+
fail <= 1'b0;
155+
end else begin
156+
if( ptr ) begin // d1 fifo has one extra unaligned word
157+
case( shift_req_oh[2:0] )
158+
3'b010: begin
159+
ptr <= ~ptr;
160+
od0[WIDTH-1:0] <= od1[WIDTH-1:0];
161+
od1[WIDTH-1:0] <= fifo_d1[WIDTH-1:0];
162+
rdreq0 = 1'b0;
163+
rdreq1 = 1'b1;
164+
end
165+
3'b100: begin
166+
//ptr <= ptr;
167+
od0[WIDTH-1:0] <= fifo_d0[WIDTH-1:0];
168+
od1[WIDTH-1:0] <= fifo_d1[WIDTH-1:0];
169+
rdreq0 = 1'b1;
170+
rdreq1 = 1'b1;
171+
end
172+
default: ; // do nothing
173+
endcase
174+
end else begin // aligned data
175+
unique case( shift_req_oh[2:0] )
176+
3'b010: begin
177+
ptr <= ~ptr;
178+
od0[WIDTH-1:0] <= od1[WIDTH-1:0];
179+
od1[WIDTH-1:0] <= fifo_d0[WIDTH-1:0];
180+
rdreq0 = 1'b1;
181+
rdreq1 = 1'b0;
182+
end
183+
3'b100: begin
184+
//ptr <= ptr;
185+
od0[WIDTH-1:0] <= fifo_d1[WIDTH-1:0];
186+
od1[WIDTH-1:0] <= fifo_d0[WIDTH-1:0];
187+
rdreq0 = 1'b1;
188+
rdreq1 = 1'b1;
189+
end
190+
default: ; // do nothing
191+
endcase
192+
end // if
193+
194+
if( |shift_req_oh[2:1] && empty0 ) begin
195+
fail <= 1'b1;
196+
end
197+
198+
end // ~nrst
199+
end
200+
201+
// valid is when both output ports show valid data
202+
assign valid = ~empty1;
203+
204+
// extra cycles for request and data propagation
205+
assign wrreq = (usedw0[USED_W-1:0] < (DEPTH-4));
206+
207+
endmodule

0 commit comments

Comments
 (0)