mirror of
https://github.com/enjoy-digital/litedram.git
synced 2025-01-04 09:52:25 -05:00
stb/req_ack becomes valid/ready + others small cleanup
This commit is contained in:
parent
19e84975f6
commit
52a0f4e617
9 changed files with 80 additions and 74 deletions
|
@ -49,10 +49,10 @@ class Interface(Record):
|
|||
self.write_latency = write_latency
|
||||
|
||||
bank_layout = [
|
||||
("adr", aw, DIR_M_TO_S),
|
||||
("valid", 1, DIR_M_TO_S),
|
||||
("ready", 1, DIR_S_TO_M),
|
||||
("we", 1, DIR_M_TO_S),
|
||||
("stb", 1, DIR_M_TO_S),
|
||||
("req_ack", 1, DIR_S_TO_M),
|
||||
("adr", aw, DIR_M_TO_S),
|
||||
("dat_w_ack", 1, DIR_S_TO_M),
|
||||
("dat_r_ack", 1, DIR_S_TO_M),
|
||||
("lock", 1, DIR_S_TO_M)
|
||||
|
@ -67,3 +67,22 @@ class Interface(Record):
|
|||
("dat_r", dw, DIR_S_TO_M)
|
||||
]
|
||||
Record.__init__(self, layout)
|
||||
|
||||
|
||||
class CommandRequest:
|
||||
def __init__(self, a, ba):
|
||||
self.a = Signal(a)
|
||||
self.ba = Signal(ba)
|
||||
self.cas_n = Signal(reset=1)
|
||||
self.ras_n = Signal(reset=1)
|
||||
self.we_n = Signal(reset=1)
|
||||
|
||||
|
||||
class CommandRequestRW(CommandRequest):
|
||||
def __init__(self, a, ba):
|
||||
CommandRequest.__init__(self, a, ba)
|
||||
self.valid = Signal()
|
||||
self.ack = Signal()
|
||||
self.is_cmd = Signal()
|
||||
self.is_read = Signal()
|
||||
self.is_write = Signal()
|
||||
|
|
|
@ -40,10 +40,10 @@ class BankMachine(Module):
|
|||
fifo = stream.SyncFIFO(layout, controller_settings.req_queue_size)
|
||||
self.submodules += fifo
|
||||
self.comb += [
|
||||
fifo.sink.valid.eq(req.stb),
|
||||
fifo.sink.valid.eq(req.valid),
|
||||
fifo.sink.we.eq(req.we),
|
||||
fifo.sink.adr.eq(req.adr),
|
||||
req.req_ack.eq(fifo.sink.ready),
|
||||
req.ready.eq(fifo.sink.ready),
|
||||
|
||||
fifo.source.ready.eq(req.dat_w_ack | req.dat_r_ack),
|
||||
req.lock.eq(fifo.source.valid),
|
||||
|
@ -81,7 +81,7 @@ class BankMachine(Module):
|
|||
|
||||
# Respect write-to-precharge specification
|
||||
self.submodules.precharge_timer = WaitTimer(2 + timing_settings.tWR - 1 + 1)
|
||||
self.comb += self.precharge_timer.wait.eq(~(self.cmd.stb &
|
||||
self.comb += self.precharge_timer.wait.eq(~(self.cmd.valid &
|
||||
self.cmd.ack &
|
||||
self.cmd.is_write))
|
||||
|
||||
|
@ -94,7 +94,7 @@ class BankMachine(Module):
|
|||
If(has_openrow,
|
||||
If(hit,
|
||||
# NB: write-to-read specification is enforced by multiplexer
|
||||
self.cmd.stb.eq(1),
|
||||
self.cmd.valid.eq(1),
|
||||
If(fifo.source.we,
|
||||
req.dat_w_ack.eq(self.cmd.ack),
|
||||
self.cmd.is_write.eq(1)
|
||||
|
@ -118,7 +118,7 @@ class BankMachine(Module):
|
|||
# 2. since we always go to the ACTIVATE state, we do not need
|
||||
# to assert track_close.
|
||||
If(self.precharge_timer.done,
|
||||
self.cmd.stb.eq(1),
|
||||
self.cmd.valid.eq(1),
|
||||
If(self.cmd.ack,
|
||||
NextState("TRP")
|
||||
),
|
||||
|
@ -130,7 +130,7 @@ class BankMachine(Module):
|
|||
fsm.act("ACTIVATE",
|
||||
s_row_adr.eq(1),
|
||||
track_open.eq(1),
|
||||
self.cmd.stb.eq(1),
|
||||
self.cmd.valid.eq(1),
|
||||
self.cmd.is_cmd.eq(1),
|
||||
If(self.cmd.ack, NextState("TRCD")),
|
||||
self.cmd.ras_n.eq(0)
|
||||
|
|
|
@ -52,19 +52,22 @@ class LiteDRAMController(Module):
|
|||
timing_settings.tREFI,timing_settings.tRFC,
|
||||
controller_settings.with_refresh)
|
||||
|
||||
self.submodules.bank_machines = [BankMachine(geom_settings,
|
||||
timing_settings,
|
||||
controller_settings,
|
||||
address_align,
|
||||
i,
|
||||
getattr(self.lasmic, "bank"+str(i)))
|
||||
for i in range(2**geom_settings.bankbits)]
|
||||
bank_machines = []
|
||||
for i in range(2**geom_settings.bankbits):
|
||||
bank_machine = BankMachine(geom_settings,
|
||||
timing_settings,
|
||||
controller_settings,
|
||||
address_align,
|
||||
i,
|
||||
getattr(self.lasmic, "bank"+str(i)))
|
||||
bank_machines.append(bank_machine)
|
||||
self.submodules += bank_machine
|
||||
|
||||
self.submodules.multiplexer = Multiplexer(phy_settings,
|
||||
geom_settings,
|
||||
timing_settings,
|
||||
controller_settings,
|
||||
self.bank_machines,
|
||||
bank_machines,
|
||||
self.refresher,
|
||||
self.dfi,
|
||||
self.lasmic)
|
||||
|
|
|
@ -3,29 +3,11 @@ from operator import or_, and_
|
|||
|
||||
from litex.gen import *
|
||||
from litex.gen.genlib.roundrobin import *
|
||||
from litex.gen.genlib.fsm import FSM, NextState
|
||||
|
||||
from litedram.core.perf import Bandwidth
|
||||
from litex.soc.interconnect.csr import AutoCSR
|
||||
|
||||
|
||||
class CommandRequest:
|
||||
def __init__(self, a, ba):
|
||||
self.a = Signal(a)
|
||||
self.ba = Signal(ba)
|
||||
self.cas_n = Signal(reset=1)
|
||||
self.ras_n = Signal(reset=1)
|
||||
self.we_n = Signal(reset=1)
|
||||
|
||||
|
||||
class CommandRequestRW(CommandRequest):
|
||||
def __init__(self, a, ba):
|
||||
CommandRequest.__init__(self, a, ba)
|
||||
self.stb = Signal()
|
||||
self.ack = Signal()
|
||||
self.is_cmd = Signal()
|
||||
self.is_read = Signal()
|
||||
self.is_write = Signal()
|
||||
from litedram.common import *
|
||||
from litedram.core.perf import Bandwidth
|
||||
|
||||
|
||||
class _CommandChooser(Module):
|
||||
|
@ -33,7 +15,7 @@ class _CommandChooser(Module):
|
|||
self.want_reads = Signal()
|
||||
self.want_writes = Signal()
|
||||
self.want_cmds = Signal()
|
||||
# NB: cas_n/ras_n/we_n are 1 when stb is inactive
|
||||
# NB: cas_n/ras_n/we_n are 1 when valid is inactive
|
||||
self.cmd = CommandRequestRW(len(requests[0].a), len(requests[0].ba))
|
||||
|
||||
# # #
|
||||
|
@ -41,23 +23,25 @@ class _CommandChooser(Module):
|
|||
rr = RoundRobin(len(requests), SP_CE)
|
||||
self.submodules += rr
|
||||
|
||||
self.comb += [rr.request[i].eq(req.stb & ((req.is_cmd & self.want_cmds) | ((req.is_read == self.want_reads) | (req.is_write == self.want_writes))))
|
||||
for i, req in enumerate(requests)]
|
||||
for i, req in enumerate(requests):
|
||||
self.comb += rr.request[i].eq(req.valid & ((req.is_cmd & self.want_cmds) |
|
||||
((req.is_read == self.want_reads) |
|
||||
(req.is_write == self.want_writes))))
|
||||
|
||||
stb = Signal()
|
||||
self.comb += stb.eq(Array(req.stb for req in requests)[rr.grant])
|
||||
valid = Signal()
|
||||
self.comb += valid.eq(Array(req.valid for req in requests)[rr.grant])
|
||||
for name in ["a", "ba", "is_read", "is_write", "is_cmd"]:
|
||||
choices = Array(getattr(req, name) for req in requests)
|
||||
self.comb += getattr(self.cmd, name).eq(choices[rr.grant])
|
||||
for name in ["cas_n", "ras_n", "we_n"]:
|
||||
# we should only assert those signals when stb is 1
|
||||
# we should only assert those signals when valid is 1
|
||||
choices = Array(getattr(req, name) for req in requests)
|
||||
self.comb += If(self.cmd.stb, getattr(self.cmd, name).eq(choices[rr.grant]))
|
||||
self.comb += self.cmd.stb.eq(stb \
|
||||
self.comb += If(self.cmd.valid, getattr(self.cmd, name).eq(choices[rr.grant]))
|
||||
self.comb += self.cmd.valid.eq(valid \
|
||||
& ((self.cmd.is_cmd & self.want_cmds) | ((self.cmd.is_read == self.want_reads) \
|
||||
& (self.cmd.is_write == self.want_writes))))
|
||||
|
||||
self.comb += [If(self.cmd.stb & self.cmd.ack & (rr.grant == i), req.ack.eq(1))
|
||||
self.comb += [If(self.cmd.valid & self.cmd.ack & (rr.grant == i), req.ack.eq(1))
|
||||
for i, req in enumerate(requests)]
|
||||
self.comb += rr.ce.eq(self.cmd.ack)
|
||||
|
||||
|
@ -70,11 +54,11 @@ class _Steerer(Module):
|
|||
|
||||
###
|
||||
|
||||
def stb_and(cmd, attr):
|
||||
if not hasattr(cmd, "stb"):
|
||||
def valid_and(cmd, attr):
|
||||
if not hasattr(cmd, "valid"):
|
||||
return 0
|
||||
else:
|
||||
return cmd.stb & getattr(cmd, attr)
|
||||
return cmd.valid & getattr(cmd, attr)
|
||||
for phase, sel in zip(dfi.phases, self.sel):
|
||||
self.comb += [
|
||||
phase.cke.eq(1),
|
||||
|
@ -90,8 +74,8 @@ class _Steerer(Module):
|
|||
phase.cas_n.eq(Array(cmd.cas_n for cmd in commands)[sel]),
|
||||
phase.ras_n.eq(Array(cmd.ras_n for cmd in commands)[sel]),
|
||||
phase.we_n.eq(Array(cmd.we_n for cmd in commands)[sel]),
|
||||
phase.rddata_en.eq(Array(stb_and(cmd, "is_read") for cmd in commands)[sel]),
|
||||
phase.wrdata_en.eq(Array(stb_and(cmd, "is_write") for cmd in commands)[sel])
|
||||
phase.rddata_en.eq(Array(valid_and(cmd, "is_read") for cmd in commands)[sel]),
|
||||
phase.wrdata_en.eq(Array(valid_and(cmd, "is_write") for cmd in commands)[sel])
|
||||
]
|
||||
|
||||
|
||||
|
@ -126,8 +110,8 @@ class Multiplexer(Module, AutoCSR):
|
|||
read_available = Signal()
|
||||
write_available = Signal()
|
||||
self.comb += [
|
||||
read_available.eq(reduce(or_, [req.stb & req.is_read for req in requests])),
|
||||
write_available.eq(reduce(or_, [req.stb & req.is_write for req in requests]))
|
||||
read_available.eq(reduce(or_, [req.valid & req.is_read for req in requests])),
|
||||
write_available.eq(reduce(or_, [req.valid & req.is_write for req in requests]))
|
||||
]
|
||||
|
||||
def anti_starvation(timeout):
|
||||
|
|
|
@ -12,12 +12,12 @@ class Bandwidth(Module, AutoCSR):
|
|||
|
||||
# # #
|
||||
|
||||
cmd_stb = Signal()
|
||||
cmd_valid = Signal()
|
||||
cmd_ack = Signal()
|
||||
cmd_is_read = Signal()
|
||||
cmd_is_write = Signal()
|
||||
self.sync += [
|
||||
cmd_stb.eq(cmd.stb),
|
||||
cmd_valid.eq(cmd.valid),
|
||||
cmd_ack.eq(cmd.ack),
|
||||
cmd_is_read.eq(cmd.is_read),
|
||||
cmd_is_write.eq(cmd.is_write)
|
||||
|
@ -36,7 +36,7 @@ class Bandwidth(Module, AutoCSR):
|
|||
nwrites_r.eq(nwrites),
|
||||
nreads.eq(0),
|
||||
nwrites.eq(0)
|
||||
).Elif(cmd_stb & cmd_ack,
|
||||
).Elif(cmd_valid & cmd_ack,
|
||||
If(cmd_is_read, nreads.eq(nreads + 1)),
|
||||
If(cmd_is_write, nwrites.eq(nwrites + 1)),
|
||||
),
|
||||
|
|
|
@ -64,7 +64,7 @@ class LiteDRAMBISTGenerator(Module):
|
|||
|
||||
self.comb += [
|
||||
self._dma.trigger.eq(self._shoot.re),
|
||||
self._dma.data.stb.eq(en),
|
||||
self._dma.data.valid.eq(en),
|
||||
lfsr.ce.eq(en & self._dma.data.ack),
|
||||
self._dma.data.d.eq(lfsr.o)
|
||||
]
|
||||
|
@ -90,14 +90,14 @@ class LiteDRAMBISTChecker(Module):
|
|||
self.comb += lfsr.reset.eq(self._reset.re)
|
||||
|
||||
self.comb += [
|
||||
lfsr.ce.eq(self._dma.data.stb),
|
||||
lfsr.ce.eq(self._dma.data.valid),
|
||||
self._dma.data.ack.eq(1)
|
||||
]
|
||||
err_cnt = self._error_count.status
|
||||
self.sync += [
|
||||
If(self._reset.re,
|
||||
err_cnt.eq(0)
|
||||
).Elif(self._dma.data.stb,
|
||||
).Elif(self._dma.data.valid,
|
||||
If(self._dma.data.d != lfsr.o, err_cnt.eq(err_cnt + 1))
|
||||
)
|
||||
]
|
||||
|
|
|
@ -14,9 +14,9 @@ class LiteDRAMWishboneBridge(Module):
|
|||
)
|
||||
)
|
||||
fsm.act("REQUEST",
|
||||
port.stb.eq(1),
|
||||
port.valid.eq(1),
|
||||
port.we.eq(wishbone.we),
|
||||
If(port.req_ack,
|
||||
If(port.ready,
|
||||
If(wishbone.we,
|
||||
NextState("WRITE_DATA")
|
||||
).Else(
|
||||
|
|
|
@ -40,7 +40,7 @@ class LiteDRAMCrossbar(Module):
|
|||
|
||||
controller = self.controller
|
||||
controller_selected = [1]*nmasters
|
||||
master_req_acks = [0]*nmasters
|
||||
master_readys = [0]*nmasters
|
||||
master_dat_w_acks = [0]*nmasters
|
||||
master_dat_r_acks = [0]*nmasters
|
||||
|
||||
|
@ -61,20 +61,20 @@ class LiteDRAMCrossbar(Module):
|
|||
|
||||
# arbitrate
|
||||
bank_selected = [cs & (ba == nb) & ~locked for cs, ba, locked in zip(controller_selected, m_ba, master_locked)]
|
||||
bank_requested = [bs & master.stb for bs, master in zip(bank_selected, self.masters)]
|
||||
bank_requested = [bs & master.valid for bs, master in zip(bank_selected, self.masters)]
|
||||
self.comb += [
|
||||
rr.request.eq(Cat(*bank_requested)),
|
||||
rr.ce.eq(~bank.stb & ~bank.lock)
|
||||
rr.ce.eq(~bank.valid & ~bank.lock)
|
||||
]
|
||||
|
||||
# route requests
|
||||
self.comb += [
|
||||
bank.adr.eq(Array(m_rca)[rr.grant]),
|
||||
bank.we.eq(Array(self.masters)[rr.grant].we),
|
||||
bank.stb.eq(Array(bank_requested)[rr.grant])
|
||||
bank.valid.eq(Array(bank_requested)[rr.grant])
|
||||
]
|
||||
master_req_acks = [master_req_ack | ((rr.grant == nm) & bank_selected[nm] & bank.req_ack)
|
||||
for nm, master_req_ack in enumerate(master_req_acks)]
|
||||
master_readys = [master_ready | ((rr.grant == nm) & bank_selected[nm] & bank.ready)
|
||||
for nm, master_ready in enumerate(master_readys)]
|
||||
master_dat_w_acks = [master_dat_w_ack | ((rr.grant == nm) & bank.dat_w_ack)
|
||||
for nm, master_dat_w_ack in enumerate(master_dat_w_acks)]
|
||||
master_dat_r_acks = [master_dat_r_ack | ((rr.grant == nm) & bank.dat_r_ack)
|
||||
|
@ -94,7 +94,7 @@ class LiteDRAMCrossbar(Module):
|
|||
master_dat_r_ack = new_master_dat_r_ack
|
||||
master_dat_r_acks[nm] = master_dat_r_ack
|
||||
|
||||
self.comb += [master.req_ack.eq(master_req_ack) for master, master_req_ack in zip(self.masters, master_req_acks)]
|
||||
self.comb += [master.ready.eq(master_ready) for master, master_ready in zip(self.masters, master_readys)]
|
||||
self.comb += [master.dat_w_ack.eq(master_dat_w_ack) for master, master_dat_w_ack in zip(self.masters, master_dat_w_acks)]
|
||||
self.comb += [master.dat_r_ack.eq(master_dat_r_ack) for master, master_dat_r_ack in zip(self.masters, master_dat_r_acks)]
|
||||
|
||||
|
|
|
@ -20,10 +20,10 @@ class LiteDRAMDMAReader(Module):
|
|||
|
||||
self.comb += [
|
||||
port.we.eq(0),
|
||||
port.stb.eq(sink.valid & request_enable),
|
||||
port.valid.eq(sink.valid & request_enable),
|
||||
port.adr.eq(sink.address),
|
||||
sink.ready.eq(port.req_ack & request_enable),
|
||||
request_issued.eq(port.stb & port.req_ack)
|
||||
sink.ready.eq(port.ready & request_enable),
|
||||
request_issued.eq(port.valid & port.ready)
|
||||
]
|
||||
|
||||
# FIFO reservation level counter
|
||||
|
@ -74,10 +74,10 @@ class LiteDRAMDMAWriter(Module):
|
|||
|
||||
self.comb += [
|
||||
port.we.eq(1),
|
||||
port.stb.eq(fifo.writable & source.valid),
|
||||
port.valid.eq(fifo.writable & source.valid),
|
||||
port.adr.eq(source.address),
|
||||
source.ready.eq(fifo.writable & port.req_ack),
|
||||
fifo.we.eq(source.valid & port.req_ack),
|
||||
source.ready.eq(fifo.writable & port.ready),
|
||||
fifo.we.eq(source.valid & port.ready),
|
||||
fifo.din.eq(source.data)
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in a new issue