[libre-riscv-dev] pipeline sync issues
Luke Kenneth Casson Leighton
lkcl at lkcl.net
Tue Apr 9 14:03:24 BST 2019
pv = Signal(reset_less=True)
m.d.comb += p_i_valid.eq(self.p.i_valid_test)
m.d.comb += pv.eq(self.p.i_valid & self.p.o_ready)
m.d.comb += self.n.o_valid.eq(data_valid)
m.d.comb += self.p._o_ready.eq(~data_valid | self.n.i_ready_test)
m.d.sync += data_valid.eq(p_i_valid | \
(~self.n.i_ready_test & data_valid))
with m.If(pv):
m.d.sync += eq(r_data, self.stage.process(self.p.i_data))
m.d.comb += eq(self.n.o_data, r_data)
i think i'm beginning to understand what the bug is. senders need to
know on the *previous* cycle that it's safe for data to be sent,
whereas the above logic says that p.o_ready and n.o_valid say that the
data is ready to go in *this* cycle..
the data and its associated valid signal really do have to be set and
travel together.
m.d.comb += self.n.o_valid.eq(buf_full | p_i_valid)
m.d.comb += self.p._o_ready.eq(~buf_full)
m.d.sync += buf_full.eq(~self.n.i_ready_test & self.n.o_valid)
odata = Mux(buf_full, buf, self.stage.process(self.p.i_data))
m.d.comb += eq(self.n.o_data, odata)
m.d.sync += eq(buf, self.n.o_data)
this one (which i cut/paste and boolean-logic adapted from
BreakReadyStage) has p.o_ready set under circumstances that also don't
make sense
p_i_valid_p_o_ready.eq(p_i_valid & self.p.o_ready),
m.d.comb += eq(result, self.stage.process(self.p.i_data))
with m.If(p_i_valid_p_o_ready):
m.d.sync += [r_busy.eq(1), # output valid
eq(self.n.o_data, result), # update output
]
with m.Elif(n_i_ready):
m.d.sync += r_busy.eq(0) # ...so set output invalid
m.d.comb += self.n.o_valid.eq(r_busy)
m.d.comb += self.p._o_ready.eq(n_i_ready)
this one makes sense because:
* if PIvalid and POready are both high, the data is accepted
* if Niready is NOT true, NOvalid goes into a "holding" pattern.
l.
More information about the libre-riscv-dev
mailing list