From c554752e8ad9b0c225493aacb0f2442645d43ad4 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 29 Aug 2024 19:39:56 +0200 Subject: [PATCH] soc/cores/hyperbus: Add automatic read burst detection. --- litex/soc/cores/hyperbus.py | 43 ++++++++++++++++------------ test/test_hyperbus.py | 57 +++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 46 deletions(-) diff --git a/litex/soc/cores/hyperbus.py b/litex/soc/cores/hyperbus.py index 56bb3f95d..b7261ec6b 100644 --- a/litex/soc/cores/hyperbus.py +++ b/litex/soc/cores/hyperbus.py @@ -308,17 +308,18 @@ class HyperRAMCore(LiteXModule): # Signals. # -------- - self.cmd = cmd = Signal(48) - self.cycles = cycles = Signal(8) - self.latency_x2 = latency_x2 = Signal() - self.bus_latch = bus_latch = Signal() - self.bus_cti = bus_cti = Signal(3) - self.bus_we = bus_we = Signal() - self.bus_sel = bus_sel = Signal(4) - self.bus_adr = bus_adr = Signal(32) - self.bus_dat_w = bus_dat_w = Signal(32) - self.burst_w = burst_w = Signal() - self.burst_r = burst_r = Signal() + self.cmd = cmd = Signal(48) + self.cycles = cycles = Signal(8) + self.latency_x2 = latency_x2 = Signal() + self.bus_latch = bus_latch = Signal() + self.bus_cti = bus_cti = Signal(3) + self.bus_we = bus_we = Signal() + self.bus_sel = bus_sel = Signal(4) + self.bus_adr = bus_adr = Signal(32) + self.bus_dat_w = bus_dat_w = Signal(32) + self.burst_w = burst_w = Signal() + self.burst_r = burst_r = Signal() + self.burst_r_first = burst_r_first = Signal() # PHY. # ---- @@ -425,8 +426,9 @@ class HyperRAMCore(LiteXModule): If(reg.stb & ~reg.we, NextState("REG-READ") ).Else( + bus_latch.eq(1), + NextValue(burst_r_first, 1), If(bus.we, - bus_latch.eq(1), NextState("DAT-WRITE") ).Else( NextState("DAT-READ") @@ -470,7 +472,7 @@ class HyperRAMCore(LiteXModule): bus_dat_w.eq(bus.dat_w), ) ] - self.comb += If(bus_latch, bus.ack.eq(1)) + self.comb += If(bus_latch, bus.ack.eq(bus.we)) self.comb += burst_w.eq( # Notified Incrementing Burst. (bus_cti == 0b010) | @@ -500,16 +502,21 @@ class HyperRAMCore(LiteXModule): # Data Read State. self.comb += burst_r.eq( # Notified Incrementing Burst. - (bus.cti == 0b10) + (bus_cti == 0b10) | + # Detected Incrementing Burst. + ((bus.we == bus_we) & (bus.adr == (bus_adr + 1))), ) fsm.act("DAT-READ", - source.valid.eq(bus.cyc & bus.stb), + source.valid.eq(1), source.dat_r.eq(1), If(dat_rx_conv.source.valid, - bus.ack.eq(1), + NextValue(burst_r_first, 0), + # Ack on first or while Incrementing Burst ongoing... + bus.ack.eq(burst_r_first | (with_bursting & bus.cyc & bus.stb & burst_r)), bus.dat_r.eq(dat_rx_conv.source.dq), - # Stay in DAT-READ while Incrementing Burst ongoing... - If(with_bursting & bus.cyc & bus.stb & burst_r, + # If Ack, stay in DAT-READ to anticipate next read... + If(bus.ack, + bus_latch.eq(1), NextState("DAT-READ") # ..else exit. ).Else( diff --git a/test/test_hyperbus.py b/test/test_hyperbus.py index ac28f2153..3e696d18a 100644 --- a/test/test_hyperbus.py +++ b/test/test_hyperbus.py @@ -178,13 +178,13 @@ class TestHyperRAM(unittest.TestCase): self.assertEqual(dat, 0xdeadbeef) def hyperram_gen(dut): - clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____" - cs_n = "----______________________________________________________________________----" - dq_oe = "______------------____________________________________________________________" - dq_o = "000000a000048d0000000000000000000000000000000000000000000000000000000000000000" - dq_i = "000000000000000000000000000000000000000000000000000000deadbeefcafefade00000000" - rwds_oe = "______________________________________________________________________________" - rwds_i = "______________________________________________________--__--__--__--__________" + clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____" + cs_n = "----______________________________________________________________________________----" + dq_oe = "______------------____________________________________________________________________" + dq_o = "000000a000048d000000000000000000000000000000000000000000000000000000000000000000000000" + dq_i = "000000000000000000000000000000000000000000000000000000deadbeefcafefade0000000000000000" + rwds_oe = "______________________________________________________________________________________" + rwds_i = "______________________________________________________--__--__--__--__________________" yield for i in range(len(clk)): yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16)) @@ -206,13 +206,13 @@ class TestHyperRAM(unittest.TestCase): self.assertEqual(dat, 0xdeadbeef) def hyperram_gen(dut): - clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____" - cs_n = "----______________________________________________________________________________----" - dq_oe = "______------------____________________________________________________________________" - dq_o = "000000a000048d000000000000000000000000000000000000000000000000000000000000000000000000" - dq_i = "00000000000000000000000000000000000000000000000000000000000000deadbeefcafefade00000000" - rwds_oe = "______________________________________________________________________________________" - rwds_i = "______________________________________________________________--__--__--__--__________" + clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____" + cs_n = "----______________________________________________________________________________________----" + dq_oe = "______------------____________________________________________________________________________" + dq_o = "000000a000048d00000000000000000000000000000000000000000000000000000000000000000000000000000000" + dq_i = "00000000000000000000000000000000000000000000000000000000000000deadbeefcafefade0000000000000000" + rwds_oe = "______________________________________________________________________________________________" + rwds_i = "______________________________________________________________--__--__--__--__________________" yield for i in range(len(clk)): yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16)) @@ -233,14 +233,15 @@ class TestHyperRAM(unittest.TestCase): dat = yield from dut.bus.read(0x1234) self.assertEqual(dat, 0xdeadbeef) + def hyperram_gen(dut): - clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____" - cs_n = "----______________________________________________________________________________________----" - dq_oe = "______------------____________________________________________________________________________" - dq_o = "000000a000048d00000000000000000000000000000000000000000000000000000000000000000000000000000000" - dq_i = "0000000000000000000000000000000000000000000000000000000000000000000000deadbeefcafefade00000000" - rwds_oe = "______________________________________________________________________________________________" - rwds_i = "______________________________________________________________________--__--__--__--__________" + clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____" + cs_n = "----______________________________________________________________________________________________----" + dq_oe = "______------------____________________________________________________________________________________" + dq_o = "000000a000048d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + dq_i = "0000000000000000000000000000000000000000000000000000000000000000000000deadbeefcafefade0000000000000000" + rwds_oe = "______________________________________________________________________________________________________" + rwds_i = "______________________________________________________________________--__--__--__--__________________" yield for i in range(len(clk)): yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16)) @@ -262,13 +263,13 @@ class TestHyperRAM(unittest.TestCase): self.assertEqual(dat, 0xdeadbeef) def hyperram_gen(dut): - clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__-______" - cs_n = "----________________________________________________________------" - dq_oe = "______------------________________________________________________" - dq_o = "000000a000048d0000000000000000000000000000000000000000000000000000" - dq_i = "0000000000000000000000000000000000000000deadbeefcafefade0000000000" - rwds_oe = "__________________________________________________________________" - rwds_i = "________________________________________--__--__--__--____________" + clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__-______" + cs_n = "----________________________________________________________________------" + dq_oe = "______------------________________________________________________________" + dq_o = "000000a000048d000000000000000000000000000000000000000000000000000000000000" + dq_i = "0000000000000000000000000000000000000000deadbeefcafefade000000000000000000" + rwds_oe = "__________________________________________________________________________" + rwds_i = "________________________________________--__--__--__--____________________" yield for i in range(len(clk)): yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16))