s6ddrphy: improve genericity by adding wr_bitslip and dqs_ddr_alignment parameters...
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Wed, 6 Nov 2013 14:56:53 +0000 (15:56 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 8 Nov 2013 23:59:11 +0000 (00:59 +0100)
milkymist/s6ddrphy/__init__.py
top.py

index a1491f5a060af1dd828c695c5a957af482627aae..119f977935199a71890b7ec2d0b7835828cb3cd4 100644 (file)
@@ -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)
diff --git a/top.py b/top.py
index 0d873d50d1ab5207b5d7ec60b35c342f4868d894..d25a95af498563795da4342dfb1508e3d36b2425 100644 (file)
--- a/top.py
+++ b/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)