punk@1
|
1 import FIFO::*;
|
punk@1
|
2 import FIFOF::*;
|
punk@1
|
3 import List::*;
|
punk@1
|
4 import Assert::*;
|
punk@1
|
5
|
punk@1
|
6 module mkBFIFO1( FIFO#(item_t) ) provisos ( Bits#(item_t,item_sz) );
|
punk@1
|
7
|
punk@1
|
8 RWire#(item_t) inputWire <- mkRWire();
|
punk@1
|
9 PulseWire deqEnabled <- mkPulseWire();
|
punk@1
|
10 PulseWire clearEnabled <- mkPulseWire();
|
punk@1
|
11
|
punk@1
|
12 Reg#(item_t) register <- mkRegU();
|
punk@1
|
13 Reg#(Bool) valid <- mkReg(False);
|
punk@1
|
14
|
punk@1
|
15 // If there is an input item on the inputWire wire and dequeue did not
|
punk@1
|
16 // execute this cycle then we need to store the item in the register
|
punk@1
|
17
|
punk@1
|
18 (*fire_when_enabled*)
|
punk@1
|
19 rule update ( True );
|
punk@1
|
20 case (inputWire.wget()) matches
|
punk@1
|
21 tagged Invalid:
|
punk@1
|
22 if (deqEnabled || clearEnabled)
|
punk@1
|
23 valid <= False;
|
punk@1
|
24 tagged Valid .x:
|
punk@1
|
25 begin
|
punk@1
|
26 register <= x;
|
punk@1
|
27 valid <= !(deqEnabled || clearEnabled);
|
punk@1
|
28 end
|
punk@1
|
29 endcase
|
punk@1
|
30 endrule
|
punk@1
|
31
|
punk@1
|
32 // On enqueue we write the input item to the inputWire wire
|
punk@1
|
33
|
punk@1
|
34 method Action enq( item_t item ) if ( !valid );
|
punk@1
|
35 inputWire.wset(item);
|
punk@1
|
36 endmethod
|
punk@1
|
37
|
punk@1
|
38 // On dequeue we always invalidate the storage register regardless
|
punk@1
|
39 // of whether or not the item was actually bypassed or not. We also
|
punk@1
|
40 // set a combinational signal so that we know not to move the item
|
punk@1
|
41 // into the register this cycle.
|
punk@1
|
42
|
punk@1
|
43 method Action deq() if ( valid || isValid(inputWire.wget()) );
|
punk@1
|
44 deqEnabled.send();
|
punk@1
|
45 endmethod
|
punk@1
|
46
|
punk@1
|
47 // We get the item either from the register (if register is valid) or
|
punk@1
|
48 // from the combinational bypasss (if the rwire is valid).
|
punk@1
|
49
|
punk@1
|
50 method item_t first() if ( valid || isValid(inputWire.wget()) );
|
punk@1
|
51 if ( valid )
|
punk@1
|
52 return register;
|
punk@1
|
53 else
|
punk@1
|
54 return unJust(inputWire.wget());
|
punk@1
|
55 endmethod
|
punk@1
|
56
|
punk@1
|
57 method Action clear();
|
punk@1
|
58 clearEnabled.send();
|
punk@1
|
59 endmethod
|
punk@1
|
60
|
punk@1
|
61 endmodule
|
punk@1
|
62
|
punk@1
|
63 module mkSizedBFIFO#(Integer n) ( FIFO#(item_t) ) provisos ( Bits#(item_t,item_sz) );
|
punk@1
|
64
|
punk@1
|
65 RWire#(item_t) inputWire <- mkRWire();
|
punk@1
|
66 PulseWire deqEnabled <- mkPulseWire();
|
punk@1
|
67 PulseWire clearEnabled <- mkPulseWire();
|
punk@1
|
68
|
punk@1
|
69 List#(Reg#(item_t)) registers <- replicateM(n, mkRegU);
|
punk@1
|
70 List#(Reg#(Bool)) valids <- replicateM(n, mkReg(False));
|
punk@1
|
71
|
punk@1
|
72 function Nat getNextFree (List#(Reg#(Bool)) vs);
|
punk@1
|
73
|
punk@1
|
74 Nat res = fromInteger(n - 1);
|
punk@1
|
75
|
punk@1
|
76 for (Integer x = n - 1; x > -1; x = x - 1)
|
punk@1
|
77 res = !vs[x]._read() ? fromInteger(x) : res;
|
punk@1
|
78
|
punk@1
|
79 return res;
|
punk@1
|
80
|
punk@1
|
81 endfunction
|
punk@1
|
82
|
punk@1
|
83 function Bool notFull();
|
punk@1
|
84
|
punk@1
|
85 Bool full = True;
|
punk@1
|
86
|
punk@1
|
87 for (Integer x = 0; x < length(valids); x = x + 1)
|
punk@1
|
88 full = full && valids[x]._read();
|
punk@1
|
89
|
punk@1
|
90 return !full;
|
punk@1
|
91
|
punk@1
|
92 endfunction
|
punk@1
|
93 // If there is an input item on the inputWire wire and dequeue did not
|
punk@1
|
94 // execute this cycle then we need to store the item in the register
|
punk@1
|
95
|
punk@1
|
96 rule update ( True );
|
punk@1
|
97 Nat next = getNextFree(valids);
|
punk@1
|
98
|
punk@1
|
99 next = (deqEnabled) ? next - 1 : next;
|
punk@1
|
100
|
punk@1
|
101 (valids[next]) <= isValid(inputWire.wget());
|
punk@1
|
102 (registers[next]) <= validValue(inputWire.wget());
|
punk@1
|
103
|
punk@1
|
104 if (deqEnabled && !clearEnabled)
|
punk@1
|
105 begin
|
punk@1
|
106
|
punk@1
|
107 for (Nat x = 0; x < (next - 1); x = x + 1)
|
punk@1
|
108 begin
|
punk@1
|
109 (valids[x]) <= valids[x+1]._read();
|
punk@1
|
110 (registers[x]) <= registers[x+1]._read();
|
punk@1
|
111 end
|
punk@1
|
112
|
punk@1
|
113 end
|
punk@1
|
114 else if (clearEnabled)
|
punk@1
|
115 begin
|
punk@1
|
116
|
punk@1
|
117 for (Integer x = 0; x < n; x = x + 1)
|
punk@1
|
118 (valids[x]) <= False;
|
punk@1
|
119
|
punk@1
|
120 end
|
punk@1
|
121 endrule
|
punk@1
|
122
|
punk@1
|
123 // On enqueue we write the input item to the inputWire wire
|
punk@1
|
124
|
punk@1
|
125 method Action enq( item_t item ) if ( notFull );
|
punk@1
|
126 inputWire.wset(item);
|
punk@1
|
127 endmethod
|
punk@1
|
128
|
punk@1
|
129 // On dequeue we always invalidate the storage register regardless
|
punk@1
|
130 // of whether or not the item was actually bypassed or not. We also
|
punk@1
|
131 // set a combinational signal so that we know not to move the item
|
punk@1
|
132 // into the register this cycle.
|
punk@1
|
133
|
punk@1
|
134 method Action deq() if ( valids[0]._read() || isValid(inputWire.wget()) );
|
punk@1
|
135 deqEnabled.send();
|
punk@1
|
136 endmethod
|
punk@1
|
137
|
punk@1
|
138 // We get the item either from the register (if register is valid) or
|
punk@1
|
139 // from the combinational bypasss (if the rwire is valid).
|
punk@1
|
140
|
punk@1
|
141 method item_t first() if ( valids[0]._read() || isValid(inputWire.wget()) );
|
punk@1
|
142 if ( valids[0]._read() )
|
punk@1
|
143 return registers[0]._read();
|
punk@1
|
144 else
|
punk@1
|
145 return unJust(inputWire.wget());
|
punk@1
|
146 endmethod
|
punk@1
|
147
|
punk@1
|
148
|
punk@1
|
149 method Action clear();
|
punk@1
|
150 clearEnabled.send();
|
punk@1
|
151 endmethod
|
punk@1
|
152
|
punk@1
|
153 endmodule
|
punk@1
|
154
|
punk@1
|
155
|
punk@1
|
156 module mkBFIFOF1( FIFOF#(item_t) ) provisos ( Bits#(item_t,item_sz) );
|
punk@1
|
157
|
punk@1
|
158 RWire#(item_t) inputWire <- mkRWire();
|
punk@1
|
159 RWire#(Bool) deqEnabled <- mkRWire();
|
punk@1
|
160
|
punk@1
|
161 Reg#(Maybe#(item_t)) register <- mkReg(Invalid);
|
punk@1
|
162
|
punk@1
|
163 // If there is an input item on the inputWire wire and dequeue did not
|
punk@1
|
164 // execute this cycle then we need to store the item in the register
|
punk@1
|
165
|
punk@1
|
166 rule noDeq ( isValid(inputWire.wget()) && !isValid(deqEnabled.wget()) );
|
punk@1
|
167 register <= inputWire.wget();
|
punk@1
|
168 endrule
|
punk@1
|
169
|
punk@1
|
170 // On enqueue we write the input item to the inputWire wire
|
punk@1
|
171
|
punk@1
|
172 method Action enq( item_t item ) if ( !isValid(register) );
|
punk@1
|
173 inputWire.wset(item);
|
punk@1
|
174 endmethod
|
punk@1
|
175
|
punk@1
|
176 // On dequeue we always invalidate the storage register regardless
|
punk@1
|
177 // of whether or not the item was actually bypassed or not. We also
|
punk@1
|
178 // set a combinational signal so that we know not to move the item
|
punk@1
|
179 // into the register this cycle.
|
punk@1
|
180
|
punk@1
|
181 method Action deq() if ( isValid(register) || isValid(inputWire.wget()) );
|
punk@1
|
182 register <= Invalid;
|
punk@1
|
183 deqEnabled.wset(True);
|
punk@1
|
184 endmethod
|
punk@1
|
185
|
punk@1
|
186 // We get the item either from the register (if register is valid) or
|
punk@1
|
187 // from the combinational bypasss (if the rwire is valid).
|
punk@1
|
188
|
punk@1
|
189 method item_t first() if ( isValid(register) || isValid(inputWire.wget()) );
|
punk@1
|
190 if ( isValid(register) )
|
punk@1
|
191 return unJust(register);
|
punk@1
|
192 else
|
punk@1
|
193 return unJust(inputWire.wget());
|
punk@1
|
194 endmethod
|
punk@1
|
195
|
punk@1
|
196 // FIFOF adds the following two methods
|
punk@1
|
197
|
punk@1
|
198 method Bool notFull();
|
punk@1
|
199 return !isValid(register);
|
punk@1
|
200 endmethod
|
punk@1
|
201
|
punk@1
|
202 method Bool notEmpty();
|
punk@1
|
203 return (isValid(register) || isValid(inputWire.wget()));
|
punk@1
|
204 endmethod
|
punk@1
|
205
|
punk@1
|
206 // Not sure about the clear method ...
|
punk@1
|
207
|
punk@1
|
208 method Action clear();
|
punk@1
|
209 dynamicAssert( False, "BFIFO.clear() not implemented yet!" );
|
punk@1
|
210 endmethod
|
punk@1
|
211
|
punk@1
|
212 endmodule
|
punk@1
|
213
|
punk@1
|
214 (* synthesize *)
|
punk@1
|
215 module mkBFIFO_16 (FIFO#(Bit#(16)));
|
punk@1
|
216
|
punk@1
|
217 let f <- mkBFIFO1();
|
punk@1
|
218
|
punk@1
|
219 return f;
|
punk@1
|
220
|
punk@1
|
221 endmodule
|
punk@1
|
222
|