@@ -187,3 +187,45 @@ comp DecimateTime[W, N]<'G: 1>(
187187 out = in;
188188 valid = eq.out;
189189}
190+
191+ // Takes a stream of signals with a valid tag and produces a block of size
192+ // N where all the signals are valid.
193+ //
194+ // `block_valid` is only asserted the unit at collected `N` valid signals after
195+ // which it resets.
196+ comp CollectValid[W, N]<'G:1>(
197+ en: interface['G],
198+ in: ['G, 'G+1] W,
199+ valid: ['G, 'G+1] 1
200+ ) -> (
201+ out[N]: ['G, 'G+1] W,
202+ block_valid: ['G, 'G+1] 1
203+ ) where W > 0 {
204+ let Bits = log2(N)+1; assume Bits > 0;
205+
206+ // Increment the index if the value on the stream is valid
207+ idx := new Prev[Bits, 1]<'G>(mux.out);
208+ one := new Const[Bits, 1]<'G>();
209+ add := new Add[Bits]<'G>(idx.prev, one.out);
210+ mux := new Mux[Bits]<'G>(valid, add.out, idx.prev);
211+
212+ // Are all the blocks valid?
213+ n := new Const[Bits, N]<'G>();
214+ n_sub_1 := new Sub[Bits]<'G>(n.out, one.out);
215+ max_reached := new Eq[Bits]<'G>(n_sub_1.out, idx.prev);
216+ block_valid = max_reached.out;
217+
218+ // Take the location index points to within the output block and assign the
219+ // value to it (which then gets latched).
220+ zero := new Const[W, 0]<'G>();
221+ for i in 0..N {
222+ p := new Prev[W, 1]<'G>(next.out);
223+ v := new Const[Bits, i]<'G>();
224+ eq := new Eq[Bits]<'G>(v.out, idx.prev);
225+ eq_and_valid := new And[1]<'G>(eq.out, valid);
226+ assign_mux := new Mux[W]<'G>(eq_and_valid.out, in, p.prev);
227+ // max ? 0 : eq ? in : p;
228+ next := new Mux[W]<'G>(max_reached.out, zero.out, assign_mux.out);
229+ out{i} = p.prev;
230+ }
231+ }
0 commit comments