core/refresher: improve naming/parameters of refresh postponing

This commit is contained in:
Florent Kermarrec 2019-09-11 08:38:17 +02:00
parent dc1bb53a88
commit f861d99903
4 changed files with 28 additions and 24 deletions

2
README
View File

@ -33,7 +33,7 @@ Core:
- Fully pipelined, high performance.
- Configurable commands depth on bankmachines.
- Auto-Precharge.
- Periodic refresh/ZQ short calibration.
- Periodic refresh/ZQ short calibration (up to 8 postponed refreshes).
Frontend:
- Configurable crossbar (simply use crossbar.get_port() to add a new port!)
- Ports arbitration transparent to the user.

View File

@ -18,7 +18,7 @@ class ControllerSettings(Settings):
cmd_buffer_depth=8, cmd_buffer_buffered=False,
read_time=32, write_time=16,
with_bandwidth=False,
with_refresh=True, refresher_cls=Refresher, refresher_zqcs_freq=1e0,
with_refresh=True, refresh_cls=Refresher, refresh_zqcs_freq=1e0, refresh_postponing=1,
with_auto_precharge=True,
address_mapping="ROW_BANK_COL"):
self.set_attributes(locals())
@ -53,7 +53,10 @@ class LiteDRAMController(Module):
# # #
# Refresher --------------------------------------------------------------------------------
self.submodules.refresher = self.settings.refresher_cls(self.settings, clk_freq)
self.submodules.refresher = self.settings.refresh_cls(self.settings,
clk_freq = clk_freq,
zqcs_freq = self.settings.refresh_zqcs_freq,
postponing = self.settings.refresh_postponing)
# Bank Machines ----------------------------------------------------------------------------
bank_machines = []

View File

@ -72,7 +72,7 @@ class RefreshSequencer(Module):
Sequence N refreshs to the DRAM.
"""
def __init__(self, cmd, trp, trfc, n=1):
def __init__(self, cmd, trp, trfc, postponing=1):
self.start = Signal()
self.done = Signal()
@ -81,7 +81,7 @@ class RefreshSequencer(Module):
executer = RefreshExecuter(cmd, trp, trfc)
self.submodules += executer
count = Signal(bits_for(n), reset=n-1)
count = Signal(bits_for(postponing), reset=postponing-1)
self.sync += [
If(self.start,
count.eq(count.reset)
@ -124,20 +124,20 @@ class RefreshTimer(Module):
self.count.eq(count)
]
# RefreshAccumulator -------------------------------------------------------------------------------
# RefreshPostponer -------------------------------------------------------------------------------
class RefreshAccumulator(Module):
"""Refresh Accumulator
class RefreshPostponer(Module):
"""Refresh Postponer
Accumulate N Refresh requests and generate a request when N is reached.
Postpone N Refresh requests and generate a request when N is reached.
"""
def __init__(self, n=1):
def __init__(self, postponing=1):
self.req_i = Signal()
self.req_o = Signal()
# # #
count = Signal(bits_for(n), reset=n-1)
count = Signal(bits_for(postponing), reset=postponing-1)
self.sync += [
self.req_o.eq(0),
If(self.req_i,
@ -215,7 +215,8 @@ class Refresher(Module):
transactions are done, the Refresher can execute the refresh Sequence and release the Controller.
"""
def __init__(self, settings, clk_freq, n=1):
def __init__(self, settings, clk_freq, zqcs_freq=1e0, postponing=1):
assert postponing <= 8
abits = settings.geom.addressbits
babits = settings.geom.bankbits + log2_int(settings.phy.nranks)
self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a=abits, ba=babits))
@ -230,19 +231,19 @@ class Refresher(Module):
self.submodules.timer = timer
self.comb += timer.wait.eq(~timer.done)
# Refresh Accumulator ----------------------------------------------------------------------
accum = RefreshAccumulator(n=n)
self.submodules.accum = accum
self.comb += accum.req_i.eq(self.timer.done)
self.comb += wants_refresh.eq(accum.req_o)
# Refresh Postponer ------------------------------------------------------------------------
postponer = RefreshPostponer(postponing)
self.submodules.postponer = postponer
self.comb += postponer.req_i.eq(self.timer.done)
self.comb += wants_refresh.eq(postponer.req_o)
# Refresh Sequencer ------------------------------------------------------------------------
sequencer = RefreshSequencer(cmd, settings.timing.tRP, settings.timing.tRFC, n=n)
sequencer = RefreshSequencer(cmd, settings.timing.tRP, settings.timing.tRFC, postponing)
self.submodules.sequencer = sequencer
if settings.timing.tZQCS is not None:
# ZQCS Timer ---------------------------------------------------------------------------
zqcs_timer = RefreshTimer(int(clk_freq/settings.refresher_zqcs_freq))
zqcs_timer = RefreshTimer(int(clk_freq/zqcs_freq))
self.submodules.zqcs_timer = zqcs_timer
self.comb += wants_zqcs.eq(zqcs_timer.done)

View File

@ -66,11 +66,11 @@ class TestRefresh(unittest.TestCase):
for i in range(1, 32):
self.refresh_timer_test(i)
def refresher_test(self, n):
def refresher_test(self, postponing):
class Obj: pass
settings = Obj()
settings.with_refresh = True
settings.refresher_zqcs_freq = 1e0
settings.refresh_zqcs_freq = 1e0
settings.timing = Obj()
settings.timing.tREFI = 64
settings.timing.tRP = 1
@ -95,14 +95,14 @@ class TestRefresh(unittest.TestCase):
while (yield dut.cmd.valid) == 0:
cmd_valid_gap += 1
yield
if cmd_valid_gap != n*settings.timing.tREFI:
if cmd_valid_gap != postponing*settings.timing.tREFI:
print(cmd_valid_gap)
dut.errors += 1
dut = Refresher(settings, n=n, clk_freq=100e6)
dut = Refresher(settings, clk_freq=100e6, postponing=postponing)
run_simulation(dut, [generator(dut)])
self.assertEqual(dut.errors, 0)
def test_refresher(self):
for i in [1, 2, 4, 8]:
self.refresher_test(n=i)
self.refresher_test(postponing=i)