From 3a284b9c1ece996bad1e0d83c5d8edfed72ea16b Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 10 Jun 2013 22:29:39 +0200 Subject: [PATCH] actorlib: LASMI DMA (untested) --- migen/actorlib/dma_lasmi.py | 107 ++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 migen/actorlib/dma_lasmi.py diff --git a/migen/actorlib/dma_lasmi.py b/migen/actorlib/dma_lasmi.py new file mode 100644 index 00000000..3a0956e9 --- /dev/null +++ b/migen/actorlib/dma_lasmi.py @@ -0,0 +1,107 @@ +from migen.fhdl.std import * +from migen.flow.actor import * +from migen.genlib.fifo import SyncFIFO + +class Reader(Module): + def __init__(self, lasmim, fifo_depth=None): + self.address = Sink([("a", lasmim.aw)]) + self.data = Source([("d", lasmim.dw)]) + self.busy = Signal() + + ### + + if fifo_depth is None: + fifo_depth = lasmim.read_latency + 2 + assert(fifo_depth >= lasmim.read_latency) + + # request issuance + request_enable = Signal() + request_issued = Signal() + + self.comb += [ + self.bus.we.eq(0), + lasmim.stb.eq(self.address.stb & request_enable), + lasmim.adr.eq(self.address.payload.a), + self.address.ack.eq(lasmim.ack), + request_issued.eq(lasmim.stb & lasmim.ack) + ] + + # FIFO reservation level counter + # incremented when data is planned to be queued + # decremented when data is dequeued + data_dequeued = Signal() + rsv_level = Signal(max=fifo_depth+1) + self.sync += [ + If(request_issued, + If(~data_dequeued, rsv_level.eq(rsv_level + 1)) + ).Elif(data_dequeued, + rsv_level.eq(rsv_level - 1) + ) + ] + self.comb += [ + self.busy.eq(rsv_level != 0), + request_enable.eq(rsv_level != fifo_depth) + ] + + # data available + data_available = request_issued + for i in range(lasmim.read_latency): + new_data_available = Signal() + self.sync += new_data_available.eq(data_available) + data_available = new_data_available + + # FIFO + fifo = SyncFIFO(lasmim.dw, fifo_depth) + self.submodules += fifo + + self.comb += [ + fifo.din.eq(lasmim.dat_r), + fifo.we.eq(data_available), + + self.data.stb.eq(fifo.readable), + fifo.re.eq(self.data.ack), + self.data.payload.d.eq(fifo.dout), + data_dequeued.eq(self.data.stb & self.data.ack) + ] + + +class Writer(Module): + def __init__(self, lasmim): + self.address_data = Sink([("a", lasmim.aw), ("d", lasmim.dw)]) + self.busy = Signal() + + ### + + self.comb += [ + lasmim.we.eq(1), + lasmim.stb.eq(self.address_data.stb), + lasmim.adr.eq(self.address_data.payload.a), + self.address_data.ack.eq(lasmim.ack) + ] + + busy_expr = 0 + data_valid = Signal() + data = Signal(lasmim.dw) + self.comb += [ + data_valid.eq(lasmim.stb & lasmim.ack), + data.eq(self.address_data.payload.d) + ] + + for i in range(lasmim.write_latency): + new_data_valid = Signal() + new_data = Signal(lasmim.dw) + self.sync += [ + new_data_valid.eq(data_valid), + new_data.eq(data) + ] + busy_expr = busy_expr | new_data_valid + data_valid = new_data_valid + data = new_data + + self.comb += [ + If(data_valid, + lasmim.dat_we.eq(2**(lasmim.dw//8)-1), + lasmim.dat_w.eq(data) + ), + self.busy.eq(busy_expr) + ] -- 2.30.2