###
if fifo_depth is None:
- fifo_depth = lasmim.read_latency + 2
- assert(fifo_depth >= lasmim.read_latency)
+ fifo_depth = lasmim.req_queue_size + lasmim.read_latency + 2
# request issuance
request_enable = Signal()
lasmim.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)
+ self.address.ack.eq(lasmim.req_ack),
+ request_issued.eq(lasmim.stb & lasmim.req_ack)
]
# FIFO reservation level counter
]
# data available
- data_available = request_issued
+ data_available = lasmim.dat_ack
for i in range(lasmim.read_latency):
new_data_available = Signal()
self.sync += new_data_available.eq(data_available)
class Writer(Module):
- def __init__(self, lasmim):
+ 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(self.address_data.stb),
+ lasmim.stb.eq(fifo.writable & 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)
+ 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()
- new_data = Signal(lasmim.dw)
- self.sync += [
- new_data_valid.eq(data_valid),
- new_data.eq(data)
- ]
- busy_expr = busy_expr | new_data_valid
+ self.sync += new_data_valid.eq(data_valid),
data_valid = new_data_valid
- data = new_data
self.comb += [
+ fifo.re.eq(data_valid),
If(data_valid,
lasmim.dat_we.eq(2**(lasmim.dw//8)-1),
- lasmim.dat_w.eq(data)
+ lasmim.dat_w.eq(fifo.dout)
),
- self.busy.eq(busy_expr)
+ self.busy.eq(fifo.readable)
]
from migen.genlib.misc import optree
class Interface(Record):
- def __init__(self, aw, dw, nbanks, read_latency, write_latency):
+ def __init__(self, aw, dw, nbanks, req_queue_size, read_latency, write_latency):
self.aw = aw
self.dw = dw
self.nbanks = nbanks
+ self.req_queue_size = req_queue_size
self.read_latency = read_latency
self.write_latency = write_latency
("adr", aw, DIR_M_TO_S),
("we", 1, DIR_M_TO_S),
("stb", 1, DIR_M_TO_S),
- ("ack", 1, DIR_S_TO_M)
+ ("req_ack", 1, DIR_S_TO_M),
+ ("dat_ack", 1, DIR_S_TO_M),
+ ("lock", 1, DIR_S_TO_M)
]
if nbanks > 1:
layout = [("bank"+str(i), bank_layout) for i in range(nbanks)]
rca_bits = _getattr_all(controllers, "aw")
dw = _getattr_all(controllers, "dw")
nbanks = _getattr_all(controllers, "nbanks")
+ req_queue_size = _getattr_all(controllers, "req_queue_size")
read_latency = _getattr_all(controllers, "read_latency")
write_latency = _getattr_all(controllers, "write_latency")
bank_bits = log2_int(nbanks, False)
controller_bits = log2_int(ncontrollers, False)
- self.masters = [Interface(rca_bits + bank_bits + controller_bits, dw, 1, read_latency, write_latency)
+ self.masters = [Interface(rca_bits + bank_bits + controller_bits, dw, 1, req_queue_size, read_latency, write_latency)
for i in range(nmasters)]
###
controller_selected = [ca == nc for ca in m_ca]
else:
controller_selected = [1]*nmasters
- master_acks = [0]*nmasters
+ master_req_acks = [0]*nmasters
+ master_dat_acks = [0]*nmasters
for nb in range(nbanks):
bank = getattr(controller, "bank"+str(nb))
# arbitrate
- rr = roundrobin.RoundRobin(nmasters, roundrobin.SP_WITHDRAW)
+ rr = roundrobin.RoundRobin(nmasters, roundrobin.SP_CE)
self.submodules += rr
bank_selected = [cs & (ba == nb) for cs, ba in zip(controller_selected, m_ba)]
bank_requested = [bs & master.stb for bs, master in zip(bank_selected, self.masters)]
- self.comb += rr.request.eq(Cat(*bank_requested)),
+ self.comb += [
+ rr.request.eq(Cat(*bank_requested)),
+ rr.ce.eq(~bank.stb & ~bank.lock)
+ ]
# route requests
self.comb += [
bank.we.eq(Array(self.masters)[rr.grant].we),
bank.stb.eq(Array(bank_requested)[rr.grant])
]
- master_acks = [master_ack | ((rr.grant == nm) & bank.ack)
- for nm, master_ack in enumerate(master_acks)]
+ master_req_acks = [master_req_ack | ((rr.grant == nm) & Array(bank_selected)[rr.grant] & bank.req_ack)
+ for nm, master_req_ack in enumerate(master_req_acks)]
+ master_dat_acks = [master_dat_ack | ((rr.grant == nm) & bank.dat_ack)
+ for nm, master_dat_ack in enumerate(master_dat_acks)]
- self.comb += [master.ack.eq(master_ack) for master, master_ack in zip(self.masters, master_acks)]
+ self.comb += [master.req_ack.eq(master_req_ack) for master, master_req_ack in zip(self.masters, master_req_acks)]
+ self.comb += [master.dat_ack.eq(master_dat_ack) for master, master_dat_ack in zip(self.masters, master_dat_acks)]
# route data writes
controller_selected_wl = controller_selected
# Control FSM
assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
fsm = FSM("IDLE", "TEST_HIT",
- "EVICT_REQUEST", "EVICT_DATA",
- "REFILL_WRTAG", "REFILL_REQUEST", "REFILL_DATA",
+ "EVICT_REQUEST", "EVICT_WAIT_DATA_ACK", "EVICT_DATA",
+ "REFILL_WRTAG", "REFILL_REQUEST", "REFILL_WAIT_DATA_ACK", "REFILL_DATA",
delayed_enters=[
("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1),
("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1)
fsm.act(fsm.EVICT_REQUEST,
lasmim.stb.eq(1),
lasmim.we.eq(1),
- If(lasmim.ack, fsm.next_state(fsm.EVICT_DATAD))
+ If(lasmim.req_ack, fsm.next_state(fsm.EVICT_WAIT_DATA_ACK))
+ )
+ fsm.act(fsm.EVICT_WAIT_DATA_ACK,
+ If(lasmim.dat_ack, fsm.next_state(fsm.EVICT_DATAD))
)
fsm.act(fsm.EVICT_DATA,
write_to_lasmi.eq(1),
)
fsm.act(fsm.REFILL_REQUEST,
lasmim.stb.eq(1),
- If(lasmim.ack, fsm.next_state(fsm.REFILL_DATAD))
+ If(lasmim.req_ack, fsm.next_state(fsm.REFILL_WAIT_DATA_ACK))
+ )
+ fsm.act(fsm.REFILL_WAIT_DATA_ACK,
+ If(lasmim.dat_ack, fsm.next_state(fsm.REFILL_DATAD))
)
fsm.act(fsm.REFILL_DATA,
write_from_lasmi.eq(1),