def __init__(self, **kwargs): platform = sim.Platform() SoCSDRAM.__init__(self, platform, clk_freq=int((1/(platform.default_clk_period))*1000000000), integrated_rom_size=0x8000, ident="LiteX simulation example design", with_uart=False, **kwargs) self.submodules.crg = CRG(platform.request(platform.default_clk_name)) self.submodules.uart_phy = uart.RS232PHYModel(platform.request("serial")) self.submodules.uart = uart.UART(self.uart_phy) if not self.integrated_main_ram_size: sdram_module = IS42S16160(self.clk_freq, "1:1") phy_settings = PhySettings( memtype="SDR", dfi_databits=1*16, nphases=1, rdphase=0, wrphase=0, rdcmdphase=0, wrcmdphase=0, cl=2, read_latency=4, write_latency=0 ) self.submodules.sdrphy = SDRAMPHYModel(sdram_module, phy_settings) self.register_sdram(self.sdrphy, sdram_module.geom_settings, sdram_module.timing_settings, controller_settings=ControllerSettings(with_refresh=False)) # reduce memtest size to speed up simulation self.add_constant("MEMTEST_DATA_SIZE", 8*1024) self.add_constant("MEMTEST_ADDR_SIZE", 8*1024)
def __init__(self, pads, cl=2): addressbits = len(pads.a) bankbits = len(pads.ba) nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n) databits = len(pads.dq) self.settings = PhySettings(memtype="SDR", dfi_databits=databits, nranks=nranks, nphases=1, rdphase=0, wrphase=0, rdcmdphase=0, wrcmdphase=0, cl=cl, read_latency=cl + 2, write_latency=0) self.dfi = dfi = Interface(addressbits, bankbits, nranks, databits) # # # # Command/address self.sync += [ pads.a.eq(dfi.p0.address), pads.ba.eq(dfi.p0.bank), pads.cas_n.eq(dfi.p0.cas_n), pads.ras_n.eq(dfi.p0.ras_n), pads.we_n.eq(dfi.p0.we_n) ] if hasattr(pads, "cke"): self.sync += pads.cke.eq(dfi.p0.cke) if hasattr(pads, "cs_n"): self.sync += pads.cs_n.eq(dfi.p0.cs_n) # DQ/DQS/DM data dq_o = Signal(databits) dq_oe = Signal() dq_i = Signal(databits) self.sync += dq_o.eq(dfi.p0.wrdata) self.specials += Tristate(pads.dq, dq_o, dq_oe, dq_i) if hasattr(pads, "dm"): self.sync += \ If(dfi.p0.wrdata_en, pads.dm.eq(dfi.p0.wrdata_mask) ).Else( pads.dm.eq(0) ) dq_in = Signal(databits) self.sync.sys_ps += dq_in.eq(dq_i) self.sync += dfi.p0.rddata.eq(dq_in) # DQ/DM control wrdata_en = Signal() self.sync += wrdata_en.eq(dfi.p0.wrdata_en) self.comb += dq_oe.eq(wrdata_en) rddata_en = Signal(cl + 2) self.sync += rddata_en.eq(Cat(dfi.p0.rddata_en, rddata_en[:cl + 1])) self.comb += dfi.p0.rddata_valid.eq(rddata_en[cl + 1])
def __init__(self): # phy sdram_module = SimModule(1000, "1:1") phy_settings = PhySettings(memtype="SDR", dfi_databits=1 * 16, nphases=1, rdphase=0, wrphase=0, rdcmdphase=0, wrcmdphase=0, cl=2, read_latency=4, write_latency=0) self.submodules.sdrphy = SDRAMPHYModel(sdram_module, phy_settings, we_granularity=0) # controller self.submodules.controller = LiteDRAMController( phy_settings, sdram_module.geom_settings, sdram_module.timing_settings, ControllerSettings(with_refresh=False)) self.comb += self.controller.dfi.connect(self.sdrphy.dfi) self.submodules.crossbar = LiteDRAMCrossbar(self.controller.interface, self.controller.nrowbits) # write port write_user_port = self.crossbar.get_port("write", cd="write") read_user_port = self.crossbar.get_port("read", cd="read") # generator / checker self.submodules.generator = LiteDRAMBISTGenerator(write_user_port) self.submodules.checker = LiteDRAMBISTChecker(read_user_port)
def __init__(self, platform, **kwargs): dict_set_max(kwargs, 'integrated_rom_size', 0x10000) if kwargs.get('cpu_type', None) == 'mor1kx': dict_set_max(kwargs, 'integrated_rom_size', 0x10000) else: dict_set_max(kwargs, 'integrated_rom_size', 0x8000) dict_set_max(kwargs, 'integrated_sram_size', 0x8000) dict_set_max(kwargs, 'firmware_ram_size', 0x10000) if 'firmware_filename' not in kwargs: kwargs[ 'firmware_filename'] = "build/sim_{}_{}/software/firmware/firmware.fbi".format( self.__class__.__name__.lower()[:-3], kwargs.get('cpu_type', 'lm32')) clk_freq = int((1 / (platform.default_clk_period)) * 1000000000) SoCSDRAM.__init__(self, platform, clk_freq, with_uart=False, **kwargs) self.submodules.crg = CRG(platform.request(platform.default_clk_name)) self.submodules.uart_phy = uart.RS232PHYModel( platform.request("serial")) self.submodules.uart = uart.UART(self.uart_phy) # firmware self.submodules.firmware_ram = firmware.FirmwareROM( firmware_ram_size, firmware_filename) self.register_mem("firmware_ram", self.mem_map["firmware_ram"], self.firmware_ram.bus, firmware_ram_size) self.flash_boot_address = self.mem_map["firmware_ram"] define_flash_constants(self) # sdram sdram_module = IS42S16160(self.clk_freq, "1:1") phy_settings = PhySettings(memtype="SDR", dfi_databits=1 * 32, nphases=1, rdphase=0, wrphase=0, rdcmdphase=0, wrcmdphase=0, cl=2, read_latency=4, write_latency=0) self.submodules.sdrphy = SDRAMPHYModel(sdram_module, phy_settings) controller_settings = ControllerSettings(with_refresh=False) self.register_sdram(self.sdrphy, sdram_module.geom_settings, sdram_module.timing_settings, controller_settings=controller_settings) # reduce memtest size to speed up simulation self.add_constant("MEMTEST_DATA_SIZE", 1024) self.add_constant("MEMTEST_ADDR_SIZE", 1024) self.add_constant("SIMULATION", 1)
def __init__(self, firmware_ram_size=0x10000, firmware_filename="firmware/firmware.bin", **kwargs): platform = sim.Platform() SoCSDRAM.__init__(self, platform, clk_freq=int((1/(platform.default_clk_period))*1000000000), integrated_rom_size=0x8000, integrated_sram_size=0x8000, with_uart=False, **kwargs) self.submodules.crg = CRG(platform.request(platform.default_clk_name)) self.submodules.uart_phy = uart.RS232PHYModel(platform.request("serial")) self.submodules.uart = uart.UART(self.uart_phy) # firmware self.submodules.firmware_ram = firmware.FirmwareROM(firmware_ram_size, firmware_filename) self.register_mem("firmware_ram", self.mem_map["firmware_ram"], self.firmware_ram.bus, firmware_ram_size) self.add_constant("ROM_BOOT_ADDRESS", self.mem_map["firmware_ram"]) # sdram sdram_module = IS42S16160(self.clk_freq, "1:1") phy_settings = PhySettings( memtype="SDR", dfi_databits=1*32, nphases=1, rdphase=0, wrphase=0, rdcmdphase=0, wrcmdphase=0, cl=2, read_latency=4, write_latency=0 ) self.submodules.sdrphy = SDRAMPHYModel(sdram_module, phy_settings) controller_settings = ControllerSettings(with_refresh=False) self.register_sdram(self.sdrphy, sdram_module.geom_settings, sdram_module.timing_settings, controller_settings=controller_settings) # reduce memtest size to speed up simulation self.add_constant("MEMTEST_DATA_SIZE", 1024) self.add_constant("MEMTEST_ADDR_SIZE", 1024) self.add_constant("SIMULATION", 1) self.submodules.video_out = VideoOutCore(self.sdram.crossbar.get_port()) self.submodules.vga = VGAModel(platform.request("vga")) self.comb += self.video_out.source.connect(self.vga.sink)
def __init__(self, pads, sys_clk_freq=100e6): memtype = "DDR3" tck = 2 / (2 * 2 * sys_clk_freq) addressbits = len(pads.a) bankbits = len(pads.ba) nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n) databits = len(pads.dq) nphases = 2 # Init ------------------------------------------------------------------------------------- self.submodules.init = ClockDomainsRenamer("init")( ECP5DDRPHYInit("sys2x")) # Registers -------------------------------------------------------------------------------- self._dly_sel = CSRStorage(databits // 8) self._rdly_dq_rst = CSR() self._rdly_dq_inc = CSR() self._rdly_dq_bitslip_rst = CSR() self._rdly_dq_bitslip = CSR() self._burstdet_clr = CSR() self._burstdet_seen = CSRStatus(databits // 8) # Observation self.datavalid = Signal(databits // 8) # PHY settings ----------------------------------------------------------------------------- cl, cwl = get_cl_cw(memtype, tck) cl_sys_latency = get_sys_latency(nphases, cl) cwl_sys_latency = get_sys_latency(nphases, cwl) rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl) wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl) self.settings = PhySettings(memtype=memtype, databits=databits, dfi_databits=4 * databits, nranks=nranks, nphases=nphases, rdphase=rdphase, wrphase=wrphase, rdcmdphase=rdcmdphase, wrcmdphase=wrcmdphase, cl=cl, cwl=cwl, read_latency=2 + cl_sys_latency + 2 + log2_int(4 // nphases) + 6, write_latency=cwl_sys_latency) # DFI Interface ---------------------------------------------------------------------------- self.dfi = Interface(addressbits, bankbits, nranks, 4 * databits, 4) # # # bl8_sel = Signal() self.specials # VCCIO for i in range(len(pads.vccio)): self.comb += pads.vccio[i].eq(1) # Clock ------------------------------------------------------------------------------------ for i in range(len(pads.clk_p)): sd_clk_se = Signal() self.specials += [ Instance("ODDRX2F", i_D0=0, i_D1=1, i_D2=0, i_D3=1, i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), i_RST=ResetSignal("sys2x"), o_Q=pads.clk_p[i]), ] # Addresses and Commands ------------------------------------------------------------------- for i in range(addressbits): self.specials += \ Instance("ODDRX2F", i_D0=self.dfi.phases[0].address[i], i_D1=self.dfi.phases[0].address[i], i_D2=self.dfi.phases[1].address[i], i_D3=self.dfi.phases[1].address[i], i_ECLK=ClockSignal("sys2x_a"), i_SCLK=ClockSignal("sys_a"), i_RST=ResetSignal("sys2x"), o_Q=pads.a[i] ) for i in range(bankbits): self.specials += \ Instance("ODDRX2F", i_D0=self.dfi.phases[0].bank[i], i_D1=self.dfi.phases[0].bank[i], i_D2=self.dfi.phases[1].bank[i], i_D3=self.dfi.phases[1].bank[i], i_ECLK=ClockSignal("sys2x_a"), i_SCLK=ClockSignal("sys_a"), i_RST=ResetSignal("sys2x"), o_Q=pads.ba[i] ) controls = ["ras_n", "cas_n", "we_n", "odt", "cs_n"] controls_a = ["cke", "reset_n"] for name in controls: for i in range(len(getattr(pads, name))): self.specials += \ Instance("ODDRX2F", i_D0=getattr(self.dfi.phases[0], name)[i], i_D1=getattr(self.dfi.phases[0], name)[i], i_D2=getattr(self.dfi.phases[1], name)[i], i_D3=getattr(self.dfi.phases[1], name)[i], i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), i_RST=ResetSignal("sys2x"), o_Q=getattr(pads, name)[i] ) for name in controls_a: for i in range(len(getattr(pads, name))): self.specials += \ Instance("ODDRX2F", i_D0=getattr(self.dfi.phases[0], name)[i], i_D1=getattr(self.dfi.phases[0], name)[i], i_D2=getattr(self.dfi.phases[1], name)[i], i_D3=getattr(self.dfi.phases[1], name)[i], i_ECLK=ClockSignal("sys2x_a"), i_SCLK=ClockSignal("sys_a"), i_RST=ResetSignal("sys2x"), o_Q=getattr(pads, name)[i] ) # DQ --------------------------------------------------------------------------------------- oe_dq = Signal() oe_dqs = Signal() dqs_postamble = Signal() dqs_preamble = Signal() dqs_read = Signal() for i in range(databits // 8): # DQSBUFM dqs_i = Signal() dqsr90 = Signal() dqsw270 = Signal() dqsw = Signal() rdpntr = Signal(3) wrpntr = Signal(3) rdly = Signal(7) self.sync += \ If(self._dly_sel.storage[i], If(self._rdly_dq_rst.re, rdly.eq(0), ).Elif(self._rdly_dq_inc.re, rdly.eq(rdly + 1), ) ) datavalid = Signal() burstdet = Signal() self.specials += Instance( "DQSBUFM", p_DQS_LI_DEL_ADJ="MINUS", p_DQS_LI_DEL_VAL=1, p_DQS_LO_DEL_ADJ="MINUS", p_DQS_LO_DEL_VAL=4, # Clocks / Reset i_SCLK=ClockSignal("sys"), i_ECLK=ClockSignal("sys2x"), i_RST=ResetSignal("sys2x"), i_DDRDEL=self.init.delay, i_PAUSE=self.init.pause | self._dly_sel.storage[i], # Control # Assert LOADNs to use DDRDEL control i_RDLOADN=0, i_RDMOVE=0, i_RDDIRECTION=1, i_WRLOADN=0, i_WRMOVE=0, i_WRDIRECTION=1, # Reads (generate shifted DQS clock for reads) i_READ0=dqs_read, i_READ1=dqs_read, i_READCLKSEL0=rdly[0], i_READCLKSEL1=rdly[1], i_READCLKSEL2=rdly[2], i_DQSI=dqs_i, o_DQSR90=dqsr90, o_RDPNTR0=rdpntr[0], o_RDPNTR1=rdpntr[1], o_RDPNTR2=rdpntr[2], o_WRPNTR0=wrpntr[0], o_WRPNTR1=wrpntr[1], o_WRPNTR2=wrpntr[2], o_DATAVALID=self.datavalid[i], o_BURSTDET=burstdet, # Writes (generate shifted ECLK clock for writes) o_DQSW270=dqsw270, o_DQSW=dqsw) burstdet_d = Signal() self.sync += [ burstdet_d.eq(burstdet), If(self._burstdet_clr.re, self._burstdet_seen.status[i].eq(0)).Elif( burstdet & ~burstdet_d, self._burstdet_seen.status[i].eq(1)) ] # DQS and DM --------------------------------------------------------------------------- dqs_serdes_pattern = Signal(8, reset=0b1010) dm_o_data = Signal(8) dm_o_data_d = Signal(8) dm_o_data_muxed = Signal(4) self.comb += dm_o_data.eq( Cat(self.dfi.phases[0].wrdata_mask[0 * databits // 8 + i], self.dfi.phases[0].wrdata_mask[1 * databits // 8 + i], self.dfi.phases[0].wrdata_mask[2 * databits // 8 + i], self.dfi.phases[0].wrdata_mask[3 * databits // 8 + i], self.dfi.phases[1].wrdata_mask[0 * databits // 8 + i], self.dfi.phases[1].wrdata_mask[1 * databits // 8 + i], self.dfi.phases[1].wrdata_mask[2 * databits // 8 + i], self.dfi.phases[1].wrdata_mask[3 * databits // 8 + i]), ) self.sync += dm_o_data_d.eq(dm_o_data) self.sync += \ If(bl8_sel, dm_o_data_muxed.eq(dm_o_data_d[4:]) ).Else( dm_o_data_muxed.eq(dm_o_data[:4]) ) self.specials += \ Instance("ODDRX2DQA", i_D0=dm_o_data_muxed[0], i_D1=dm_o_data_muxed[1], i_D2=dm_o_data_muxed[2], i_D3=dm_o_data_muxed[3], i_RST=ResetSignal("sys2x"), i_DQSW270=dqsw270, i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), o_Q=pads.dm[i] ) dqs = Signal() dqs_oe_n = Signal() self.specials += \ Instance("ODDRX2DQSB", i_D0=dqs_serdes_pattern[0], i_D1=dqs_serdes_pattern[1], i_D2=dqs_serdes_pattern[2], i_D3=dqs_serdes_pattern[3], i_RST=ResetSignal("sys2x"), i_DQSW=dqsw, i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), o_Q=dqs ) self.specials += \ Instance("TSHX2DQSA", i_T0=~(oe_dqs|dqs_postamble), i_T1=~(oe_dqs|dqs_preamble), i_SCLK=ClockSignal(), i_ECLK=ClockSignal("sys2x"), i_DQSW=dqsw, i_RST=ResetSignal("sys2x"), o_Q=dqs_oe_n, ) self.specials += Tristate(pads.dqs_p[i], dqs, ~dqs_oe_n, dqs_i) for j in range(8 * i, 8 * (i + 1)): dq_o = Signal() dq_i = Signal() dq_oe_n = Signal() dq_i_delayed = Signal() dq_i_data = Signal(4) dq_o_data = Signal(8) dq_o_data_d = Signal(8) dq_o_data_muxed = Signal(4) self.comb += dq_o_data.eq( Cat(self.dfi.phases[0].wrdata[0 * databits + j], self.dfi.phases[0].wrdata[1 * databits + j], self.dfi.phases[0].wrdata[2 * databits + j], self.dfi.phases[0].wrdata[3 * databits + j], self.dfi.phases[1].wrdata[0 * databits + j], self.dfi.phases[1].wrdata[1 * databits + j], self.dfi.phases[1].wrdata[2 * databits + j], self.dfi.phases[1].wrdata[3 * databits + j])) self.sync += dq_o_data_d.eq(dq_o_data) self.sync += \ If(bl8_sel, dq_o_data_muxed.eq(dq_o_data_d[4:]) ).Else( dq_o_data_muxed.eq(dq_o_data[:4]) ) self.specials += \ Instance("ODDRX2DQA", i_D0=dq_o_data_muxed[0], i_D1=dq_o_data_muxed[1], i_D2=dq_o_data_muxed[2], i_D3=dq_o_data_muxed[3], i_RST=ResetSignal("sys2x"), i_DQSW270=dqsw270, i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), o_Q=dq_o ) self.specials += \ Instance("DELAYF", i_A=dq_i, i_LOADN=1, i_MOVE=0, i_DIRECTION=0, o_Z=dq_i_delayed, p_DEL_MODE="DQS_ALIGNED_X2" ) self.specials += \ Instance("IDDRX2DQA", i_D=dq_i_delayed, i_RST=ResetSignal("sys2x"), i_DQSR90=dqsr90, i_SCLK=ClockSignal(), i_ECLK=ClockSignal("sys2x"), i_RDPNTR0=rdpntr[0], i_RDPNTR1=rdpntr[1], i_RDPNTR2=rdpntr[2], i_WRPNTR0=wrpntr[0], i_WRPNTR1=wrpntr[1], i_WRPNTR2=wrpntr[2], o_Q0=dq_i_data[0], o_Q1=dq_i_data[1], o_Q2=dq_i_data[2], o_Q3=dq_i_data[3], ) dq_bitslip = BitSlip(4) self.comb += dq_bitslip.i.eq(dq_i_data) self.sync += \ If(self._dly_sel.storage[i], If(self._rdly_dq_bitslip_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 dq_bitslip_o_d = Signal(4) self.sync += dq_bitslip_o_d.eq(dq_bitslip.o) self.comb += [ self.dfi.phases[0].rddata[0 * databits + j].eq( dq_bitslip_o_d[0]), self.dfi.phases[0].rddata[1 * databits + j].eq( dq_bitslip_o_d[1]), self.dfi.phases[0].rddata[2 * databits + j].eq( dq_bitslip_o_d[2]), self.dfi.phases[0].rddata[3 * databits + j].eq( dq_bitslip_o_d[3]), self.dfi.phases[1].rddata[0 * databits + j].eq( dq_bitslip.o[0]), self.dfi.phases[1].rddata[1 * databits + j].eq( dq_bitslip.o[1]), self.dfi.phases[1].rddata[2 * databits + j].eq( dq_bitslip.o[2]), self.dfi.phases[1].rddata[3 * databits + j].eq( dq_bitslip.o[3]), ] self.specials += \ Instance("TSHX2DQA", i_T0=~oe_dq, i_T1=~oe_dq, i_SCLK=ClockSignal(), i_ECLK=ClockSignal("sys2x"), i_DQSW270=dqsw270, i_RST=ResetSignal("sys2x"), o_Q=dq_oe_n, ) self.specials += Tristate(pads.dq[j], dq_o, ~dq_oe_n, dq_i) # Flow control ----------------------------------------------------------------------------- # # total read latency: # ODDRX2DQA latency # cl_sys_latency # IDDRX2DQA latency rddata_en = self.dfi.phases[self.settings.rdphase].rddata_en rddata_ens = Array( [Signal() for i in range(self.settings.read_latency - 1)]) for i in range(self.settings.read_latency - 1): n_rddata_en = Signal() self.sync += n_rddata_en.eq(rddata_en) self.comb += rddata_ens[i].eq(rddata_en) rddata_en = n_rddata_en self.sync += [ phase.rddata_valid.eq(rddata_en) for phase in self.dfi.phases ] self.comb += dqs_read.eq(rddata_ens[cl_sys_latency + 1] | rddata_ens[cl_sys_latency + 2]) oe = Signal() last_wrdata_en = Signal(cwl_sys_latency + 3) wrphase = self.dfi.phases[self.settings.wrphase] self.sync += last_wrdata_en.eq( Cat(wrphase.wrdata_en, last_wrdata_en[:-1])) self.comb += oe.eq(last_wrdata_en[cwl_sys_latency - 1] | last_wrdata_en[cwl_sys_latency] | last_wrdata_en[cwl_sys_latency + 1] | last_wrdata_en[cwl_sys_latency + 2]) self.sync += oe_dqs.eq(oe), oe_dq.eq(oe) self.sync += bl8_sel.eq(last_wrdata_en[cwl_sys_latency - 1]) self.sync += dqs_preamble.eq(last_wrdata_en[cwl_sys_latency - 2]) self.sync += dqs_postamble.eq(oe_dqs)
def __init__(self, pads, with_odelay, memtype="DDR3", nphases=4, sys_clk_freq=100e6, iodelay_clk_freq=200e6): assert not (memtype == "DDR3" and nphases == 2) # FIXME: Needs BL8 support for nphases=2 tck = 2/(2*nphases*sys_clk_freq) addressbits = len(pads.a) bankbits = len(pads.ba) nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n) databits = len(pads.dq) nphases = nphases iodelay_tap_average = { 200e6: 78e-12, 300e6: 52e-12, 400e6: 39e-12, # Only valid for -3 and -2/2E speed grades } half_sys8x_taps = math.floor(tck/(4*iodelay_tap_average[iodelay_clk_freq])) self._half_sys8x_taps = CSRStorage(4, reset=half_sys8x_taps) if with_odelay: 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_rst = CSR() self._rdly_dq_bitslip = CSR() if with_odelay: self._wdly_dq_rst = CSR() self._wdly_dq_inc = CSR() self._wdly_dqs_rst = CSR() self._wdly_dqs_inc = CSR() # compute phy settings cl, cwl = get_cl_cw(memtype, tck) cl_sys_latency = get_sys_latency(nphases, cl) cwl_sys_latency = get_sys_latency(nphases, cwl) rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl) wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl) self.settings = PhySettings( memtype=memtype, dfi_databits=2*databits, nranks=nranks, nphases=nphases, rdphase=rdphase, wrphase=wrphase, rdcmdphase=rdcmdphase, wrcmdphase=wrcmdphase, cl=cl, cwl=cwl, read_latency=2 + cl_sys_latency + 2 + 3, write_latency=cwl_sys_latency ) self.dfi = Interface(addressbits, bankbits, nranks, 2*databits, 4) # # # # Clock ddr_clk = "sys2x" if nphases == 2 else "sys4x" for i in range(len(pads.clk_p)): sd_clk_se = Signal() self.specials += [ Instance("OSERDESE2", p_DATA_WIDTH=2*nphases, 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(ddr_clk), 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[i], o_OB=pads.clk_n[i] ) ] # Addresses and commands for i in range(addressbits): self.specials += \ Instance("OSERDESE2", p_DATA_WIDTH=2*nphases, 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(ddr_clk), 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=2*nphases, 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(ddr_clk), 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"] 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("OSERDESE2", p_DATA_WIDTH=2*nphases, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=getattr(pads, name)[i], i_OCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal(ddr_clk), i_CLKDIV=ClockSignal(), i_D1=getattr(self.dfi.phases[0], name)[i], i_D2=getattr(self.dfi.phases[0], name)[i], i_D3=getattr(self.dfi.phases[1], name)[i], i_D4=getattr(self.dfi.phases[1], name)[i], i_D5=getattr(self.dfi.phases[2], name)[i], i_D6=getattr(self.dfi.phases[2], name)[i], i_D7=getattr(self.dfi.phases[3], name)[i], i_D8=getattr(self.dfi.phases[3], name)[i] ) # DQS and DM oe_dqs = Signal() dqs_preamble = Signal() dqs_postamble = Signal() dqs_serdes_pattern = Signal(8, reset=0b01010101) if with_odelay: self.comb += \ If(self._wlevel_en.storage, If(self._wlevel_strobe.re, dqs_serdes_pattern.eq(0b00000001) ).Else( dqs_serdes_pattern.eq(0b00000000) ) ).Elif(dqs_preamble | dqs_postamble, dqs_serdes_pattern.eq(0b0000000) ).Else( dqs_serdes_pattern.eq(0b01010101) ) else: self.comb += [ If(dqs_preamble | dqs_postamble, dqs_serdes_pattern.eq(0b0000000) ).Else( dqs_serdes_pattern.eq(0b01010101) ) ] for i in range(databits//8): dm_o_nodelay = Signal() self.specials += \ Instance("OSERDESE2", p_DATA_WIDTH=2*nphases, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=dm_o_nodelay if with_odelay else pads.dm[i], i_OCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal(ddr_clk), 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] ) if with_odelay: self.specials += \ Instance("ODELAYE2", p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA", p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=iodelay_clk_freq/1e6, p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=0, i_C=ClockSignal(), i_LD=self._dly_sel.storage[i] & self._wdly_dq_rst.re, i_CE=self._dly_sel.storage[i] & self._wdly_dq_inc.re, i_LDPIPEEN=0, i_INC=1, o_ODATAIN=dm_o_nodelay, o_DATAOUT=pads.dm[i] ) dqs_nodelay = Signal() dqs_delayed = Signal() dqs_t = Signal() self.specials += \ Instance("OSERDESE2", p_DATA_WIDTH=2*nphases, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OFB=dqs_nodelay if with_odelay else Signal(), o_OQ=Signal() if with_odelay else dqs_nodelay, o_TQ=dqs_t, i_OCE=1, i_TCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal(ddr_clk) if with_odelay else ClockSignal(ddr_clk+"_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 ) if with_odelay: self.specials += \ Instance("ODELAYE2", p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA", p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=iodelay_clk_freq/1e6, p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=half_sys8x_taps, i_C=ClockSignal(), i_LD=self._dly_sel.storage[i] & self._wdly_dqs_rst.re, i_CE=self._dly_sel.storage[i] & self._wdly_dqs_inc.re, i_LDPIPEEN=0, i_INC=1, o_ODATAIN=dqs_nodelay, o_DATAOUT=dqs_delayed ) self.specials += \ Instance("OBUFTDS", i_I=dqs_delayed if with_odelay else dqs_nodelay, 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_nodelay = Signal() dq_o_delayed = Signal() dq_i_nodelay = Signal() dq_i_delayed = Signal() dq_t = Signal() self.specials += \ Instance("OSERDESE2", p_DATA_WIDTH=2*nphases, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=dq_o_nodelay, o_TQ=dq_t, i_OCE=1, i_TCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal(ddr_clk), 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 ) dq_i_data = Signal(8) self.specials += \ Instance("ISERDESE2", p_DATA_WIDTH=2*nphases, 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(), i_CLK=ClockSignal(ddr_clk), i_CLKB=~ClockSignal(ddr_clk), i_CLKDIV=ClockSignal(), i_BITSLIP=0, o_Q8=dq_i_data[0], o_Q7=dq_i_data[1], o_Q6=dq_i_data[2], o_Q5=dq_i_data[3], o_Q4=dq_i_data[4], o_Q3=dq_i_data[5], o_Q2=dq_i_data[6], o_Q1=dq_i_data[7] ) dq_bitslip = BitSlip(8) self.comb += dq_bitslip.i.eq(dq_i_data) self.sync += \ If(self._dly_sel.storage[i//8], If(self._rdly_dq_bitslip_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.comb += [ self.dfi.phases[0].rddata[i].eq(dq_bitslip.o[0]), self.dfi.phases[0].rddata[databits+i].eq(dq_bitslip.o[1]), self.dfi.phases[1].rddata[i].eq(dq_bitslip.o[2]), self.dfi.phases[1].rddata[databits+i].eq(dq_bitslip.o[3]), self.dfi.phases[2].rddata[i].eq(dq_bitslip.o[4]), self.dfi.phases[2].rddata[databits+i].eq(dq_bitslip.o[5]), self.dfi.phases[3].rddata[i].eq(dq_bitslip.o[6]), self.dfi.phases[3].rddata[databits+i].eq(dq_bitslip.o[7]) ] if with_odelay: self.specials += \ Instance("ODELAYE2", p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA", p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=iodelay_clk_freq/1e6, p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=0, i_C=ClockSignal(), i_LD=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_LDPIPEEN=0, i_INC=1, o_ODATAIN=dq_o_nodelay, o_DATAOUT=dq_o_delayed ) self.specials += \ Instance("IDELAYE2", p_DELAY_SRC="IDATAIN", p_SIGNAL_PATTERN="DATA", p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=iodelay_clk_freq/1e6, p_PIPE_SEL="FALSE", p_IDELAY_TYPE="VARIABLE", p_IDELAY_VALUE=0, 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 ) self.specials += \ Instance("IOBUF", i_I=dq_o_delayed if with_odelay else dq_o_nodelay, o_O=dq_i_nodelay, i_T=dq_t, io_IO=pads.dq[i] ) # Flow control # # total read latency: # 2 cycles through OSERDESE2 # cl_sys_latency cycles CAS # 2 cycles through ISERDESE2 # 3 cycles through Bitslip rddata_en = self.dfi.phases[self.settings.rdphase].rddata_en for i in range(self.settings.read_latency-1): n_rddata_en = Signal() self.sync += n_rddata_en.eq(rddata_en) rddata_en = n_rddata_en if with_odelay: self.sync += [phase.rddata_valid.eq(rddata_en | self._wlevel_en.storage) for phase in self.dfi.phases] else: self.sync += [phase.rddata_valid.eq(rddata_en) for phase in self.dfi.phases] oe = Signal() last_wrdata_en = Signal(cwl_sys_latency+2) wrphase = self.dfi.phases[self.settings.wrphase] self.sync += last_wrdata_en.eq(Cat(wrphase.wrdata_en, last_wrdata_en[:-1])) self.comb += oe.eq( last_wrdata_en[cwl_sys_latency-1] | last_wrdata_en[cwl_sys_latency] | last_wrdata_en[cwl_sys_latency+1]) if with_odelay: self.sync += \ If(self._wlevel_en.storage, oe_dqs.eq(1), oe_dq.eq(0) ).Else( oe_dqs.eq(oe), oe_dq.eq(oe) ) else: self.sync += [ oe_dqs.eq(oe), oe_dq.eq(oe) ] # dqs preamble/postamble if memtype == "DDR2": dqs_sys_latency = cwl_sys_latency-1 elif memtype == "DDR3": dqs_sys_latency = cwl_sys_latency-1 if with_odelay else cwl_sys_latency self.comb += [ dqs_preamble.eq(last_wrdata_en[dqs_sys_latency-1] & ~last_wrdata_en[dqs_sys_latency]), dqs_postamble.eq(last_wrdata_en[dqs_sys_latency+1] & ~last_wrdata_en[dqs_sys_latency]), ]
def __init__(self, pads): addressbits = len(pads.a) bankbits = len(pads.ba) databits = len(pads.dq) self.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, with_sdram=False, with_ethernet=False, with_etherbone=False, etherbone_mac_address=0x10e2d5000000, etherbone_ip_address="192.168.1.50", with_analyzer=False, **kwargs): platform = Platform() sys_clk_freq = int(1e6) # SoCSDRAM --------------------------------------------------------------------------------- SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq, integrated_rom_size=0x8000, ident="LiteX Simulation", ident_version=True, with_uart=False, **kwargs) # CRG -------------------------------------------------------------------------------------- self.submodules.crg = CRG(platform.request("sys_clk")) # Serial ----------------------------------------------------------------------------------- self.submodules.uart_phy = uart.RS232PHYModel( platform.request("serial")) self.submodules.uart = uart.UART(self.uart_phy) self.add_csr("uart") self.add_interrupt("uart") # SDRAM ------------------------------------------------------------------------------------ if with_sdram: sdram_module = MT48LC16M16(100e6, "1:1") # use 100MHz timings phy_settings = PhySettings(memtype="SDR", databits=32, dfi_databits=16, nphases=1, rdphase=0, wrphase=0, rdcmdphase=0, wrcmdphase=0, cl=2, read_latency=4, write_latency=0) self.submodules.sdrphy = SDRAMPHYModel(sdram_module, phy_settings) self.register_sdram(self.sdrphy, sdram_module.geom_settings, sdram_module.timing_settings) # Reduce memtest size for simulation speedup self.add_constant("MEMTEST_DATA_SIZE", 8 * 1024) self.add_constant("MEMTEST_ADDR_SIZE", 8 * 1024) assert not (with_ethernet and with_etherbone ) # FIXME: fix simulator with 2 ethernet interfaces # Ethernet --------------------------------------------------------------------------------- if with_ethernet: # Ethernet PHY self.submodules.ethphy = LiteEthPHYModel( self.platform.request("eth", 0)) self.add_csr("ethphy") # Ethernet MAC ethmac = LiteEthMAC(phy=self.ethphy, dw=32, interface="wishbone", endianness=self.cpu.endianness) if with_etherbone: ethmac = ClockDomainsRenamer({ "eth_tx": "ethphy_eth_tx", "eth_rx": "ethphy_eth_rx" })(ethmac) self.submodules.ethmac = ethmac self.add_wb_slave(self.mem_map["ethmac"], self.ethmac.bus, 0x2000) self.add_memory_region("ethmac", self.mem_map["ethmac"], 0x2000, type="io") self.add_csr("ethmac") self.add_interrupt("ethmac") # Ethernet --------------------------------------------------------------------------------- if with_etherbone: # Ethernet PHY self.submodules.etherbonephy = LiteEthPHYModel( self.platform.request("eth", 0)) # FIXME self.add_csr("etherbonephy") # Ethernet MAC etherbonecore = LiteEthUDPIPCore(self.etherbonephy, mac_address=etherbone_mac_address, ip_address=etherbone_ip_address, clk_freq=sys_clk_freq) self.submodules.etherbonecore = etherbonecore # Etherbone self.submodules.etherbone = LiteEthEtherbone( self.etherbonecore.udp, 1234, mode="master") self.add_wb_master(self.etherbone.wishbone.bus) # Analyzer --------------------------------------------------------------------------------- if with_analyzer: analyzer_signals = [ # FIXME: find interesting signals to probe self.cpu.ibus, self.cpu.dbus ] self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals, 512) self.add_csr("analyzer")
def __init__(self, *args, **kwargs): # Add the PHY in new clock domain, self.internal_cd = internal_cd phy = phy_cls(*args, csr_cdc=self.csr_cdc, **kwargs) # Remap clock domains in the PHY # Workaround: do this in two steps to avoid errors due to the fact that renaming is done # sequentially. Consider mapping {"sys": "sys2x", "sys2x": "sys4x"}, it would lead to: # sys2x = sys # sys4x = sys2x # resulting in all sync operations in sys4x domain. mapping = [tuple(i) for i in clock_mapping.items()] map_tmp = { clk_from: f"tmp{i}" for i, (clk_from, clk_to) in enumerate(mapping) } map_final = { f"tmp{i}": clk_to for i, (clk_from, clk_to) in enumerate(mapping) } self.submodules.phy = ClockDomainsRenamer(map_final)( ClockDomainsRenamer(map_tmp)(phy)) # Copy some attributes of the PHY for attr in phy_attrs or []: setattr(self, attr, getattr(self.phy, attr)) # Insert DFI rate converter to self.submodules.dfi_converter = DFIRateConverter( phy.dfi, clkdiv="sys", clk=self.internal_cd, ratio=ratio, write_delay=phy.settings.write_latency % ratio, read_delay=phy.settings.read_latency % ratio, **converter_kwargs, ) self.dfi = self.dfi_converter.dfi # Generate new PhySettings converter_latency = self.dfi_converter.ser_latency + self.dfi_converter.des_latency self.settings = PhySettings( phytype=phy.settings.phytype, memtype=phy.settings.memtype, databits=phy.settings.databits, dfi_databits=len(self.dfi.p0.wrdata), nranks=phy.settings.nranks, nphases=len(self.dfi.phases), rdphase=phy.settings.rdphase, wrphase=phy.settings.wrphase, cl=phy.settings.cl, cwl=phy.settings.cwl, read_latency=phy.settings.read_latency // ratio + converter_latency, write_latency=phy.settings.write_latency // ratio, cmd_latency=phy.settings.cmd_latency, cmd_delay=phy.settings.cmd_delay, write_leveling=phy.settings.write_leveling, write_dq_dqs_training=phy.settings.write_dq_dqs_training, write_latency_calibration=phy.settings. write_latency_calibration, read_leveling=phy.settings.read_leveling, delays=phy.settings.delays, bitslips=phy.settings.bitslips, ) # Copy any non-default PhySettings (e.g. electrical settings) for attr, value in vars(self.phy.settings).items(): if not hasattr(self.settings, attr): setattr(self.settings, attr, value)
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 = 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_CLK=ClockSignal(), i_RST=ResetSignal(), i_EN_VTC=1, 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_CLK=ClockSignal(), i_RST=ResetSignal(), i_EN_VTC=1, 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_CLK=ClockSignal(), i_RST=ResetSignal(), i_EN_VTC=1, 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_CLK=ClockSignal(), i_RST=ResetSignal(), i_EN_VTC=1, 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=ResetSignal() | (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=ResetSignal() | (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_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=ResetSignal() | (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=ResetSignal() | (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, memtype="DDR3", sys_clk_freq=100e6, iodelay_clk_freq=200e6, cmd_latency=0): tck = 2 / (2 * 4 * sys_clk_freq) addressbits = len(pads.a) if memtype == "DDR4": addressbits += 3 # cas_n/ras_n/we_n multiplexed with address bankbits = len( pads.ba) if memtype == "DDR3" else len(pads.ba) + len(pads.bg) nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n) databits = len(pads.dq) nphases = 4 if hasattr(pads, "ten"): self.comb += pads.ten.eq(0) self._en_vtc = CSRStorage(reset=1) self._half_sys8x_taps = CSRStatus(9) self._wlevel_en = CSRStorage() self._wlevel_strobe = CSR() self._cdly_rst = CSR() self._cdly_inc = CSR() self._dly_sel = CSRStorage(databits // 8) self._rdly_dq_rst = CSR() self._rdly_dq_inc = CSR() self._rdly_dq_bitslip_rst = 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() # compute phy settings cl, cwl = get_cl_cw(memtype, tck) cwl = cwl + cmd_latency cl_sys_latency = get_sys_latency(nphases, cl) cwl_sys_latency = get_sys_latency(nphases, cwl) rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl) wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl) self.settings = PhySettings(memtype=memtype, databits=databits, dfi_databits=2 * databits, nranks=nranks, nphases=nphases, rdphase=rdphase, wrphase=wrphase, rdcmdphase=rdcmdphase, wrcmdphase=wrcmdphase, cl=cl, cwl=cwl - cmd_latency, read_latency=2 + cl_sys_latency + 1 + 3, write_latency=cwl_sys_latency) self.dfi = Interface(addressbits, bankbits, nranks, 2 * databits, nphases) if memtype == "DDR3": _dfi = self.dfi else: _dfi = Interface(addressbits, bankbits, nranks, 2 * databits, nphases) dfi_mux = DDR4DFIMux(self.dfi, _dfi) self.submodules += dfi_mux # # # # 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=iodelay_clk_freq / 1e6, 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._cdly_rst.re, i_CE=self._cdly_inc.re, 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 if memtype == "DDR3" else addressbits - 3): 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(_dfi.phases[0].address[i], _dfi.phases[0].address[i], _dfi.phases[1].address[i], _dfi.phases[1].address[i], _dfi.phases[2].address[i], _dfi.phases[2].address[i], _dfi.phases[3].address[i], _dfi.phases[3].address[i])), Instance("ODELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=iodelay_clk_freq / 1e6, 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._cdly_rst.re, i_CE=self._cdly_inc.re, i_ODATAIN=a_o_nodelay, o_DATAOUT=pads.a[i]) ] pads_ba = Signal(bankbits) if memtype == "DDR3": self.comb += pads.ba.eq(pads_ba) else: self.comb += pads.ba.eq(pads_ba[:len(pads.ba)]) self.comb += pads.bg.eq(pads_ba[len(pads.ba):]) 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(_dfi.phases[0].bank[i], _dfi.phases[0].bank[i], _dfi.phases[1].bank[i], _dfi.phases[1].bank[i], _dfi.phases[2].bank[i], _dfi.phases[2].bank[i], _dfi.phases[3].bank[i], _dfi.phases[3].bank[i])), Instance("ODELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=iodelay_clk_freq / 1e6, 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._cdly_rst.re, i_CE=self._cdly_inc.re, i_ODATAIN=ba_o_nodelay, o_DATAOUT=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") if hasattr(pads, "act_n"): controls.append("act_n") for name in controls: 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(_dfi.phases[0], name), getattr(_dfi.phases[0], name), getattr(_dfi.phases[1], name), getattr(_dfi.phases[1], name), getattr(_dfi.phases[2], name), getattr(_dfi.phases[2], name), getattr(_dfi.phases[3], name), getattr(_dfi.phases[3], name))), Instance("ODELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=iodelay_clk_freq / 1e6, 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._cdly_rst.re, i_CE=self._cdly_inc.re, 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(_dfi.phases[0].wrdata_mask[i], _dfi.phases[0].wrdata_mask[databits//8+i], _dfi.phases[1].wrdata_mask[i], _dfi.phases[1].wrdata_mask[databits//8+i], _dfi.phases[2].wrdata_mask[i], _dfi.phases[2].wrdata_mask[databits//8+i], _dfi.phases[3].wrdata_mask[i], _dfi.phases[3].wrdata_mask[databits//8+i]) ) self.specials += \ Instance("ODELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=iodelay_clk_freq/1e6, 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._half_sys8x_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=iodelay_clk_freq / 1e6, p_IS_CLK_INVERTED=0, p_IS_RST_INVERTED=0, p_DELAY_FORMAT="TIME", p_DELAY_TYPE="VARIABLE", p_DELAY_VALUE=int(tck * 1e12 / 4), 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._rdly_dq_bitslip_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(_dfi.phases[0].wrdata[i], _dfi.phases[0].wrdata[databits + i], _dfi.phases[1].wrdata[i], _dfi.phases[1].wrdata[databits + i], _dfi.phases[2].wrdata[i], _dfi.phases[2].wrdata[databits + i], _dfi.phases[3].wrdata[i], _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_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=iodelay_clk_freq / 1e6, 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=iodelay_clk_freq / 1e6, 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 += [ _dfi.phases[0].rddata[i].eq(dq_bitslip.o[0]), _dfi.phases[1].rddata[i].eq(dq_bitslip.o[2]), _dfi.phases[2].rddata[i].eq(dq_bitslip.o[4]), _dfi.phases[3].rddata[i].eq(dq_bitslip.o[6]), _dfi.phases[0].rddata[databits + i].eq(dq_bitslip.o[1]), _dfi.phases[1].rddata[databits + i].eq(dq_bitslip.o[3]), _dfi.phases[2].rddata[databits + i].eq(dq_bitslip.o[5]), _dfi.phases[3].rddata[databits + i].eq(dq_bitslip.o[7]), ] # Flow control # # total read latency: # 2 cycles through OSERDESE2 # cl_sys_latency cycles CAS # 2 cycles through ISERDESE2 # 3 cycles through Bitslip rddata_en = _dfi.phases[self.settings.rdphase].rddata_en for i in range(self.settings.read_latency - 1): n_rddata_en = Signal() self.sync += n_rddata_en.eq(rddata_en) rddata_en = n_rddata_en for phase in _dfi.phases: phase_rddata_valid = Signal() self.sync += phase_rddata_valid.eq(rddata_en | self._wlevel_en.storage) self.comb += phase.rddata_valid.eq(phase_rddata_valid) oe = Signal() last_wrdata_en = Signal(cwl_sys_latency + 2) wrphase = _dfi.phases[self.settings.wrphase] self.sync += last_wrdata_en.eq( Cat(wrphase.wrdata_en, last_wrdata_en[:-1])) self.comb += oe.eq(last_wrdata_en[cwl_sys_latency - 1] | last_wrdata_en[cwl_sys_latency] | last_wrdata_en[cwl_sys_latency + 1]) 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, with_sdram=False, with_ethernet=False, with_etherbone=False, etherbone_mac_address=0x10e2d5000000, etherbone_ip_address="192.168.1.50", with_analyzer=False, **kwargs): platform = Platform() sys_clk_freq = int(1e9/platform.default_clk_period) SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq, integrated_rom_size=0x8000, ident="LiteX Simulation", ident_version=True, with_uart=False, **kwargs) # crg self.submodules.crg = CRG(platform.request(platform.default_clk_name)) # serial self.submodules.uart_phy = uart.RS232PHYModel(platform.request("serial")) self.submodules.uart = uart.UART(self.uart_phy) # sdram if with_sdram: sdram_module = IS42S16160(sys_clk_freq, "1:1") phy_settings = PhySettings( memtype="SDR", dfi_databits=1*16, nphases=1, rdphase=0, wrphase=0, rdcmdphase=0, wrcmdphase=0, cl=2, read_latency=4, write_latency=0 ) self.submodules.sdrphy = SDRAMPHYModel(sdram_module, phy_settings) self.register_sdram( self.sdrphy, sdram_module.geom_settings, sdram_module.timing_settings, controller_settings=ControllerSettings(with_refresh=False)) # reduce memtest size for simulation speedup self.add_constant("MEMTEST_DATA_SIZE", 8*1024) self.add_constant("MEMTEST_ADDR_SIZE", 8*1024) assert not (with_ethernet and with_etherbone) # FIXME: fix simulator with 2 ethernet interfaces # ethernet if with_ethernet: # eth phy self.submodules.ethphy = LiteEthPHYModel(self.platform.request("eth", 0)) # eth mac ethmac = LiteEthMAC(phy=self.ethphy, dw=32, interface="wishbone", endianness=self.cpu.endianness) if with_etherbone: ethmac = ClockDomainsRenamer({"eth_tx": "ethphy_eth_tx", "eth_rx": "ethphy_eth_rx"})(ethmac) self.submodules.ethmac = ethmac self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus) self.add_memory_region("ethmac", self.mem_map["ethmac"] | self.shadow_base, 0x2000) # etherbone if with_etherbone: # eth phy self.submodules.etherbonephy = LiteEthPHYModel(self.platform.request("eth", 0)) # FIXME # eth core etherbonecore = LiteEthUDPIPCore(self.etherbonephy, etherbone_mac_address, convert_ip(etherbone_ip_address), sys_clk_freq) if with_ethernet: etherbonecore = ClockDomainsRenamer({"eth_tx": "etherbonephy_eth_tx", "eth_rx": "etherbonephy_eth_rx"})(etherbonecore) self.submodules.etherbonecore = etherbonecore # etherbone self.submodules.etherbone = LiteEthEtherbone(self.etherbonecore.udp, 1234, mode="master") self.add_wb_master(self.etherbone.wishbone.bus) # analyzer if with_analyzer: analyzer_signals = [ # FIXME: find interesting signals to probe self.cpu.ibus, self.cpu.dbus ] self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals, 512)
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) nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n) databits = len(pads.dq) nphases = 2 if memtype == "DDR3": self.settings = PhySettings(memtype="DDR3", databits=databits, dfi_databits=2 * databits, nranks=nranks, nphases=nphases, rdphase=0, wrphase=1, rdcmdphase=1, wrcmdphase=0, cl=5, cwl=6, read_latency=6, write_latency=2) else: self.settings = PhySettings(memtype=memtype, databits=databits, dfi_databits=2 * databits, nranks=nranks, nphases=nphases, rdphase=0, wrphase=1, rdcmdphase=1, wrcmdphase=0, cl=3, read_latency=5, write_latency=0) self.dfi = Interface(addressbits, bankbits, nranks, 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, nranks=nranks)) 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) if memtype == "DDR3": r_dfi_wrdata_en = Signal(max(self.settings.cwl, self.settings.cl)) else: r_dfi_wrdata_en = Signal(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._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.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] ) for name in "ras_n", "cas_n", "we_n", "cs_n", "cke", "odt", "reset_n": 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) 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("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=dm_o_nodelay, 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] ) self.specials += \ Instance("ODELAYE2", p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA", p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0, p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=0, i_C=ClockSignal(), i_LD=self._dly_sel.storage[i] & self._wdly_dq_rst.re, i_CE=self._dly_sel.storage[i] & self._wdly_dq_inc.re, i_LDPIPEEN=0, i_INC=1, o_ODATAIN=dm_o_nodelay, o_DATAOUT=pads.dm[i] ) dqs_nodelay = Signal() dqs_delayed = 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_OFB=dqs_nodelay, o_TQ=dqs_t, i_OCE=1, i_TCE=1, i_RST=ResetSignal(), i_CLK=ClockSignal("sys4x"), 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("ODELAYE2", p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA", p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0, p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=6, i_C=ClockSignal(), i_LD=self._dly_sel.storage[i] & self._wdly_dqs_rst.re, i_CE=self._dly_sel.storage[i] & self._wdly_dqs_inc.re, i_LDPIPEEN=0, i_INC=1, o_ODATAIN=dqs_nodelay, o_DATAOUT=dqs_delayed), Instance("OBUFTDS", i_I=dqs_delayed, 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_nodelay = Signal() dq_o_delayed = 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_nodelay, 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._wdly_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( "ODELAYE2", p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA", p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0, p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=0, i_C=ClockSignal(), i_LD=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_LDPIPEEN=0, i_INC=1, o_ODATAIN=dq_o_nodelay, o_DATAOUT=dq_o_delayed), 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_delayed, 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 | 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, 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) nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n) databits = len(pads.dq) nphases = 4 self.settings = PhySettings(memtype="DDR3", dfi_databits=2 * databits, nranks=nranks, 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, nranks, 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_omit = set(["rddata", "rddata_valid", "wrdata_en"]) self.comb += [ If( ~phase_sel, self.dfi.phases[0].connect(half_rate_phy.dfi.phases[0], omit=dfi_omit), self.dfi.phases[1].connect(half_rate_phy.dfi.phases[1], omit=dfi_omit), ).Else( self.dfi.phases[2].connect(half_rate_phy.dfi.phases[0], omit=dfi_omit), self.dfi.phases[3].connect(half_rate_phy.dfi.phases[1], omit=dfi_omit), ), ] 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, sys_clk_freq=100e6): memtype = "DDR3" tck = 2 / (2 * 2 * sys_clk_freq) addressbits = len(pads.a) bankbits = len(pads.ba) nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n) databits = len(pads.dq) nphases = 2 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_rst = 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() # compute phy settings cl, cwl = get_cl_cw(memtype, tck) cl_sys_latency = get_sys_latency(nphases, cl) cwl_sys_latency = get_sys_latency(nphases, cwl) rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl) wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl) self.settings = PhySettings( memtype=memtype, dfi_databits=4 * databits, nranks=nranks, nphases=nphases, rdphase=rdphase, wrphase=wrphase, rdcmdphase=rdcmdphase, wrcmdphase=wrcmdphase, cl=cl, cwl=cwl, read_latency=2 + cl_sys_latency + 2 + log2_int(4 // nphases) + 3, # FIXME write_latency=cwl_sys_latency) self.dfi = Interface(addressbits, bankbits, nranks, 4 * databits, 4) # # # bl8_sel = Signal() # Clock for i in range(len(pads.clk_p)): sd_clk_se = Signal() self.specials += [ Instance("ODDRX2F", i_D0=0, i_D1=1, i_D2=0, i_D3=1, i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), i_RST=ResetSignal(), o_Q=pads.clk_p[i]), ] # Addresses and commands for i in range(addressbits): self.specials += \ Instance("ODDRX2F", i_D0=self.dfi.phases[0].address[i], i_D1=self.dfi.phases[0].address[i], i_D2=self.dfi.phases[1].address[i], i_D3=self.dfi.phases[1].address[i], i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), i_RST=ResetSignal(), o_Q=pads.a[i] ) for i in range(bankbits): self.specials += \ Instance("ODDRX2F", i_D0=self.dfi.phases[0].bank[i], i_D1=self.dfi.phases[0].bank[i], i_D2=self.dfi.phases[1].bank[i], i_D3=self.dfi.phases[1].bank[i], i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), i_RST=ResetSignal(), 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", i_D0=getattr(self.dfi.phases[0], name)[i], i_D1=getattr(self.dfi.phases[0], name)[i], i_D2=getattr(self.dfi.phases[1], name)[i], i_D3=getattr(self.dfi.phases[1], name)[i], i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), i_RST=ResetSignal(), o_Q=getattr(pads, name)[i] ) # DQSBUFM dqsr90 = Signal() dqsw270 = Signal() dqsw = Signal() rdpntr = Signal(3) wrpntr = Signal(3) self.specials += Instance( "DQSBUFM", i_DDRDEL=0b0, i_PAUSE=0b0, i_DQSI=pads.dqs_p[0], i_READ0=0b0, i_READ1=0b0, i_READCLKSEL0=0b0, i_READCLKSEL1=0b0, i_READCLKSEL2=0b0, i_DYNDELAY0=0b0, i_DYNDELAY1=0b0, i_DYNDELAY2=0b0, i_DYNDELAY3=0b0, i_DYNDELAY4=0b0, i_DYNDELAY5=0b0, i_DYNDELAY6=0b0, i_DYNDELAY7=0b0, i_RDLOADN=0, i_RDMOVE=0, i_RDDIRECTION=0, i_WRLOADN=0, i_WRMOVE=0, i_WRDIRECTION=0, #o_RDCFLAG=, #o_WRCFLAG=, #o_DATAVALID=, #o_BURSTDET=, o_DQSR90=dqsr90, o_RDPNTR0=rdpntr[0], o_RDPNTR1=rdpntr[1], o_RDPNTR2=rdpntr[2], o_WRPNTR0=wrpntr[0], o_WRPNTR1=wrpntr[1], o_WRPNTR2=wrpntr[2], i_SCLK=ClockSignal("sys"), i_ECLK=ClockSignal("sys2x"), o_DQSW270=dqsw270, o_DQSW=dqsw) # DQS and DM oe_dqs = Signal() dqs_preamble = Signal() dqs_postamble = Signal() dqs_serdes_pattern = Signal(8, reset=0b01010101) self.comb += \ If(self._wlevel_en.storage, If(self._wlevel_strobe.re, dqs_serdes_pattern.eq(0b00000001) ).Else( dqs_serdes_pattern.eq(0b00000000) ) ).Elif(dqs_preamble | dqs_postamble, dqs_serdes_pattern.eq(0b0000000) ).Else( dqs_serdes_pattern.eq(0b01010101) ) for i in range(databits // 8): dm_o_nodelay = Signal() dm_data = Signal(8) dm_data_d = Signal(8) dm_data_muxed = Signal(4) self.comb += dm_data.eq( Cat(self.dfi.phases[0].wrdata_mask[0 * databits // 8 + i], self.dfi.phases[0].wrdata_mask[1 * databits // 8 + i], self.dfi.phases[0].wrdata_mask[2 * databits // 8 + i], self.dfi.phases[0].wrdata_mask[3 * databits // 8 + i], self.dfi.phases[1].wrdata_mask[0 * databits // 8 + i], self.dfi.phases[1].wrdata_mask[1 * databits // 8 + i], self.dfi.phases[1].wrdata_mask[2 * databits // 8 + i], self.dfi.phases[1].wrdata_mask[3 * databits // 8 + i]), ) self.sync += dm_data_d.eq(dm_data) self.comb += \ If(bl8_sel, dm_data_muxed.eq(dm_data_d[4:]) ).Else( dm_data_muxed.eq(dm_data[:4]) ) self.specials += \ Instance("ODDRX2DQA", i_D0=dm_data_muxed[0], i_D1=dm_data_muxed[1], i_D2=dm_data_muxed[2], i_D3=dm_data_muxed[3], i_RST=ResetSignal(), i_DQSW270=dqsw270, i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), o_Q=dm_o_nodelay ) self.specials += \ Instance("DELAYF", i_A=dm_o_nodelay, i_LOADN=self._dly_sel.storage[i] & self._wdly_dq_rst.re, i_MOVE=self._dly_sel.storage[i] & self._wdly_dq_inc.re, i_DIRECTION=0, o_Z=pads.dm[i], #o_CFLAG=, ) dqs_nodelay = Signal() dqs_delayed = Signal() dqs_oe = Signal() self.specials += \ Instance("ODDRX2DQSB", i_D0=dqs_serdes_pattern[0], i_D1=dqs_serdes_pattern[1], i_D2=dqs_serdes_pattern[2], i_D3=dqs_serdes_pattern[3], i_RST=ResetSignal(), i_DQSW=dqsw, i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), o_Q=dqs_nodelay ) self.specials += \ Instance("DELAYF", i_A=dqs_nodelay, i_LOADN=self._dly_sel.storage[i] & self._wdly_dqs_rst.re, i_MOVE=self._dly_sel.storage[i] & self._wdly_dqs_inc.re, i_DIRECTION=0, o_Z=dqs_delayed, #o_CFLAG=, ) self.specials += \ Instance("TSHX2DQSA", i_T0=oe_dqs, i_T1=oe_dqs, i_SCLK=ClockSignal(), i_ECLK=ClockSignal("sys2x"), i_DQSW=dqsw, i_RST=ResetSignal(), o_Q=dqs_oe, ) self.specials += Tristate(pads.dqs_p[i], dqs_delayed, dqs_oe) # 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_oe = Signal() dq_data = Signal(8) dq_data_d = Signal(8) dq_data_muxed = Signal(4) self.comb += dq_data.eq( Cat(self.dfi.phases[0].wrdata[0 * databits + i], self.dfi.phases[0].wrdata[1 * databits + i], self.dfi.phases[0].wrdata[2 * databits + i], self.dfi.phases[0].wrdata[3 * databits + i], self.dfi.phases[1].wrdata[0 * databits + i], self.dfi.phases[1].wrdata[1 * databits + i], self.dfi.phases[1].wrdata[2 * databits + i], self.dfi.phases[1].wrdata[3 * databits + i])) self.sync += dq_data_d.eq(dq_data) self.comb += \ If(bl8_sel, dq_data_muxed.eq(dq_data_d[4:]) ).Else( dq_data_muxed.eq(dq_data[:4]) ) self.specials += \ Instance("ODDRX2DQA", i_D0=dq_data_muxed[0], i_D1=dq_data_muxed[1], i_D2=dq_data_muxed[2], i_D3=dq_data_muxed[3], i_RST=ResetSignal(), i_DQSW270=dqsw270, i_ECLK=ClockSignal("sys2x"), i_SCLK=ClockSignal(), o_Q=dq_o_nodelay ) self.specials += \ Instance("DELAYF", i_A=dq_o_nodelay, i_LOADN=self._dly_sel.storage[i//8] & self._wdly_dq_rst.re, i_MOVE=self._dly_sel.storage[i//8] & self._wdly_dq_inc.re, i_DIRECTION=0, o_Z=dq_o_delayed, #o_CFLAG=, ) dq_i_data = Signal(8) dq_i_data_d = Signal(8) self.specials += \ Instance("IDDRX2DQA", i_D=dq_i_delayed, i_RST=ResetSignal(), i_DQSR90=dqsr90, i_SCLK=ClockSignal(), i_ECLK=ClockSignal("sys2x"), i_RDPNTR0=rdpntr[0], i_RDPNTR1=rdpntr[1], i_RDPNTR2=rdpntr[2], i_WRPNTR0=wrpntr[0], i_WRPNTR1=wrpntr[1], i_WRPNTR2=wrpntr[2], o_Q0=dq_i_data[0], o_Q1=dq_i_data[1], o_Q2=dq_i_data[2], o_Q3=dq_i_data[3], ) dq_bitslip = BitSlip(4) self.comb += dq_bitslip.i.eq(dq_i_data) self.sync += \ If(self._dly_sel.storage[i//8], If(self._rdly_dq_bitslip_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.sync += dq_i_data_d.eq(dq_i_data) self.comb += [ self.dfi.phases[0].rddata[i].eq(dq_bitslip.o[0]), self.dfi.phases[0].rddata[databits + i].eq(dq_bitslip.o[1]), self.dfi.phases[1].rddata[i].eq(dq_bitslip.o[2]), self.dfi.phases[1].rddata[databits + i].eq(dq_bitslip.o[3]) ] #self.specials += \ # Instance("DELAYF", # i_A=dq_i_nodelay, # i_LOADN=self._dly_sel.storage[i//8] & self._rdly_dq_rst.re, # i_MOVE=self._dly_sel.storage[i//8] & self._wdly_dq_inc.re, # i_DIRECTION=0, # o_Z=dq_i_delayed, # #o_CFLAG=, # ) self.specials += \ Instance("TSHX2DQA", i_T0=oe_dq, i_T1=oe_dq, i_SCLK=ClockSignal(), i_ECLK=ClockSignal("sys2x"), i_DQSW270=dqsw270, i_RST=ResetSignal(), o_Q=dq_oe, ) self.specials += Tristate(pads.dq[i], dq_o_delayed, dq_oe, dq_i_delayed) # Flow control # # total read latency: # N cycles through ODDRX2DQA FIXME # cl_sys_latency cycles CAS # M cycles through IDDRX2DQA FIXME rddata_en = self.dfi.phases[self.settings.rdphase].rddata_en for i in range(self.settings.read_latency - 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(cwl_sys_latency + 3) wrphase = self.dfi.phases[self.settings.wrphase] self.sync += last_wrdata_en.eq( Cat(wrphase.wrdata_en, last_wrdata_en[:-1])) self.comb += oe.eq(last_wrdata_en[cwl_sys_latency - 1] | last_wrdata_en[cwl_sys_latency] | last_wrdata_en[cwl_sys_latency + 1] | last_wrdata_en[cwl_sys_latency + 2]) self.sync += \ If(self._wlevel_en.storage, oe_dqs.eq(1), oe_dq.eq(0) ).Else( oe_dqs.eq(oe), oe_dq.eq(oe) ) self.sync += bl8_sel.eq(last_wrdata_en[cwl_sys_latency - 1])