soc/cores/hyperbus: Add automatic read burst detection.

This commit is contained in:
Florent Kermarrec 2024-08-29 19:39:56 +02:00
parent 3bde3e9848
commit c554752e8a
2 changed files with 54 additions and 46 deletions

View File

@ -308,17 +308,18 @@ class HyperRAMCore(LiteXModule):
# Signals. # Signals.
# -------- # --------
self.cmd = cmd = Signal(48) self.cmd = cmd = Signal(48)
self.cycles = cycles = Signal(8) self.cycles = cycles = Signal(8)
self.latency_x2 = latency_x2 = Signal() self.latency_x2 = latency_x2 = Signal()
self.bus_latch = bus_latch = Signal() self.bus_latch = bus_latch = Signal()
self.bus_cti = bus_cti = Signal(3) self.bus_cti = bus_cti = Signal(3)
self.bus_we = bus_we = Signal() self.bus_we = bus_we = Signal()
self.bus_sel = bus_sel = Signal(4) self.bus_sel = bus_sel = Signal(4)
self.bus_adr = bus_adr = Signal(32) self.bus_adr = bus_adr = Signal(32)
self.bus_dat_w = bus_dat_w = Signal(32) self.bus_dat_w = bus_dat_w = Signal(32)
self.burst_w = burst_w = Signal() self.burst_w = burst_w = Signal()
self.burst_r = burst_r = Signal() self.burst_r = burst_r = Signal()
self.burst_r_first = burst_r_first = Signal()
# PHY. # PHY.
# ---- # ----
@ -425,8 +426,9 @@ class HyperRAMCore(LiteXModule):
If(reg.stb & ~reg.we, If(reg.stb & ~reg.we,
NextState("REG-READ") NextState("REG-READ")
).Else( ).Else(
bus_latch.eq(1),
NextValue(burst_r_first, 1),
If(bus.we, If(bus.we,
bus_latch.eq(1),
NextState("DAT-WRITE") NextState("DAT-WRITE")
).Else( ).Else(
NextState("DAT-READ") NextState("DAT-READ")
@ -470,7 +472,7 @@ class HyperRAMCore(LiteXModule):
bus_dat_w.eq(bus.dat_w), 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( self.comb += burst_w.eq(
# Notified Incrementing Burst. # Notified Incrementing Burst.
(bus_cti == 0b010) | (bus_cti == 0b010) |
@ -500,16 +502,21 @@ class HyperRAMCore(LiteXModule):
# Data Read State. # Data Read State.
self.comb += burst_r.eq( self.comb += burst_r.eq(
# Notified Incrementing Burst. # 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", fsm.act("DAT-READ",
source.valid.eq(bus.cyc & bus.stb), source.valid.eq(1),
source.dat_r.eq(1), source.dat_r.eq(1),
If(dat_rx_conv.source.valid, 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), bus.dat_r.eq(dat_rx_conv.source.dq),
# Stay in DAT-READ while Incrementing Burst ongoing... # If Ack, stay in DAT-READ to anticipate next read...
If(with_bursting & bus.cyc & bus.stb & burst_r, If(bus.ack,
bus_latch.eq(1),
NextState("DAT-READ") NextState("DAT-READ")
# ..else exit. # ..else exit.
).Else( ).Else(

View File

@ -178,13 +178,13 @@ class TestHyperRAM(unittest.TestCase):
self.assertEqual(dat, 0xdeadbeef) self.assertEqual(dat, 0xdeadbeef)
def hyperram_gen(dut): def hyperram_gen(dut):
clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____" clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____"
cs_n = "----______________________________________________________________________----" cs_n = "----______________________________________________________________________________----"
dq_oe = "______------------____________________________________________________________" dq_oe = "______------------____________________________________________________________________"
dq_o = "000000a000048d0000000000000000000000000000000000000000000000000000000000000000" dq_o = "000000a000048d000000000000000000000000000000000000000000000000000000000000000000000000"
dq_i = "000000000000000000000000000000000000000000000000000000deadbeefcafefade00000000" dq_i = "000000000000000000000000000000000000000000000000000000deadbeefcafefade0000000000000000"
rwds_oe = "______________________________________________________________________________" rwds_oe = "______________________________________________________________________________________"
rwds_i = "______________________________________________________--__--__--__--__________" rwds_i = "______________________________________________________--__--__--__--__________________"
yield yield
for i in range(len(clk)): for i in range(len(clk)):
yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16)) 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) self.assertEqual(dat, 0xdeadbeef)
def hyperram_gen(dut): def hyperram_gen(dut):
clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____" clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____"
cs_n = "----______________________________________________________________________________----" cs_n = "----______________________________________________________________________________________----"
dq_oe = "______------------____________________________________________________________________" dq_oe = "______------------____________________________________________________________________________"
dq_o = "000000a000048d000000000000000000000000000000000000000000000000000000000000000000000000" dq_o = "000000a000048d00000000000000000000000000000000000000000000000000000000000000000000000000000000"
dq_i = "00000000000000000000000000000000000000000000000000000000000000deadbeefcafefade00000000" dq_i = "00000000000000000000000000000000000000000000000000000000000000deadbeefcafefade0000000000000000"
rwds_oe = "______________________________________________________________________________________" rwds_oe = "______________________________________________________________________________________________"
rwds_i = "______________________________________________________________--__--__--__--__________" rwds_i = "______________________________________________________________--__--__--__--__________________"
yield yield
for i in range(len(clk)): for i in range(len(clk)):
yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16)) 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) dat = yield from dut.bus.read(0x1234)
self.assertEqual(dat, 0xdeadbeef) self.assertEqual(dat, 0xdeadbeef)
def hyperram_gen(dut): def hyperram_gen(dut):
clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____" clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_____"
cs_n = "----______________________________________________________________________________________----" cs_n = "----______________________________________________________________________________________________----"
dq_oe = "______------------____________________________________________________________________________" dq_oe = "______------------____________________________________________________________________________________"
dq_o = "000000a000048d00000000000000000000000000000000000000000000000000000000000000000000000000000000" dq_o = "000000a000048d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
dq_i = "0000000000000000000000000000000000000000000000000000000000000000000000deadbeefcafefade00000000" dq_i = "0000000000000000000000000000000000000000000000000000000000000000000000deadbeefcafefade0000000000000000"
rwds_oe = "______________________________________________________________________________________________" rwds_oe = "______________________________________________________________________________________________________"
rwds_i = "______________________________________________________________________--__--__--__--__________" rwds_i = "______________________________________________________________________--__--__--__--__________________"
yield yield
for i in range(len(clk)): for i in range(len(clk)):
yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16)) 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) self.assertEqual(dat, 0xdeadbeef)
def hyperram_gen(dut): def hyperram_gen(dut):
clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__-______" clk = "_______--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__-______"
cs_n = "----________________________________________________________------" cs_n = "----________________________________________________________________------"
dq_oe = "______------------________________________________________________" dq_oe = "______------------________________________________________________________"
dq_o = "000000a000048d0000000000000000000000000000000000000000000000000000" dq_o = "000000a000048d000000000000000000000000000000000000000000000000000000000000"
dq_i = "0000000000000000000000000000000000000000deadbeefcafefade0000000000" dq_i = "0000000000000000000000000000000000000000deadbeefcafefade000000000000000000"
rwds_oe = "__________________________________________________________________" rwds_oe = "__________________________________________________________________________"
rwds_i = "________________________________________--__--__--__--____________" rwds_i = "________________________________________--__--__--__--____________________"
yield yield
for i in range(len(clk)): for i in range(len(clk)):
yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16)) yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16))