[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.


More information about the libre-riscv-dev mailing list