From c2cdda0f973a81910bdaed2a4fdc26d6158bd1c4 Mon Sep 17 00:00:00 2001 From: Jean THOMAS Date: Tue, 21 Jul 2020 14:20:01 +0200 Subject: [PATCH] Fix write timings --- gram/phy/ecp5ddrphy.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/gram/phy/ecp5ddrphy.py b/gram/phy/ecp5ddrphy.py index 89bc244..ea5d58c 100644 --- a/gram/phy/ecp5ddrphy.py +++ b/gram/phy/ecp5ddrphy.py @@ -312,15 +312,18 @@ class ECP5DDRPHY(Peripheral, Elaboratable): with m.Else(): m.d.sync += dm_o_data_muxed.eq(dm_o_data[:4]) + dm_o_data_muxed_d = Signal(4) + m.d.sync += dm_o_data_muxed_d.eq(dm_o_data_muxed) + m.submodules += Instance("ODDRX2DQA", i_RST=ResetSignal("dramsync"), i_ECLK=ClockSignal("sync2x"), i_SCLK=ClockSignal("dramsync"), i_DQSW270=dqsw270, - i_D0=dm_o_data_muxed[0], - i_D1=dm_o_data_muxed[1], - i_D2=dm_o_data_muxed[2], - i_D3=dm_o_data_muxed[3], + i_D2=dm_o_data_muxed[0], + i_D3=dm_o_data_muxed[1], + i_D0=dm_o_data_muxed_d[2], + i_D1=dm_o_data_muxed_d[3], o_Q=self.pads.dm.o[i]) dqs = Signal() @@ -368,28 +371,32 @@ class ECP5DDRPHY(Peripheral, Elaboratable): dfi.phases[0].wrdata[1*databits+j], dfi.phases[0].wrdata[2*databits+j], dfi.phases[0].wrdata[3*databits+j], - dfi.phases[1].wrdata[0*databits+j], dfi.phases[1].wrdata[1*databits+j], dfi.phases[1].wrdata[2*databits+j], dfi.phases[1].wrdata[3*databits+j]) ) + m.d.sync += dq_o_data_d.eq(dq_o_data) with m.Switch(bl8_chunk): with m.Case(0): m.d.sync += dq_o_data_muxed.eq(dq_o_data[:4]) with m.Case(1): m.d.sync += dq_o_data_muxed.eq(dq_o_data_d[4:]) + + dq_o_data_muxed_d = Signal.like(dq_o_data_muxed) + m.d.sync += dq_o_data_muxed_d.eq(dq_o_data_muxed) + m.submodules += [ Instance("ODDRX2DQA", i_RST=ResetSignal("dramsync"), i_ECLK=ClockSignal("sync2x"), i_SCLK=ClockSignal(), i_DQSW270=dqsw270, - i_D0=dq_o_data_muxed[0], - i_D1=dq_o_data_muxed[1], - i_D2=dq_o_data_muxed[2], - i_D3=dq_o_data_muxed[3], + i_D0=dq_o_data_muxed_d[2], + i_D1=dq_o_data_muxed_d[3], + i_D2=dq_o_data_muxed[0], + i_D3=dq_o_data_muxed[1], o_Q=dq_o ), Instance("DELAYF", @@ -468,19 +475,19 @@ class ECP5DDRPHY(Peripheral, Elaboratable): # 2x for DDR, 2x for halfrate) but DDR3 requires a burst of 8 datas (BL8) for best efficiency. # Writes are then performed in 2 sys_clk cycles and data needs to be selected for each cycle. # FIXME: understand +2 - wrdata_en = Signal(cwl_sys_latency + 4) + wrdata_en = Signal(cwl_sys_latency + 5) wrdata_en_last = Signal.like(wrdata_en) m.d.comb += wrdata_en.eq(Cat(dfi.phases[self.settings.wrphase].wrdata_en, wrdata_en_last)) m.d.sync += wrdata_en_last.eq(wrdata_en) m.d.comb += dq_oe.eq(wrdata_en[cwl_sys_latency + 1] | wrdata_en[cwl_sys_latency + 2]) m.d.comb += bl8_chunk.eq(wrdata_en[cwl_sys_latency + 1]) - m.d.comb += dqs_oe.eq(dq_oe) + m.d.comb += dqs_oe.eq(dq_oe | wrdata_en[cwl_sys_latency + 3]) # Write DQS Postamble/Preamble Control Path ------------------------------------------------ # Generates DQS Preamble 1 cycle before the first write and Postamble 1 cycle after the last # write. During writes, DQS tristate is configured as output for at least 4 sys_clk cycles: # 1 for Preamble, 2 for the Write and 1 for the Postamble. m.d.comb += dqs_preamble.eq(wrdata_en[cwl_sys_latency + 0] & ~wrdata_en[cwl_sys_latency + 1]) - m.d.comb += dqs_postamble.eq(wrdata_en[cwl_sys_latency + 3] & ~wrdata_en[cwl_sys_latency + 2]) + m.d.comb += dqs_postamble.eq(wrdata_en[cwl_sys_latency + 4] & ~wrdata_en[cwl_sys_latency + 3]) return m -- 2.30.2