Example #1
0
    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)
Example #2
0
    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])
Example #3
0
    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)
Example #4
0
    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)
Example #5
0
    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)
Example #6
0
    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)
Example #7
0
    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]),
        ]
Example #8
0
    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]))
Example #9
0
    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")
Example #10
0
        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)
Example #11
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 = 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)
            )
Example #12
0
    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)
            )
Example #13
0
    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]),
            ]
Example #15
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)
        ]
Example #17
0
    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])