diff --git a/litedram/frontend/wishbone.py b/litedram/frontend/wishbone.py index 966439b..911a56d 100644 --- a/litedram/frontend/wishbone.py +++ b/litedram/frontend/wishbone.py @@ -36,37 +36,44 @@ class LiteDRAMWishbone2Native(Module): adr_offset = base_address >> log2_int(port.data_width//8) - # latch ready signals of cmd/wdata and then wait until all are ready - cmd_consumed = Signal() - wdata_consumed = Signal() - self.sync += [ - If(wishbone.ack, - cmd_consumed.eq(0), - wdata_consumed.eq(0), - ).Else( - If(port.cmd.valid & port.cmd.ready, cmd_consumed.eq(1)), - If(port.wdata.valid & port.wdata.ready, wdata_consumed.eq(1)), - ), - ] - - ack_cmd = Signal() - ack_wdata = Signal() - ack_rdata = Signal() + # Write Datapath --------------------------------------------------------------------------- self.comb += [ - port.cmd.addr.eq(wishbone.adr - adr_offset), - port.cmd.we.eq(wishbone.we), port.wdata.data.eq(wishbone.dat_w), port.wdata.we.eq(wishbone.sel), - wishbone.dat_r.eq(port.rdata.data), - # always wait for reads, flush write when transaction ends - port.flush.eq(~wishbone.cyc), - port.cmd.last.eq(~wishbone.we), - # make sure cmd/wdata won't stay valid after it is consumed - port.cmd.valid.eq(wishbone.cyc & wishbone.stb & ~cmd_consumed), - port.wdata.valid.eq((port.cmd.valid | cmd_consumed) & port.cmd.we & ~wdata_consumed), - port.rdata.ready.eq((port.cmd.valid | cmd_consumed) & ~port.cmd.we), - wishbone.ack.eq(ack_cmd & ((wishbone.we & ack_wdata) | (~wishbone.we & ack_rdata))), - ack_cmd.eq((port.cmd.valid & port.cmd.ready) | cmd_consumed), - ack_wdata.eq((port.wdata.valid & port.wdata.ready) | wdata_consumed), - ack_rdata.eq(port.rdata.valid & port.rdata.ready), ] + + # Read Datapath ---------------------------------------------------------------------------- + self.comb += [ + wishbone.dat_r.eq(port.rdata.data), + ] + + # Control ---------------------------------------------------------------------------------- + self.submodules.fsm = fsm = FSM(reset_state="CMD") + fsm.act("CMD", + port.flush.eq(~wishbone.cyc), # Flush write when transaction ends. + port.cmd.last.eq(~wishbone.we), # Always wait for reads. + port.cmd.valid.eq(wishbone.cyc & wishbone.stb), + port.cmd.we.eq(wishbone.we), + port.cmd.addr.eq(wishbone.adr - adr_offset), + If(port.cmd.valid & port.cmd.ready, + If(wishbone.we, + NextState("WAIT-WRITE") + ).Else( + NextState("WAIT-READ") + ) + ) + ) + fsm.act("WAIT-WRITE", + port.wdata.valid.eq(1), + If(port.wdata.ready, + wishbone.ack.eq(1), + NextState("CMD") + ) + ) + fsm.act("WAIT-READ", + port.rdata.ready.eq(1), + If(port.rdata.valid, + wishbone.ack.eq(1), + NextState("CMD") + ) + )