s6ddrphy: improve genericity by adding wr_bitslip and dqs_ddr_alignment parameters bitslip parameter is renamed to rd_bitslip
This commit is contained in:
parent
e7c72a826c
commit
307fb41ca3
|
@ -27,12 +27,11 @@ from migen.genlib.record import *
|
|||
from milkymist import lasmicon
|
||||
|
||||
class S6DDRPHY(Module):
|
||||
def __init__(self, pads, memtype, nphases, cl, bitslip):
|
||||
def __init__(self, pads, memtype, nphases, cl, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
|
||||
if memtype not in ["DDR", "LPDDR", "DDR2"]:
|
||||
raise NotImplementedError("S6DDRPHY only supports DDR, LPDDR and DDR2")
|
||||
if cl != 3:
|
||||
raise NotImplementedError("S6DDRPHY only supports CAS LATENCY 3")
|
||||
|
||||
a = flen(pads.a)
|
||||
ba = flen(pads.ba)
|
||||
d = flen(pads.dq)
|
||||
|
@ -118,7 +117,7 @@ class S6DDRPHY(Module):
|
|||
bitslip_inc = Signal()
|
||||
|
||||
sd_sys += [
|
||||
If(bitslip_cnt == bitslip,
|
||||
If(bitslip_cnt == rd_bitslip,
|
||||
bitslip_inc.eq(0)
|
||||
).Else(
|
||||
bitslip_cnt.eq(bitslip_cnt+1),
|
||||
|
@ -148,7 +147,7 @@ class S6DDRPHY(Module):
|
|||
for i in range(d//8):
|
||||
# DQS output
|
||||
self.specials += Instance("ODDR2",
|
||||
Instance.Parameter("DDR_ALIGNMENT", "C1"),
|
||||
Instance.Parameter("DDR_ALIGNMENT", dqs_ddr_alignment),
|
||||
Instance.Parameter("INIT", 0),
|
||||
Instance.Parameter("SRTYPE", "ASYNC"),
|
||||
|
||||
|
@ -166,7 +165,7 @@ class S6DDRPHY(Module):
|
|||
|
||||
# DQS tristate cmd
|
||||
self.specials += Instance("ODDR2",
|
||||
Instance.Parameter("DDR_ALIGNMENT", "C1"),
|
||||
Instance.Parameter("DDR_ALIGNMENT", dqs_ddr_alignment),
|
||||
Instance.Parameter("INIT", 0),
|
||||
Instance.Parameter("SRTYPE", "ASYNC"),
|
||||
|
||||
|
@ -218,18 +217,20 @@ class S6DDRPHY(Module):
|
|||
|
||||
|
||||
drive_dq = Signal()
|
||||
drive_dq_n = Signal()
|
||||
d_drive_dq = Signal()
|
||||
d_drive_dq_n = Signal()
|
||||
self.comb += [
|
||||
drive_dq_n.eq(~drive_dq),
|
||||
d_drive_dq_n.eq(~d_drive_dq)
|
||||
]
|
||||
drive_dq_n = [Signal() for i in range(2)]
|
||||
self.comb += drive_dq_n[0].eq(~drive_dq)
|
||||
sd_sys += drive_dq_n[1].eq(drive_dq_n[0])
|
||||
|
||||
dq_t = Signal(d)
|
||||
dq_o = Signal(d)
|
||||
dq_i = Signal(d)
|
||||
|
||||
dq_wrdata = []
|
||||
for i in range(2):
|
||||
for j in reversed(range(nphases)):
|
||||
dq_wrdata.append(d_dfi[i*nphases+j].wrdata[:d])
|
||||
dq_wrdata.append(d_dfi[i*nphases+j].wrdata[d:])
|
||||
|
||||
for i in range(d):
|
||||
# Data serializer
|
||||
self.specials += Instance("OSERDES2",
|
||||
|
@ -247,15 +248,16 @@ class S6DDRPHY(Module):
|
|||
Instance.Input("RST", 0),
|
||||
Instance.Input("CLKDIV", sys_clk),
|
||||
|
||||
Instance.Input("D1", d_dfi[1*nphases+0].wrdata[i]),
|
||||
Instance.Input("D2", d_dfi[1*nphases+1].wrdata[i+d]),
|
||||
Instance.Input("D3", d_dfi[1*nphases+1].wrdata[i]),
|
||||
Instance.Input("D4", d_dfi[0*nphases+0].wrdata[i+d]),
|
||||
Instance.Input("D1", dq_wrdata[wr_bitslip+3][i]),
|
||||
Instance.Input("D2", dq_wrdata[wr_bitslip+2][i]),
|
||||
Instance.Input("D3", dq_wrdata[wr_bitslip+1][i]),
|
||||
Instance.Input("D4", dq_wrdata[wr_bitslip+0][i]),
|
||||
|
||||
Instance.Output("TQ", dq_t[i]),
|
||||
Instance.Input("T1", d_drive_dq_n),
|
||||
Instance.Input("T2", d_drive_dq_n),
|
||||
Instance.Input("T3", d_drive_dq_n),
|
||||
Instance.Input("T4", drive_dq_n),
|
||||
Instance.Input("T1", drive_dq_n[(wr_bitslip+3)//4]),
|
||||
Instance.Input("T2", drive_dq_n[(wr_bitslip+2)//4]),
|
||||
Instance.Input("T3", drive_dq_n[(wr_bitslip+1)//4]),
|
||||
Instance.Input("T4", drive_dq_n[(wr_bitslip+0)//4]),
|
||||
Instance.Input("TRAIN", 0),
|
||||
Instance.Input("TCE", 1),
|
||||
Instance.Input("SHIFTIN1", 0),
|
||||
|
@ -309,6 +311,12 @@ class S6DDRPHY(Module):
|
|||
Instance.InOut("IO", pads.dq[i])
|
||||
)
|
||||
|
||||
dq_wrdata_mask = []
|
||||
for i in range(2):
|
||||
for j in reversed(range(nphases)):
|
||||
dq_wrdata_mask.append(d_dfi[i*nphases+j].wrdata_mask[:d//8])
|
||||
dq_wrdata_mask.append(d_dfi[i*nphases+j].wrdata_mask[d//8:])
|
||||
|
||||
for i in range(d//8):
|
||||
# Mask serializer
|
||||
self.specials += Instance("OSERDES2",
|
||||
|
@ -326,10 +334,11 @@ class S6DDRPHY(Module):
|
|||
Instance.Input("RST", 0),
|
||||
Instance.Input("CLKDIV", sys_clk),
|
||||
|
||||
Instance.Input("D1", d_dfi[1*nphases+0].wrdata_mask[i]),
|
||||
Instance.Input("D2", d_dfi[1*nphases+1].wrdata_mask[i+d//8]),
|
||||
Instance.Input("D3", d_dfi[1*nphases+1].wrdata_mask[i]),
|
||||
Instance.Input("D4", d_dfi[0*nphases+0].wrdata_mask[i+d//8]),
|
||||
Instance.Input("D1", dq_wrdata_mask[wr_bitslip+3][i]),
|
||||
Instance.Input("D2", dq_wrdata_mask[wr_bitslip+2][i]),
|
||||
Instance.Input("D3", dq_wrdata_mask[wr_bitslip+1][i]),
|
||||
Instance.Input("D4", dq_wrdata_mask[wr_bitslip+0][i]),
|
||||
|
||||
Instance.Output("TQ"),
|
||||
Instance.Input("T1"),
|
||||
Instance.Input("T2"),
|
||||
|
@ -359,7 +368,6 @@ class S6DDRPHY(Module):
|
|||
# DQ/DQS/DM control
|
||||
#
|
||||
self.comb += drive_dq.eq(d_dfi[self.phy_settings.wrphase].wrdata_en)
|
||||
sd_sys += d_drive_dq.eq(drive_dq)
|
||||
|
||||
d_dfi_wrdata_en = Signal()
|
||||
sd_sys += d_dfi_wrdata_en.eq(d_dfi[self.phy_settings.wrphase].wrdata_en)
|
||||
|
|
2
top.py
2
top.py
|
@ -92,7 +92,7 @@ class SoC(Module):
|
|||
#
|
||||
# DFI
|
||||
#
|
||||
self.submodules.ddrphy = s6ddrphy.S6DDRPHY(platform.request("ddram"), memtype="DDR", nphases=2, cl=3, bitslip=0)
|
||||
self.submodules.ddrphy = s6ddrphy.S6DDRPHY(platform.request("ddram"), memtype="DDR", nphases=2, cl=3, rd_bitslip=0, wr_bitslip=3, dqs_ddr_alignment="C1")
|
||||
self.submodules.dfii = dfii.DFIInjector(sdram_geom.mux_a, sdram_geom.bank_a,
|
||||
self.ddrphy.phy_settings.dfi_d, self.ddrphy.phy_settings.nphases)
|
||||
self.submodules.dficon0 = dfi.Interconnect(self.dfii.master, self.ddrphy.dfi)
|
||||
|
|
Loading…
Reference in New Issue