phy/lpddr5/sim: reset FSM to initial state when RESET_n is pulled low

This commit is contained in:
Jędrzej Boczar 2021-07-15 16:07:24 +02:00 committed by Alessandro Comodi
parent 59467f8ae6
commit 2c8a06ed00
1 changed files with 27 additions and 5 deletions

View File

@ -318,8 +318,19 @@ class CommandsSim(Module, AutoCSR):
self.submodules.tinit4 = PulseTiming(5) # (min) stabilized CK before CS high; not really applicable in this simulation self.submodules.tinit4 = PulseTiming(5) # (min) stabilized CK before CS high; not really applicable in this simulation
self.submodules.tinit5 = PulseTiming(ck(2*us)) # (min) idle time before first MRW/MRR cmmand self.submodules.tinit5 = PulseTiming(ck(2*us)) # (min) idle time before first MRW/MRR cmmand
self.submodules.tzqlat = PulseTiming(max(4, ck(30*ns))) # (min) ZQCAL latch quiet time self.submodules.tzqlat = PulseTiming(max(4, ck(30*ns))) # (min) ZQCAL latch quiet time
self.submodules.tpw_reset = PulseTiming(ck(100*ns)) # (min) RESET_n low time for Reset initialization with stable power
self.comb += [ self.comb += [
self.tpw_reset.trigger.eq(~pads.reset_n),
self.tinit2.valid.eq(~pads.cs),
If(edge(self, pads.reset_n),
If(~self.tinit2.ready,
self.log.warn("tINIT2 violated: CS LOW for too short before deasserting RESET")
),
If(~self.tpw_reset.ready,
self.log.warn("tPW_RESET violated: RESET_n held low for too short")
),
),
If(edge(self, pads.reset_n), If(edge(self, pads.reset_n),
self.log.info("RESET released"), self.log.info("RESET released"),
).Elif(edge(self, ~pads.reset_n), ).Elif(edge(self, ~pads.reset_n),
@ -327,19 +338,30 @@ class CommandsSim(Module, AutoCSR):
), ),
] ]
# We use an FSM that will be automatically reset to the RESET state when reset pad is asserted.
# NOTE: for simulation purpose we assume that CK is always running because CommandsSim is clocked # NOTE: for simulation purpose we assume that CK is always running because CommandsSim is clocked
# from it, or else the states up to Tc would make no sense because the timings would not be counted # from it, or else the states up to Tc would make no sense because the timings would not be counted
self.submodules.fsm = fsm = FSM() class ResetFSM(FSM):
def __init__(self, tpw_reset):
self.tpw_reset = tpw_reset
super().__init__(reset_state="RESET")
def act(self, state, *statements):
if state != "RESET":
statements = [
If(edge(self, self.tpw_reset.ready),
NextState("RESET"),
).Else(*statements)
]
super().act(state, statements)
self.submodules.fsm = fsm = ResetFSM(self.tpw_reset)
fsm.act("RESET", fsm.act("RESET",
self.tinit1.trigger.eq(1), self.tinit1.trigger.eq(1),
self.tinit2.valid.eq(~pads.cs),
If(edge(self, pads.reset_n), If(edge(self, pads.reset_n),
If(~self.tinit1.ready, If(~self.tinit1.ready,
self.log.warn("tINIT1 violated: RESET deasserted too fast") self.log.warn("tINIT1 violated: RESET deasserted too fast")
), ),
If(~self.tinit2.ready,
self.log.warn("tINIT2 violated: CS LOW for too short before deasserting RESET")
),
NextState("WAIT-NOP") # Tc NextState("WAIT-NOP") # Tc
), ),
) )