phy/ecp5ddrphy: simplify commands and ODDR/IDDR data mapping.
This commit is contained in:
parent
db8eaff086
commit
b772bb54a7
|
@ -64,16 +64,16 @@ class ECP5DDRPHYInit(Module):
|
||||||
self.sync.init += [
|
self.sync.init += [
|
||||||
# Wait DDRDLLA Lock
|
# Wait DDRDLLA Lock
|
||||||
timeline(new_lock, [
|
timeline(new_lock, [
|
||||||
(1*t, [freeze.eq(1)]), # Freeze DDRDLLA
|
( 1*t, [freeze.eq(1)]), # Freeze DDRDLLA
|
||||||
(2*t, [stop.eq(1)]), # Stop ECLK domain
|
( 2*t, [ stop.eq(1)]), # Stop ECLK domain
|
||||||
(3*t, [reset.eq(1)]), # Reset ECLK domain
|
( 3*t, [ reset.eq(1)]), # Reset ECLK domain
|
||||||
(4*t, [reset.eq(0)]), # Release ECLK domain reset
|
( 4*t, [ reset.eq(0)]), # Release ECLK domain reset
|
||||||
(5*t, [stop.eq(0)]), # Release ECLK domain stop
|
( 5*t, [ stop.eq(0)]), # Release ECLK domain stop
|
||||||
(6*t, [freeze.eq(0)]), # Release DDRDLLA freeze
|
( 6*t, [freeze.eq(0)]), # Release DDRDLLA freeze
|
||||||
(7*t, [pause.eq(1)]), # Pause DQSBUFM
|
( 7*t, [ pause.eq(1)]), # Pause DQSBUFM
|
||||||
(8*t, [update.eq(1)]), # Update DDRDLLA
|
( 8*t, [update.eq(1)]), # Update DDRDLLA
|
||||||
(9*t, [update.eq(0)]), # Release DDRDMMA update
|
( 9*t, [update.eq(0)]), # Release DDRDMMA update
|
||||||
(10*t, [pause.eq(0)]), # Release DQSBUFM pause
|
(10*t, [ pause.eq(0)]), # Release DQSBUFM pause
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -159,52 +159,31 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
i_RST = ResetSignal("sys"),
|
i_RST = ResetSignal("sys"),
|
||||||
i_SCLK = ClockSignal("sys"),
|
i_SCLK = ClockSignal("sys"),
|
||||||
i_ECLK = ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_D0 = 0,
|
**{f"i_D{n}": (0b1010 >> n) & 0b1 for n in range(4)},
|
||||||
i_D1 = 1,
|
|
||||||
i_D2 = 0,
|
|
||||||
i_D3 = 1,
|
|
||||||
o_Q = pads.clk_p[i]
|
o_Q = pads.clk_p[i]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Addresses and Commands ---------------------------------------------------------------
|
# Commands -----------------------------------------------------------------------------
|
||||||
for i in range(addressbits):
|
commands = {
|
||||||
self.specials += Instance("ODDRX2F",
|
"a" : "address",
|
||||||
i_RST = ResetSignal("sys"),
|
"ba" : "bank" ,
|
||||||
i_SCLK = ClockSignal("sys"),
|
"ras_n": "ras_n" ,
|
||||||
i_ECLK = ClockSignal("sys2x"),
|
"cas_n": "cas_n" ,
|
||||||
i_D0 = dfi.phases[0].address[i],
|
"we_n" : "we_n" ,
|
||||||
i_D1 = dfi.phases[0].address[i],
|
"cke" : "cke" ,
|
||||||
i_D2 = dfi.phases[1].address[i],
|
"odt" : "odt" ,
|
||||||
i_D3 = dfi.phases[1].address[i],
|
}
|
||||||
o_Q = pads.a[i]
|
if hasattr(pads, "reset_n"): commands.update({"reset_n" : "reset_n"})
|
||||||
)
|
if hasattr(pads, "cs_n") : commands.update({"cs_n" : "cs_n"})
|
||||||
for i in range(bankbits):
|
for pad_name, dfi_name in commands.items():
|
||||||
self.specials += Instance("ODDRX2F",
|
pad = getattr(pads, pad_name)
|
||||||
i_RST = ResetSignal("sys"),
|
for i in range(len(pad)):
|
||||||
i_SCLK = ClockSignal("sys"),
|
|
||||||
i_ECLK = ClockSignal("sys2x"),
|
|
||||||
i_D0 = dfi.phases[0].bank[i],
|
|
||||||
i_D1 = dfi.phases[0].bank[i],
|
|
||||||
i_D2 = dfi.phases[1].bank[i],
|
|
||||||
i_D3 = dfi.phases[1].bank[i],
|
|
||||||
o_Q = pads.ba[i]
|
|
||||||
)
|
|
||||||
controls = ["ras_n", "cas_n", "we_n", "cke", "odt"]
|
|
||||||
if hasattr(pads, "reset_n"):
|
|
||||||
controls.append("reset_n")
|
|
||||||
if hasattr(pads, "cs_n"):
|
|
||||||
controls.append("cs_n")
|
|
||||||
for name in controls:
|
|
||||||
for i in range(len(getattr(pads, name))):
|
|
||||||
self.specials += Instance("ODDRX2F",
|
self.specials += Instance("ODDRX2F",
|
||||||
i_RST = ResetSignal("sys"),
|
i_RST = ResetSignal("sys"),
|
||||||
i_SCLK = ClockSignal("sys"),
|
i_SCLK = ClockSignal("sys"),
|
||||||
i_ECLK = ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_D0 = getattr(dfi.phases[0], name)[i],
|
**{f"i_D{n}": getattr(dfi.phases[n//2], dfi_name)[i] for n in range(4)},
|
||||||
i_D1 = getattr(dfi.phases[0], name)[i],
|
o_Q = pad[i]
|
||||||
i_D2 = getattr(dfi.phases[1], name)[i],
|
|
||||||
i_D3 = getattr(dfi.phases[1], name)[i],
|
|
||||||
o_Q = getattr(pads, name)[i]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# DQS/DM/DQ --------------------------------------------------------------------------------
|
# DQS/DM/DQ --------------------------------------------------------------------------------
|
||||||
|
@ -251,17 +230,11 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
# Reads (generate shifted DQS clock for reads)
|
# Reads (generate shifted DQS clock for reads)
|
||||||
i_READ0 = dqs_re,
|
i_READ0 = dqs_re,
|
||||||
i_READ1 = dqs_re,
|
i_READ1 = dqs_re,
|
||||||
i_READCLKSEL0 = rdly[0],
|
**{f"i_READCLKSEL{n}": rdly[n] for n in range(3)},
|
||||||
i_READCLKSEL1 = rdly[1],
|
|
||||||
i_READCLKSEL2 = rdly[2],
|
|
||||||
i_DQSI = dqs_i,
|
i_DQSI = dqs_i,
|
||||||
o_DQSR90 = dqsr90,
|
o_DQSR90 = dqsr90,
|
||||||
o_RDPNTR0 = rdpntr[0],
|
**{f"o_RDPNTR{n}": rdpntr[n] for n in range(3)},
|
||||||
o_RDPNTR1 = rdpntr[1],
|
**{f"o_WRPNTR{n}": wrpntr[n] for n in range(3)},
|
||||||
o_RDPNTR2 = rdpntr[2],
|
|
||||||
o_WRPNTR0 = wrpntr[0],
|
|
||||||
o_WRPNTR1 = wrpntr[1],
|
|
||||||
o_WRPNTR2 = wrpntr[2],
|
|
||||||
o_DATAVALID = self.datavalid[i],
|
o_DATAVALID = self.datavalid[i],
|
||||||
o_BURSTDET = burstdet,
|
o_BURSTDET = burstdet,
|
||||||
|
|
||||||
|
@ -285,10 +258,7 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
i_SCLK = ClockSignal("sys"),
|
i_SCLK = ClockSignal("sys"),
|
||||||
i_ECLK = ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_DQSW = dqsw,
|
i_DQSW = dqsw,
|
||||||
i_D0 = 0,
|
**{f"i_D{n}": (0b1010 >> n) & 0b1 for n in range(4)},
|
||||||
i_D1 = 1,
|
|
||||||
i_D2 = 0,
|
|
||||||
i_D3 = 1,
|
|
||||||
o_Q = dqs
|
o_Q = dqs
|
||||||
),
|
),
|
||||||
Instance("TSHX2DQSA",
|
Instance("TSHX2DQSA",
|
||||||
|
@ -307,17 +277,8 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
dm_o_data = Signal(8)
|
dm_o_data = Signal(8)
|
||||||
dm_o_data_d = Signal(8)
|
dm_o_data_d = Signal(8)
|
||||||
dm_o_data_muxed = Signal(4)
|
dm_o_data_muxed = Signal(4)
|
||||||
self.comb += dm_o_data.eq(Cat(
|
for n in range(8):
|
||||||
dfi.phases[0].wrdata_mask[0*databits//8+i],
|
self.comb += dm_o_data[n].eq(dfi.phases[n//4].wrdata_mask[n%4*databits//8+i])
|
||||||
dfi.phases[0].wrdata_mask[1*databits//8+i],
|
|
||||||
dfi.phases[0].wrdata_mask[2*databits//8+i],
|
|
||||||
dfi.phases[0].wrdata_mask[3*databits//8+i],
|
|
||||||
|
|
||||||
dfi.phases[1].wrdata_mask[0*databits//8+i],
|
|
||||||
dfi.phases[1].wrdata_mask[1*databits//8+i],
|
|
||||||
dfi.phases[1].wrdata_mask[2*databits//8+i],
|
|
||||||
dfi.phases[1].wrdata_mask[3*databits//8+i]),
|
|
||||||
)
|
|
||||||
self.sync += dm_o_data_d.eq(dm_o_data)
|
self.sync += dm_o_data_d.eq(dm_o_data)
|
||||||
dm_bl8_cases = {}
|
dm_bl8_cases = {}
|
||||||
dm_bl8_cases[0] = dm_o_data_muxed.eq(dm_o_data[:4])
|
dm_bl8_cases[0] = dm_o_data_muxed.eq(dm_o_data[:4])
|
||||||
|
@ -328,10 +289,7 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
i_SCLK = ClockSignal("sys"),
|
i_SCLK = ClockSignal("sys"),
|
||||||
i_ECLK = ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_DQSW270 = dqsw270,
|
i_DQSW270 = dqsw270,
|
||||||
i_D0 = dm_o_data_muxed[0],
|
**{f"i_D{n}": dm_o_data_muxed[n] for n in range(4)},
|
||||||
i_D1 = dm_o_data_muxed[1],
|
|
||||||
i_D2 = dm_o_data_muxed[2],
|
|
||||||
i_D3 = dm_o_data_muxed[3],
|
|
||||||
o_Q = pads.dm[i]
|
o_Q = pads.dm[i]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -341,21 +299,12 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
dq_i = Signal()
|
dq_i = Signal()
|
||||||
dq_oe_n = Signal()
|
dq_oe_n = Signal()
|
||||||
dq_i_delayed = Signal()
|
dq_i_delayed = Signal()
|
||||||
dq_i_data = Signal(4)
|
dq_i_data = Signal(8)
|
||||||
dq_o_data = Signal(8)
|
dq_o_data = Signal(8)
|
||||||
dq_o_data_d = Signal(8)
|
dq_o_data_d = Signal(8)
|
||||||
dq_o_data_muxed = Signal(4)
|
dq_o_data_muxed = Signal(4)
|
||||||
self.comb += dq_o_data.eq(Cat(
|
for n in range(8):
|
||||||
dfi.phases[0].wrdata[0*databits+j],
|
self.comb += dq_o_data[n].eq(dfi.phases[n//4].wrdata[n%4*databits+j])
|
||||||
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])
|
|
||||||
)
|
|
||||||
self.sync += dq_o_data_d.eq(dq_o_data)
|
self.sync += dq_o_data_d.eq(dq_o_data)
|
||||||
dq_bl8_cases = {}
|
dq_bl8_cases = {}
|
||||||
dq_bl8_cases[0] = dq_o_data_muxed.eq(dq_o_data[:4])
|
dq_bl8_cases[0] = dq_o_data_muxed.eq(dq_o_data[:4])
|
||||||
|
@ -367,12 +316,16 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
i_SCLK = ClockSignal("sys"),
|
i_SCLK = ClockSignal("sys"),
|
||||||
i_ECLK = ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_DQSW270 = dqsw270,
|
i_DQSW270 = dqsw270,
|
||||||
i_D0 = dq_o_data_muxed[0],
|
**{f"i_D{n}": dq_o_data_muxed[n] for n in range(4)},
|
||||||
i_D1 = dq_o_data_muxed[1],
|
|
||||||
i_D2 = dq_o_data_muxed[2],
|
|
||||||
i_D3 = dq_o_data_muxed[3],
|
|
||||||
o_Q = dq_o
|
o_Q = dq_o
|
||||||
),
|
)
|
||||||
|
]
|
||||||
|
dq_i_bitslip = BitSlip(4,
|
||||||
|
rst = self._dly_sel.storage[i] & self._rdly_dq_bitslip_rst.re,
|
||||||
|
slp = self._dly_sel.storage[i] & self._rdly_dq_bitslip.re,
|
||||||
|
cycles = 1)
|
||||||
|
self.submodules += dq_i_bitslip
|
||||||
|
self.specials += [
|
||||||
Instance("DELAYF",
|
Instance("DELAYF",
|
||||||
p_DEL_MODE = "DQS_ALIGNED_X2",
|
p_DEL_MODE = "DQS_ALIGNED_X2",
|
||||||
i_LOADN = 1,
|
i_LOADN = 1,
|
||||||
|
@ -386,38 +339,17 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
i_SCLK = ClockSignal("sys"),
|
i_SCLK = ClockSignal("sys"),
|
||||||
i_ECLK = ClockSignal("sys2x"),
|
i_ECLK = ClockSignal("sys2x"),
|
||||||
i_DQSR90 = dqsr90,
|
i_DQSR90 = dqsr90,
|
||||||
i_RDPNTR0 = rdpntr[0],
|
**{f"i_RDPNTR{n}": rdpntr[n] for n in range(3)},
|
||||||
i_RDPNTR1 = rdpntr[1],
|
**{f"i_WRPNTR{n}": wrpntr[n] for n in range(3)},
|
||||||
i_RDPNTR2 = rdpntr[2],
|
|
||||||
i_WRPNTR0 = wrpntr[0],
|
|
||||||
i_WRPNTR1 = wrpntr[1],
|
|
||||||
i_WRPNTR2 = wrpntr[2],
|
|
||||||
i_D = dq_i_delayed,
|
i_D = dq_i_delayed,
|
||||||
o_Q0 = dq_i_data[0],
|
**{f"o_Q{n}": dq_i_bitslip.i[n] for n in range(4)},
|
||||||
o_Q1 = dq_i_data[1],
|
|
||||||
o_Q2 = dq_i_data[2],
|
|
||||||
o_Q3 = dq_i_data[3],
|
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
dq_i_bitslip = BitSlip(4,
|
|
||||||
rst = self._dly_sel.storage[i] & self._rdly_dq_bitslip_rst.re,
|
|
||||||
slp = self._dly_sel.storage[i] & self._rdly_dq_bitslip.re,
|
|
||||||
cycles = 1)
|
|
||||||
self.submodules += dq_i_bitslip
|
|
||||||
dq_i_bitslip_o_d = Signal(4)
|
dq_i_bitslip_o_d = Signal(4)
|
||||||
self.comb += dq_i_bitslip.i.eq(dq_i_data)
|
|
||||||
self.sync += dq_i_bitslip_o_d.eq(dq_i_bitslip.o)
|
self.sync += dq_i_bitslip_o_d.eq(dq_i_bitslip.o)
|
||||||
self.comb += [
|
self.comb += dq_i_data.eq(Cat(dq_i_bitslip_o_d, dq_i_bitslip.o))
|
||||||
dfi.phases[0].rddata[0*databits+j].eq(dq_i_bitslip_o_d[0]),
|
for n in range(8):
|
||||||
dfi.phases[0].rddata[1*databits+j].eq(dq_i_bitslip_o_d[1]),
|
self.comb += dfi.phases[n//4].rddata[n%4*databits+j].eq(dq_i_data[n])
|
||||||
dfi.phases[0].rddata[2*databits+j].eq(dq_i_bitslip_o_d[2]),
|
|
||||||
dfi.phases[0].rddata[3*databits+j].eq(dq_i_bitslip_o_d[3]),
|
|
||||||
dfi.phases[1].rddata[0*databits+j].eq(dq_i_bitslip.o[0]),
|
|
||||||
dfi.phases[1].rddata[1*databits+j].eq(dq_i_bitslip.o[1]),
|
|
||||||
dfi.phases[1].rddata[2*databits+j].eq(dq_i_bitslip.o[2]),
|
|
||||||
dfi.phases[1].rddata[3*databits+j].eq(dq_i_bitslip.o[3]),
|
|
||||||
]
|
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("TSHX2DQA",
|
Instance("TSHX2DQA",
|
||||||
i_RST = ResetSignal("sys"),
|
i_RST = ResetSignal("sys"),
|
||||||
|
|
Loading…
Reference in New Issue