diff --git a/litex/soc/cores/hyperbus.py b/litex/soc/cores/hyperbus.py index 1c20553a4..ade68d2b1 100644 --- a/litex/soc/cores/hyperbus.py +++ b/litex/soc/cores/hyperbus.py @@ -24,7 +24,7 @@ class HyperRAM(Module): This core favors portability and ease of use over performance. """ - def __init__(self, pads, latency=6): + def __init__(self, frequency, pads, latency=6, Tcsm=4e-6): self.pads = pads self.bus = bus = wishbone.Interface() @@ -61,6 +61,25 @@ class HyperRAM(Module): else: self.specials += DifferentialOutput(clk, pads.clk_p, pads.clk_n) + # Timeout counter -------------------------------------------------------------------------- + timeout_value = int(Tcsm * frequency) + timeout_cnt = Signal(32) + timeout_rst = Signal() + timeout = Signal() + + self.sync += [ + If(timeout_rst, + timeout_cnt.eq(0), + timeout.eq(0) + ).Else( + If(timeout_cnt < timeout_value, + timeout_cnt.eq(timeout_cnt + 1) + ).Else( + timeout.eq(1) + ) + ), + ] + # Clock Generation (sys_clk/4) ------------------------------------------------------------- self.sync += clk_phase.eq(clk_phase + 1) cases = {} @@ -122,6 +141,7 @@ class HyperRAM(Module): first = Signal() self.submodules.fsm = fsm = FSM(reset_state="IDLE") fsm.act("IDLE", + timeout_rst.eq(1), NextValue(first, 1), If(bus.cyc & bus.stb, If(clk_phase == 0, @@ -139,7 +159,9 @@ class HyperRAM(Module): # Wait for 6*2 cycles... If(cycles == (6*2 - 1), NextState("WAIT-LATENCY") - ) + ), + # Always check if bus cycle is still active + If(~bus.cyc, NextState("IDLE")) ) fsm.act("WAIT-LATENCY", # Set CSn. @@ -151,7 +173,9 @@ class HyperRAM(Module): # Early Write Ack (to allow bursting). bus.ack.eq(bus.we), NextState("READ-WRITE-DATA0") - ) + ), + # Always check if bus cycle is still active + If(~bus.cyc, NextState("IDLE")) ) states = {8:4, 16:2}[dw] for n in range(states): @@ -172,7 +196,7 @@ class HyperRAM(Module): If(n == (states - 1), NextValue(first, 0), # Continue burst when a consecutive access is ready. - If(bus.stb & bus.cyc & (bus.we == bus_we) & (bus.adr == (bus_adr + 1)), + If(bus.stb & bus.cyc & (bus.we == bus_we) & (bus.adr == (bus_adr + 1)) & ~timeout, # Latch Bus. bus_latch.eq(1), # Early Write Ack (to allow bursting).