fwft=True, pipe=False):
""" FIFO Control
- * :depth: number of entries in the FIFO
- * :stage: data processing block
- * :fwft: first word fall-thru mode (non-fwft introduces delay)
- * :buffered: use buffered FIFO (introduces extra cycle delay)
+ * :depth: number of entries in the FIFO
+ * :stage: data processing block
+ * :fwft: first word fall-thru mode (non-fwft introduces delay)
+ * :pipe: specifies pipe mode.
- NOTE 1: FPGAs may have trouble with the defaults for SyncFIFO
- (fwft=True, buffered=False). XXX TODO: fix this by
- using Queue in all cases instead.
+ when fwft = True it indicates that transfers may occur
+ combinatorially through stage processing in the same clock cycle.
+ This requires that the Stage be a Moore FSM:
+ https://en.wikipedia.org/wiki/Moore_machine
+
+ when fwft = False it indicates that all output signals are
+ produced only from internal registers or memory, i.e. that the
+ Stage is a Mealy FSM:
+ https://en.wikipedia.org/wiki/Mealy_machine
data is processed (and located) as follows:
fifo = Queue(fwidth, self.fdepth, fwft=self.fwft, pipe=self.pipe)
m.submodules.fifo = fifo
- # store result of processing in combinatorial temporary
- result = _spec(self.stage.ospec, "r_temp")
- m.d.comb += nmoperator.eq(result, self.data_r)
+ def processfn(data_i):
+ # store result of processing in combinatorial temporary
+ result = _spec(self.stage.ospec, "r_temp")
+ m.d.comb += nmoperator.eq(result, self.process(data_i))
+ return nmoperator.cat(result)
+
+ ## prev: make the FIFO "look" like a PrevControl...
+ m.submodules.fp = fp = PrevControl()
+ fp.valid_i, fp._ready_o, fp.data_i = fifo.we, fifo.writable, fifo.din
+ m.d.comb += fp._connect_in(self.p, fn=processfn)
+
+ # next: make the FIFO "look" like a NextControl...
+ m.submodules.fn = fn = NextControl()
+ fn.valid_o, fn.ready_i, fn.data_o = fifo.readable, fifo.re, fifo.dout
+ connections = fn._connect_out(self.n, fn=nmoperator.cat)
- # connect previous rdy/valid/data - do cat on data_i
- # NOTE: cannot do the PrevControl-looking trick because
- # of need to process the data. shaaaame....
- m.d.comb += [fifo.we.eq(self.p.valid_i_test),
- self.p.ready_o.eq(fifo.writable),
- nmoperator.eq(fifo.din, nmoperator.cat(result)),
- ]
-
- # connect next rdy/valid/data - do cat on data_o (further below)
- connections = [self.n.valid_o.eq(fifo.readable),
- fifo.re.eq(self.n.ready_i_test),
- ]
+ # ok ok so we can't just do the ready/valid eqs straight:
+ # first 2 from connections are the ready/valid, 3rd is data.
if self.fwft:
- m.d.comb += connections # combinatorial on next ready/valid
+ m.d.comb += connections[:2] # combinatorial on next ready/valid
else:
- m.d.sync += connections # unbuffered fwft mode needs sync
- data_o = nmoperator.cat(self.n.data_o).eq(fifo.dout)
+ m.d.sync += connections[:2] # unbuffered fwft mode needs sync
+ data_o = connections[2]
data_o = self._postprocess(data_o) # XXX TBD, does nothing right now
m.d.comb += data_o