diff --git a/litex/soc/interconnect/axi.py b/litex/soc/interconnect/axi.py index 5cb1e9add..f9dd20784 100644 --- a/litex/soc/interconnect/axi.py +++ b/litex/soc/interconnect/axi.py @@ -66,66 +66,54 @@ class AXIInterface(Record): # AXI Bursts to Beats ------------------------------------------------------------------------------ class AXIBurst2Beat(Module): - def __init__(self, ax_burst, ax_beat): + def __init__(self, ax_burst, ax_beat, capabilities={BURST_FIXED, BURST_INCR, BURST_WRAP}): + assert BURST_FIXED in capabilities # # # - self.count = count = Signal(8) - size = Signal(8 + 4) - offset = Signal(8 + 4) + beat_count = Signal(8) + beat_size = Signal(8 + 4) + beat_offset = Signal(8 + 4) + beat_wrap = Signal(8 + 4) - # convert burst size to bytes - cases = {} - cases["default"] = size.eq(1024) - for i in range(10): - cases[i] = size.eq(2**i) - self.comb += Case(ax_burst.size, cases) + # compute parameters + self.comb += beat_size.eq(1 << ax_burst.size) + self.comb += beat_wrap.eq(ax_burst.len*beat_size) - # fsm - self.submodules.fsm = fsm = FSM(reset_state="IDLE") - fsm.act("IDLE", - ax_beat.valid.eq(ax_burst.valid), - ax_beat.first.eq(1), - ax_beat.last.eq(ax_burst.len == 0), - ax_beat.addr.eq(ax_burst.addr), + # combinatorial logic + self.comb += [ + ax_beat.valid.eq(ax_burst.valid | ~ax_beat.first), + ax_beat.first.eq(beat_count == 0), + ax_beat.last.eq(beat_count == ax_burst.len), + ax_beat.addr.eq(ax_burst.addr + beat_offset), ax_beat.id.eq(ax_burst.id), - If(ax_beat.valid & ax_beat.ready, - If(ax_burst.len != 0, - NextState("BURST2BEAT") - ).Else( + If(ax_beat.ready, + If(ax_beat.last, ax_burst.ready.eq(1) ) - ), - NextValue(count, 1), - NextValue(offset, size), - ) - wrap_offset = Signal(8 + 4) - self.sync += wrap_offset.eq((ax_burst.len - 1)*size) - fsm.act("BURST2BEAT", - ax_beat.valid.eq(1), - ax_beat.first.eq(0), - ax_beat.last.eq(count == ax_burst.len), - If((ax_burst.burst == BURST_INCR) | - (ax_burst.burst == BURST_WRAP), - ax_beat.addr.eq(ax_burst.addr + offset) - ).Else( - ax_beat.addr.eq(ax_burst.addr) - ), - ax_beat.id.eq(ax_burst.id), + ) + ] + + # synchronous logic + self.sync += [ If(ax_beat.valid & ax_beat.ready, If(ax_beat.last, - ax_burst.ready.eq(1), - NextState("IDLE") + beat_count.eq(0), + beat_offset.eq(0) + ).Else( + beat_count.eq(beat_count + 1), + If(((ax_burst.burst == BURST_INCR) & (BURST_INCR in capabilities)) | + ((ax_burst.burst == BURST_WRAP) & (BURST_WRAP in capabilities)), + beat_offset.eq(beat_offset + beat_size) + ) ), - NextValue(count, count + 1), - NextValue(offset, offset + size), - If(ax_burst.burst == BURST_WRAP, - If(offset == wrap_offset, - NextValue(offset, 0) + If((ax_burst.burst == BURST_WRAP) & (BURST_WRAP in capabilities), + If(beat_offset == beat_wrap, + beat_offset.eq(0) ) ) ) - ) + ] # AXI to Wishbone ---------------------------------------------------------------------------------- diff --git a/test/test_axi.py b/test/test_axi.py index 6c51caa82..c8d23880a 100644 --- a/test/test_axi.py +++ b/test/test_axi.py @@ -23,7 +23,7 @@ class Burst: offset = i*2**(self.size) r += [Beat(self.addr + offset)] elif self.type == BURST_WRAP: - offset = (i*2**(self.size))%((2**self.size)*(self.len)) + offset = (i*2**(self.size))%((2**self.size)*(self.len + 1)) r += [Beat(self.addr + offset)] else: r += [Beat(self.addr)]