Пример #1
0
    def __init__(self, width, idomain, odomain, timeout=128):
        self.i = Signal(width)
        self.o = Signal(width, reset_less=True)

        if width == 1:
            self.specials += MultiReg(self.i, self.o, odomain)
        else:
            sync_i = getattr(self.sync, idomain)
            sync_o = getattr(self.sync, odomain)

            starter = Signal(reset=1)
            sync_i += starter.eq(0)
            self.submodules._ping = PulseSynchronizer(idomain, odomain)
            self.submodules._pong = PulseSynchronizer(odomain, idomain)
            self.submodules._timeout = ClockDomainsRenamer(idomain)(
                WaitTimer(timeout))
            self.comb += [
                self._timeout.wait.eq(~self._ping.i),
                self._ping.i.eq(starter | self._pong.o | self._timeout.done),
                self._pong.i.eq(self._ping.i)
            ]

            ibuffer = Signal(width, reset_less=True)
            obuffer = Signal(width)  # registered reset_less by MultiReg
            sync_i += If(self._pong.o, ibuffer.eq(self.i))
            ibuffer.attr.add("no_retiming")
            self.specials += MultiReg(ibuffer, obuffer, odomain)
            sync_o += If(self._ping.o, self.o.eq(obuffer))
Пример #2
0
    def __init__(self, width, idomain, odomain, timeout=128):
        self.i = Signal(width)
        self.o = Signal(width)

        if width == 1:
            self.specials += MultiReg(self.i, self.o, odomain)
        else:
            sync_i = getattr(self.sync, idomain)
            sync_o = getattr(self.sync, odomain)

            starter = Signal(reset=1)
            sync_i += starter.eq(0)
            self.submodules._ping = PulseSynchronizer(idomain, odomain)
            self.submodules._pong = PulseSynchronizer(odomain, idomain)
            self.submodules._timeout = WaitTimer(timeout)
            self.comb += [
                self._timeout.wait.eq(~self._ping.i),
                self._ping.i.eq(starter | self._pong.o | self._timeout.done),
                self._pong.i.eq(self._ping.i)
            ]

            ibuffer = Signal(width)
            obuffer = Signal(width)
            sync_i += If(self._pong.o, ibuffer.eq(self.i))
            self.specials += MultiReg(ibuffer, obuffer, odomain)
            sync_o += If(self._ping.o, self.o.eq(obuffer))
Пример #3
0
    def __init__(self, clock_pads, pads, with_hw_init_reset):
        self._reset = CSRStorage()

        # # #

        self.clock_domains.cd_eth_rx = ClockDomain()
        self.clock_domains.cd_eth_tx = ClockDomain()

        # RX
        dcm_reset = Signal()
        dcm_locked = Signal()

        timer = WaitTimer(1024)
        fsm = FSM(reset_state="DCM_RESET")
        self.submodules += timer, fsm

        fsm.act("DCM_RESET", dcm_reset.eq(1), timer.wait.eq(1),
                If(timer.done, timer.wait.eq(0), NextState("DCM_WAIT")))
        fsm.act("DCM_WAIT", timer.wait.eq(1),
                If(timer.done, NextState("DCM_CHECK_LOCK")))
        fsm.act("DCM_CHECK_LOCK", If(~dcm_locked, NextState("DCM_RESET")))

        clk90_rx = Signal()
        clk0_rx = Signal()
        clk0_rx_bufg = Signal()
        self.specials += Instance("DCM",
                                  i_CLKIN=clock_pads.rx,
                                  i_CLKFB=clk0_rx_bufg,
                                  o_CLK0=clk0_rx,
                                  o_CLK90=clk90_rx,
                                  o_LOCKED=dcm_locked,
                                  i_PSEN=0,
                                  i_PSCLK=0,
                                  i_PSINCDEC=0,
                                  i_RST=dcm_reset)

        self.specials += Instance("BUFG", i_I=clk0_rx, o_O=clk0_rx_bufg)
        self.specials += Instance("BUFG", i_I=clk90_rx, o_O=self.cd_eth_rx.clk)

        # TX
        self.specials += DDROutput(1, 0, clock_pads.tx, ClockSignal("eth_tx"))
        self.specials += Instance("BUFG",
                                  i_I=self.cd_eth_rx.clk,
                                  o_O=self.cd_eth_tx.clk)

        # Reset
        reset = Signal()
        if with_hw_init_reset:
            self.submodules.hw_reset = LiteEthPHYHWReset()
            self.comb += reset.eq(self._reset.storage | self.hw_reset.reset)
        else:
            self.comb += reset.eq(self._reset.storage)

        self.comb += pads.rst_n.eq(~reset)
        self.specials += [
            AsyncResetSynchronizer(self.cd_eth_tx, reset),
            AsyncResetSynchronizer(self.cd_eth_rx, reset),
        ]
Пример #4
0
    def __init__(self, clk_freq, timeout=10):
        self.sink = sink = stream.Endpoint(phy_description(32))
        self.source = source = stream.Endpoint(user_description(32))

        # # #

        # Packet description
        #   - preamble : 4 bytes
        #   - length   : 4 bytes
        #   - payload

        fsm = FSM(reset_state="IDLE")
        self.submodules += fsm

        self.submodules.timer = WaitTimer(clk_freq*timeout)
        self.comb += self.timer.wait.eq(~fsm.ongoing("IDLE"))

        fsm.act("IDLE",
            sink.ready.eq(1),
            If(sink.valid & (sink.data == 0x5aa55aa5),
                   NextState("RECEIVE_LENGTH")
            )
        )
        fsm.act("RECEIVE_LENGTH",
            sink.ready.eq(1),
            If(sink.valid,
                NextValue(source.length, sink.data),
                NextState("COPY")
            )
        )
        last = Signal()
        cnt = Signal(32)
        fsm.act("COPY",
            source.valid.eq(sink.valid),
            source.last.eq(last),
            source.data.eq(sink.data),
            sink.ready.eq(source.ready),
            If((source.valid & source.ready & last) | self.timer.done,
                NextState("IDLE")
            )
        )
        self.sync += \
            If(fsm.ongoing("IDLE"),
                cnt.eq(0)
            ).Elif(source.valid & source.ready,
                cnt.eq(cnt + 1)
            )
        self.comb += last.eq(cnt == source.length[2:] - 1)
Пример #5
0
    def __init__(self):
        self.sink = sink = stream.Endpoint(phy_description(32))

        # # #

        self.submodules.timer = WaitTimer(256 * 16)

        charisk_match = sink.charisk == 0b0001
        data_match = sink.data == primitives["ALIGN"]

        self.comb += \
            If(sink.valid &
              (sink.charisk == 0b0001) &
              (sink.data == primitives["ALIGN"]),
                self.timer.wait.eq(0)
            ).Else(
                self.timer.wait.eq(1),
            )
Пример #6
0
    def __init__(self, settings):
        # 1st command 1 cycle after assertion of ready
        self.cmd = cmd = stream.Endpoint(
            cmd_request_rw_layout(settings.geom.addressbits,
                                  settings.geom.bankbits))

        # # #

        # Refresh sequence generator:
        # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done
        seq_start = Signal()
        seq_done = Signal()
        self.sync += [
            cmd.a.eq(2**10),
            cmd.ba.eq(0),
            cmd.cas.eq(0),
            cmd.ras.eq(0),
            cmd.we.eq(0),
            seq_done.eq(0)
        ]
        self.sync += timeline(seq_start, [
            (1, [cmd.ras.eq(1), cmd.we.eq(1)]),
            (1 + settings.timing.tRP, [cmd.cas.eq(1),
                                       cmd.ras.eq(1)]),
            (1 + settings.timing.tRP + settings.timing.tRFC, [seq_done.eq(1)])
        ])

        # Periodic refresh counter
        self.submodules.timer = WaitTimer(settings.timing.tREFI)
        self.comb += self.timer.wait.eq(settings.with_refresh
                                        & ~self.timer.done)

        # Control FSM
        self.submodules.fsm = fsm = FSM()
        fsm.act("IDLE", If(self.timer.done, NextState("WAIT_GRANT")))
        fsm.act("WAIT_GRANT", cmd.valid.eq(1),
                If(cmd.ready, seq_start.eq(1), NextState("WAIT_SEQ")))
        fsm.act(
            "WAIT_SEQ",
            If(seq_done, cmd.last.eq(1),
               NextState("IDLE")).Else(cmd.valid.eq(1)))
Пример #7
0
    def __init__(self, platform, clk_freq):
        switches = Signal(1)
        leds = Signal(2)

        self.reset = Signal()

        # # #

        self.submodules.switches = GPIOIn(switches)
        self.submodules.leds = GPIOOut(leds)
        self.comb += [
            switches[0].eq(~platform.request("pwrsw")),
            platform.request("hdled").eq(~leds[0]),
            platform.request("pwled").eq(~leds[1]),
        ]

        # generate a reset when power switch is pressed for 1 second
        self.submodules.reset_timer = WaitTimer(clk_freq)
        self.comb += [
            self.reset_timer.wait.eq(switches[0]),
            self.reset.eq(self.reset_timer.done)
        ]
Пример #8
0
    def __init__(self, clock_pads_or_refclk, pads, gtx, revision, clk_freq):
        self.tx_reset = Signal()
        self.rx_reset = Signal()
        self.ready = Signal()
        self.cplllock = Signal()

        self.clock_domains.cd_sata_tx = ClockDomain()
        self.clock_domains.cd_sata_rx = ClockDomain()

        # CPLL
        #   (sata_gen3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps
        #   (sata_gen2 & sata_gen1) VCO still @ 3 GHz, Line rate is
        #   decreased with output dividers.
        if isinstance(clock_pads_or_refclk, Signal):
            self.refclk = clock_pads_or_refclk
        else:
            self.refclk = Signal()
            clock_pads = clock_pads_or_refclk
            self.specials += Instance("IBUFDS_GTE2",
                i_CEB=0,
                i_I=clock_pads.refclk_p,
                i_IB=clock_pads.refclk_n,
                o_O=self.refclk
            )

        self.comb += gtx.gtrefclk0.eq(self.refclk)

        # TX clocking
        #   (sata_gen3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits) /  150MHz (32-bits)
        #   (sata_gen2) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 150MHz (16-bits) /   75MHz (32-bits)
        #   (sata_gen1) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 75MHz  (16-bits) / 37.5MHz (32-bits)
        mmcm_mult = 8.0
        mmcm_div_config = {
            "sata_gen1":   16.0*gtx.dw/16,
            "sata_gen2":    8.0*gtx.dw/16,
            "sata_gen3":    4.0*gtx.dw/16
        }
        mmcm_div = mmcm_div_config[revision]
        use_mmcm = mmcm_mult/mmcm_div != 1.0

        if use_mmcm:
            mmcm_reset = Signal()
            mmcm_locked_async = Signal()
            mmcm_locked = Signal()
            mmcm_fb = Signal()
            mmcm_clk_i = Signal()
            mmcm_clk0_o = Signal()
            self.specials += [
                Instance("BUFG", i_I=gtx.txoutclk, o_O=mmcm_clk_i),
                Instance("MMCME2_ADV",
                     p_BANDWIDTH="HIGH", p_COMPENSATION="ZHOLD", i_RST=mmcm_reset, o_LOCKED=mmcm_locked_async,

                     # DRP
                     i_DCLK=0, i_DEN=0, i_DWE=0, #o_DRDY=,
                     i_DADDR=0, i_DI=0, #o_DO=,

                     # VCO
                     p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=6.66667,
                     p_CLKFBOUT_MULT_F=mmcm_mult, p_CLKFBOUT_PHASE=0.000, p_DIVCLK_DIVIDE=1,
                     i_CLKIN1=mmcm_clk_i, i_CLKFBIN=mmcm_fb, o_CLKFBOUT=mmcm_fb,

                     # CLK0
                     p_CLKOUT0_DIVIDE_F=mmcm_div, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk0_o,
                ),
                Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_sata_tx.clk),
                MultiReg(mmcm_locked_async, mmcm_locked, "sys"),
            ]
        else:
            mmcm_locked = Signal(reset=1)
            mmcm_reset = Signal()
            self.specials += Instance("BUFG", i_I=gtx.txoutclk, o_O=self.cd_sata_tx.clk)

        self.comb += [
            gtx.txusrclk.eq(self.cd_sata_tx.clk),
            gtx.txusrclk2.eq(self.cd_sata_tx.clk)
        ]

        # RX clocking
        #   (sata_gen3) sata_rx recovered clk @  @ 300MHz (16-bits) /  150MHz (32-bits) from GTX RXOUTCLK
        #   (sata_gen2) sata_rx recovered clk @  @ 150MHz (16-bits) /   75MHz (32-bits) from GTX RXOUTCLK
        #   (sata_gen1) sata_rx recovered clk @  @ 75MHz  (16-bits) / 37.5MHz (32-bits) from GTX RXOUTCLK
        self.specials += [
            Instance("BUFG", i_I=gtx.rxoutclk, o_O=self.cd_sata_rx.clk),
        ]
        self.comb += [
            gtx.rxusrclk.eq(self.cd_sata_rx.clk),
            gtx.rxusrclk2.eq(self.cd_sata_rx.clk)
        ]

        # Configuration Reset
        #   After configuration, GTX's resets have to stay low for at least 500ns
        #   See AR43482
        startup_cycles = ceil(500*clk_freq/1000000000)
        startup_timer = WaitTimer(startup_cycles)
        self.submodules += startup_timer
        self.comb += startup_timer.wait.eq(~(self.tx_reset | self.rx_reset))

        # TX Startup FSM
        self.tx_ready = Signal()
        self.tx_startup_fsm = tx_startup_fsm = ResetInserter()(FSM(reset_state="IDLE"))
        self.submodules += tx_startup_fsm

        txphaligndone = Signal(reset=1)
        txphaligndone_rising = Signal()
        self.sync += txphaligndone.eq(gtx.txphaligndone)
        self.comb += txphaligndone_rising.eq(gtx.txphaligndone & ~txphaligndone)

        # Wait 500ns of AR43482
        tx_startup_fsm.act("IDLE",
            If(startup_timer.done,
                NextState("RESET_ALL")
            )
        )
        # Reset CPLL, MMCM, GTX
        tx_startup_fsm.act("RESET_ALL",
            gtx.cpllreset.eq(1),
            mmcm_reset.eq(1),
            gtx.gttxreset.eq(1),
            If(~self.cplllock,
               NextState("RELEASE_CPLL")
            )
        )
        # Release CPLL reset and wait for lock
        tx_startup_fsm.act("RELEASE_CPLL",
            mmcm_reset.eq(1),
            gtx.gttxreset.eq(1),
            If(self.cplllock,
                NextState("RELEASE_MMCM")
            )
        )
        # Release MMCM reset and wait for lock
        tx_startup_fsm.act("RELEASE_MMCM",
            gtx.gttxreset.eq(1),
            If(mmcm_locked,
                NextState("RELEASE_GTX")
            )
        )
        # Release GTX reset and wait for GTX resetdone
        # (from UG476, GTX is reseted on falling edge
        # of gttxreset)
        tx_startup_fsm.act("RELEASE_GTX",
            gtx.txuserrdy.eq(1),
            If(gtx.txresetdone,
                NextState("ALIGN")
            )
        )
        # Start Delay alignment (Pulse)
        tx_startup_fsm.act("ALIGN",
            gtx.txuserrdy.eq(1),
            gtx.txdlyreset.eq(1),
            NextState("WAIT_ALIGN")
        )
        # Wait Delay alignment
        tx_startup_fsm.act("WAIT_ALIGN",
            gtx.txuserrdy.eq(1),
            If(gtx.txdlyresetdone,
                NextState("WAIT_FIRST_ALIGN_DONE")
            )
        )
        # Wait 2 rising edges of txphaligndone
        # (from UG476 in buffer bypass config)
        tx_startup_fsm.act("WAIT_FIRST_ALIGN_DONE",
            gtx.txuserrdy.eq(1),
            If(txphaligndone_rising,
               NextState("WAIT_SECOND_ALIGN_DONE")
            )
        )
        tx_startup_fsm.act("WAIT_SECOND_ALIGN_DONE",
            gtx.txuserrdy.eq(1),
            If(txphaligndone_rising,
               NextState("READY")
            )
        )
        tx_startup_fsm.act("READY",
            gtx.txuserrdy.eq(1),
            self.tx_ready.eq(1)
        )

        tx_ready_timer = WaitTimer(2*clk_freq//1000)
        self.submodules += tx_ready_timer
        self.comb += [
            tx_ready_timer.wait.eq(~self.tx_ready & ~tx_startup_fsm.reset),
            tx_startup_fsm.reset.eq(self.tx_reset | tx_ready_timer.done),
        ]


        # RX Startup FSM
        self.rx_ready = Signal()
        self.rx_startup_fsm = rx_startup_fsm = ResetInserter()(FSM(reset_state="IDLE"))
        self.submodules += rx_startup_fsm

        cdr_stable_timer = WaitTimer(1024)
        self.submodules += cdr_stable_timer

        rxphaligndone = Signal(reset=1)
        rxphaligndone_rising = Signal()
        self.sync += rxphaligndone.eq(gtx.rxphaligndone)
        self.comb += rxphaligndone_rising.eq(gtx.rxphaligndone & ~rxphaligndone)

        # Wait 500ns of AR43482
        rx_startup_fsm.act("IDLE",
            If(startup_timer.done,
                NextState("RESET_GTX")
            )
        )
        # Reset GTX
        rx_startup_fsm.act("RESET_GTX",
            gtx.gtrxreset.eq(1),
            If(~gtx.gttxreset,
               NextState("WAIT_CPLL")
            )
        )
        # Wait for CPLL lock
        rx_startup_fsm.act("WAIT_CPLL",
            gtx.gtrxreset.eq(1),
            If(self.cplllock,
                NextState("RELEASE_GTX")
            )
        )
        # Release GTX reset and wait for GTX resetdone
        # (from UG476, GTX is reseted on falling edge
        # of gttxreset)
        rx_startup_fsm.act("RELEASE_GTX",
            gtx.rxuserrdy.eq(1),
            cdr_stable_timer.wait.eq(1),
            If(gtx.rxresetdone &  cdr_stable_timer.done,
                NextState("ALIGN")
            )
        )
        # Start Delay alignment (Pulse)
        rx_startup_fsm.act("ALIGN",
            gtx.rxuserrdy.eq(1),
            gtx.rxdlyreset.eq(1),
            NextState("WAIT_ALIGN")
        )
        # Wait Delay alignment
        rx_startup_fsm.act("WAIT_ALIGN",
            gtx.rxuserrdy.eq(1),
            If(gtx.rxdlyresetdone,
                NextState("WAIT_FIRST_ALIGN_DONE")
            )
        )
        # Wait 2 rising edges of rxphaligndone
        # (from UG476 in buffer bypass config)
        rx_startup_fsm.act("WAIT_FIRST_ALIGN_DONE",
            gtx.rxuserrdy.eq(1),
            If(rxphaligndone_rising,
               NextState("WAIT_SECOND_ALIGN_DONE")
            )
        )
        rx_startup_fsm.act("WAIT_SECOND_ALIGN_DONE",
            gtx.rxuserrdy.eq(1),
            If(rxphaligndone_rising,
               NextState("READY")
            )
        )
        rx_startup_fsm.act("READY",
            gtx.rxuserrdy.eq(1),
            self.rx_ready.eq(1)
        )

        rx_ready_timer = WaitTimer(2*clk_freq//1000)
        self.submodules += rx_ready_timer
        self.comb += [
            rx_ready_timer.wait.eq(~self.rx_ready & ~rx_startup_fsm.reset),
            rx_startup_fsm.reset.eq(self.rx_reset | rx_ready_timer.done),
        ]

        # Ready
        self.comb += self.ready.eq(self.tx_ready & self.rx_ready)

        # Reset for SATA TX/RX clock domains
        self.specials += [
            AsyncResetSynchronizer(self.cd_sata_tx, ~(gtx.cplllock & mmcm_locked) | self.tx_reset),
            AsyncResetSynchronizer(self.cd_sata_rx, ~gtx.cplllock | self.rx_reset),
            MultiReg(gtx.cplllock, self.cplllock, "sys"),
        ]
Пример #9
0
    def __init__(self, phy_settings, geom_settings, timing_settings):
        if phy_settings.memtype in ["SDR"]:
            burst_length = phy_settings.nphases * 1  # command multiplication*SDR
        elif phy_settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
            burst_length = phy_settings.nphases * 2  # command multiplication*DDR
        burst_width = phy_settings.dfi_databits * phy_settings.nphases
        address_align = log2_int(burst_length)

        # # #

        self.dfi = dfi = dfibus.Interface(geom_settings.addressbits,
                                          geom_settings.bankbits,
                                          phy_settings.dfi_databits,
                                          phy_settings.nphases)

        self.bus = bus = wishbone.Interface(burst_width)

        rdphase = phy_settings.rdphase
        wrphase = phy_settings.wrphase

        precharge_all = Signal()
        activate = Signal()
        refresh = Signal()
        write = Signal()
        read = Signal()

        # Compute current column, bank and row from wishbone address
        slicer = _AddressSlicer(geom_settings.colbits, geom_settings.bankbits,
                                geom_settings.rowbits, address_align)

        # Manage banks
        bank_idle = Signal()
        bank_hit = Signal()

        banks = []
        for i in range(2**geom_settings.bankbits):
            bank = _Bank(geom_settings)
            self.comb += [
                bank.open.eq(activate),
                bank.reset.eq(precharge_all),
                bank.row.eq(slicer.row(bus.adr))
            ]
            banks.append(bank)
        self.submodules += banks

        cases = {}
        for i, bank in enumerate(banks):
            cases[i] = [bank.ce.eq(1)]
        self.comb += Case(slicer.bank(bus.adr), cases)

        self.comb += [
            bank_hit.eq(reduce(or_, [bank.hit & bank.ce for bank in banks])),
            bank_idle.eq(reduce(or_, [bank.idle & bank.ce for bank in banks])),
        ]

        # Timings
        write2precharge_timer = WaitTimer(2 + timing_settings.tWR - 1)
        self.submodules += write2precharge_timer
        self.comb += write2precharge_timer.wait.eq(~write)

        refresh_timer = WaitTimer(timing_settings.tREFI)
        self.submodules += refresh_timer
        self.comb += refresh_timer.wait.eq(~refresh)

        # Main FSM
        self.submodules.fsm = fsm = FSM()
        fsm.act(
            "IDLE",
            If(refresh_timer.done, NextState("PRECHARGE-ALL")).Elif(
                bus.stb & bus.cyc,
                If(bank_hit,
                   If(bus.we,
                      NextState("WRITE")).Else(NextState("READ"))).Elif(
                          ~bank_idle,
                          If(write2precharge_timer.done,
                             NextState("PRECHARGE"))).Else(
                                 NextState("ACTIVATE"))))
        fsm.act(
            "READ",
            read.eq(1),
            dfi.phases[rdphase].ras_n.eq(1),
            dfi.phases[rdphase].cas_n.eq(0),
            dfi.phases[rdphase].we_n.eq(1),
            dfi.phases[rdphase].rddata_en.eq(1),
            NextState("WAIT-READ-DONE"),
        )
        fsm.act(
            "WAIT-READ-DONE",
            If(dfi.phases[rdphase].rddata_valid, bus.ack.eq(1),
               NextState("IDLE")))
        fsm.act("WRITE", write.eq(1), dfi.phases[wrphase].ras_n.eq(1),
                dfi.phases[wrphase].cas_n.eq(0),
                dfi.phases[wrphase].we_n.eq(0),
                dfi.phases[wrphase].wrdata_en.eq(1),
                NextState("WRITE-LATENCY"))
        fsm.act("WRITE-ACK", bus.ack.eq(1), NextState("IDLE"))
        fsm.act("PRECHARGE-ALL", precharge_all.eq(1),
                dfi.phases[rdphase].ras_n.eq(0),
                dfi.phases[rdphase].cas_n.eq(1),
                dfi.phases[rdphase].we_n.eq(0), NextState("PRE-REFRESH"))
        fsm.act(
            "PRECHARGE",
            # do no reset bank since we are going to re-open it
            dfi.phases[0].ras_n.eq(0),
            dfi.phases[0].cas_n.eq(1),
            dfi.phases[0].we_n.eq(0),
            NextState("TRP"))
        fsm.act(
            "ACTIVATE",
            activate.eq(1),
            dfi.phases[0].ras_n.eq(0),
            dfi.phases[0].cas_n.eq(1),
            dfi.phases[0].we_n.eq(1),
            NextState("TRCD"),
        )
        fsm.act("REFRESH", refresh.eq(1), dfi.phases[rdphase].ras_n.eq(0),
                dfi.phases[rdphase].cas_n.eq(0),
                dfi.phases[rdphase].we_n.eq(1), NextState("POST-REFRESH"))
        fsm.delayed_enter("WRITE-LATENCY", "WRITE-ACK",
                          phy_settings.write_latency - 1)
        fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP - 1)
        fsm.delayed_enter("TRCD", "IDLE", timing_settings.tRCD - 1)
        fsm.delayed_enter("PRE-REFRESH", "REFRESH", timing_settings.tRP - 1)
        fsm.delayed_enter("POST-REFRESH", "IDLE", timing_settings.tRFC - 1)

        # DFI commands
        for phase in dfi.phases:
            if hasattr(phase, "reset_n"):
                self.comb += phase.reset_n.eq(1)
            if hasattr(phase, "odt"):
                self.comb += phase.odt.eq(1)
            self.comb += [
                phase.cke.eq(1),
                phase.cs_n.eq(0),
                phase.bank.eq(slicer.bank(bus.adr)),
                If(precharge_all, phase.address.eq(2**10)).Elif(
                    activate, phase.address.eq(slicer.row(bus.adr))).Elif(
                        write | read, phase.address.eq(slicer.col(bus.adr)))
            ]

        # DFI datapath
        self.comb += [
            bus.dat_r.eq(Cat(phase.rddata for phase in dfi.phases)),
            Cat(phase.wrdata for phase in dfi.phases).eq(bus.dat_w),
            Cat(phase.wrdata_mask for phase in dfi.phases).eq(~bus.sel),
        ]
Пример #10
0
    def __init__(self, phy, clk_freq):
        self.wishbone = wishbone.Interface()

        # # #

        byte_counter = Signal(3)
        byte_counter_reset = Signal()
        byte_counter_ce = Signal()
        self.sync += \
            If(byte_counter_reset,
                byte_counter.eq(0)
            ).Elif(byte_counter_ce,
                byte_counter.eq(byte_counter + 1)
            )

        word_counter = Signal(3)
        word_counter_reset = Signal()
        word_counter_ce = Signal()
        self.sync += \
            If(word_counter_reset,
                word_counter.eq(0)
            ).Elif(word_counter_ce,
                word_counter.eq(word_counter + 1)
            )

        cmd = Signal(8)
        cmd_ce = Signal()

        length = Signal(8)
        length_ce = Signal()

        address = Signal(32)
        address_ce = Signal()

        data = Signal(32)
        rx_data_ce = Signal()
        tx_data_ce = Signal()

        self.sync += [
            If(cmd_ce, cmd.eq(phy.source.data)),
            If(length_ce, length.eq(phy.source.data)),
            If(address_ce, address.eq(Cat(phy.source.data, address[0:24]))),
            If(rx_data_ce,
               data.eq(Cat(phy.source.data,
                           data[0:24]))).Elif(tx_data_ce,
                                              data.eq(self.wishbone.dat_r))
        ]

        fsm = ResetInserter()(FSM(reset_state="IDLE"))
        timer = WaitTimer(clk_freq // 10)
        self.submodules += fsm, timer
        self.comb += [fsm.reset.eq(timer.done), phy.source.ready.eq(1)]
        fsm.act(
            "IDLE",
            If(
                phy.source.valid, cmd_ce.eq(1),
                If((phy.source.data == self.cmds["write"]) |
                   (phy.source.data == self.cmds["read"]),
                   NextState("RECEIVE_LENGTH")), byte_counter_reset.eq(1),
                word_counter_reset.eq(1)))
        fsm.act(
            "RECEIVE_LENGTH",
            If(phy.source.valid, length_ce.eq(1),
               NextState("RECEIVE_ADDRESS")))
        fsm.act(
            "RECEIVE_ADDRESS",
            If(
                phy.source.valid, address_ce.eq(1), byte_counter_ce.eq(1),
                If(
                    byte_counter == 3,
                    If(cmd == self.cmds["write"],
                       NextState("RECEIVE_DATA")).Elif(
                           cmd == self.cmds["read"], NextState("READ_DATA")),
                    byte_counter_reset.eq(1),
                )))
        fsm.act(
            "RECEIVE_DATA",
            If(
                phy.source.valid, rx_data_ce.eq(1), byte_counter_ce.eq(1),
                If(byte_counter == 3, NextState("WRITE_DATA"),
                   byte_counter_reset.eq(1))))
        self.comb += [
            self.wishbone.adr.eq(address + word_counter),
            self.wishbone.dat_w.eq(data),
            self.wishbone.sel.eq(2**len(self.wishbone.sel) - 1)
        ]
        fsm.act(
            "WRITE_DATA", self.wishbone.stb.eq(1), self.wishbone.we.eq(1),
            self.wishbone.cyc.eq(1),
            If(
                self.wishbone.ack, word_counter_ce.eq(1),
                If(word_counter == (length - 1),
                   NextState("IDLE")).Else(NextState("RECEIVE_DATA"))))
        fsm.act(
            "READ_DATA", self.wishbone.stb.eq(1), self.wishbone.we.eq(0),
            self.wishbone.cyc.eq(1),
            If(self.wishbone.ack, tx_data_ce.eq(1), NextState("SEND_DATA")))
        self.comb += \
            chooser(data, byte_counter, phy.sink.data, n=4, reverse=True)
        fsm.act(
            "SEND_DATA", phy.sink.valid.eq(1),
            If(
                phy.sink.ready, byte_counter_ce.eq(1),
                If(
                    byte_counter == 3, word_counter_ce.eq(1),
                    If(word_counter == (length - 1),
                       NextState("IDLE")).Else(NextState("READ_DATA"),
                                               byte_counter_reset.eq(1)))))

        self.comb += timer.wait.eq(~fsm.ongoing("IDLE"))

        self.comb += phy.sink.last.eq((byte_counter == 3)
                                      & (word_counter == length - 1))

        if hasattr(phy.sink, "length"):
            self.comb += phy.sink.length.eq(4 * length)
Пример #11
0
    def __init__(self, clk_freq, timeout=10):
        self.sink = sink = stream.Endpoint(phy_description(8))
        self.source = source = stream.Endpoint(user_description(8))

        # # #

        # Packet description
        #   - preamble : 4 bytes
        #   - dst      : 1 byte
        #   - length   : 4 bytes
        #   - payload
        preamble = Array(Signal(8) for i in range(4))

        header = [
            # dst
            source.dst,
            # length
            source.length[24:32],
            source.length[16:24],
            source.length[8:16],
            source.length[0:8],
        ]

        header_pack = ResetInserter()(stream.Pack(phy_description(8),
                                                  len(header)))
        self.submodules += header_pack

        for i, byte in enumerate(header):
            chunk = getattr(header_pack.source.payload, "chunk" + str(i))
            self.comb += byte.eq(chunk.data)

        fsm = FSM(reset_state="IDLE")
        self.submodules += fsm

        self.comb += preamble[0].eq(sink.data)
        for i in range(1, 4):
            self.sync += If(sink.valid & sink.ready,
                            preamble[i].eq(preamble[i - 1]))
        fsm.act(
            "IDLE",
            sink.ready.eq(1),
            If((preamble[3] == 0x5A) & (preamble[2] == 0xA5) &
               (preamble[1] == 0x5A) & (preamble[0] == 0xA5) & sink.valid,
               NextState("RECEIVE_HEADER")),
            header_pack.source.ready.eq(1),
        )

        self.submodules.timer = WaitTimer(clk_freq * timeout)
        self.comb += self.timer.wait.eq(~fsm.ongoing("IDLE"))

        fsm.act(
            "RECEIVE_HEADER", header_pack.sink.valid.eq(sink.valid),
            header_pack.sink.payload.eq(sink.payload),
            If(self.timer.done, NextState("IDLE")).Elif(
                header_pack.source.valid,
                NextState("COPY")).Else(sink.ready.eq(1)))

        self.comb += header_pack.reset.eq(self.timer.done)

        last = Signal()
        cnt = Signal(32)

        fsm.act(
            "COPY", source.valid.eq(sink.valid), source.last.eq(last),
            source.data.eq(sink.data), sink.ready.eq(source.ready),
            If((source.valid & source.ready & last) | self.timer.done,
               NextState("IDLE")))

        self.sync += \
            If(fsm.ongoing("IDLE"),
                cnt.eq(0)
            ).Elif(source.valid & source.ready,
                cnt.eq(cnt + 1)
            )
        self.comb += last.eq(cnt == source.length - 1)
Пример #12
0
    def __init__(self, trx, crg, clk_freq):
        self.clk_freq = clk_freq
        self.ready = Signal()
        self.sink = sink = stream.Endpoint(phy_description(32))
        self.source = source = stream.Endpoint(phy_description(32))
        self.misalign = Signal()
        self.rx_idle = Signal()

        # # #

        self.comb += [
            source.valid.eq(1),
            sink.ready.eq(1)
        ]

        retry_timer = WaitTimer(self.us(10000))
        align_timer = WaitTimer(self.us(873))
        self.submodules += align_timer, retry_timer

        align_det = Signal()
        misalign_det = Signal()
        non_align_counter = Signal(4)
        non_align_counter_reset = Signal()
        non_align_counter_ce = Signal()
        self.sync += \
            If(non_align_counter_reset,
                non_align_counter.eq(0)
            ).Elif(non_align_counter_ce,
                non_align_counter.eq(non_align_counter + 1)
            )

        self.comb +=  [
            If(sink.valid,
                align_det.eq((self.sink.charisk == 0b0001) &
                             (self.sink.data == primitives["ALIGN"]))
            )
        ]

        self.fsm = fsm = ResetInserter()(FSM(reset_state="RESET"))
        self.submodules += fsm
        self.comb += fsm.reset.eq(retry_timer.done | align_timer.done)
        fsm.act("RESET",
            trx.tx_idle.eq(1),
            trx.rx_cdrhold.eq(1),
            crg.rx_reset.eq(1),
            crg.tx_reset.eq(1),
            NextState("AWAIT_CRG_RESET")
        )
        fsm.act("AWAIT_CRG_RESET",
            trx.tx_idle.eq(1),
            trx.rx_cdrhold.eq(1),
            non_align_counter_reset.eq(1),
            If(crg.ready,
                NextState("COMINIT")
            )
        )
        fsm.act("COMINIT",
            trx.tx_idle.eq(1),
            trx.rx_cdrhold.eq(1),
            trx.tx_cominit_stb.eq(1),
            If(trx.tx_cominit_ack & ~trx.rx_cominit_stb,
                NextState("AWAIT_COMINIT")
            )
        )
        fsm.act("AWAIT_COMINIT",
            trx.tx_idle.eq(1),
            trx.rx_cdrhold.eq(1),
            retry_timer.wait.eq(1),
            If(trx.rx_cominit_stb,
                NextState("AWAIT_NO_COMINIT")
            )
        )
        fsm.act("AWAIT_NO_COMINIT",
            trx.tx_idle.eq(1),
            trx.rx_cdrhold.eq(1),
            retry_timer.wait.eq(1),
            If(~trx.rx_cominit_stb,
                NextState("CALIBRATE")
            )
        )
        fsm.act("CALIBRATE",
            trx.tx_idle.eq(1),
            trx.rx_cdrhold.eq(1),
            NextState("COMWAKE"),
        )
        fsm.act("COMWAKE",
            trx.tx_idle.eq(1),
            trx.rx_cdrhold.eq(1),
            trx.tx_comwake_stb.eq(1),
            If(trx.tx_comwake_ack,
                NextState("AWAIT_COMWAKE")
            )
        )
        fsm.act("AWAIT_COMWAKE",
            trx.tx_idle.eq(1),
            trx.rx_cdrhold.eq(1),
            retry_timer.wait.eq(1),
            If(trx.rx_comwake_stb,
                NextState("AWAIT_NO_COMWAKE")
            )
        )
        fsm.act("AWAIT_NO_COMWAKE",
            trx.tx_idle.eq(1),
            trx.rx_cdrhold.eq(1),
            If(~trx.rx_comwake_stb,
                NextState("AWAIT_ALIGN")
            )
        )
        fsm.act("AWAIT_ALIGN",
            trx.rx_cdrhold.eq(1),
            source.data.eq(0x4A4A4A4A),  # D10.2
            source.charisk.eq(0b0000),
            align_timer.wait.eq(1),
            If(align_det & ~trx.rx_idle,
                crg.rx_reset.eq(1),
                NextState("SEND_ALIGN")
            )
        )
        fsm.act("SEND_ALIGN",
            align_timer.wait.eq(1),
            source.data.eq(primitives["ALIGN"]),
            source.charisk.eq(0b0001),
            If(sink.valid &
               (sink.charisk == 0b0001),
               If(sink.data[0:8] == 0x7C,
                   non_align_counter_ce.eq(1)
               ).Else(
                   non_align_counter_reset.eq(1)
               )
            ),
            If(non_align_counter == 3,
                NextState("READY")
            )
        )

        # wait alignement stability for 5ms before declaring ctrl is ready,
        # reset the RX part of the transceiver when misalignment is detected.
        stability_timer = WaitTimer(5*clk_freq//1000)
        self.submodules += stability_timer

        fsm.act("READY",
            source.data.eq(primitives["SYNC"]),
            source.charisk.eq(0b0001),
            stability_timer.wait.eq(1),
            self.ready.eq(stability_timer.done),
            If(self.rx_idle,
                NextState("RESET"),
            ).Elif(self.misalign,
                crg.rx_reset.eq(1),
                NextState("RESET_RX")
            )
        )
        fsm.act("RESET_RX",
            If(crg.ready,
                NextState("READY")
            )
        )
Пример #13
0
    def __init__(self, sys_clk_freq, rx):
        self.done = Signal()
        self.restart = Signal()

        # GTX signals
        self.plllock = Signal()
        self.pllreset = Signal()
        self.gtXxreset = Signal()
        self.Xxresetdone = Signal()
        self.Xxdlysreset = Signal()
        self.Xxdlysresetdone = Signal()
        self.Xxphaligndone = Signal()
        self.Xxuserrdy = Signal()

        # # #

        # Double-latch transceiver asynch outputs
        plllock = Signal()
        Xxresetdone = Signal()
        Xxdlysresetdone = Signal()
        Xxphaligndone = Signal()
        self.specials += [
            MultiReg(self.plllock, plllock),
            MultiReg(self.Xxresetdone, Xxresetdone),
            MultiReg(self.Xxdlysresetdone, Xxdlysresetdone),
            MultiReg(self.Xxphaligndone, Xxphaligndone)
        ]

        # Deglitch FSM outputs driving transceiver asynch inputs
        gtXxreset = Signal()
        Xxdlysreset = Signal()
        Xxuserrdy = Signal()
        self.sync += [
            self.gtXxreset.eq(gtXxreset),
            self.Xxdlysreset.eq(Xxdlysreset),
            self.Xxuserrdy.eq(Xxuserrdy)
        ]

        # After configuration, transceiver resets have to stay low for
        # at least 500ns (see AR43482)
        startup_cycles = ceil(500 * sys_clk_freq / 1000000000)
        startup_timer = WaitTimer(startup_cycles)
        self.submodules += startup_timer

        startup_fsm = ResetInserter()(FSM(reset_state="RESET_ALL"))
        self.submodules += startup_fsm

        ready_timer = WaitTimer(1 * sys_clk_freq // 1000)
        self.submodules += ready_timer
        self.comb += [
            ready_timer.wait.eq(~self.done & ~startup_fsm.reset),
            startup_fsm.reset.eq(self.restart | ready_timer.done)
        ]

        if rx:
            cdr_stable_timer = WaitTimer(1024)
            self.submodules += cdr_stable_timer

        Xxphaligndone_r = Signal(reset=1)
        Xxphaligndone_rising = Signal()
        self.sync += Xxphaligndone_r.eq(Xxphaligndone)
        self.comb += Xxphaligndone_rising.eq(Xxphaligndone & ~Xxphaligndone_r)

        startup_fsm.act("RESET_ALL", gtXxreset.eq(1), self.pllreset.eq(1),
                        startup_timer.wait.eq(1),
                        NextState("RELEASE_PLL_RESET"))
        startup_fsm.act(
            "RELEASE_PLL_RESET", gtXxreset.eq(1), startup_timer.wait.eq(1),
            If(plllock & startup_timer.done, NextState("RELEASE_GTX_RESET")))
        # Release GTX reset and wait for GTX resetdone
        # (from UG476, GTX is reset on falling edge
        # of gtXxreset)
        if rx:
            startup_fsm.act(
                "RELEASE_GTX_RESET", Xxuserrdy.eq(1),
                cdr_stable_timer.wait.eq(1),
                If(Xxresetdone & cdr_stable_timer.done, NextState("ALIGN")))
        else:
            startup_fsm.act("RELEASE_GTX_RESET", Xxuserrdy.eq(1),
                            If(Xxresetdone, NextState("ALIGN")))
        # Start delay alignment (pulse)
        startup_fsm.act("ALIGN", Xxuserrdy.eq(1), Xxdlysreset.eq(1),
                        NextState("WAIT_ALIGN"))
        # Wait for delay alignment
        startup_fsm.act(
            "WAIT_ALIGN", Xxuserrdy.eq(1),
            If(Xxdlysresetdone, NextState("WAIT_FIRST_ALIGN_DONE")))
        # Wait 2 rising edges of Xxphaligndone
        # (from UG476 in buffer bypass config)
        startup_fsm.act(
            "WAIT_FIRST_ALIGN_DONE", Xxuserrdy.eq(1),
            If(Xxphaligndone_rising, NextState("WAIT_SECOND_ALIGN_DONE")))
        startup_fsm.act("WAIT_SECOND_ALIGN_DONE", Xxuserrdy.eq(1),
                        If(Xxphaligndone_rising, NextState("READY")))
        startup_fsm.act("READY", Xxuserrdy.eq(1), self.done.eq(1))
Пример #14
0
    def __init__(self,
                 platform,
                 pads,
                 data_width=64,
                 bar0_size=1 * MB,
                 cd="sys",
                 pll1=None):
        self.sink = stream.Endpoint(phy_layout(data_width))
        self.source = stream.Endpoint(phy_layout(data_width))
        self.msi = stream.Endpoint(msi_layout())

        self._lnk_up = CSRStatus()
        self._msi_enable = CSRStatus()
        self._bus_master_enable = CSRStatus()
        self._max_request_size = CSRStatus(16)
        self._max_payload_size = CSRStatus(16)

        self.data_width = data_width

        self.id = Signal(16)
        self.bar0_size = bar0_size
        self.bar0_mask = get_bar_mask(bar0_size)
        self.max_request_size = Signal(16)
        self.max_payload_size = Signal(16)

        # # #

        # clocking
        pcie_clk = Signal()
        pcie_rst = Signal()
        pcie_refclk = Signal()
        self.specials += Instance("IBUFDS_GTE2",
                                  i_CEB=0,
                                  i_I=pads.clk_p,
                                  i_IB=pads.clk_n,
                                  o_O=pcie_refclk)
        pcie_refclk.attr.add("keep")
        platform.add_period_constraint(pcie_refclk, 10.0)

        self.clock_domains.cd_pcie = ClockDomain()
        self.clock_domains.cd_pcie_reset_less = ClockDomain(reset_less=True)
        self.cd_pcie.clk.attr.add("keep")
        platform.add_period_constraint(self.cd_pcie.clk, 8.0)

        pcie_refclk_present = Signal()
        pcie_refclk_timer = ClockDomainsRenamer("pcie_reset_less")(
            WaitTimer(1024))
        self.submodules += pcie_refclk_timer
        self.comb += [
            pcie_refclk_timer.wait.eq(1),
            pcie_refclk_present.eq(pcie_refclk_timer.done)
        ]

        self.comb += [
            self.cd_pcie.clk.eq(pcie_clk),
            self.cd_pcie.rst.eq(pcie_rst & pcie_refclk_present),
            self.cd_pcie_reset_less.clk.eq(pcie_clk),
        ]

        # tx cdc (fpga --> host)
        if cd == "pcie":
            s_axis_tx = self.sink
        else:
            tx_buffer = stream.Buffer(phy_layout(data_width))
            tx_buffer = ClockDomainsRenamer(cd)(tx_buffer)
            tx_cdc = stream.AsyncFIFO(phy_layout(data_width), 4)
            tx_cdc = ClockDomainsRenamer({"write": cd, "read": "pcie"})(tx_cdc)
            self.submodules += tx_buffer, tx_cdc
            self.comb += [
                self.sink.connect(tx_buffer.sink),
                tx_buffer.source.connect(tx_cdc.sink)
            ]
            s_axis_tx = tx_cdc.source

        # rx cdc (host --> fpga)
        if cd == "pcie":
            m_axis_rx = self.source
        else:
            rx_cdc = stream.AsyncFIFO(phy_layout(data_width), 4)
            rx_cdc = ClockDomainsRenamer({"write": "pcie", "read": cd})(rx_cdc)
            rx_buffer = stream.Buffer(phy_layout(data_width))
            rx_buffer = ClockDomainsRenamer(cd)(rx_buffer)
            self.submodules += rx_buffer, rx_cdc
            self.comb += [
                rx_cdc.source.connect(rx_buffer.sink),
                rx_buffer.source.connect(self.source)
            ]
            m_axis_rx = rx_cdc.sink

        # msi cdc (fpga --> host)
        if cd == "pcie":
            cfg_msi = self.msi
        else:
            msi_cdc = stream.AsyncFIFO(msi_layout(), 4)
            msi_cdc = ClockDomainsRenamer({
                "write": cd,
                "read": "pcie"
            })(msi_cdc)
            self.submodules += msi_cdc
            self.comb += self.msi.connect(msi_cdc.sink)
            cfg_msi = msi_cdc.source

        # config
        def convert_size(command, size):
            cases = {}
            value = 128
            for i in range(6):
                cases[i] = size.eq(value)
                value = value * 2
            return Case(command, cases)

        lnk_up = Signal()
        msienable = Signal()
        bus_number = Signal(8)
        device_number = Signal(5)
        function_number = Signal(3)
        command = Signal(16)
        dcommand = Signal(16)
        self.sync.pcie += [
            convert_size(dcommand[12:15], self.max_request_size),
            convert_size(dcommand[5:8], self.max_payload_size),
            self.id.eq(Cat(function_number, device_number, bus_number))
        ]
        self.specials += [
            MultiReg(lnk_up, self._lnk_up.status),
            MultiReg(command[2], self._bus_master_enable.status),
            MultiReg(msienable, self._msi_enable.status),
            MultiReg(self.max_request_size, self._max_request_size.status),
            MultiReg(self.max_payload_size, self._max_payload_size.status)
        ]

        # hard ip
        self.specials += Instance(
            "pcie_phy",
            p_C_DATA_WIDTH=data_width,
            p_C_PCIE_GT_DEVICE={
                "xc7k": "GTX",
                "xc7a": "GTP"
            }[platform.device[:4]],
            p_C_BAR0=get_bar_mask(bar0_size),
            i_sys_clk=pcie_refclk,
            i_sys_rst_n=1 if not hasattr(pads, "rst_n") else pads.rst_n,
            o_pci_exp_txp=pads.tx_p,
            o_pci_exp_txn=pads.tx_n,
            i_pci_exp_rxp=pads.rx_p,
            i_pci_exp_rxn=pads.rx_n,
            o_user_clk=pcie_clk,
            o_user_reset=pcie_rst,
            o_user_lnk_up=lnk_up,

            #o_tx_buf_av=,
            #o_tx_terr_drop=,
            #o_tx_cfg_req=,
            i_tx_cfg_gnt=1,
            i_s_axis_tx_tvalid=s_axis_tx.valid,
            i_s_axis_tx_tlast=s_axis_tx.last,
            o_s_axis_tx_tready=s_axis_tx.ready,
            i_s_axis_tx_tdata=s_axis_tx.dat,
            i_s_axis_tx_tkeep=s_axis_tx.be,
            i_s_axis_tx_tuser=0,
            i_rx_np_ok=1,
            i_rx_np_req=1,
            o_m_axis_rx_tvalid=m_axis_rx.valid,
            o_m_axis_rx_tlast=m_axis_rx.last,
            i_m_axis_rx_tready=m_axis_rx.ready,
            o_m_axis_rx_tdata=m_axis_rx.dat,
            o_m_axis_rx_tkeep=m_axis_rx.be,
            #o_m_axis_rx_tuser=,

            #o_cfg_to_turnoff=,
            o_cfg_bus_number=bus_number,
            o_cfg_device_number=device_number,
            o_cfg_function_number=function_number,
            o_cfg_command=command,
            o_cfg_dcommand=dcommand,
            o_cfg_interrupt_msienable=msienable,
            i_cfg_interrupt=cfg_msi.valid,
            o_cfg_interrupt_rdy=cfg_msi.ready,
            i_cfg_interrupt_di=cfg_msi.dat,
            p_QPLL_PLL1_FBDIV=4 if pll1 is None else pll1.config["n2"],
            p_QPLL_PLL1_FBDIV_45=4 if pll1 is None else pll1.config["n1"],
            p_QPLL_PLL1_REFCLK_DIV=1 if pll1 is None else pll1.config["m"],
            i_QPLL_GTGREFCLK1=0 if pll1 is None else pll1.gtgrefclk,
            i_QPLL_GTREFCLK1=0 if pll1 is None else pll1.gtrefclk,
            i_QPLL_PLL1LOCKEN=1,
            i_QPLL_PLL1PD=1 if pll1 is None else 0,
            i_QPLL_PLL1REFCLKSEL=0b001 if pll1 is None else pll1.refclksel,
            i_QPLL_PLL1RESET=1 if pll1 is None else pll1.reset,
            o_QPLL_PLL1LOCK=Signal() if pll1 is None else pll1.lock,
            o_QPLL_PLL1OUTCLK=Signal() if pll1 is None else pll1.clk,
            o_QPLL_PLL1OUTREFCLK=Signal() if pll1 is None else pll1.refclk)
        litepcie_phy_path = os.path.abspath(os.path.dirname(__file__))
        platform.add_source_dir(
            os.path.join(litepcie_phy_path, "xilinx", "7-series", "common"))
        if platform.device[:4] == "xc7k":
            platform.add_source_dir(
                os.path.join(litepcie_phy_path, "xilinx", "7-series",
                             "kintex7"))
        elif platform.device[:4] == "xc7a":
            platform.add_source_dir(
                os.path.join(litepcie_phy_path, "xilinx", "7-series",
                             "artix7"))
Пример #15
0
    def __init__(self, sys_clk_freq, rx):
        self.done = Signal()
        self.restart = Signal()

        # GTH signals
        self.plllock = Signal()
        self.pllreset = Signal()
        self.gtXxreset = Signal()
        self.Xxresetdone = Signal()
        self.Xxdlysreset = Signal()
        self.Xxdlysresetdone = Signal()
        self.Xxphaligndone = Signal()
        self.Xxsyncdone = Signal()
        self.Xxuserrdy = Signal()

        # # #

        # Double-latch transceiver asynch outputs
        plllock = Signal()
        Xxresetdone = Signal()
        Xxdlysresetdone = Signal()
        Xxphaligndone = Signal()
        Xxsyncdone = Signal()
        self.specials += [
            MultiReg(self.plllock, plllock),
            MultiReg(self.Xxresetdone, Xxresetdone),
            MultiReg(self.Xxdlysresetdone, Xxdlysresetdone),
            MultiReg(self.Xxphaligndone, Xxphaligndone),
            MultiReg(self.Xxsyncdone, Xxsyncdone)
        ]

        # Deglitch FSM outputs driving transceiver asynch inputs
        gtXxreset = Signal()
        Xxdlysreset = Signal()
        Xxuserrdy = Signal()
        self.sync += [
            self.gtXxreset.eq(gtXxreset),
            self.Xxdlysreset.eq(Xxdlysreset),
            self.Xxuserrdy.eq(Xxuserrdy)
        ]

        # PLL reset must be at least 2us
        pll_reset_cycles = ceil(2000 * sys_clk_freq / 1000000000)
        pll_reset_timer = WaitTimer(pll_reset_cycles)
        self.submodules += pll_reset_timer

        startup_fsm = ResetInserter()(FSM(reset_state="RESET_ALL"))
        self.submodules += startup_fsm

        ready_timer = WaitTimer(int(sys_clk_freq / 1000))
        self.submodules += ready_timer
        self.comb += [
            ready_timer.wait.eq(~self.done & ~startup_fsm.reset),
            startup_fsm.reset.eq(self.restart | ready_timer.done)
        ]

        if rx:
            cdr_stable_timer = WaitTimer(1024)
            self.submodules += cdr_stable_timer

        Xxphaligndone_r = Signal(reset=1)
        Xxphaligndone_rising = Signal()
        self.sync += Xxphaligndone_r.eq(Xxphaligndone)
        self.comb += Xxphaligndone_rising.eq(Xxphaligndone & ~Xxphaligndone_r)

        startup_fsm.act(
            "RESET_ALL", gtXxreset.eq(1), self.pllreset.eq(1),
            pll_reset_timer.wait.eq(1),
            If(pll_reset_timer.done, NextState("RELEASE_PLL_RESET")))
        startup_fsm.act("RELEASE_PLL_RESET", gtXxreset.eq(1),
                        If(plllock, NextState("RELEASE_GTH_RESET")))
        # Release GTH reset and wait for GTH resetdone
        # (from UG476, GTH is reset on falling edge
        # of gtXxreset)
        if rx:
            startup_fsm.act(
                "RELEASE_GTH_RESET", Xxuserrdy.eq(1),
                cdr_stable_timer.wait.eq(1),
                If(Xxresetdone & cdr_stable_timer.done, NextState("ALIGN")))
        else:
            startup_fsm.act("RELEASE_GTH_RESET", Xxuserrdy.eq(1),
                            If(Xxresetdone, NextState("ALIGN")))
        # Start delay alignment (pulse)
        startup_fsm.act("ALIGN", Xxuserrdy.eq(1), Xxdlysreset.eq(1),
                        NextState("WAIT_ALIGN"))
        if rx:
            # Wait for delay alignment
            startup_fsm.act("WAIT_ALIGN", Xxuserrdy.eq(1),
                            If(Xxsyncdone, NextState("READY")))
        else:
            # Wait for delay alignment
            startup_fsm.act(
                "WAIT_ALIGN", Xxuserrdy.eq(1),
                If(Xxdlysresetdone, NextState("WAIT_FIRST_ALIGN_DONE")))

        # Wait 2 rising edges of Xxphaligndone
        # (from UG576 in TX Buffer Bypass in Single-Lane Auto Mode)
        startup_fsm.act(
            "WAIT_FIRST_ALIGN_DONE", Xxuserrdy.eq(1),
            If(Xxphaligndone_rising, NextState("WAIT_SECOND_ALIGN_DONE")))
        startup_fsm.act("WAIT_SECOND_ALIGN_DONE", Xxuserrdy.eq(1),
                        If(Xxphaligndone_rising, NextState("READY")))
        startup_fsm.act("READY", Xxuserrdy.eq(1), self.done.eq(1),
                        If(self.restart, NextState("RESET_ALL")))
Пример #16
0
    def __init__(self, platform, clk_freq):

        # Work out how many LEDs this board has
        user_leds = []
        while True:
            try:
                user_leds.append(platform.request("user_led", len(user_leds)))
            except ConstraintError:
                break

        if user_leds:
            leds = Signal(len(user_leds))
            self.submodules.leds = GPIOOut(leds)
            for i in range(0, len(user_leds)):
                self.comb += [
                    user_leds[i].eq(leds[i]),
                ]
        self._leds_count = CSRConstant(len(user_leds))

        # Work out how many switches this board has
        user_sws = []
        while True:
            try:
                user_sws.append(platform.request("user_sw", len(user_sws)))
            except ConstraintError:
                break

        if user_sws:
            switches = Signal(len(user_sws))
            self.submodules.switches = GPIOIn(switches)
            for i in range(0, len(user_sws)):
                self.comb += [
                    switches[i].eq(~user_sws[i]),
                ]
        self._switches_count = CSRConstant(len(user_sws))

        # Work out how many push buttons this board has
        user_btns = []
        while True:
            try:
                user_btns.append(platform.request("user_btn", len(user_btns)))
            except ConstraintError:
                break

        if user_btns:
            self.submodules.buttons_ev = EventManager()

            _10ms = int(clk_freq*(10e-3))

            for i in range(0, len(user_btns)):
                btn_ev = EventSourceProcess()
                btn_timer = WaitTimer(_10ms)

                setattr(self.buttons_ev, "btn_ev{}".format(i), btn_ev)

                self.comb += [
                    btn_timer.wait.eq(user_btns[i]),
                    btn_ev.trigger.eq(~btn_timer.done),
                ]

                self.submodules += [btn_timer]

            self.buttons_ev.finalize()
        self._buttons_count = CSRConstant(len(user_btns))
Пример #17
0
    def __init__(self, serdes, taps, timeout=1024):
        self.reset = Signal()
        self.ready = Signal()
        self.error = Signal()

        # # #

        self.delay = delay = Signal(max=taps)
        self.delay_min = delay_min = Signal(max=taps)
        self.delay_min_found = delay_min_found = Signal()
        self.delay_max = delay_max = Signal(max=taps)
        self.delay_max_found = delay_max_found = Signal()
        self.bitslip = bitslip = Signal(max=40)

        timer = WaitTimer(timeout)
        self.submodules += timer

        self.submodules.fsm = fsm = ResetInserter()(FSM(reset_state="IDLE"))
        self.comb += self.fsm.reset.eq(self.reset)

        fsm.act("IDLE", NextValue(delay, 0), NextValue(delay_min, 0),
                NextValue(delay_min_found, 0), NextValue(delay_max, 0),
                NextValue(delay_max_found, 0), serdes.rx_delay_rst.eq(1),
                NextValue(bitslip, 0), NextState("RESET_SLAVE"),
                serdes.tx_idle.eq(1))
        fsm.act("RESET_SLAVE", timer.wait.eq(1),
                If(timer.done, timer.wait.eq(0), NextState("SEND_PATTERN")),
                serdes.tx_idle.eq(1))
        fsm.act("SEND_PATTERN", If(~serdes.rx_idle, NextState("WAIT_STABLE")),
                serdes.tx_comma.eq(1))
        fsm.act("WAIT_STABLE", timer.wait.eq(1),
                If(timer.done, timer.wait.eq(0), NextState("CHECK_PATTERN")),
                serdes.tx_comma.eq(1))
        fsm.act(
            "CHECK_PATTERN",
            If(
                ~delay_min_found,
                If(
                    serdes.rx_comma, timer.wait.eq(1),
                    If(timer.done, timer.wait.eq(0),
                       NextValue(delay_min, delay),
                       NextValue(delay_min_found,
                                 1))).Else(NextState("INC_DELAY_BITSLIP")),
            ).Else(
                If(~serdes.rx_comma, NextValue(delay_max, delay),
                   NextValue(delay_max_found, 1),
                   NextState("CHECK_SAMPLING_WINDOW")).Else(
                       NextState("INC_DELAY_BITSLIP"))), serdes.tx_comma.eq(1))
        self.comb += serdes.rx_bitslip_value.eq(bitslip)
        fsm.act(
            "INC_DELAY_BITSLIP", NextState("WAIT_STABLE"),
            If(
                delay == (taps - 1),
                If(bitslip == (40 - 1),
                   NextState("ERROR")).Else(NextValue(delay_min_found, 0),
                                            NextValue(bitslip, bitslip + 1)),
                NextValue(delay, 0),
                serdes.rx_delay_rst.eq(1)).Else(NextValue(delay, delay + 1),
                                                serdes.rx_delay_inc.eq(1),
                                                serdes.rx_delay_ce.eq(1)),
            serdes.tx_comma.eq(1))
        fsm.act(
            "CHECK_SAMPLING_WINDOW",
            If((delay_min == 0) | (delay_max == (taps - 1)) |
               ((delay_max - delay_min) < taps // 16),
               NextValue(delay_min_found, 0), NextValue(delay_max_found, 0),
               NextState("WAIT_STABLE")).Else(
                   NextState("RESET_SAMPLING_WINDOW")))
        fsm.act("RESET_SAMPLING_WINDOW", NextValue(delay, 0),
                serdes.rx_delay_rst.eq(1), NextState("WAIT_SAMPLING_WINDOW"),
                serdes.tx_comma.eq(1))
        fsm.act(
            "CONFIGURE_SAMPLING_WINDOW",
            If(delay == (delay_min + (delay_max - delay_min)[1:]),
               NextState("READY")).Else(NextValue(delay, delay + 1),
                                        serdes.rx_delay_inc.eq(1),
                                        serdes.rx_delay_ce.eq(1),
                                        NextState("WAIT_SAMPLING_WINDOW")),
            serdes.tx_comma.eq(1))
        fsm.act(
            "WAIT_SAMPLING_WINDOW", timer.wait.eq(1),
            If(timer.done, timer.wait.eq(0),
               NextState("CONFIGURE_SAMPLING_WINDOW")), serdes.tx_comma.eq(1))
        fsm.act("READY", self.ready.eq(1))
        fsm.act("ERROR", self.error.eq(1))
Пример #18
0
    def __init__(self, clk_freq, max_requests=8):
        self.sink = sink = stream.Endpoint(_arp_table_layout)  # from arp_rx
        self.source = source = stream.Endpoint(_arp_table_layout)  # to arp_tx

        # Request/Response interface
        self.request = request = stream.Endpoint(arp_table_request_layout)
        self.response = response = stream.Endpoint(arp_table_response_layout)

        # # #

        request_pending = Signal()
        request_pending_clr = Signal()
        request_pending_set = Signal()
        self.sync += \
            If(request_pending_clr,
                request_pending.eq(0)
            ).Elif(request_pending_set,
                request_pending.eq(1)
            )

        request_ip_address = Signal(32, reset_less=True)
        request_ip_address_reset = Signal()
        request_ip_address_update = Signal()
        self.sync += \
            If(request_ip_address_reset,
                request_ip_address.eq(0)
            ).Elif(request_ip_address_update,
                request_ip_address.eq(request.ip_address)
            )

        request_timer = WaitTimer(clk_freq // 10)
        self.submodules += request_timer
        request_counter = Signal(max=max_requests)
        request_counter_reset = Signal()
        request_counter_ce = Signal()
        self.sync += \
            If(request_counter_reset,
                request_counter.eq(0)
            ).Elif(request_counter_ce,
                request_counter.eq(request_counter + 1)
            )
        self.comb += request_timer.wait.eq(request_pending
                                           & ~request_counter_ce)

        # Note: Store only 1 IP/MAC couple, can be improved with a real
        # table in the future to improve performance when packets are
        # targeting multiple destinations.
        update = Signal()
        cached_valid = Signal()
        cached_ip_address = Signal(32, reset_less=True)
        cached_mac_address = Signal(48, reset_less=True)
        cached_timer = WaitTimer(clk_freq * 10)
        self.submodules += cached_timer

        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act(
            "IDLE",
            # Note: for simplicicy, if APR table is busy response from arp_rx
            # is lost. This is compensated by the protocol (retries)
            If(sink.valid & sink.request, NextState("SEND_REPLY")).Elif(
                sink.valid & sink.reply & request_pending,
                NextState("UPDATE_TABLE"),
            ).Elif(request_counter == max_requests - 1,
                   NextState("PRESENT_RESPONSE")).Elif(
                       request.valid | (request_pending & request_timer.done),
                       NextState("CHECK_TABLE")))
        fsm.act("SEND_REPLY", source.valid.eq(1), source.reply.eq(1),
                source.ip_address.eq(sink.ip_address),
                source.mac_address.eq(sink.mac_address),
                If(source.ready, NextState("IDLE")))
        fsm.act("UPDATE_TABLE", request_pending_clr.eq(1), update.eq(1),
                NextState("CHECK_TABLE"))
        self.sync += \
            If(update,
                cached_valid.eq(1),
                cached_ip_address.eq(sink.ip_address),
                cached_mac_address.eq(sink.mac_address),
            ).Else(
                If(cached_timer.done,
                    cached_valid.eq(0)
                )
            )
        self.comb += cached_timer.wait.eq(~update)
        fsm.act(
            "CHECK_TABLE",
            If(
                cached_valid,
                If(
                    request_ip_address == cached_ip_address,
                    request_ip_address_reset.eq(1),
                    NextState("PRESENT_RESPONSE"),
                ).Elif(
                    request.ip_address == cached_ip_address,
                    request.ready.eq(request.valid),
                    NextState("PRESENT_RESPONSE"),
                ).Else(request_ip_address_update.eq(request.valid),
                       NextState("SEND_REQUEST"))).Else(
                           request_ip_address_update.eq(request.valid),
                           NextState("SEND_REQUEST")))
        fsm.act(
            "SEND_REQUEST", source.valid.eq(1), source.request.eq(1),
            source.ip_address.eq(request_ip_address),
            If(source.ready, request_counter_reset.eq(request.valid),
               request_counter_ce.eq(1), request_pending_set.eq(1),
               request.ready.eq(1), NextState("IDLE")))
        self.comb += [
            If(request_counter == max_requests - 1, response.failed.eq(1),
               request_counter_reset.eq(1), request_pending_clr.eq(1)),
            response.mac_address.eq(cached_mac_address)
        ]
        fsm.act("PRESENT_RESPONSE", response.valid.eq(1),
                If(response.ready, NextState("IDLE")))
Пример #19
0
    def __init__(self, n, aw, address_align, settings):
        self.req = req = Record(cmd_layout(aw))
        self.refresh_req = Signal()
        self.refresh_gnt = Signal()
        a = settings.geom.addressbits
        ba = settings.geom.bankbits
        self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba))

        # # #

        # Command buffer
        cmd_buffer_layout = [("we", 1), ("adr", len(req.adr))]
        if settings.cmd_buffer_depth < 2:
            cmd_buffer = stream.Buffer(cmd_buffer_layout)
        else:
            cmd_buffer = stream.SyncFIFO(cmd_buffer_layout,
                                         settings.cmd_buffer_depth)
        self.submodules += cmd_buffer
        self.comb += [
            req.connect(cmd_buffer.sink,
                        omit=[
                            "wdata_valid", "wdata_ready", "rdata_valid",
                            "rdata_ready", "lock"
                        ]),
            cmd_buffer.source.ready.eq(req.wdata_ready | req.rdata_valid),
            req.lock.eq(cmd_buffer.source.valid),
        ]

        slicer = _AddressSlicer(settings.geom.colbits, address_align)

        # Row tracking
        has_openrow = Signal()
        openrow = Signal(settings.geom.rowbits, reset_less=True)
        hit = Signal()
        self.comb += hit.eq(openrow == slicer.row(cmd_buffer.source.adr))
        track_open = Signal()
        track_close = Signal()
        self.sync += \
            If(track_close,
                has_openrow.eq(0)
            ).Elif(track_open,
                has_openrow.eq(1),
                openrow.eq(slicer.row(cmd_buffer.source.adr))
            )

        # Address generation
        sel_row_adr = Signal()
        self.comb += [
            cmd.ba.eq(n),
            If(sel_row_adr, cmd.a.eq(slicer.row(cmd_buffer.source.adr))).Else(
                cmd.a.eq(slicer.col(cmd_buffer.source.adr)))
        ]

        # Respect write-to-precharge specification
        precharge_time = 2 + settings.timing.tWR - 1 + 1
        self.submodules.precharge_timer = WaitTimer(precharge_time)
        self.comb += self.precharge_timer.wait.eq(~(cmd.valid & cmd.ready
                                                    & cmd.is_write))

        # Control and command generation FSM
        self.submodules.fsm = fsm = FSM()
        fsm.act(
            "REGULAR",
            If(self.refresh_req, NextState("REFRESH")).Elif(
                cmd_buffer.source.valid,
                If(
                    has_openrow,
                    If(
                        hit,
                        # Note: write-to-read specification is enforced by
                        # multiplexer
                        cmd.valid.eq(1),
                        If(
                            cmd_buffer.source.we,
                            req.wdata_ready.eq(cmd.ready),
                            cmd.is_write.eq(1),
                            cmd.we.eq(1),
                        ).Else(req.rdata_valid.eq(cmd.ready),
                               cmd.is_read.eq(1)),
                        cmd.cas.eq(1)).Else(NextState("PRECHARGE"))).Else(
                            NextState("ACTIVATE"))))
        fsm.act(
            "PRECHARGE",
            # Note: we are presenting the column address, A10 is always low
            If(self.precharge_timer.done, cmd.valid.eq(1),
               If(cmd.ready, NextState("TRP")), cmd.ras.eq(1), cmd.we.eq(1),
               cmd.is_cmd.eq(1)),
            track_close.eq(1))
        fsm.act("ACTIVATE", sel_row_adr.eq(1), track_open.eq(1),
                cmd.valid.eq(1), cmd.is_cmd.eq(1),
                If(cmd.ready, NextState("TRCD")), cmd.ras.eq(1))
        fsm.act("REFRESH",
                If(
                    self.precharge_timer.done,
                    self.refresh_gnt.eq(1),
                ), track_close.eq(1), cmd.is_cmd.eq(1),
                If(~self.refresh_req, NextState("REGULAR")))
        fsm.delayed_enter("TRP", "ACTIVATE", settings.timing.tRP - 1)
        fsm.delayed_enter("TRCD", "REGULAR", settings.timing.tRCD - 1)