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.req_queue_size + lasmim.read_latency + 2 # request issuance request_enable = Signal() request_issued = Signal() self.comb += [ lasmim.we.eq(0), lasmim.stb.eq(self.address.stb & request_enable), lasmim.adr.eq(self.address.payload.a), self.address.ack.eq(lasmim.req_ack & request_enable), request_issued.eq(lasmim.stb & lasmim.req_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 = lasmim.dat_ack 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, fifo_depth=None): self.address_data = Sink([("a", lasmim.aw), ("d", lasmim.dw)]) self.busy = Signal() ### if fifo_depth is None: fifo_depth = lasmim.req_queue_size + lasmim.write_latency + 2 fifo = SyncFIFO(lasmim.dw, fifo_depth) self.submodules += fifo self.comb += [ lasmim.we.eq(1), lasmim.stb.eq(fifo.writable & self.address_data.stb), lasmim.adr.eq(self.address_data.payload.a), self.address_data.ack.eq(fifo.writable & lasmim.req_ack), fifo.we.eq(self.address_data.stb & lasmim.req_ack), fifo.din.eq(self.address_data.payload.d) ] data_valid = lasmim.dat_ack for i in range(lasmim.write_latency): new_data_valid = Signal() self.sync += new_data_valid.eq(data_valid), data_valid = new_data_valid self.comb += [ fifo.re.eq(data_valid), If(data_valid, lasmim.dat_we.eq(2**(lasmim.dw//8)-1), lasmim.dat_w.eq(fifo.dout) ), self.busy.eq(fifo.readable) ]