103 lines
2.6 KiB
Python
103 lines
2.6 KiB
Python
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_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.read_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)
|
|
]
|