mirror of
https://github.com/enjoy-digital/litedram.git
synced 2025-01-04 09:52:25 -05:00
lpddr5: wck sync: fix syncing and adjusted unit tests
Signed-off-by: Alessandro Comodi <acomodi@antmicro.com>
This commit is contained in:
parent
c4273146c1
commit
abc77f367c
3 changed files with 93 additions and 21 deletions
|
@ -704,8 +704,8 @@ def get_lpddr5_phy_init_sequence(phy_settings, timing_settings):
|
|||
mr[18] = reg([
|
||||
(0, 3, rzq_map[wck_odt]),
|
||||
(3, 1, 0), # WCK low frequency mode
|
||||
(4, 1, 0), # WCK always on mode enabled
|
||||
(6, 1, 0), # WCK2CK leveling diabled
|
||||
(4, 1, 0), # WCK always on mode disabled
|
||||
(6, 1, 0), # WCK2CK leveling disabled
|
||||
(7, 1, {2: 1, 4: 0}[wck_ck_ratio]),
|
||||
])
|
||||
# MR19 - defaults
|
||||
|
|
|
@ -303,10 +303,12 @@ class LPDDR5PHY(Module, AutoCSR):
|
|||
|
||||
wck_pattern = Signal(8) # for WCK:CK=2:1 we take wck_pattern[::2]
|
||||
patterns = {
|
||||
"disabled": "________",
|
||||
"static": "________",
|
||||
"toggle": "--__--__",
|
||||
"toggle_4:1": "-_-_-_-_",
|
||||
"disabled": "________",
|
||||
"static": "________",
|
||||
"toggle": "--__--__",
|
||||
"toggle_4:1": "-_-_-_-_",
|
||||
"postamble": "--______",
|
||||
"postamble_4:1": "-_-_-___",
|
||||
}
|
||||
|
||||
assert frange.t_wckpre_static > 0 # The algorithm assumes it's never 0
|
||||
|
@ -332,7 +334,7 @@ class LPDDR5PHY(Module, AutoCSR):
|
|||
wck_fsm.act("TOGGLE",
|
||||
wck_pattern.eq(bitpattern(patterns["toggle"])),
|
||||
If(~wck_sync_done,
|
||||
NextState("DISABLED")
|
||||
NextState("POSTAMBLE")
|
||||
).Elif((wck_ck_ratio == 4), # go to full speed in the next cycle
|
||||
NextState("TOGGLE_4:1")
|
||||
),
|
||||
|
@ -340,9 +342,22 @@ class LPDDR5PHY(Module, AutoCSR):
|
|||
wck_fsm.act("TOGGLE_4:1",
|
||||
wck_pattern.eq(bitpattern(patterns["toggle_4:1"])),
|
||||
If(~wck_sync_done,
|
||||
NextState("DISABLED")
|
||||
NextState("POSTAMBLE")
|
||||
),
|
||||
)
|
||||
wck_fsm.act("POSTAMBLE",
|
||||
If((wck_ck_ratio == 4),
|
||||
wck_pattern.eq(bitpattern(patterns["postamble_4:1"])),
|
||||
NextState("DISABLED")
|
||||
).Else(
|
||||
wck_pattern.eq(bitpattern(patterns["toggle"])),
|
||||
NextState("POSTAMBLE_2:1")
|
||||
)
|
||||
)
|
||||
wck_fsm.act("POSTAMBLE_2:1",
|
||||
wck_pattern.eq(bitpattern(patterns["postamble"])),
|
||||
NextState("DISABLED")
|
||||
)
|
||||
|
||||
wck_out = {2: wck_pattern[::2], 4: wck_pattern}[wck_ck_ratio]
|
||||
assert len(wck_out) == len(self.out.wck[0]), (len(wck_out), len(self.out.wck))
|
||||
|
@ -424,17 +439,22 @@ class LPDDR5PHY(Module, AutoCSR):
|
|||
self.dfi.p0.rddata_valid.eq(rddata_converter.source.valid),
|
||||
]
|
||||
|
||||
|
||||
# -2 is to take into account the serialization time for wck
|
||||
read_wck_latency = cmd_latency + cl + burst_ck_cycles - 2
|
||||
write_wck_latency = cmd_latency + cwl + burst_ck_cycles - 2
|
||||
|
||||
self.wck_sync_state = Signal(2)
|
||||
self.sync += If(self.adapter.wck_sync != 0,
|
||||
wck_sync_done.eq(1),
|
||||
self.wck_sync_state.eq(self.adapter.wck_sync)
|
||||
).Elif(self.wck_sync_state == WCKSyncType.RD,
|
||||
If(reduce(or_, rddata_en.taps[0:rddata_start+burst_ck_cycles]) == 0,
|
||||
If(reduce(or_, rddata_en.taps[0:read_wck_latency]) == 0,
|
||||
wck_sync_done.eq(0),
|
||||
self.wck_sync_state.eq(0b00),
|
||||
)
|
||||
).Elif(self.wck_sync_state == WCKSyncType.WR,
|
||||
If(reduce(or_, wrdata_en.taps[0:wrtap+burst_ck_cycles]) == 0,
|
||||
If(reduce(or_, wrdata_en.taps[0:write_wck_latency]) == 0,
|
||||
wck_sync_done.eq(0),
|
||||
self.wck_sync_state.eq(0b00),
|
||||
)
|
||||
|
|
|
@ -185,7 +185,7 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
read, # with WCK sync
|
||||
{},
|
||||
{},
|
||||
read, # no WCK sync
|
||||
read, # with WCK sync
|
||||
{},
|
||||
{},
|
||||
],
|
||||
|
@ -215,7 +215,7 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
mrr, # with WCK sync
|
||||
{},
|
||||
{},
|
||||
mrr, # no WCK sync
|
||||
mrr, # with WCK sync
|
||||
{},
|
||||
{},
|
||||
],
|
||||
|
@ -249,7 +249,7 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
write, # with WCK sync
|
||||
{},
|
||||
{},
|
||||
write, # no WCK sync
|
||||
write, # with WCK sync
|
||||
{},
|
||||
{},
|
||||
],
|
||||
|
@ -291,12 +291,12 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
dfi_sequence = [
|
||||
{},
|
||||
{0: read}, {}, # WCK sync
|
||||
{0: write_ap}, {}, # no WCK sync
|
||||
{0: write_ap}, {}, # with WCK sync
|
||||
{0: activate}, {},
|
||||
{0: refresh_ab},{},
|
||||
{0: precharge}, {},
|
||||
{0: mrw}, {},
|
||||
{0: mrr}, {}, # no WCK sync
|
||||
{0: mrr}, {}, # with WCK sync
|
||||
{0: zqc_start}, {},
|
||||
{0: zqc_latch}, {},
|
||||
],
|
||||
|
@ -497,12 +497,31 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
0: dict(wrdata=0xfffefffffffefffffffefffffffefffffffefffffffefffffffefffffffeffff),
|
||||
}
|
||||
latency = [{}] * (wl - 1)
|
||||
|
||||
# minimum latency to have correct wck synchronization
|
||||
consecutive_burst_latency = [{}] * 6
|
||||
|
||||
wck_preamble = "00 00" * t["t_wckenl_wr"] + "00 00" * t["t_wckenl_static"] + "10 10" * t["t_wckenl_toggle_wr"]
|
||||
wck_burst = "10 10" * (16//4)
|
||||
wck_postamble = "10 10" + "10 00"
|
||||
|
||||
self.run_test(phy,
|
||||
dfi_sequence = [
|
||||
{0: dict(cs_n=0, cas_n=0, ras_n=1, we_n=0, wrdata_en=1)},
|
||||
*latency,
|
||||
dfi_data
|
||||
dfi_data,
|
||||
*consecutive_burst_latency,
|
||||
{0: dict(cs_n=0, cas_n=0, ras_n=1, we_n=0, wrdata_en=1)},
|
||||
*latency,
|
||||
dfi_data,
|
||||
*consecutive_burst_latency,
|
||||
{0: dict(cs_n=0, cas_n=0, ras_n=1, we_n=0, wrdata_en=1)},
|
||||
*latency,
|
||||
dfi_data,
|
||||
*consecutive_burst_latency,
|
||||
{0: dict(cs_n=0, cas_n=0, ras_n=1, we_n=0, wrdata_en=1)},
|
||||
*latency,
|
||||
dfi_data,
|
||||
],
|
||||
pad_checkers = {
|
||||
"sys_270": {
|
||||
|
@ -516,7 +535,10 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
# tWCKENL_WR starts counting from first command (CAS) so we add command latency,
|
||||
# then preamble, then toggle for the whole burst, then postamble for tWCKPST=2.5tCK
|
||||
# (but for now we assume that WCK is never disabled)
|
||||
"wck0": "0000 0000" + wck_preamble + "10 10" * (16//4) + "10 10 1" + "0 10" + "00 00"*2,
|
||||
"wck0": "0000 0000" + wck_preamble + wck_burst + wck_postamble + \
|
||||
"0000" + wck_preamble + wck_burst + wck_postamble + \
|
||||
"0000" + wck_preamble + wck_burst + wck_postamble + \
|
||||
"0000" + wck_preamble + wck_burst + wck_postamble,
|
||||
},
|
||||
},
|
||||
chunk_size=4,
|
||||
|
@ -540,12 +562,31 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
0: dict(wrdata=0xfffefffffffefffffffefffffffefffffffefffffffefffffffefffffffeffff),
|
||||
}
|
||||
latency = [{}] * (wl - 1)
|
||||
|
||||
# minimum latency to have correct wck synchronization
|
||||
consecutive_burst_latency = [{}] * 3
|
||||
|
||||
wck_preamble = "00000000" * (t["t_wckenl_wr"] + t["t_wckenl_static"]) + "11001100" + "10101010" * (t["t_wckenl_toggle_wr"] - 1)
|
||||
wck_burst = "10101010" * (16//8)
|
||||
wck_postamble = "10101000"
|
||||
|
||||
self.run_test(phy,
|
||||
dfi_sequence = [
|
||||
{0: dict(cs_n=0, cas_n=0, ras_n=1, we_n=0, wrdata_en=1)},
|
||||
*latency,
|
||||
dfi_data
|
||||
dfi_data,
|
||||
*consecutive_burst_latency,
|
||||
{0: dict(cs_n=0, cas_n=0, ras_n=1, we_n=0, wrdata_en=1)},
|
||||
*latency,
|
||||
dfi_data,
|
||||
*consecutive_burst_latency,
|
||||
{0: dict(cs_n=0, cas_n=0, ras_n=1, we_n=0, wrdata_en=1)},
|
||||
*latency,
|
||||
dfi_data,
|
||||
*consecutive_burst_latency,
|
||||
{0: dict(cs_n=0, cas_n=0, ras_n=1, we_n=0, wrdata_en=1)},
|
||||
*latency,
|
||||
dfi_data,
|
||||
],
|
||||
pad_checkers = {
|
||||
"sys_270": {
|
||||
|
@ -559,7 +600,10 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
# tWCKENL_WR starts counting from first command (CAS) so we add command latency,
|
||||
# then preamble, then toggle for the whole burst, then postamble for tWCKPST=2.5tCK
|
||||
# (but for now we assume that WCK is never disabled)
|
||||
"wck0": "00000000 00000000" + wck_preamble + "10101010" * (16//8) + "10101" + "0 10" + "10 10"*2,
|
||||
"wck0": "00000000 00000000" + wck_preamble + wck_burst + wck_postamble + \
|
||||
"00000000" + wck_preamble + wck_burst + wck_postamble + \
|
||||
"00000000" + wck_preamble + wck_burst + wck_postamble + \
|
||||
"00000000" + wck_preamble + wck_burst + wck_postamble,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
@ -579,7 +623,11 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
phy = LPDDR5SimPHY(sys_clk_freq=sys_clk_freq)
|
||||
rl = phy.settings.read_latency
|
||||
latency = [{}] * (rl - 1)
|
||||
|
||||
wck_preamble = "00 00" * t["t_wckenl_rd"] + "00 00" * t["t_wckenl_static"] + "10 10" * t["t_wckenl_toggle_rd"]
|
||||
wck_burst = "10 10" * (16//4)
|
||||
wck_postamble = "10 10" + "10 00"
|
||||
|
||||
self.run_test(phy,
|
||||
dfi_sequence = [
|
||||
{0: dict(cs_n=0, cas_n=0, ras_n=1, we_n=1, rddata_en=1)},
|
||||
|
@ -591,7 +639,7 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
"cs": "01100000",
|
||||
},
|
||||
"sys4x_270": {
|
||||
"wck0": "0000 0000" + wck_preamble + "10 10" * (16//4) + "10 10 1" + "0 10" + "10 10"*2,
|
||||
"wck0": "0000 0000" + wck_preamble + wck_burst + wck_postamble + "00 00",
|
||||
},
|
||||
},
|
||||
chunk_size=4,
|
||||
|
@ -612,7 +660,11 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
phy = LPDDR5SimPHY(sys_clk_freq=sys_clk_freq, wck_ck_ratio=4)
|
||||
rl = phy.settings.read_latency
|
||||
latency = [{}] * (rl - 1)
|
||||
|
||||
wck_preamble = "00000000" * (t["t_wckenl_rd"] + t["t_wckenl_static"]) + "11001100" + "10101010" * (t["t_wckenl_toggle_rd"] - 1)
|
||||
wck_burst = "10101010" * (16//8)
|
||||
wck_postamble = "10101000"
|
||||
|
||||
self.run_test(phy,
|
||||
dfi_sequence = [
|
||||
{0: dict(cs_n=0, cas_n=0, ras_n=1, we_n=1, rddata_en=1)},
|
||||
|
@ -624,7 +676,7 @@ class LPDDR5Tests(unittest.TestCase):
|
|||
"cs": "01100000",
|
||||
},
|
||||
"sys8x_270": {
|
||||
"wck0": "00000000 00000000" + wck_preamble + "10101010" * (16//8) + "10101" + "0 10" + "10 10"*2,
|
||||
"wck0": "00000000 00000000" + wck_preamble + wck_burst + wck_postamble + "00000000",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue