def __init__(self, pads, rd_bitslip, wr_bitslip, dqs_ddr_alignment): half_rate_phy = S6HalfRateDDRPHY(pads, "DDR3", rd_bitslip, wr_bitslip, dqs_ddr_alignment) self.submodules += ClockDomainsRenamer("sys2x")(half_rate_phy) addressbits = len(pads.a) bankbits = len(pads.ba) databits = len(pads.dq) nphases = 4 self.settings = sdram_settings.PhySettings(memtype="DDR3", dfi_databits=2 * databits, nphases=nphases, rdphase=0, wrphase=1, rdcmdphase=1, wrcmdphase=0, cl=5, cwl=6, read_latency=6 // 2 + 1, write_latency=2 // 2) self.dfi = Interface(addressbits, bankbits, 2 * databits, nphases) self.clk8x_wr_strb = half_rate_phy.clk4x_wr_strb self.clk8x_rd_strb = half_rate_phy.clk4x_rd_strb # sys_clk : system clk, used for dfi interface # sys2x_clk : 2x system clk sd_sys = getattr(self.sync, "sys") sd_sys2x = getattr(self.sync, "sys2x") # select active sys2x phase # sys_clk ----____----____ # phase_sel 0 1 0 1 phase_sel = Signal() phase_sys2x = Signal.like(phase_sel) phase_sys = Signal.like(phase_sys2x) sd_sys += phase_sys.eq(phase_sys2x) sd_sys2x += [ If( phase_sys2x == phase_sys, phase_sel.eq(0), ).Else(phase_sel.eq(~phase_sel)), phase_sys2x.eq(~phase_sel) ] # DFI adaptation # Commands and writes dfi_leave_out = set(["rddata", "rddata_valid", "wrdata_en"]) self.comb += [ If( ~phase_sel, self.dfi.phases[0].connect(half_rate_phy.dfi.phases[0], leave_out=dfi_leave_out), self.dfi.phases[1].connect(half_rate_phy.dfi.phases[1], leave_out=dfi_leave_out), ).Else( self.dfi.phases[2].connect(half_rate_phy.dfi.phases[0], leave_out=dfi_leave_out), self.dfi.phases[3].connect(half_rate_phy.dfi.phases[1], leave_out=dfi_leave_out), ), ] wr_data_en = self.dfi.phases[ self.settings.wrphase].wrdata_en & ~phase_sel wr_data_en_d = Signal() sd_sys2x += wr_data_en_d.eq(wr_data_en) self.comb += half_rate_phy.dfi.phases[ half_rate_phy.settings.wrphase].wrdata_en.eq(wr_data_en | wr_data_en_d) # Reads rddata = Array(Signal(2 * databits) for i in range(2)) rddata_valid = Signal(2) for i in range(2): sd_sys2x += [ rddata_valid[i].eq(half_rate_phy.dfi.phases[i].rddata_valid), rddata[i].eq(half_rate_phy.dfi.phases[i].rddata) ] sd_sys += [ self.dfi.phases[0].rddata.eq(rddata[0]), self.dfi.phases[0].rddata_valid.eq(rddata_valid[0]), self.dfi.phases[1].rddata.eq(rddata[1]), self.dfi.phases[1].rddata_valid.eq(rddata_valid[1]), self.dfi.phases[2].rddata.eq(half_rate_phy.dfi.phases[0].rddata), self.dfi.phases[2].rddata_valid.eq( half_rate_phy.dfi.phases[0].rddata_valid), self.dfi.phases[3].rddata.eq(half_rate_phy.dfi.phases[1].rddata), self.dfi.phases[3].rddata_valid.eq( half_rate_phy.dfi.phases[1].rddata_valid) ]
def __init__(self, pads, memtype, rd_bitslip, wr_bitslip, dqs_ddr_alignment): if memtype not in ["DDR", "LPDDR", "DDR2", "DDR3"]: raise NotImplementedError( "S6HalfRateDDRPHY only supports DDR, LPDDR, DDR2 and DDR3") addressbits = len(pads.a) bankbits = len(pads.ba) databits = len(pads.dq) nphases = 2 if memtype == "DDR3": self.settings = sdram_settings.PhySettings(memtype="DDR3", dfi_databits=2 * databits, nphases=nphases, rdphase=0, wrphase=1, rdcmdphase=1, wrcmdphase=0, cl=5, cwl=6, read_latency=6, write_latency=2) else: self.settings = sdram_settings.PhySettings(memtype=memtype, dfi_databits=2 * databits, nphases=nphases, rdphase=0, wrphase=1, rdcmdphase=1, wrcmdphase=0, cl=3, read_latency=5, write_latency=0) self.dfi = Interface(addressbits, bankbits, 2 * databits, nphases) self.clk4x_wr_strb = Signal() self.clk4x_rd_strb = Signal() ### # 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 read clk sd_sys = getattr(self.sync, "sys") sd_sdram_half = getattr(self.sync, "sdram_half") 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=2) 0 1 0 1 Half Rate phase_sel = Signal(log2_int(nphases)) phase_half = Signal.like(phase_sel) phase_sys = Signal.like(phase_half) sd_sys += phase_sys.eq(phase_half) sd_sdram_half += [ If( phase_half == phase_sys, phase_sel.eq(0), ).Else(phase_sel.eq(phase_sel + 1)), phase_half.eq(phase_half + 1), ] # register dfi cmds on half_rate clk r_dfi = Array( Record(phase_cmd_description(addressbits, bankbits)) for i in range(nphases)) for n, phase in enumerate(self.dfi.phases): sd_sdram_half += [ r_dfi[n].reset_n.eq(phase.reset_n), r_dfi[n].odt.eq(phase.odt), 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.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) ] # optional pads for name in "reset_n", "cs_n", "odt": if hasattr(pads, name): sd_sdram_half += getattr(pads, name).eq( getattr(r_dfi[phase_sel], name)) # # Bitslip # bitslip_cnt = Signal(4) bitslip_inc = Signal() sd_sys += [ If(bitslip_cnt == rd_bitslip, bitslip_inc.eq(0)).Else(bitslip_cnt.eq(bitslip_cnt + 1), bitslip_inc.eq(1)) ] # # DQ/DQS/DM data # sdram_half_clk_n = Signal() self.comb += sdram_half_clk_n.eq(~sdram_half_clk) postamble = Signal() drive_dqs = Signal() dqs_t_d0 = Signal() dqs_t_d1 = Signal() dqs_o = Signal(databits // 8) dqs_t = Signal(databits // 8) self.comb += [ dqs_t_d0.eq(~(drive_dqs | postamble)), dqs_t_d1.eq(~drive_dqs), ] for i in range(databits // 8): # DQS output self.specials += Instance("ODDR2", p_DDR_ALIGNMENT=dqs_ddr_alignment, p_INIT=0, p_SRTYPE="ASYNC", i_C0=sdram_half_clk, i_C1=sdram_half_clk_n, i_CE=1, i_D0=0, i_D1=1, i_R=0, i_S=0, o_Q=dqs_o[i]) # DQS tristate cmd self.specials += Instance("ODDR2", p_DDR_ALIGNMENT=dqs_ddr_alignment, p_INIT=0, p_SRTYPE="ASYNC", i_C0=sdram_half_clk, i_C1=sdram_half_clk_n, i_CE=1, i_D0=dqs_t_d0, i_D1=dqs_t_d1, i_R=0, i_S=0, o_Q=dqs_t[i]) # DQS tristate buffer if hasattr(pads, "dqs_n"): self.specials += Instance( "OBUFTDS", i_I=dqs_o[i], i_T=dqs_t[i], o_O=pads.dqs[i], o_OB=pads.dqs_n[i], ) else: self.specials += Instance("OBUFT", i_I=dqs_o[i], i_T=dqs_t[i], o_O=pads.dqs[i]) sd_sdram_half += postamble.eq(drive_dqs) d_dfi = [ Record( phase_wrdata_description(nphases * databits) + phase_rddata_description(nphases * databits)) 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 = Signal() 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(databits) dq_o = Signal(databits) dq_i = Signal(databits) dq_wrdata = [] for i in range(2): for j in reversed(range(nphases)): dq_wrdata.append(d_dfi[i * nphases + j].wrdata[:databits]) dq_wrdata.append(d_dfi[i * nphases + j].wrdata[databits:]) for i in range(databits): # Data serializer self.specials += Instance( "OSERDES2", p_DATA_WIDTH=4, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR", p_SERDES_MODE="NONE", p_OUTPUT_MODE="SINGLE_ENDED", o_OQ=dq_o[i], i_OCE=1, i_CLK0=sdram_full_wr_clk, i_CLK1=0, i_IOCE=self.clk4x_wr_strb, i_RST=0, i_CLKDIV=sys_clk, i_D1=dq_wrdata[wr_bitslip + 3][i], i_D2=dq_wrdata[wr_bitslip + 2][i], i_D3=dq_wrdata[wr_bitslip + 1][i], i_D4=dq_wrdata[wr_bitslip + 0][i], o_TQ=dq_t[i], i_T1=drive_dq_n[(wr_bitslip + 3) // 4], i_T2=drive_dq_n[(wr_bitslip + 2) // 4], i_T3=drive_dq_n[(wr_bitslip + 1) // 4], i_T4=drive_dq_n[(wr_bitslip + 0) // 4], i_TRAIN=0, i_TCE=1, i_SHIFTIN1=0, i_SHIFTIN2=0, i_SHIFTIN3=0, i_SHIFTIN4=0, ) # Data deserializer self.specials += Instance( "ISERDES2", p_DATA_WIDTH=4, p_DATA_RATE="SDR", p_BITSLIP_ENABLE="TRUE", p_SERDES_MODE="NONE", p_INTERFACE_TYPE="RETIMED", i_D=dq_i[i], i_CE0=1, i_CLK0=sdram_full_rd_clk, i_CLK1=0, i_IOCE=self.clk4x_rd_strb, i_RST=ResetSignal(), i_CLKDIV=sys_clk, i_BITSLIP=bitslip_inc, o_Q1=d_dfi[0 * nphases + 0].rddata[i + databits], o_Q2=d_dfi[0 * nphases + 0].rddata[i], o_Q3=d_dfi[0 * nphases + 1].rddata[i + databits], o_Q4=d_dfi[0 * nphases + 1].rddata[i], ) # Data buffer self.specials += Instance("IOBUF", i_I=dq_o[i], o_O=dq_i[i], i_T=dq_t[i], io_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[:databits // 8]) dq_wrdata_mask.append(d_dfi[i * nphases + j].wrdata_mask[databits // 8:]) for i in range(databits // 8): # Mask serializer self.specials += Instance( "OSERDES2", p_DATA_WIDTH=4, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR", p_SERDES_MODE="NONE", p_OUTPUT_MODE="SINGLE_ENDED", o_OQ=pads.dm[i], i_OCE=1, i_CLK0=sdram_full_wr_clk, i_CLK1=0, i_IOCE=self.clk4x_wr_strb, i_RST=0, i_CLKDIV=sys_clk, i_D1=dq_wrdata_mask[wr_bitslip + 3][i], i_D2=dq_wrdata_mask[wr_bitslip + 2][i], i_D3=dq_wrdata_mask[wr_bitslip + 1][i], i_D4=dq_wrdata_mask[wr_bitslip + 0][i], i_TRAIN=0, i_TCE=0, i_SHIFTIN1=0, i_SHIFTIN2=0, i_SHIFTIN3=0, i_SHIFTIN4=0, ) # # DQ/DQS/DM control # # write wrdata_en = Signal() self.comb += wrdata_en.eq( reduce(or_, [d_dfi[p].wrdata_en for p in range(nphases)])) if memtype == "DDR3": r_drive_dq = Signal(self.settings.cwl - 1) sd_sdram_half += r_drive_dq.eq(Cat(wrdata_en, r_drive_dq)) self.comb += drive_dq.eq(r_drive_dq[self.settings.cwl - 2]) else: self.comb += drive_dq.eq(wrdata_en) wrdata_en_d = Signal() sd_sys += wrdata_en_d.eq(wrdata_en) r_dfi_wrdata_en = Signal(max(self.settings.cwl, self.settings.cl)) sd_sdram_half += r_dfi_wrdata_en.eq(Cat(wrdata_en_d, r_dfi_wrdata_en)) if memtype == "DDR3": self.comb += drive_dqs.eq(r_dfi_wrdata_en[self.settings.cwl - 1]) else: self.comb += drive_dqs.eq(r_dfi_wrdata_en[1]) # read rddata_en = Signal() self.comb += rddata_en.eq( reduce(or_, [d_dfi[p].rddata_en for p in range(nphases)])) rddata_sr = Signal(self.settings.read_latency) sd_sys += rddata_sr.eq( Cat(rddata_sr[1:self.settings.read_latency], 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]), ]
def __init__(self, pads): addressbits = len(pads.a) bankbits = len(pads.ba) databits = len(pads.dq) nphases = 4 self._en_vtc = CSRStorage(reset=1) self._wlevel_en = CSRStorage() self._wlevel_strobe = CSR() self._dly_sel = CSRStorage(databits // 8) self._rdly_dq_rst = CSR() self._rdly_dq_inc = CSR() self._rdly_dq_bitslip = CSR() self._wdly_dq_rst = CSR() self._wdly_dq_inc = CSR() self._wdly_dqs_rst = CSR() self._wdly_dqs_inc = CSR() self._wdly_dqs_taps = CSRStatus(9) self.settings = sdram_settings.PhySettings(memtype="DDR3", dfi_databits=2 * databits, nphases=nphases, rdphase=0, wrphase=2, rdcmdphase=1, wrcmdphase=0, cl=7, cwl=6, read_latency=8, write_latency=2) self.dfi = Interface(addressbits, bankbits, 2 * databits, nphases) # # # # Clock clk_o_nodelay = Signal() clk_o_delayed = Signal() self.specials += [ Instance("OSERDESE3", p_DATA_WIDTH=8, p_INIT=0, p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, o_OQ=clk_o_nodelay, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D=0b10101010), Instance("ODELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=200.0, p_DELAY_FORMAT="TIME", p_DELAY_TYPE="FIXED", p_DELAY_VALUE=0, i_ODATAIN=clk_o_nodelay, o_DATAOUT=clk_o_delayed), Instance("OBUFDS", i_I=clk_o_delayed, o_O=pads.clk_p, o_OB=pads.clk_n) ] # Addresses and commands for i in range(addressbits): a_o_nodelay = Signal() self.specials += [ Instance("OSERDESE3", p_DATA_WIDTH=8, p_INIT=0, p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, o_OQ=a_o_nodelay, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D=Cat(self.dfi.phases[0].address[i], self.dfi.phases[0].address[i], self.dfi.phases[1].address[i], self.dfi.phases[1].address[i], self.dfi.phases[2].address[i], self.dfi.phases[2].address[i], self.dfi.phases[3].address[i], self.dfi.phases[3].address[i])), Instance("ODELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=200.0, p_DELAY_FORMAT="TIME", p_DELAY_TYPE="FIXED", p_DELAY_VALUE=0, i_ODATAIN=a_o_nodelay, o_DATAOUT=pads.a[i]) ] for i in range(bankbits): ba_o_nodelay = Signal() self.specials += [ Instance("OSERDESE3", p_DATA_WIDTH=8, p_INIT=0, p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, o_OQ=ba_o_nodelay, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D=Cat(self.dfi.phases[0].bank[i], self.dfi.phases[0].bank[i], self.dfi.phases[1].bank[i], self.dfi.phases[1].bank[i], self.dfi.phases[2].bank[i], self.dfi.phases[2].bank[i], self.dfi.phases[3].bank[i], self.dfi.phases[3].bank[i])), Instance("ODELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=200.0, p_DELAY_FORMAT="TIME", p_DELAY_TYPE="FIXED", p_DELAY_VALUE=0, i_ODATAIN=ba_o_nodelay, o_DATAOUT=pads.ba[i]) ] for name in "ras_n", "cas_n", "we_n", "cs_n", "cke", "odt", "reset_n": x_o_nodelay = Signal() self.specials += [ Instance("OSERDESE3", p_DATA_WIDTH=8, p_INIT=0, p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, o_OQ=x_o_nodelay, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D=Cat(getattr(self.dfi.phases[0], name), getattr(self.dfi.phases[0], name), getattr(self.dfi.phases[1], name), getattr(self.dfi.phases[1], name), getattr(self.dfi.phases[2], name), getattr(self.dfi.phases[2], name), getattr(self.dfi.phases[3], name), getattr(self.dfi.phases[3], name))), Instance("ODELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=200.0, p_DELAY_FORMAT="TIME", p_DELAY_TYPE="FIXED", p_DELAY_VALUE=0, i_ODATAIN=x_o_nodelay, o_DATAOUT=getattr(pads, name)) ] # DQS and DM oe_dqs = Signal() dqs_serdes_pattern = Signal(8) self.comb += \ If(self._wlevel_en.storage, If(self._wlevel_strobe.re, dqs_serdes_pattern.eq(0b00000001) ).Else( dqs_serdes_pattern.eq(0b00000000) ) ).Else( dqs_serdes_pattern.eq(0b01010101) ) for i in range(databits // 8): dm_o_nodelay = Signal() self.specials += \ Instance("OSERDESE3", p_DATA_WIDTH=8, p_INIT=0, p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, o_OQ=dm_o_nodelay, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D=Cat(self.dfi.phases[0].wrdata_mask[i], self.dfi.phases[0].wrdata_mask[databits//8+i], self.dfi.phases[1].wrdata_mask[i], self.dfi.phases[1].wrdata_mask[databits//8+i], self.dfi.phases[2].wrdata_mask[i], self.dfi.phases[2].wrdata_mask[databits//8+i], self.dfi.phases[3].wrdata_mask[i], self.dfi.phases[3].wrdata_mask[databits//8+i]) ) self.specials += \ Instance("ODELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=200.0, p_IS_CLK_INVERTED=0, p_IS_RST_INVERTED=0, p_DELAY_FORMAT="TIME", p_DELAY_TYPE="VARIABLE", p_DELAY_VALUE=0, i_CLK=ClockSignal(), i_INC=1, i_EN_VTC=self._en_vtc.storage, i_RST=self._dly_sel.storage[i] & self._wdly_dq_rst.re, i_CE=self._dly_sel.storage[i] & self._wdly_dq_inc.re, i_ODATAIN=dm_o_nodelay, o_DATAOUT=pads.dm[i] ) dqs_nodelay = Signal() dqs_delayed = Signal() dqs_t = Signal() if i == 0: # Store initial DQS DELAY_VALUE (in taps) to # be able to reload DELAY_VALUE after reset. dqs_taps = Signal(9) dqs_taps_timer = WaitTimer(2**16) self.submodules += dqs_taps_timer dqs_taps_done = Signal() self.comb += dqs_taps_timer.wait.eq(~dqs_taps_done) self.sync += \ If(dqs_taps_timer.done, dqs_taps_done.eq(1), self._wdly_dqs_taps.status.eq(dqs_taps) ) self.specials += [ Instance( "OSERDESE3", p_DATA_WIDTH=8, p_INIT=0, p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, o_OQ=dqs_nodelay, o_T_OUT=dqs_t, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D=Cat(dqs_serdes_pattern[0], dqs_serdes_pattern[1], dqs_serdes_pattern[2], dqs_serdes_pattern[3], dqs_serdes_pattern[4], dqs_serdes_pattern[5], dqs_serdes_pattern[6], dqs_serdes_pattern[7]), i_T=~oe_dqs, ), Instance("ODELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=200.0, p_IS_CLK_INVERTED=0, p_IS_RST_INVERTED=0, p_DELAY_FORMAT="TIME", p_DELAY_TYPE="VARIABLE", p_DELAY_VALUE=500, i_CLK=ClockSignal(), i_INC=1, i_EN_VTC=self._en_vtc.storage, i_RST=self._dly_sel.storage[i] & self._wdly_dqs_rst.re, i_CE=self._dly_sel.storage[i] & self._wdly_dqs_inc.re, o_CNTVALUEOUT=Signal(9) if i != 0 else dqs_taps, i_ODATAIN=dqs_nodelay, o_DATAOUT=dqs_delayed), Instance("IOBUFDSE3", i_I=dqs_delayed, i_T=dqs_t, io_IO=pads.dqs_p[i], io_IOB=pads.dqs_n[i]) ] # DQ oe_dq = Signal() for i in range(databits): dq_o_nodelay = Signal() dq_o_delayed = Signal() dq_i_nodelay = Signal() dq_i_delayed = Signal() dq_t = Signal() dq_bitslip = BitSlip(8) self.sync += \ If(self._dly_sel.storage[i//8], If(self._wdly_dq_rst.re, dq_bitslip.value.eq(0) ).Elif(self._rdly_dq_bitslip.re, dq_bitslip.value.eq(dq_bitslip.value + 1) ) ) self.submodules += dq_bitslip self.specials += [ Instance("OSERDESE3", p_DATA_WIDTH=8, p_INIT=0, p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, o_OQ=dq_o_nodelay, o_T_OUT=dq_t, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D=Cat(self.dfi.phases[0].wrdata[i], self.dfi.phases[0].wrdata[databits + i], self.dfi.phases[1].wrdata[i], self.dfi.phases[1].wrdata[databits + i], self.dfi.phases[2].wrdata[i], self.dfi.phases[2].wrdata[databits + i], self.dfi.phases[3].wrdata[i], self.dfi.phases[3].wrdata[databits + i]), i_T=~oe_dq), Instance( "ISERDESE3", p_IS_CLK_INVERTED=0, p_IS_CLK_B_INVERTED=1, p_DATA_WIDTH=8, i_D=dq_i_delayed, i_RST=ResetSignal(), i_FIFO_RD_CLK=0, i_FIFO_RD_EN=0, i_CLK=ClockSignal("sys4x"), i_CLK_B=ClockSignal("sys4x"), # locally inverted i_CLKDIV=ClockSignal(), o_Q=dq_bitslip.i), Instance( "ODELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=200.0, p_IS_CLK_INVERTED=0, p_IS_RST_INVERTED=0, p_DELAY_FORMAT="TIME", p_DELAY_TYPE="VARIABLE", p_DELAY_VALUE=0, i_CLK=ClockSignal(), i_INC=1, i_EN_VTC=self._en_vtc.storage, i_RST=self._dly_sel.storage[i // 8] & self._wdly_dq_rst.re, i_CE=self._dly_sel.storage[i // 8] & self._wdly_dq_inc.re, i_ODATAIN=dq_o_nodelay, o_DATAOUT=dq_o_delayed), Instance( "IDELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=200.0, p_IS_CLK_INVERTED=0, p_IS_RST_INVERTED=0, p_DELAY_FORMAT="TIME", p_DELAY_SRC="IDATAIN", p_DELAY_TYPE="VARIABLE", p_DELAY_VALUE=0, i_CLK=ClockSignal(), i_INC=1, i_EN_VTC=self._en_vtc.storage, i_RST=self._dly_sel.storage[i // 8] & self._rdly_dq_rst.re, i_CE=self._dly_sel.storage[i // 8] & self._rdly_dq_inc.re, i_IDATAIN=dq_i_nodelay, o_DATAOUT=dq_i_delayed), Instance("IOBUF", i_I=dq_o_delayed, o_O=dq_i_nodelay, i_T=dq_t, io_IO=pads.dq[i]) ] self.comb += [ self.dfi.phases[0].rddata[i].eq(dq_bitslip.o[0]), self.dfi.phases[1].rddata[i].eq(dq_bitslip.o[2]), self.dfi.phases[2].rddata[i].eq(dq_bitslip.o[4]), self.dfi.phases[3].rddata[i].eq(dq_bitslip.o[6]), self.dfi.phases[0].rddata[databits + i].eq(dq_bitslip.o[1]), self.dfi.phases[1].rddata[databits + i].eq(dq_bitslip.o[3]), self.dfi.phases[2].rddata[databits + i].eq(dq_bitslip.o[5]), self.dfi.phases[3].rddata[databits + i].eq(dq_bitslip.o[7]), ] # Flow control # # total read latency = 8: # 2 cycles through OSERDESE3 # 2 cycles CAS # 2 cycles through ISERDESE3 # 2 cycles through BitSlip rddata_en = self.dfi.phases[self.settings.rdphase].rddata_en for i in range(8 - 1): n_rddata_en = Signal() self.sync += n_rddata_en.eq(rddata_en) rddata_en = n_rddata_en self.sync += [ phase.rddata_valid.eq(rddata_en | self._wlevel_en.storage) for phase in self.dfi.phases ] oe = Signal() last_wrdata_en = Signal(4) wrphase = self.dfi.phases[self.settings.wrphase] self.sync += last_wrdata_en.eq( Cat(wrphase.wrdata_en, last_wrdata_en[:3])) self.comb += oe.eq(last_wrdata_en[1] | last_wrdata_en[2] | last_wrdata_en[3]) self.sync += \ If(self._wlevel_en.storage, oe_dqs.eq(1), oe_dq.eq(0) ).Else( oe_dqs.eq(oe), oe_dq.eq(oe) )
def __init__(self, pads): addressbits = len(pads.a) bankbits = len(pads.ba) databits = len(pads.dq) nphases = 4 self._dly_sel = CSRStorage(databits // 8) self._rdly_dq_rst = CSR() self._rdly_dq_inc = CSR() self._rdly_dq_bitslip = CSR() self.settings = sdram_settings.PhySettings(memtype="DDR3", dfi_databits=2 * databits, nphases=nphases, rdphase=0, wrphase=2, rdcmdphase=1, wrcmdphase=0, cl=7, cwl=6, read_latency=6, write_latency=2) self.dfi = Interface(addressbits, bankbits, 2 * databits, nphases) # # # # Clock sd_clk_se = Signal() self.specials += [ Instance("OSERDESE2", p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=sd_clk_se, i_OCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D1=0, i_D2=1, i_D3=0, i_D4=1, i_D5=0, i_D6=1, i_D7=0, i_D8=1), Instance("OBUFDS", i_I=sd_clk_se, o_O=pads.clk_p, o_OB=pads.clk_n) ] # Addresses and commands for i in range(addressbits): self.specials += \ Instance("OSERDESE2", p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=pads.a[i], i_OCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D1=self.dfi.phases[0].address[i], i_D2=self.dfi.phases[0].address[i], i_D3=self.dfi.phases[1].address[i], i_D4=self.dfi.phases[1].address[i], i_D5=self.dfi.phases[2].address[i], i_D6=self.dfi.phases[2].address[i], i_D7=self.dfi.phases[3].address[i], i_D8=self.dfi.phases[3].address[i] ) for i in range(bankbits): self.specials += \ Instance("OSERDESE2", p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=pads.ba[i], i_OCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D1=self.dfi.phases[0].bank[i], i_D2=self.dfi.phases[0].bank[i], i_D3=self.dfi.phases[1].bank[i], i_D4=self.dfi.phases[1].bank[i], i_D5=self.dfi.phases[2].bank[i], i_D6=self.dfi.phases[2].bank[i], i_D7=self.dfi.phases[3].bank[i], i_D8=self.dfi.phases[3].bank[i] ) controls = ["ras_n", "cas_n", "we_n", "cke", "odt", "reset_n"] if hasattr(pads, "cs_n"): controls.append("cs_n") for name in controls: self.specials += \ Instance("OSERDESE2", p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=getattr(pads, name), i_OCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D1=getattr(self.dfi.phases[0], name), i_D2=getattr(self.dfi.phases[0], name), i_D3=getattr(self.dfi.phases[1], name), i_D4=getattr(self.dfi.phases[1], name), i_D5=getattr(self.dfi.phases[2], name), i_D6=getattr(self.dfi.phases[2], name), i_D7=getattr(self.dfi.phases[3], name), i_D8=getattr(self.dfi.phases[3], name) ) # DQS and DM oe_dqs = Signal() dqs_serdes_pattern = Signal(8, reset=0b01010101) for i in range(databits // 8): self.specials += \ Instance("OSERDESE2", p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=pads.dm[i], i_OCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D1=self.dfi.phases[0].wrdata_mask[i], i_D2=self.dfi.phases[0].wrdata_mask[databits//8+i], i_D3=self.dfi.phases[1].wrdata_mask[i], i_D4=self.dfi.phases[1].wrdata_mask[databits//8+i], i_D5=self.dfi.phases[2].wrdata_mask[i], i_D6=self.dfi.phases[2].wrdata_mask[databits//8+i], i_D7=self.dfi.phases[3].wrdata_mask[i], i_D8=self.dfi.phases[3].wrdata_mask[databits//8+i] ) dqs = Signal() dqs_t = Signal() self.specials += [ Instance("OSERDESE2", p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=dqs, o_TQ=dqs_t, i_OCE=1, i_TCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x_dqs"), i_CLKDIV=ClockSignal(), i_D1=dqs_serdes_pattern[0], i_D2=dqs_serdes_pattern[1], i_D3=dqs_serdes_pattern[2], i_D4=dqs_serdes_pattern[3], i_D5=dqs_serdes_pattern[4], i_D6=dqs_serdes_pattern[5], i_D7=dqs_serdes_pattern[6], i_D8=dqs_serdes_pattern[7], i_T1=~oe_dqs), Instance("OBUFTDS", i_I=dqs, i_T=dqs_t, o_O=pads.dqs_p[i], o_OB=pads.dqs_n[i]) ] # DQ oe_dq = Signal() for i in range(databits): dq_o = Signal() dq_i_nodelay = Signal() dq_i_delayed = Signal() dq_t = Signal() self.specials += [ Instance("OSERDESE2", p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=dq_o, o_TQ=dq_t, i_OCE=1, i_TCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_D1=self.dfi.phases[0].wrdata[i], i_D2=self.dfi.phases[0].wrdata[databits + i], i_D3=self.dfi.phases[1].wrdata[i], i_D4=self.dfi.phases[1].wrdata[databits + i], i_D5=self.dfi.phases[2].wrdata[i], i_D6=self.dfi.phases[2].wrdata[databits + i], i_D7=self.dfi.phases[3].wrdata[i], i_D8=self.dfi.phases[3].wrdata[databits + i], i_T1=~oe_dq), Instance( "ISERDESE2", p_DATA_WIDTH=8, p_DATA_RATE="DDR", p_SERDES_MODE="MASTER", p_INTERFACE_TYPE="NETWORKING", p_NUM_CE=1, p_IOBDELAY="IFD", i_DDLY=dq_i_delayed, i_CE1=1, i_RST=ResetSignal() | (self._dly_sel.storage[i // 8] & self._rdly_dq_rst.re), i_CLK=ClockSignal("sys4x"), i_CLKB=~ClockSignal("sys4x"), i_CLKDIV=ClockSignal(), i_BITSLIP=self._dly_sel.storage[i // 8] & self._rdly_dq_bitslip.re, o_Q8=self.dfi.phases[0].rddata[i], o_Q7=self.dfi.phases[0].rddata[databits + i], o_Q6=self.dfi.phases[1].rddata[i], o_Q5=self.dfi.phases[1].rddata[databits + i], o_Q4=self.dfi.phases[2].rddata[i], o_Q3=self.dfi.phases[2].rddata[databits + i], o_Q2=self.dfi.phases[3].rddata[i], o_Q1=self.dfi.phases[3].rddata[databits + i]), Instance( "IDELAYE2", p_DELAY_SRC="IDATAIN", p_SIGNAL_PATTERN="DATA", p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0, p_PIPE_SEL="FALSE", p_IDELAY_TYPE="VARIABLE", p_IDELAY_VALUE=6, i_C=ClockSignal(), i_LD=self._dly_sel.storage[i // 8] & self._rdly_dq_rst.re, i_CE=self._dly_sel.storage[i // 8] & self._rdly_dq_inc.re, i_LDPIPEEN=0, i_INC=1, i_IDATAIN=dq_i_nodelay, o_DATAOUT=dq_i_delayed), Instance("IOBUF", i_I=dq_o, o_O=dq_i_nodelay, i_T=dq_t, io_IO=pads.dq[i]) ] # Flow control # # total read latency = 6: # 2 cycles through OSERDESE2 # 2 cycles CAS # 2 cycles through ISERDESE2 rddata_en = self.dfi.phases[self.settings.rdphase].rddata_en for i in range(6 - 1): n_rddata_en = Signal() self.sync += n_rddata_en.eq(rddata_en) rddata_en = n_rddata_en self.sync += [ phase.rddata_valid.eq(rddata_en) for phase in self.dfi.phases ] oe = Signal() last_wrdata_en = Signal(4) wrphase = self.dfi.phases[self.settings.wrphase] self.sync += last_wrdata_en.eq( Cat(wrphase.wrdata_en, last_wrdata_en[:3])) self.comb += oe.eq(last_wrdata_en[1] | last_wrdata_en[2] | last_wrdata_en[3]) self.sync += [oe_dqs.eq(oe), oe_dq.eq(oe)]
def __init__(self, pads): addressbits = len(pads.a) bankbits = len(pads.ba) databits = len(pads.dq) self.settings = sdram_settings.PhySettings(memtype="SDR", dfi_databits=databits, nphases=1, rdphase=0, wrphase=0, rdcmdphase=0, wrcmdphase=0, cl=2, read_latency=4, write_latency=0) self.dfi = Interface(addressbits, bankbits, databits) ### # # Command/address # self.sync += [ pads.a.eq(self.dfi.p0.address), pads.ba.eq(self.dfi.p0.bank), pads.cke.eq(self.dfi.p0.cke), pads.cas_n.eq(self.dfi.p0.cas_n), pads.ras_n.eq(self.dfi.p0.ras_n), pads.we_n.eq(self.dfi.p0.we_n) ] if hasattr(pads, "cs_n"): self.sync += pads.cs_n.eq(self.dfi.p0.cs_n) # # DQ/DQS/DM data # sd_dq_out = Signal(databits) drive_dq = Signal() self.sync += sd_dq_out.eq(self.dfi.p0.wrdata) self.specials += Tristate(pads.dq, sd_dq_out, drive_dq) self.sync += \ If(self.dfi.p0.wrdata_en, pads.dm.eq(self.dfi.p0.wrdata_mask) ).Else( pads.dm.eq(0) ) sd_dq_in_ps = Signal(databits) self.sync.sys_ps += sd_dq_in_ps.eq(pads.dq) self.sync += self.dfi.p0.rddata.eq(sd_dq_in_ps) # # DQ/DM control # d_dfi_wrdata_en = Signal() self.sync += d_dfi_wrdata_en.eq(self.dfi.p0.wrdata_en) self.comb += drive_dq.eq(d_dfi_wrdata_en) rddata_sr = Signal(4) self.comb += self.dfi.p0.rddata_valid.eq(rddata_sr[3]) self.sync += rddata_sr.eq(Cat(self.dfi.p0.rddata_en, rddata_sr[:3]))
def __init__(self, pads): addressbits = len(pads.a) bankbits = len(pads.ba) databits = len(pads.dq_i) assert (len(pads.dq_i) == len(pads.dq_o)) read_latency = 4 self.settings = sdram_settings.PhySettings(memtype="SDR", dfi_databits=databits, nphases=1, rdphase=0, wrphase=0, rdcmdphase=0, wrcmdphase=0, cl=2, read_latency=read_latency, write_latency=0) self.dfi = Interface(addressbits, bankbits, databits) # # Command/address # self.comb += [ pads.a.eq(self.dfi.p0.address), pads.ba.eq(self.dfi.p0.bank), pads.cke.eq(self.dfi.p0.cke), pads.cas_n.eq(self.dfi.p0.cas_n), pads.ras_n.eq(self.dfi.p0.ras_n), pads.we_n.eq(self.dfi.p0.we_n) ] if hasattr(pads, "cs_n"): self.sync += pads.cs_n.eq(self.dfi.p0.cs_n) # # DQ/DQS/DM data # self.comb += pads.dq_o.eq(self.dfi.p0.wrdata) self.comb += \ If(self.dfi.p0.wrdata_en, pads.dm.eq(self.dfi.p0.wrdata_mask) ).Else( pads.dm.eq(0) ) sd_dq_in_ps = Signal(databits) self.comb += sd_dq_in_ps.eq(pads.dq_i) self.comb += self.dfi.p0.rddata.eq(sd_dq_in_ps) # # DQ/DM control # d_dfi_wrdata_en = Signal() self.comb += d_dfi_wrdata_en.eq(self.dfi.p0.wrdata_en) self.comb += pads.dq_oe.eq(d_dfi_wrdata_en) rddata_sr = Signal(read_latency) self.comb += self.dfi.p0.rddata_valid.eq(rddata_sr[read_latency - 1]) self.sync += rddata_sr.eq( Cat(self.dfi.p0.rddata_en, rddata_sr[:read_latency - 1])) # These registers are read always by the kernel code - but in reality they have no use # for our pass-through model self._en_vtc = CSRStorage(reset=1) self._wlevel_en = CSRStorage() self._wlevel_strobe = CSR() self._dly_sel = CSRStorage(32 // 8) self._rdly_dq_rst = CSR() self._rdly_dq_inc = CSR() self._rdly_dq_bitslip = CSR() self._wdly_dq_rst = CSR() self._wdly_dq_inc = CSR() self._wdly_dqs_rst = CSR() self._wdly_dqs_inc = CSR() self._wdly_dqs_taps = CSRStatus(9)