use Migen s6ddrphy, generate sdram init_sequence in cif.py
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 9 Jul 2013 17:41:28 +0000 (19:41 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Wed, 10 Jul 2013 17:56:09 +0000 (19:56 +0200)
make.py
milkymist/cif.py
milkymist/lasmicon/__init__.py
milkymist/mxcrg/__init__.py
milkymist/s6ddrphy/__init__.py
software/bios/sdram.c
top.py
verilog/s6ddrphy/s6ddrphy.v [deleted file]

diff --git a/make.py b/make.py
index a69b77d6d4e5ec5f5d8a6a2486e41e79e375788a..040499b68892a8712848b46dcad959e2e0723203 100755 (executable)
--- a/make.py
+++ b/make.py
@@ -27,7 +27,7 @@ TIMESPEC "TSise_sucks1" = FROM "GRPvga_clk" TO "GRPsys_clk" TIG;
 TIMESPEC "TSise_sucks2" = FROM "GRPsys_clk" TO "GRPvga_clk" TIG;
 """)
 
-       for d in ["mxcrg", "s6ddrphy", "minimac3"]:
+       for d in ["mxcrg", "minimac3"]:
                platform.add_source_dir(os.path.join("verilog", d))
        platform.add_sources(os.path.join("verilog", "lm32", "submodule", "rtl"), 
                "lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v",
@@ -47,12 +47,16 @@ TIMESPEC "TSise_sucks2" = FROM "GRPsys_clk" TO "GRPvga_clk" TIG;
        if build_header:
                csr_header = cif.get_csr_header(soc.csr_base, soc.csrbankarray, soc.interrupt_map)
                write_to_file("software/include/hw/csr.h", csr_header)
+               
+               sdram_phy_header = cif.get_sdram_phy_header(soc.ddrphy)
+               write_to_file("software/include/hw/sdram_phy.h", sdram_phy_header)
+
 
 def main():
        parser = argparse.ArgumentParser(description="milkymist-ng - a high performance SoC built on Migen technology.")
        parser.add_argument("-p", "--platform", default="mixxeo", help="platform to build for")
        parser.add_argument("-B", "--no-bitstream", default=False, action="store_true", help="do not build bitstream file")
-       parser.add_argument("-H", "--no-header", default=False, action="store_true", help="do not build C header file with CSR/IRQ defs")
+       parser.add_argument("-H", "--no-header", default=False, action="store_true", help="do not build C header file with CSR/IRQ/SDRAM_PHY defs")
        parser.add_argument("-l", "--load", default=False, action="store_true", help="load bitstream to SRAM")
        parser.add_argument("-f", "--flash", default=False, action="store_true", help="load bitstream to flash")
        args = parser.parse_args()
index ace7b2af0ae951477a7898f0a34ec142388252e9..da253fb842d54e75ccfe2392aaaa73021e9b0842 100644 (file)
@@ -1,6 +1,7 @@
 from operator import itemgetter
 import re
 
+from migen.fhdl.std import *
 from migen.bank.description import CSRStatus
 
 def get_macros(filename):
@@ -64,3 +65,137 @@ def get_csr_header(csr_base, bank_array, interrupt_map):
                        r += "#define "+name.upper()+"_INTERRUPT "+str(interrupt_nr)+"\n"
        r += "\n#endif\n"
        return r
+
+def get_sdram_phy_header(sdram_phy):
+
+               if sdram_phy.phy_settings.type not in ["SDR", "DDR", "LPDDR", "DDR2"]:
+                       raise NotImplementedError("sdram phy header generator only supports SDR, DDR, LPDDR and DDR2")
+
+               r = "#ifndef __HW_SDRAM_PHY_H\n#define __SDRAM_PHY_H\n"
+               r += "#include <hw/common.h>\n#include <hw/csr.h>\n#include <hw/flags.h>\n\n"
+
+               r += "extern void cdelay(int i);\n"
+
+               #
+               # commands_px functions
+               # 
+               for n in range(sdram_phy.phy_settings.nphases):
+                       r += """
+static void command_p{n}(int cmd)
+{{
+       dfii_pi{n}_command_write(cmd);
+       dfii_pi{n}_command_issue_write(1);
+}}""".format(n=str(n))
+               r += "\n\n"
+
+               #
+               # rd/wr access macros
+               #
+               r += """
+#define dfii_pird_address_write(X) dfii_pi{rdphase}_address_write(X)
+#define dfii_piwr_address_write(X) dfii_pi{wrphase}_address_write(X)
+
+#define dfii_pird_baddress_write(X) dfii_pi{rdphase}_baddress_write(X)
+#define dfii_piwr_baddress_write(X) dfii_pi{wrphase}_baddress_write(X)
+
+#define command_prd(X) command_p{rdphase}(X)
+#define command_pwr(X) command_p{wrphase}(X)
+""".format(rdphase=str(sdram_phy.phy_settings.rdphase), wrphase=str(sdram_phy.phy_settings.wrphase)) 
+               r +="\n"
+               
+               #
+               # init sequence
+               # 
+               cmds = {
+                       "PRECHARGE_ALL" : "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
+                       "MODE_REGISTER" : "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
+                       "AUTO_REFRESH"  : "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS",
+                       "CKE"           : "DFII_CONTROL_CKE"
+               }
+
+               def gen_cmd(comment, a, ba, cmd, delay):        
+                       r = "\t/* %s */\n" %comment
+                       r += "\tdfii_pi0_address_write(0x%04X);\n" %a
+                       r += "\tdfii_pi0_baddress_write(%d);\n" %ba
+                       if "CKE" in cmd:
+                               r += "\tdfii_control_write(%s);\n" %cmd
+                       else:
+                               r += "\tcommand_p0(%s);\n" %cmd
+                       r += "\tcdelay(%d);\n" %delay
+                       r += "\n"
+                       return r
+
+
+               r += "static void init_sequence(void) {\n"
+
+               cl = sdram_phy.phy_settings.cl
+               
+               if sdram_phy.phy_settings.type == "SDR":
+                       bl = 1*sdram_phy.phy_settings.nphases
+                       mr  = log2_int(bl) + (cl << 4)
+                       reset_dll = 1 << 8
+
+                       init_sequence = [
+                               ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+                               ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+                               ("Load Mode Register / Reset DLL, CL=%d, BL=%d" %(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+                               ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+                               ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+                               ("Load Mode Register / CL=%d, BL=%d" %(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+                       ]
+
+               elif sdram_phy.phy_settings.type == "DDR":
+                       bl = 2*sdram_phy.phy_settings.nphases
+                       mr  = log2_int(bl) + (cl << 4)
+                       emr = 0
+                       reset_dll = 1 << 8
+                       init_sequence = [
+                               ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+                               ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+                               ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
+                               ("Load Mode Register / Reset DLL, CL=%d, BL=%d" %(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+                               ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+                               ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+                               ("Load Mode Register / CL=%d, BL=%d" %(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+                       ]
+
+               elif sdram_phy.phy_settings.type == "LPDDR":
+                       bl = 2*sdram_phy.phy_settings.nphases
+                       mr  = log2_int(bl) + (cl << 4)
+                       emr = 0
+                       reset_dll = 1 << 8
+
+                       init_sequence = [
+                               ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+                               ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+                               ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0),
+                               ("Load Mode Register / Reset DLL, CL=%d, BL=%d" %(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+                               ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+                               ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+                               ("Load Mode Register / CL=%d, BL=%d" %(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+                       ]
+
+               elif sdram_phy.phy_settings.type == "DDR2":
+                       bl = 2*sdram_phy.phy_settings.nphases
+                       mr  = log2_int(bl) + (cl << 4)
+                       emr = 0
+                       reset_dll = 1 << 8
+
+                       init_sequence = [
+                               ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+                               ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+                               ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
+                               ("Load Mode Register / Reset DLL, CL=%d, BL=%d" %(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+                               ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+                               ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+                               ("Load Mode Register / CL=%d, BL=%d" %(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+                       ]
+
+               for comment, a, ba, cmd, delay in init_sequence:
+                       r += gen_cmd(comment, a, ba, cmd, delay)
+
+               r += "}\n"
+               r += "#endif\n"
+
+               return r
index f56e91604fc26d113fb9e9fc41dfb908a5c7b5cc..f0a38999472a7643271c303aa81c31ffc5542a73 100644 (file)
@@ -7,7 +7,7 @@ from milkymist.lasmicon.refresher import *
 from milkymist.lasmicon.bankmachine import *
 from milkymist.lasmicon.multiplexer import *
 
-PhySettings = namedtuple("PhySettings", "dfi_d nphases rdphase wrphase")
+PhySettings = namedtuple("PhySettings", "type dfi_d nphases rdphase wrphase cl")
 
 class GeomSettings(namedtuple("_GeomSettings", "bank_a row_a col_a")):
        def __init__(self, *args, **kwargs):
index 7107d023688254bf3f527d762701ff8c0ea32960..c487f07ad27993b96d2bb29b7d9ee036bd11afda 100644 (file)
@@ -6,9 +6,9 @@ from migen.bank.description import *
 class MXCRG(Module, AutoCSR):
        def __init__(self, pads, outfreq1x):
                self.clock_domains.cd_sys = ClockDomain()
-               self.clock_domains.cd_sys2x_270 = ClockDomain()
-               self.clock_domains.cd_sys4x_wr = ClockDomain()
-               self.clock_domains.cd_sys4x_rd = ClockDomain()
+               self.clock_domains.cd_sdram_half = ClockDomain()
+               self.clock_domains.cd_sdram_full_wr = ClockDomain()
+               self.clock_domains.cd_sdram_full_rd = ClockDomain()
                self.clock_domains.cd_eth_rx = ClockDomain()
                self.clock_domains.cd_eth_tx = ClockDomain()
                self.clock_domains.cd_vga = ClockDomain(reset_less=True)
@@ -44,9 +44,9 @@ class MXCRG(Module, AutoCSR):
                        
                        Instance.Output("sys_clk", self.cd_sys.clk),
                        Instance.Output("sys_rst", self.cd_sys.rst),
-                       Instance.Output("clk2x_270", self.cd_sys2x_270.clk),
-                       Instance.Output("clk4x_wr", self.cd_sys4x_wr.clk),
-                       Instance.Output("clk4x_rd", self.cd_sys4x_rd.clk),
+                       Instance.Output("clk2x_270", self.cd_sdram_half.clk),
+                       Instance.Output("clk4x_wr", self.cd_sdram_full_wr.clk),
+                       Instance.Output("clk4x_rd", self.cd_sdram_full_rd.clk),
                        Instance.Output("eth_rx_clk", self.cd_eth_rx.clk),
                        Instance.Output("eth_tx_clk", self.cd_eth_tx.clk),
                        Instance.Output("vga_clk", self.cd_vga.clk),
index bd684ce908f8a41ec6017a5594e44d7c31043693..c21a331857089b6fce80e517ca20c2866379c2be 100644 (file)
+#
+# 1:2 frequency-ratio DDR / LPDDR / DDR2 PHY for 
+# Spartan-6
+# 
+# Assert dfi_wrdata_en and present the data 
+# on dfi_wrdata_mask/dfi_wrdata in the same
+# cycle as the write command.
+#
+# Assert dfi_rddata_en in the same cycle as the read
+# command. The data will come back on dfi_rddata
+# CL + 2 cycles later, along with the assertion 
+# of dfi_rddata_valid.
+#
+# This PHY supports configurable CAS Latency.
+# Read commands must be sent on phase RDPHASE.
+# Write commands must be sent on phase WRPHASE.
+#/
+
+# Todo:
+#      - use CSR for bitslip?
+#   - move sdram clk generation to phy?
+
 from migen.fhdl.std import *
-from migen.bus import dfi
+from migen.bus.dfi import *
+from migen.genlib.record import *
 
 class S6DDRPHY(Module):
-       def __init__(self, pads):
-               self.dfi = dfi.Interface(flen(pads.a), flen(pads.ba), 2*flen(pads.dq), 2)
+       def __init__(self, pads, phy_settings, bitslip):
+               
+               if phy_settings.type not in ["DDR", "LPDDR", "DDR2"]:
+                       raise NotImplementedError("S6DDRPHY only supports DDR, LPDDR and DDR2")
+
+               a = flen(pads.a)
+               ba = flen(pads.ba)
+               d = flen(pads.dq)
+               nphases = phy_settings.nphases
+               self.phy_settings = phy_settings
+
+               self.dfi = Interface(a, ba, nphases*d, nphases)
                self.clk4x_wr_strb = Signal()
                self.clk4x_rd_strb = Signal()
 
                ###
 
-               inst_items = [
-                       Instance.Parameter("NUM_AD", flen(pads.a)),
-                       Instance.Parameter("NUM_BA", flen(pads.ba)),
-                       Instance.Parameter("NUM_D", 2*flen(pads.dq)),
-
-                       Instance.Input("sys_clk", ClockSignal()),
-                       Instance.Input("clk2x_270", ClockSignal("sys2x_270")),
-                       Instance.Input("clk4x_wr", ClockSignal("sys4x_wr")),
-                       Instance.Input("clk4x_rd", ClockSignal("sys4x_rd")),
-
-                       Instance.Input("clk4x_wr_strb", self.clk4x_wr_strb),
-                       Instance.Input("clk4x_rd_strb", self.clk4x_rd_strb),
-
-                       Instance.Output("sd_a", pads.a),
-                       Instance.Output("sd_ba", pads.ba),
-                       Instance.Output("sd_cs_n", pads.cs_n),
-                       Instance.Output("sd_cke", pads.cke),
-                       Instance.Output("sd_ras_n", pads.ras_n),
-                       Instance.Output("sd_cas_n", pads.cas_n),
-                       Instance.Output("sd_we_n", pads.we_n),
-                       Instance.InOut("sd_dq", pads.dq),
-                       Instance.Output("sd_dm", pads.dm),
-                       Instance.InOut("sd_dqs", pads.dqs)
+               # sys_clk           : system clk, used for dfi interface
+               # sdram_half_clk    : half rate sdram clk 
+               # sdram_full_wr_clk : full rate sdram write clk
+               # sdram_full_rd_clk : full rate sdram write clk
+               sd_sys = getattr(self.sync, "sys")
+               sd_sdram_half = getattr(self.sync, "sdram_half")
+               sd_sdram_full_wr = getattr(self.sync, "sdram_full_wr")
+               sd_sdram_full_rd = getattr(self.sync, "sdram_full_rd")
+
+               sys_clk = ClockSignal("sys")
+               sdram_half_clk = ClockSignal("sdram_half")
+               sdram_full_wr_clk = ClockSignal("sdram_full_wr")
+               sdram_full_rd_clk = ClockSignal("sdram_full_rd")
+
+               # 
+               # Command/address
+               #
+
+               # select active phase
+               #             sys_clk   ____----____----
+               #  phase_sel(nphases=1) 0       0
+               #  phase_sel(nphases=2) 0   1   0   1
+               #  phase_sel(nphases=4) 0 1 2 3 0 1 2 3
+               phase_sel = Signal(log2_int(nphases))
+               sys_clk_d = Signal()
+
+               sd_sdram_half += [
+                       If(sys_clk & ~sys_clk_d, phase_sel.eq(0)
+                       ).Else(phase_sel.eq(phase_sel+1)),
+                       sys_clk_d.eq(sys_clk)
+               ]
+
+               # register dfi cmds on half_rate clk
+               r_dfi = Array(Record(phase_cmd_description(a, ba)) for i in range(nphases))
+               for n, phase in enumerate(self.dfi.phases):
+                       sd_sdram_half +=[
+                               r_dfi[n].address.eq(phase.address),
+                               r_dfi[n].bank.eq(phase.bank),
+                               r_dfi[n].cs_n.eq(phase.cs_n),
+                               r_dfi[n].cke.eq(phase.cke),
+                               r_dfi[n].cas_n.eq(phase.cas_n),
+                               r_dfi[n].ras_n.eq(phase.ras_n),
+                               r_dfi[n].we_n.eq(phase.we_n)
+                       ]
+
+               # output cmds
+               sd_sdram_half += [
+                       pads.a.eq(r_dfi[phase_sel].address),
+                       pads.ba.eq(r_dfi[phase_sel].bank),
+                       pads.cs_n.eq(r_dfi[phase_sel].cs_n),
+                       pads.cke.eq(r_dfi[phase_sel].cke),
+                       pads.ras_n.eq(r_dfi[phase_sel].ras_n),
+                       pads.cas_n.eq(r_dfi[phase_sel].cas_n),
+                       pads.we_n.eq(r_dfi[phase_sel].we_n)
+               ]
+
+
+               # 
+               # Bitslip
+               #
+               bitslip_cnt   = Signal(4)
+               bitslip_inc = Signal()
+
+               sd_sys +=[
+                       If(bitslip_cnt==bitslip, 
+                               bitslip_inc.eq(0)
+                       ).Else(
+                               bitslip_cnt.eq(bitslip_cnt+1),
+                               bitslip_inc.eq(1)
+                       )
                ]
-               inst_items += [Instance.Input(name, signal) 
-                       for name, signal in self.dfi.get_standard_names(True, False)]
-               inst_items += [Instance.Output(name, signal)
-                       for name, signal in self.dfi.get_standard_names(False, True)]
-               self.specials += Instance("s6ddrphy", *inst_items)
+
+               # 
+               # DQ/DQS/DM data
+               #
+               sdram_half_clk_n = Signal()
+               self.comb += sdram_half_clk_n.eq(~sdram_half_clk)
+
+               postamble, drive_dqs, dqs_t_d0, dqs_t_d1 = (Signal() for i in range(4))
+
+               dqs_o = Signal(d//8) 
+               dqs_t = Signal(d//8)
+
+               self.comb += [
+                       dqs_t_d0.eq(~(drive_dqs | postamble)),
+                       dqs_t_d1.eq(~drive_dqs),
+               ]
+
+               for i in range(d//8):
+
+                       # DQS output
+                       self.specials += Instance("ODDR2",
+                               Instance.Parameter("DDR_ALIGNMENT", "C1"),
+                               Instance.Parameter("INIT", 0),
+                               Instance.Parameter("SRTYPE", "ASYNC"),
+
+                               Instance.Input("C0", sdram_half_clk),
+                               Instance.Input("C1", sdram_half_clk_n),
+
+                               Instance.Input("CE", 1),
+                               Instance.Input("D0", 0),
+                               Instance.Input("D1", 1),
+                               Instance.Input("R", 0),
+                               Instance.Input("S", 0),
+
+                               Instance.Output("Q", dqs_o[i])
+                               )
+
+                       # DQS tristate cmd
+                       self.specials += Instance("ODDR2",
+                               Instance.Parameter("DDR_ALIGNMENT", "C1"),
+                               Instance.Parameter("INIT", 0),
+                               Instance.Parameter("SRTYPE", "ASYNC"),
+
+                               Instance.Input("C0", sdram_half_clk),
+                               Instance.Input("C1", sdram_half_clk_n),
+
+                               Instance.Input("CE", 1),
+                               Instance.Input("D0", dqs_t_d0),
+                               Instance.Input("D1", dqs_t_d1),
+                               Instance.Input("R", 0),
+                               Instance.Input("S", 0),
+
+                               Instance.Output("Q", dqs_t[i])
+                               )
+
+                       # DQS tristate buffer
+                       self.specials += Instance("OBUFT",
+                               Instance.Input("I", dqs_o[i]),
+                               Instance.Input("T", dqs_t[i]),
+
+                               Instance.Output("O", pads.dqs[i])
+                               )
+
+               sd_sdram_half += postamble.eq(drive_dqs)
+
+               d_dfi = [Record(phase_wrdata_description(nphases*d)+phase_rddata_description(nphases*d)) 
+                       for i in range(2*nphases)]
+
+               for n, phase in enumerate(self.dfi.phases):
+                       self.comb +=[
+                               d_dfi[n].wrdata.eq(phase.wrdata),
+                               d_dfi[n].wrdata_mask.eq(phase.wrdata_mask),
+                               d_dfi[n].wrdata_en.eq(phase.wrdata_en),
+                               d_dfi[n].rddata_en.eq(phase.rddata_en),
+                       ]
+                       sd_sys +=[
+                                       d_dfi[nphases+n].wrdata.eq(phase.wrdata),
+                                       d_dfi[nphases+n].wrdata_mask.eq(phase.wrdata_mask)
+                       ]
+
+
+               drive_dq, drive_dq_n, d_drive_dq, d_drive_dq_n = (Signal() for i in range(4))
+               self.comb +=[
+                       drive_dq_n.eq(~drive_dq),
+                       d_drive_dq_n.eq(~d_drive_dq)
+               ]
+
+               dq_t, dq_o, dq_i = (Signal(d) for i in range(3))
+
+               for i in range(d):
+
+                       # Data serializer
+                       self.specials += Instance("OSERDES2",
+                               Instance.Parameter("DATA_WIDTH", 4),
+                               Instance.Parameter("DATA_RATE_OQ", "SDR"),
+                               Instance.Parameter("DATA_RATE_OT", "SDR"),
+                               Instance.Parameter("SERDES_MODE", "NONE"),
+                               Instance.Parameter("OUTPUT_MODE", "SINGLE_ENDED"),
+
+                               Instance.Output("OQ", dq_o[i]),
+                               Instance.Input("OCE", 1),
+                               Instance.Input("CLK0", sdram_full_wr_clk),
+                               Instance.Input("CLK1", 0),
+                               Instance.Input("IOCE", self.clk4x_wr_strb),
+                               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.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("TRAIN", 0),
+                               Instance.Input("TCE", 1),
+                               Instance.Input("SHIFTIN1", 0),
+                               Instance.Input("SHIFTIN2", 0),
+                               Instance.Input("SHIFTIN3", 0),
+                               Instance.Input("SHIFTIN4", 0),
+
+                               Instance.Output("SHIFTOUT1"),
+                               Instance.Output("SHIFTOUT2"),
+                               Instance.Output("SHIFTOUT3"),
+                               Instance.Output("SHIFTOUT4"),
+                               )
+
+                       # Data deserializer
+                       self.specials += Instance("ISERDES2",
+                               Instance.Parameter("DATA_WIDTH", 4),
+                               Instance.Parameter("DATA_RATE", "SDR"),
+                               Instance.Parameter("BITSLIP_ENABLE", "TRUE"),
+                               Instance.Parameter("SERDES_MODE", "NONE"),
+                               Instance.Parameter("INTERFACE_TYPE", "RETIMED"),
+
+                               Instance.Input("D", dq_i[i]),
+                               Instance.Input("CE0", 1),
+                               Instance.Input("CLK0", sdram_full_rd_clk),
+                               Instance.Input("CLK1", 0),
+                               Instance.Input("IOCE", self.clk4x_rd_strb),
+                               Instance.Input("RST", ResetSignal()),
+                               Instance.Input("CLKDIV", sys_clk),
+                               Instance.Output("SHIFTIN"),
+                               Instance.Input("BITSLIP", bitslip_inc),
+                               Instance.Output("FABRICOUT"),
+
+                               Instance.Output("Q1", d_dfi[0*nphases+0].rddata[i+d]),
+                               Instance.Output("Q2", d_dfi[0*nphases+0].rddata[i]),
+                               Instance.Output("Q3", d_dfi[0*nphases+1].rddata[i+d]),
+                               Instance.Output("Q4", d_dfi[0*nphases+1].rddata[i]),
+
+                               Instance.Output("DFB"),
+                               Instance.Output("CFB0"),
+                               Instance.Output("CFB1"),
+                               Instance.Output("VALID"),
+                               Instance.Output("INCDEC"),
+                               Instance.Output("SHIFTOUT")
+                               )
+
+                       # Data buffer
+                       self.specials += Instance("IOBUF",
+                               Instance.Input("I", dq_o[i]),
+                               Instance.Output("O", dq_i[i]),
+                               Instance.Input("T", dq_t[i]),
+                               Instance.InOut("IO", pads.dq[i])
+                               )
+
+               for i in range(d//8):
+
+                       # Mask serializer
+                       self.specials += Instance("OSERDES2",
+                               Instance.Parameter("DATA_WIDTH", 4),
+                               Instance.Parameter("DATA_RATE_OQ", "SDR"),
+                               Instance.Parameter("DATA_RATE_OT", "SDR"),
+                               Instance.Parameter("SERDES_MODE", "NONE"),
+                               Instance.Parameter("OUTPUT_MODE", "SINGLE_ENDED"),
+
+                               Instance.Output("OQ", pads.dm[i]),
+                               Instance.Input("OCE", 1),
+                               Instance.Input("CLK0", sdram_full_wr_clk),
+                               Instance.Input("CLK1", 0),
+                               Instance.Input("IOCE", self.clk4x_wr_strb),
+                               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.Output("TQ"),
+                               Instance.Input("T1"),
+                               Instance.Input("T2"),
+                               Instance.Input("T3"),
+                               Instance.Input("T4"),
+                               Instance.Input("TRAIN", 0),
+                               Instance.Input("TCE", 0),
+                               Instance.Input("SHIFTIN1", 0),
+                               Instance.Input("SHIFTIN2", 0),
+                               Instance.Input("SHIFTIN3", 0),
+                               Instance.Input("SHIFTIN4", 0),
+
+                               Instance.Output("SHIFTOUT1"),
+                               Instance.Output("SHIFTOUT2"),
+                               Instance.Output("SHIFTOUT3"),
+                               Instance.Output("SHIFTOUT4"),
+                               )
+
+
+               # 
+               # DQ/DQS/DM control
+               #
+               self.comb += drive_dq.eq(d_dfi[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[phy_settings.wrphase].wrdata_en)
+               
+               r_dfi_wrdata_en = Signal(2)
+               sd_sdram_half += r_dfi_wrdata_en.eq(Cat(d_dfi_wrdata_en, r_dfi_wrdata_en[0])) 
+
+               self.comb += drive_dqs.eq(r_dfi_wrdata_en[1])
+
+               rddata_sr = Signal(phy_settings.cl+2)
+               sd_sys += rddata_sr.eq(Cat(rddata_sr[1:phy_settings.cl+2], d_dfi[phy_settings.rdphase].rddata_en))
+               
+               for n, phase in enumerate(self.dfi.phases):
+                       self.comb += [
+                               phase.rddata.eq(d_dfi[n].rddata),
+                               phase.rddata_valid.eq(rddata_sr[0]),
+                       ]
index 5604cc923737863ecbda5f0f7fd75f779ffaf968..7e8d7f84ab058d63b4ff9f8c4eaef96e164286e2 100644 (file)
@@ -2,12 +2,13 @@
 #include <stdlib.h>
 
 #include <hw/csr.h>
+#include <hw/sdram_phy.h>
 #include <hw/flags.h>
 #include <hw/mem.h>
 
 #include "sdram.h"
 
-static void cdelay(int i)
+void cdelay(int i)
 {
        while(i > 0) {
                __asm__ volatile("nop");
@@ -15,59 +16,6 @@ static void cdelay(int i)
        }
 }
 
-static void command_p0(int cmd)
-{
-       dfii_pi0_command_write(cmd);
-       dfii_pi0_command_issue_write(1);
-}
-
-static void command_p1(int cmd)
-{
-       dfii_pi1_command_write(cmd);
-       dfii_pi1_command_issue_write(1);
-}
-
-static void init_sequence(void)
-{
-       int i;
-       
-       /* Bring CKE high */
-       dfii_pi0_address_write(0x0000);
-       dfii_pi0_baddress_write(0);
-       dfii_control_write(DFII_CONTROL_CKE);
-       
-       /* Precharge All */
-       dfii_pi0_address_write(0x0400);
-       command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-       
-       /* Load Extended Mode Register */
-       dfii_pi0_baddress_write(1);
-       dfii_pi0_address_write(0x0000);
-       command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-       dfii_pi0_baddress_write(0);
-       
-       /* Load Mode Register */
-       dfii_pi0_address_write(0x0132); /* Reset DLL, CL=3, BL=4 */
-       command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-       cdelay(200);
-       
-       /* Precharge All */
-       dfii_pi0_address_write(0x0400);
-       command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-       
-       /* 2x Auto Refresh */
-       for(i=0;i<2;i++) {
-               dfii_pi0_address_write(0);
-               command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS);
-               cdelay(4);
-       }
-       
-       /* Load Mode Register */
-       dfii_pi0_address_write(0x0032); /* CL=3, BL=4 */
-       command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS);
-       cdelay(200);
-}
-
 void ddrsw(void)
 {
        dfii_control_write(DFII_CONTROL_CKE);
@@ -121,9 +69,9 @@ void ddrrd(char *startaddr)
                return;
        }
        
-       dfii_pi0_address_write(addr);
-       dfii_pi0_baddress_write(0);
-       command_p0(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
+       dfii_pird_address_write(addr);
+       dfii_pird_baddress_write(0);
+       command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA);
        cdelay(15);
        
        for(i=0;i<8;i++)
@@ -154,9 +102,9 @@ void ddrwr(char *startaddr)
                MMPTR(0xe000106c+4*i) = 0xf0 + i;
        }
        
-       dfii_pi1_address_write(addr);
-       dfii_pi1_baddress_write(0);
-       command_p1(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA);
+       dfii_piwr_address_write(addr);
+       dfii_piwr_baddress_write(0);
+       command_pwr(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA);
 }
 
 #define TEST_SIZE (4*1024*1024)
diff --git a/top.py b/top.py
index 4935d26f24524781c8cb441799bacd4b5f58083a..b2fb603f162ab46349568f9b8ce054a9d6c87181 100644 (file)
--- a/top.py
+++ b/top.py
@@ -26,10 +26,12 @@ def ns(t, margin=True):
        return ceil(t/clk_period_ns)
 
 sdram_phy = lasmicon.PhySettings(
+       type="DDR",
        dfi_d=64, 
        nphases=2,
        rdphase=0,
-       wrphase=1
+       wrphase=1,
+       cl=3
 )
 sdram_geom = lasmicon.GeomSettings(
        bank_a=2,
@@ -109,7 +111,7 @@ class SoC(Module):
                #
                # DFI
                #
-               self.submodules.ddrphy = s6ddrphy.S6DDRPHY(platform.request("ddram"))
+               self.submodules.ddrphy = s6ddrphy.S6DDRPHY(platform.request("ddram"), sdram_phy, 0)
                self.submodules.dfii = dfii.DFIInjector(sdram_geom.mux_a, sdram_geom.bank_a, sdram_phy.dfi_d,
                        sdram_phy.nphases)
                self.submodules.dficon0 = dfi.Interconnect(self.dfii.master, self.ddrphy.dfi)
diff --git a/verilog/s6ddrphy/s6ddrphy.v b/verilog/s6ddrphy/s6ddrphy.v
deleted file mode 100644 (file)
index 9fb5cdc..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * 1:2 frequency-ratio DDR PHY for Spartan-6
- *
- * Assert dfi_wrdata_en and present the data 
- * on dfi_wrdata_mask/dfi_wrdata in the same
- * cycle as the write command.
- *
- * Assert dfi_rddata_en in the same cycle as the read
- * command. The data will come back on dfi_rddata
- * 5 cycles later, along with the assertion of
- * dfi_rddata_valid.
- *
- * This PHY only supports CAS Latency 3.
- * Read commands must be sent on phase 0.
- * Write commands must be sent on phase 1.
- */
-
-module s6ddrphy #(
-       parameter NUM_AD = 0,
-       parameter NUM_BA = 0,
-       parameter NUM_D = 0 /* < number of data lines per DFI phase */
-) (
-       /* Clocks */
-       input sys_clk,
-       input clk2x_270,
-       input clk4x_wr,
-       input clk4x_wr_strb,
-       input clk4x_rd,
-       input clk4x_rd_strb,
-       
-       /* DFI phase 0 */
-       input [NUM_AD-1:0] dfi_address_p0,
-       input [NUM_BA-1:0] dfi_bank_p0,
-       input dfi_cs_n_p0,
-       input dfi_cke_p0,
-       input dfi_ras_n_p0,
-       input dfi_cas_n_p0,
-       input dfi_we_n_p0,
-       input dfi_wrdata_en_p0,
-       input [NUM_D/8-1:0] dfi_wrdata_mask_p0,
-       input [NUM_D-1:0] dfi_wrdata_p0,
-       input dfi_rddata_en_p0,
-       output [NUM_D-1:0] dfi_rddata_w0,
-       output dfi_rddata_valid_w0,
-       
-       /* DFI phase 1 */
-       input [NUM_AD-1:0] dfi_address_p1,
-       input [NUM_BA-1:0] dfi_bank_p1,
-       input dfi_cs_n_p1,
-       input dfi_cke_p1,
-       input dfi_ras_n_p1,
-       input dfi_cas_n_p1,
-       input dfi_we_n_p1,
-       input dfi_wrdata_en_p1,
-       input [NUM_D/8-1:0] dfi_wrdata_mask_p1,
-       input [NUM_D-1:0] dfi_wrdata_p1,
-       input dfi_rddata_en_p1,
-       output [NUM_D-1:0] dfi_rddata_w1,
-       output dfi_rddata_valid_w1,
-       
-       /* DDR SDRAM pads */
-       output reg [NUM_AD-1:0] sd_a,
-       output reg [NUM_BA-1:0] sd_ba,
-       output reg sd_cs_n,
-       output reg sd_cke,
-       output reg sd_ras_n,
-       output reg sd_cas_n,
-       output reg sd_we_n,
-       inout [NUM_D/2-1:0] sd_dq,
-       output [NUM_D/16-1:0] sd_dm,
-       inout [NUM_D/16-1:0] sd_dqs
-);
-
-/* 
- * Command/address
- */
-
-reg phase_sel;
-always @(posedge clk2x_270)
-       phase_sel <= sys_clk;
-
-reg [NUM_AD-1:0] r_dfi_address_p0;
-reg [NUM_BA-1:0] r_dfi_bank_p0;
-reg r_dfi_cs_n_p0;
-reg r_dfi_cke_p0;
-reg r_dfi_ras_n_p0;
-reg r_dfi_cas_n_p0;
-reg r_dfi_we_n_p0;
-reg [NUM_AD-1:0] r_dfi_address_p1;
-reg [NUM_BA-1:0] r_dfi_bank_p1;
-reg r_dfi_cs_n_p1;
-reg r_dfi_cke_p1;
-reg r_dfi_ras_n_p1;
-reg r_dfi_cas_n_p1;
-reg r_dfi_we_n_p1;
-       
-always @(posedge clk2x_270) begin
-       r_dfi_address_p0 <= dfi_address_p0;
-       r_dfi_bank_p0 <= dfi_bank_p0;
-       r_dfi_cs_n_p0 <= dfi_cs_n_p0;
-       r_dfi_cke_p0 <= dfi_cke_p0;
-       r_dfi_ras_n_p0 <= dfi_ras_n_p0;
-       r_dfi_cas_n_p0 <= dfi_cas_n_p0;
-       r_dfi_we_n_p0 <= dfi_we_n_p0;
-       
-       r_dfi_address_p1 <= dfi_address_p1;
-       r_dfi_bank_p1 <= dfi_bank_p1;
-       r_dfi_cs_n_p1 <= dfi_cs_n_p1;
-       r_dfi_cke_p1 <= dfi_cke_p1;
-       r_dfi_ras_n_p1 <= dfi_ras_n_p1;
-       r_dfi_cas_n_p1 <= dfi_cas_n_p1;
-       r_dfi_we_n_p1 <= dfi_we_n_p1;
-end
-
-always @(posedge clk2x_270) begin
-       if(phase_sel) begin
-               sd_a <= r_dfi_address_p0;
-               sd_ba <= r_dfi_bank_p0;
-               sd_cs_n <= r_dfi_cs_n_p0;
-               sd_cke <= r_dfi_cke_p0;
-               sd_ras_n <= r_dfi_ras_n_p0;
-               sd_cas_n <= r_dfi_cas_n_p0;
-               sd_we_n <= r_dfi_we_n_p0;
-       end else begin
-               sd_a <= r_dfi_address_p1;
-               sd_ba <= r_dfi_bank_p1;
-               sd_cs_n <= r_dfi_cs_n_p1;
-               sd_cke <= r_dfi_cke_p1;
-               sd_ras_n <= r_dfi_ras_n_p1;
-               sd_cas_n <= r_dfi_cas_n_p1;
-               sd_we_n <= r_dfi_we_n_p1;
-       end
-end
-
-/* 
- * DQ/DQS/DM data
- */
-
-genvar i;
-
-wire drive_dqs;
-wire [NUM_D/16-1:0] dqs_o;
-wire [NUM_D/16-1:0] dqs_t;
-reg postamble;
-generate
-       for(i=0;i<NUM_D/16;i=i+1)
-       begin: gen_dqs
-               ODDR2 #(
-                       .DDR_ALIGNMENT("C1"),
-                       .INIT(1'b0),
-                       .SRTYPE("ASYNC")
-               ) dqs_o_oddr (
-                       .Q(dqs_o[i]),
-                       .C0(clk2x_270),
-                       .C1(~clk2x_270),
-                       .CE(1'b1),
-                       .D0(1'b0),
-                       .D1(1'b1),
-                       .R(1'b0),
-                       .S(1'b0)
-               );
-               ODDR2 #(
-                       .DDR_ALIGNMENT("C1"),
-                       .INIT(1'b0),
-                       .SRTYPE("ASYNC")
-               ) dqs_t_oddr (
-                       .Q(dqs_t[i]),
-                       .C0(clk2x_270),
-                       .C1(~clk2x_270),
-                       .CE(1'b1),
-                       .D0(~(drive_dqs | postamble)),
-                       .D1(~drive_dqs),
-                       .R(1'b0),
-                       .S(1'b0)
-               );
-               OBUFT dqs_obuft(
-                       .I(dqs_o[i]),
-                       .T(dqs_t[i]),
-                       .O(sd_dqs[i])
-               );
-       end
-endgenerate
-always @(posedge clk2x_270)
-       postamble <= drive_dqs;
-
-reg [NUM_D-1:0] d_dfi_wrdata_p0;
-reg [NUM_D-1:0] d_dfi_wrdata_p1;
-reg [NUM_D/8-1:0] d_dfi_wrdata_mask_p0;
-reg [NUM_D/8-1:0] d_dfi_wrdata_mask_p1;
-always @(posedge sys_clk) begin
-       d_dfi_wrdata_p0 <= dfi_wrdata_p0;
-       d_dfi_wrdata_p1 <= dfi_wrdata_p1;
-       d_dfi_wrdata_mask_p0 <= dfi_wrdata_mask_p0;
-       d_dfi_wrdata_mask_p1 <= dfi_wrdata_mask_p1;
-end
-
-wire drive_dq;
-wire d_drive_dq;
-wire [NUM_D/2-1:0] dq_i;
-wire [NUM_D/2-1:0] dq_o;
-wire [NUM_D/2-1:0] dq_t;
-generate
-       for(i=0;i<NUM_D/2;i=i+1)
-       begin: gen_dq
-               OSERDES2 #(
-                       .DATA_WIDTH(4),
-                       .DATA_RATE_OQ("SDR"),
-                       .DATA_RATE_OT("SDR"),
-                       .SERDES_MODE("NONE"),
-                       .OUTPUT_MODE("SINGLE_ENDED")
-               ) dq_oserdes (
-                       .OQ(dq_o[i]),
-                       .OCE(1'b1),
-                       .CLK0(clk4x_wr),
-                       .CLK1(1'b0),
-                       .IOCE(clk4x_wr_strb),
-                       .RST(1'b0),
-                       .CLKDIV(sys_clk),
-                       .D1(d_dfi_wrdata_p0[i]),
-                       .D2(d_dfi_wrdata_p1[i+NUM_D/2]),
-                       .D3(d_dfi_wrdata_p1[i]),
-                       .D4(dfi_wrdata_p0[i+NUM_D/2]),
-                       .TQ(dq_t[i]),
-                       .T1(~d_drive_dq),
-                       .T2(~d_drive_dq),
-                       .T3(~d_drive_dq),
-                       .T4(~drive_dq),
-                       .TRAIN(1'b0),
-                       .TCE(1'b1),
-                       .SHIFTIN1(1'b0),
-                       .SHIFTIN2(1'b0),
-                       .SHIFTIN3(1'b0),
-                       .SHIFTIN4(1'b0),
-                       .SHIFTOUT1(),
-                       .SHIFTOUT2(),
-                       .SHIFTOUT3(),
-                       .SHIFTOUT4()
-               );
-               ISERDES2 #(
-                       .DATA_WIDTH(4),
-                       .DATA_RATE("SDR"),
-                       .BITSLIP_ENABLE("FALSE"),
-                       .SERDES_MODE("NONE"),
-                       .INTERFACE_TYPE("RETIMED")
-               ) dq_iserdes (
-                       .D(dq_i[i]),
-                       .CE0(1'b1),
-                       .CLK0(clk4x_rd),
-                       .CLK1(1'b0),
-                       .IOCE(clk4x_rd_strb),
-                       .RST(1'b0),
-                       .CLKDIV(sys_clk),
-                       .SHIFTIN(),
-                       .BITSLIP(1'b0),
-                       .FABRICOUT(),
-                       .Q1(dfi_rddata_w0[i+NUM_D/2]),
-                       .Q2(dfi_rddata_w0[i]),
-                       .Q3(dfi_rddata_w1[i+NUM_D/2]),
-                       .Q4(dfi_rddata_w1[i]),
-                       .DFB(),
-                       .CFB0(),
-                       .CFB1(),
-                       .VALID(),
-                       .INCDEC(),
-                       .SHIFTOUT()
-               );
-               IOBUF dq_iobuf(
-                       .I(dq_o[i]),
-                       .O(dq_i[i]),
-                       .T(dq_t[i]),
-                       .IO(sd_dq[i])
-               );
-       end
-endgenerate
-
-generate
-       for(i=0;i<NUM_D/16;i=i+1)
-       begin: gen_dm_oserdes
-               OSERDES2 #(
-                       .DATA_WIDTH(4),
-                       .DATA_RATE_OQ("SDR"),
-                       .DATA_RATE_OT("SDR"),
-                       .SERDES_MODE("NONE"),
-                       .OUTPUT_MODE("SINGLE_ENDED")
-               ) dm_oserdes (
-                       .OQ(sd_dm[i]),
-                       .OCE(1'b1),
-                       .CLK0(clk4x_wr),
-                       .CLK1(1'b0),
-                       .IOCE(clk4x_wr_strb),
-                       .RST(1'b0),
-                       .CLKDIV(sys_clk),
-                       .D1(d_dfi_wrdata_mask_p0[i]),
-                       .D2(d_dfi_wrdata_mask_p1[i+NUM_D/16]),
-                       .D3(d_dfi_wrdata_mask_p1[i]),
-                       .D4(dfi_wrdata_mask_p0[i+NUM_D/16]),
-                       .TQ(),
-                       .T1(),
-                       .T2(),
-                       .T3(),
-                       .T4(),
-                       .TRAIN(1'b0),
-                       .TCE(1'b0),
-                       .SHIFTIN1(1'b0),
-                       .SHIFTIN2(1'b0),
-                       .SHIFTIN3(1'b0),
-                       .SHIFTIN4(1'b0),
-                       .SHIFTOUT1(),
-                       .SHIFTOUT2(),
-                       .SHIFTOUT3(),
-                       .SHIFTOUT4()
-               );
-       end
-endgenerate
-/* 
- * DQ/DQS/DM control
- */
-
-reg d_dfi_wrdata_en_p1;
-always @(posedge sys_clk)
-       d_dfi_wrdata_en_p1 <= dfi_wrdata_en_p1;
-assign drive_dq = dfi_wrdata_en_p1;
-assign d_drive_dq = d_dfi_wrdata_en_p1;
-reg r_dfi_wrdata_en;
-reg r2_dfi_wrdata_en;
-always @(posedge clk2x_270) begin
-       r_dfi_wrdata_en <= d_dfi_wrdata_en_p1;
-       r2_dfi_wrdata_en <= r_dfi_wrdata_en;
-end
-
-assign drive_dqs = r2_dfi_wrdata_en;
-
-wire rddata_valid;
-reg [4:0] rddata_sr;
-assign dfi_rddata_valid_w0 = rddata_sr[0];
-assign dfi_rddata_valid_w1 = rddata_sr[0];
-always @(posedge sys_clk)
-       rddata_sr <= {dfi_rddata_en_p0, rddata_sr[4:1]};
-
-endmodule