From 635ae2b289604631c768f603746923d4fe045ef1 Mon Sep 17 00:00:00 2001 From: Catherine Date: Wed, 27 Mar 2024 21:33:23 +0000 Subject: [PATCH] wip: actually working now i swear --- software/glasgow/gateware/hyperram.py | 56 ++++++++++++++---------- software/tests/gateware/test_hyperram.py | 46 +++++++++++-------- 2 files changed, 61 insertions(+), 41 deletions(-) diff --git a/software/glasgow/gateware/hyperram.py b/software/glasgow/gateware/hyperram.py index aa2d1a090..659ac491f 100644 --- a/software/glasgow/gateware/hyperram.py +++ b/software/glasgow/gateware/hyperram.py @@ -34,11 +34,12 @@ def p(self): class _IOBufferWithEn(wiring.Component): - def __init__(self, pins): + def __init__(self, pins, *, pin_type=C(0b1101_00, 6)): self.pins = pins + self.pin_type = pin_type super().__init__(Signature({ - "en" : In(1, reset=1), # clock enable (for both input and output) + "en" : In(1), # clock enable (for both input and output) "oe" : In(1), # output enable "o" : Out(len(self.pins)), # output "i" : In(len(self.pins)), # input @@ -48,7 +49,7 @@ def elaborate(self, platform): m = Module() for index, pin in enumerate(self.pins): m.submodules += Instance("SB_IO", - p_PIN_TYPE=C(0b1101_00, 6), + p_PIN_TYPE=self.pin_type, i_INPUT_CLK=ClockSignal(), i_OUTPUT_CLK=ClockSignal(), i_CLOCK_ENABLE=self.en, @@ -126,12 +127,23 @@ def elaborate(self, platform): # the positive polarity may be used), driven as source synchronous DDR output. This clock # idles low and toggles whenever the FSM transitions, at 90° phase offset referenced to # DQ[7:0]. The I/O buffer is configured as DDR to introduce the phase offset. - m.d.comb += pins.ck_p.o_clk.eq(ClockSignal()) - m.d.comb += pins.ck_n.o_clk.eq(ClockSignal()) - - # CS#[`cs_count`-1:0] are a set of output pins. - m.submodules.pins_cs_n = pins_cs_n = self.pins_cs_n = _IOBufferWithEn(pins.cs) - m.d.comb += pins_cs_n.oe.eq(1) + m.d.comb += [ + pins.ck_p.o_clk.eq(ClockSignal()), + pins.ck_n.o_clk.eq(ClockSignal()), + ] + + # CS#[`cs_count`-1:0] are a set of output pins. They use the same type of IO buffer because + # iCE40 has packing constraints on clock enables in adjacent SB_IO cells (same diffpair). + # For the same reason the enable of CS# must be tied to that of RWDS, which requires this + # awkward bit of logic to add a register not tied to RWDS enable. + m.submodules.pins_cs_n = pins_cs_n = self.pins_cs_n = \ + _IOBufferWithEn(pins.cs, pin_type=C(0b0110_01, 6)) # Cat(PIN_INPUT, PIN_OUTPUT) + pins_cs_o_n_reg = Signal.like(pins_cs_n.o, reset=~0) + pins_cs_o = Signal.like(pins_cs_n.o) + pins_cs_o_en = Signal() + m.d.comb += pins_cs_n.o.eq(pins_cs_o_n_reg) + with m.If(pins_cs_o_en): + m.d.sync += pins_cs_o_n_reg.eq(~pins_cs_o) # RWDS is an input/output pin. It has three distinct functions: # - During command/address phase, RWDS is a memory output and FPGA input indicating whether @@ -144,6 +156,7 @@ def elaborate(self, platform): # with data output by the memory, indicating a pause in data transfer when the address # crosses page boundaries. m.submodules.pins_rwds = pins_rwds = self.pins_rwds = _IOBufferWithEn(pins.rwds) + m.d.comb += pins_cs_n.en.eq(pins_rwds.en) # oh, iCE40... pins_rwds_i_regl = Signal.like(pins_rwds.i) pins_rwds_i_regh = Signal.like(pins_rwds.i) @@ -168,18 +181,19 @@ def elaborate(self, platform): ] with m.State("Select/Deselect"): + m.d.comb += [ + pins_cs_o_en.eq(1), + # Release DQ and RWDS if the last operation was a write. + pins_dq.oe.eq(0), + pins_dq.en.eq(1), + pins_rwds.oe.eq(0), + pins_rwds.en.eq(1), + ] m.d.sync += clocked.eq(0) with m.If(self.o.valid & (self.o.p.mode == PHYMode.Select)): + m.d.comb += self.o.ready.eq(1) cs_decoded = Cat(self.o.p.data == n for n in range(1, self.cs_count + 1)) - m.d.comb += [ - pins_cs_n.o.eq(~cs_decoded), - pins_cs_n.en.eq(1), - pins_dq.oe.eq(0), - pins_dq.en.eq(1), - pins_rwds.oe.eq(0), - pins_rwds.en.eq(1), - self.o.ready.eq(1), - ] + m.d.comb += pins_cs_o.eq(cs_decoded) with m.If(cs_decoded != 0): m.next = "Sample-Latency" @@ -426,8 +440,7 @@ def elaborate(self, platform): phy.o.valid.eq(1), self.write.ready.eq(phy.o.ready), ] - # with m.If(self.control.valid): - with m.If(self.write.valid & self.write.ready): + with m.If(self.control.valid): m.next = "Deselect" with m.State("Latency-Read"): @@ -452,8 +465,7 @@ def elaborate(self, platform): phy.o.valid.eq(1), ] wiring.connect(m, wiring.flipped(self.read), phy.i) - # with m.If(self.control.valid): - with m.If(self.read.valid & self.read.ready): + with m.If(self.control.valid): m.next = "Deselect" with m.State("Deselect"): diff --git a/software/tests/gateware/test_hyperram.py b/software/tests/gateware/test_hyperram.py index 6f7e1d2b7..7f268081d 100644 --- a/software/tests/gateware/test_hyperram.py +++ b/software/tests/gateware/test_hyperram.py @@ -46,7 +46,6 @@ def elaborate(self, platform): seq.control.payload.cmd_addr.burst_type.eq(hyperram.BurstType.Linear), seq.control.payload.cmd_addr.address_space.eq(self.space), seq.control.payload.cmd_addr.operation.eq(self.mode), - # seq.control.payload.cmd_addr.eq(0x800000000001), seq.control.payload.latency.eq(self.latency), ] @@ -267,24 +266,33 @@ async def write_mem(start, data, *, latency): await read_reg(0x000000) # ID0 == 0c86 await read_reg(0x000001) # ID1 == 0001 - await read_reg(0x000800) # CR0 == 8f2f - await write_reg(0x000800, 0x8f1f) - await read_reg(0x000800) - await write_reg(0x400800, 0x8f1f) - await read_reg(0x400800) - - await read_reg(0x000801) # CR1 == ffc1 - - await read_mem(0x00000000, 1) - await read_mem(0x00000001, 1) - await write_mem(0x00000000, [0xaabb], latency=6) - await write_mem(0x00000001, [0xccdd], latency=6) - await read_mem(0x00000000, 1) - await read_mem(0x00000001, 1) - await write_mem(0x00000000, [0], latency=6) - await write_mem(0x00000001, [0], latency=6) - await read_mem(0x00000000, 1) - await read_mem(0x00000001, 1) + await write_mem(0x00000000, [0x0000, 0x0000, 0x0000], latency=7) + await read_mem( 0x00000000, 1) + await read_mem( 0x00000001, 1) + await read_mem( 0x00000002, 1) + await write_mem(0x00000000, [0x1234, 0x5678, 0xabcd], latency=7) + await read_mem( 0x00000000, 1) + await read_mem( 0x00000001, 1) + await read_mem( 0x00000002, 1) + + # await read_reg(0x000800) # CR0 == 8f2f + # await write_reg(0x000800, 0x8f1f) + # await read_reg(0x000800) + # await write_reg(0x400800, 0x8f1f) + # await read_reg(0x400800) + + # await read_reg(0x000801) # CR1 == ffc1 + + # await read_mem(0x00000000, 1) + # await read_mem(0x00000001, 1) + # await write_mem(0x00000000, [0xaabb], latency=6) + # await write_mem(0x00000001, [0xccdd], latency=6) + # await read_mem(0x00000000, 1) + # await read_mem(0x00000001, 1) + # await write_mem(0x00000000, [0], latency=6) + # await write_mem(0x00000001, [0], latency=6) + # await read_mem(0x00000000, 1) + # await read_mem(0x00000001, 1) # await read_reg(0x400000) # ID0 == 0c86 # await read_reg(0x400001) # ID1 == 0001