Beispiel #1
0
    def __init__(self, platform):
        self.clock_domains.cd_sys = ClockDomain()
        self.clock_domains.cd_sys4x = ClockDomain(reset_less=True)
        self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True)
        self.clock_domains.cd_clk200 = ClockDomain()
        self.clock_domains.cd_clk100 = ClockDomain()

        clk50 = platform.request("clk50")
        rst = Signal()

        pll_locked = Signal()
        pll_fb = Signal()
        self.pll_sys = Signal()
        pll_sys4x = Signal()
        pll_sys4x_dqs = Signal()
        pll_clk200 = Signal()
        self.specials += [
            Instance("PLLE2_BASE",
                     p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,

                     # VCO @ 1600 MHz
                     p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=20.0,
                     p_CLKFBOUT_MULT=32, p_DIVCLK_DIVIDE=1,
                     i_CLKIN1=clk50, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb,

                     # 100 MHz
                     p_CLKOUT0_DIVIDE=16, p_CLKOUT0_PHASE=0.0,
                     o_CLKOUT0=self.pll_sys,

                     # 400 MHz
                     p_CLKOUT1_DIVIDE=4, p_CLKOUT1_PHASE=0.0,
                     o_CLKOUT1=pll_sys4x,

                     # 400 MHz dqs
                     p_CLKOUT2_DIVIDE=4, p_CLKOUT2_PHASE=90.0,
                     o_CLKOUT2=pll_sys4x_dqs,

                     # 200 MHz
                     p_CLKOUT3_DIVIDE=8, p_CLKOUT3_PHASE=0.0,
                     o_CLKOUT3=pll_clk200
            ),
            Instance("BUFG", i_I=self.pll_sys, o_O=self.cd_sys.clk),
            Instance("BUFG", i_I=self.pll_sys, o_O=self.cd_clk100.clk),
            Instance("BUFG", i_I=pll_clk200, o_O=self.cd_clk200.clk),
            Instance("BUFG", i_I=pll_sys4x, o_O=self.cd_sys4x.clk),
            Instance("BUFG", i_I=pll_sys4x_dqs, o_O=self.cd_sys4x_dqs.clk),
            AsyncResetSynchronizer(self.cd_sys, ~pll_locked | rst),
            AsyncResetSynchronizer(self.cd_clk200, ~pll_locked | rst),
            AsyncResetSynchronizer(self.cd_clk100, ~pll_locked | rst)
        ]

        reset_counter = Signal(4, reset=15)
        ic_reset = Signal(reset=1)
        self.sync.clk200 += \
            If(reset_counter != 0,
                reset_counter.eq(reset_counter - 1)
            ).Else(
                ic_reset.eq(0)
            )
        self.specials += Instance("IDELAYCTRL", i_REFCLK=ClockSignal("clk200"), i_RST=ic_reset)
Beispiel #2
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()
        self.comb += [
            self.cd_eth_rx.clk.eq(ClockSignal("eth")),
            self.cd_eth_tx.clk.eq(ClockSignal("eth"))
        ]

        self.specials += DDROutput(0, 1, clock_pads.ref_clk,
                                   ClockSignal("eth_tx"))

        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),
        ]
Beispiel #3
0
    def __init__(self, clock_pads, pads, with_hw_init_reset):
        self._reset = CSRStorage()

        # # #

        if hasattr(clock_pads, "phy"):
            self.sync.base50 += clock_pads.phy.eq(~clock_pads.phy)

        self.clock_domains.cd_eth_rx = ClockDomain()
        self.clock_domains.cd_eth_tx = ClockDomain()
        self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx)
        self.comb += self.cd_eth_tx.clk.eq(clock_pads.tx)

        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),
        ]
Beispiel #4
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),
        ]
Beispiel #5
0
    def __init__(self, platform):
        self.clock_domains.cd_sys = ClockDomain()
        self.clock_domains.cd_sys4x = ClockDomain(reset_less=True)
        self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True)
        self.clock_domains.cd_clk200 = ClockDomain()

        clk50 = platform.request("clk50")
        clk50_bufr = Signal()

        pll_locked = Signal()
        pll_fb = Signal()
        pll_sys = Signal()
        pll_sys4x = Signal()
        pll_sys4x_dqs = Signal()
        pll_clk200 = Signal()
        self.specials += [
            Instance("BUFR", i_I=clk50, o_O=clk50_bufr),
            Instance("PLLE2_BASE",
                     p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,

                     # VCO @ 1GHz
                     p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=20.0,
                     p_CLKFBOUT_MULT=20, p_DIVCLK_DIVIDE=1,
                     i_CLKIN1=clk50_bufr, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb,

                     # 125MHz
                     p_CLKOUT0_DIVIDE=8, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=pll_sys,

                     # 500MHz
                     p_CLKOUT1_DIVIDE=2, p_CLKOUT1_PHASE=0.0, o_CLKOUT1=pll_sys4x,

                     # 500MHz dqs
                     p_CLKOUT2_DIVIDE=2, p_CLKOUT2_PHASE=90.0, o_CLKOUT2=pll_sys4x_dqs,

                     # 200MHz
                     p_CLKOUT3_DIVIDE=5, p_CLKOUT3_PHASE=0.0, o_CLKOUT3=pll_clk200
            ),
            Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk),
            Instance("BUFG", i_I=pll_sys4x, o_O=self.cd_sys4x.clk),
            Instance("BUFG", i_I=pll_sys4x_dqs, o_O=self.cd_sys4x_dqs.clk),
            Instance("BUFG", i_I=pll_clk200, o_O=self.cd_clk200.clk),
            AsyncResetSynchronizer(self.cd_sys, ~pll_locked),
            AsyncResetSynchronizer(self.cd_clk200, ~pll_locked),
        ]
        platform.add_platform_command("set_property CLOCK_DEDICATED_ROUTE BACKBONE [get_nets crg_clk50_bufr]")

        reset_counter = Signal(4, reset=15)
        ic_reset = Signal(reset=1)
        self.sync.clk200 += \
            If(reset_counter != 0,
                reset_counter.eq(reset_counter - 1)
            ).Else(
                ic_reset.eq(0)
            )
        self.specials += Instance("IDELAYCTRL", p_SIM_DEVICE="ULTRASCALE",
            i_REFCLK=ClockSignal("clk200"), i_RST=ic_reset)
Beispiel #6
0
    def __init__(self, iwidth, idomain, owidth, odomain):
        self.i = Signal(iwidth)
        self.o = Signal(owidth)

        # # #

        reset = Signal()
        cd_write = ClockDomain()
        cd_read = ClockDomain()
        self.comb += [
            cd_write.clk.eq(ClockSignal(idomain)),
            cd_read.clk.eq(ClockSignal(odomain)),
            reset.eq(ResetSignal(idomain) | ResetSignal(odomain))
        ]
        self.specials += [
            AsyncResetSynchronizer(cd_write, reset),
            AsyncResetSynchronizer(cd_read, reset)
        ]
        self.clock_domains += cd_write, cd_read

        storage = Signal(lcm(iwidth, owidth))
        wrchunks = len(storage) // iwidth
        rdchunks = len(storage) // owidth
        wrpointer = Signal(max=wrchunks,
                           reset=0 if iwidth > owidth else wrchunks - 1)
        rdpointer = Signal(max=rdchunks,
                           reset=rdchunks - 1 if iwidth > owidth else 0)

        self.sync.write += \
            If(wrpointer == wrchunks-1,
                wrpointer.eq(0)
            ).Else(
                wrpointer.eq(wrpointer + 1)
            )
        cases = {}
        for i in range(wrchunks):
            cases[i] = [storage[iwidth * i:iwidth * (i + 1)].eq(self.i)]
        self.sync.write += Case(wrpointer, cases)


        self.sync.read += \
            If(rdpointer == rdchunks-1,
                rdpointer.eq(0)
            ).Else(
                rdpointer.eq(rdpointer + 1)
            )
        cases = {}
        for i in range(rdchunks):
            cases[i] = [self.o.eq(storage[owidth * i:owidth * (i + 1)])]
        self.sync.read += Case(rdpointer, cases)
Beispiel #7
0
    def __init__(self, platform):
        self.clock_domains.cd_sys = ClockDomain()

        # # #

        clk100 = platform.request("clk100")
        rst = ~platform.request("cpu_reset")

        pll_locked = Signal()
        pll_fb = Signal()
        pll_sys = Signal()
        self.specials += [
            Instance(
                "PLLE2_BASE",
                p_STARTUP_WAIT="FALSE",
                o_LOCKED=pll_locked,

                # VCO @ 1600 MHz
                p_REF_JITTER1=0.01,
                p_CLKIN1_PERIOD=10.0,
                p_CLKFBOUT_MULT=16,
                p_DIVCLK_DIVIDE=1,
                i_CLKIN1=clk100,
                i_CLKFBIN=pll_fb,
                o_CLKFBOUT=pll_fb,

                # 100 MHz
                p_CLKOUT0_DIVIDE=16,
                p_CLKOUT0_PHASE=0.0,
                o_CLKOUT0=pll_sys),
            Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk),
            AsyncResetSynchronizer(self.cd_sys, ~pll_locked | rst),
        ]
Beispiel #8
0
    def __init__(self, clock_pads, pads):
        self.reset = CSRStorage()

        # # #

        reset = self.reset.storage

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

        self.comb += self.cd_eth_tx.clk.eq(self.cd_eth_rx.clk)

        self.comb += pads.rst_n.eq(~reset)
        self.specials += [
            AsyncResetSynchronizer(self.cd_eth_tx, reset),
            AsyncResetSynchronizer(self.cd_eth_rx, reset)
        ]
Beispiel #9
0
    def __init__(self, width, depth, idomain, odomain):
        self.din = Signal(width)
        self.dout = Signal(width)

        # # #

        reset = Signal()
        cd_write = ClockDomain()
        cd_read = ClockDomain()
        self.comb += [
            cd_write.clk.eq(ClockSignal(idomain)),
            cd_read.clk.eq(ClockSignal(odomain)),
            reset.eq(ResetSignal(idomain) | ResetSignal(odomain))
        ]
        self.specials += [
            AsyncResetSynchronizer(cd_write, reset),
            AsyncResetSynchronizer(cd_read, reset)
        ]
        self.clock_domains += cd_write, cd_read

        wrpointer = Signal(max=depth, reset=depth // 2)
        rdpointer = Signal(max=depth)

        storage = Memory(width, depth)
        self.specials += storage

        wrport = storage.get_port(write_capable=True, clock_domain="write")
        rdport = storage.get_port(clock_domain="read")
        self.specials += wrport, rdport

        self.sync.write += wrpointer.eq(wrpointer + 1)
        self.sync.read += rdpointer.eq(rdpointer + 1)

        self.comb += [
            wrport.we.eq(1),
            wrport.adr.eq(wrpointer),
            wrport.dat_w.eq(self.din),
            rdport.adr.eq(rdpointer),
            self.dout.eq(rdport.dat_r)
        ]
Beispiel #10
0
    def __init__(self, clock_pads, pads, with_hw_init_reset, mii_mode=0):
        self._reset = CSRStorage()

        # # #

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

        # RX : Let the synthesis tool insert the appropriate clock buffer
        self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx)

        # TX : GMII: Drive clock_pads.gtx, clock_pads.tx unused
        #      MII: Use PHY clock_pads.tx as eth_tx_clk, do not drive clock_pads.gtx
        self.specials += DDROutput(1, mii_mode, clock_pads.gtx,
                                   ClockSignal("eth_tx"))
        if isinstance(mii_mode, int) and (mii_mode == 0):
            self.comb += self.cd_eth_tx.clk.eq(self.cd_eth_rx.clk)
        else:
            # XXX Xilinx specific, replace BUFGMUX with a generic clock buffer?
            self.specials += Instance("BUFGMUX",
                                      i_I0=self.cd_eth_rx.clk,
                                      i_I1=clock_pads.tx,
                                      i_S=mii_mode,
                                      o_O=self.cd_eth_tx.clk)

        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),
        ]
Beispiel #11
0
    def __init__(self, platform):
        self.clock_domains.cd_sys = ClockDomain("sys")

        # soft reset generaton
        self._soft_rst = CSR()
        soft_rst = Signal()
        # trigger soft reset 1us after CSR access to terminate
        # Wishbone access when reseting from PCIe
        self.sync += [
            timeline(self._soft_rst.re & self._soft_rst.r, [(125, [soft_rst.eq(1)])]),
        ]

        # sys_clk / sys_rst (from PCIe)
        self.comb += self.cd_sys.clk.eq(ClockSignal("pcie"))
        self.specials += AsyncResetSynchronizer(self.cd_sys, ResetSignal("pcie") | soft_rst)
Beispiel #12
0
    def __init__(self, platform, clk_freq):
        self.clock_domains.cd_sys = ClockDomain()
        self.clock_domains.cd_sys_ps = ClockDomain()

        f0 = 32*1000000
        clk32 = platform.request("clk32")
        clk32a = Signal()
        self.specials += Instance("IBUFG", i_I=clk32, o_O=clk32a)
        clk32b = Signal()
        self.specials += Instance("BUFIO2", p_DIVIDE=1,
                                  p_DIVIDE_BYPASS="******", p_I_INVERT="FALSE",
                                  i_I=clk32a, o_DIVCLK=clk32b)
        f = Fraction(int(clk_freq), int(f0))
        n, m, p = f.denominator, f.numerator, 8
        assert f0/n*m == clk_freq
        pll_lckd = Signal()
        pll_fb = Signal()
        pll = Signal(6)
        self.specials.pll = Instance("PLL_ADV", p_SIM_DEVICE="SPARTAN6",
                                     p_BANDWIDTH="OPTIMIZED", p_COMPENSATION="INTERNAL",
                                     p_REF_JITTER=.01, p_CLK_FEEDBACK="CLKFBOUT",
                                     i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0, i_RST=0, i_REL=0,
                                     p_DIVCLK_DIVIDE=1, p_CLKFBOUT_MULT=m*p//n, p_CLKFBOUT_PHASE=0.,
                                     i_CLKIN1=clk32b, i_CLKIN2=0, i_CLKINSEL=1,
                                     p_CLKIN1_PERIOD=1000000000/f0, p_CLKIN2_PERIOD=0.,
                                     i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, o_LOCKED=pll_lckd,
                                     o_CLKOUT0=pll[0], p_CLKOUT0_DUTY_CYCLE=.5,
                                     o_CLKOUT1=pll[1], p_CLKOUT1_DUTY_CYCLE=.5,
                                     o_CLKOUT2=pll[2], p_CLKOUT2_DUTY_CYCLE=.5,
                                     o_CLKOUT3=pll[3], p_CLKOUT3_DUTY_CYCLE=.5,
                                     o_CLKOUT4=pll[4], p_CLKOUT4_DUTY_CYCLE=.5,
                                     o_CLKOUT5=pll[5], p_CLKOUT5_DUTY_CYCLE=.5,
                                     p_CLKOUT0_PHASE=0., p_CLKOUT0_DIVIDE=p//1,
                                     p_CLKOUT1_PHASE=0., p_CLKOUT1_DIVIDE=p//1,
                                     p_CLKOUT2_PHASE=0., p_CLKOUT2_DIVIDE=p//1,
                                     p_CLKOUT3_PHASE=0., p_CLKOUT3_DIVIDE=p//1,
                                     p_CLKOUT4_PHASE=0., p_CLKOUT4_DIVIDE=p//1,  # sys
                                     p_CLKOUT5_PHASE=270., p_CLKOUT5_DIVIDE=p//1,  # sys_ps
        )
        self.specials += Instance("BUFG", i_I=pll[4], o_O=self.cd_sys.clk)
        self.specials += Instance("BUFG", i_I=pll[5], o_O=self.cd_sys_ps.clk)
        self.specials += AsyncResetSynchronizer(self.cd_sys, ~pll_lckd)

        self.specials += Instance("ODDR2", p_DDR_ALIGNMENT="NONE",
                                  p_INIT=0, p_SRTYPE="SYNC",
                                  i_D0=0, i_D1=1, i_S=0, i_R=0, i_CE=1,
                                  i_C0=self.cd_sys.clk, i_C1=~self.cd_sys.clk,
                                  o_Q=platform.request("sdram_clock"))
Beispiel #13
0
    def __init__(self, platform):
        self.clock_domains.cd_sys = ClockDomain()

        clk200 = platform.request("clk200")
        clk200_se = Signal()
        self.specials += Instance("IBUFDS",
                                  i_I=clk200.p,
                                  i_IB=clk200.n,
                                  o_O=clk200_se)

        pll_locked = Signal()
        pll_fb = Signal()
        pll_sys = Signal()
        self.specials += [
            Instance(
                "PLLE2_BASE",
                p_STARTUP_WAIT="FALSE",
                o_LOCKED=pll_locked,

                # VCO @ 1GHz
                p_REF_JITTER1=0.01,
                p_CLKIN1_PERIOD=5.0,
                p_CLKFBOUT_MULT=5,
                p_DIVCLK_DIVIDE=1,
                i_CLKIN1=clk200_se,
                i_CLKFBIN=pll_fb,
                o_CLKFBOUT=pll_fb,

                # 200MHz
                p_CLKOUT0_DIVIDE=5,
                p_CLKOUT0_PHASE=0.0,
                o_CLKOUT0=pll_sys,
                p_CLKOUT1_DIVIDE=2,
                p_CLKOUT1_PHASE=0.0,  #o_CLKOUT1=,
                p_CLKOUT2_DIVIDE=2,
                p_CLKOUT2_PHASE=0.0,  #o_CLKOUT2=,
                p_CLKOUT3_DIVIDE=2,
                p_CLKOUT3_PHASE=0.0,  #o_CLKOUT3=,
                p_CLKOUT4_DIVIDE=2,
                p_CLKOUT4_PHASE=0.0,  #o_CLKOUT4=
            ),
            Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk),
            AsyncResetSynchronizer(self.cd_sys, ~pll_locked
                                   | platform.request("cpu_reset")),
        ]
Beispiel #14
0
    def __init__(self, platform, pads):
        self.sink = sink = stream.Endpoint([("data", 8)])

        # # #

        self.clock_domains.cd_usb = ClockDomain()
        self.specials += [
            Instance("IBUFG", i_I=pads.ifclk, o_O=self.cd_usb.clk),
        ]

        self.specials += AsyncResetSynchronizer(self.cd_usb, ResetSignal())

        fifo = stream.AsyncFIFO([("data", 8)], 4)
        fifo = ClockDomainsRenamer({"write": "encoder", "read": "usb"})(fifo)
        self.submodules.fifo = fifo
        self.comb += Record.connect(sink, fifo.sink)

        self.specials += Instance(
            "fx2_jpeg_streamer",
            # clk, rst
            i_rst=ResetSignal("usb"),
            i_clk=ClockSignal("usb"),

            # jpeg encoder interface
            i_sink_stb=fifo.source.valid,
            i_sink_data=fifo.source.data,
            o_sink_ack=fifo.source.ready,

            # cypress fx2 slave fifo interface
            io_fx2_data=pads.data,
            i_fx2_full_n=pads.flagb,
            i_fx2_empty_n=pads.flagc,
            o_fx2_addr=pads.addr,
            o_fx2_cs_n=pads.cs_n,
            o_fx2_wr_n=pads.wr_n,
            o_fx2_rd_n=pads.rd_n,
            o_fx2_oe_n=pads.oe_n,
            o_fx2_pktend_n=pads.pktend_n)

        # add vhdl sources
        platform.add_source_dir(os.path.join("gateware", "streamer", "vhdl"))
Beispiel #15
0
    def __init__(self, sys_clk_freq=50e6, max_sd_clk_freq=100e6):
        self._cmd_data = CSRStorage(10)
        self._send_cmd_data = CSR()
        self._send_go = CSR()
        self._status = CSRStatus(4)
        self._max_sd_clk_freq = CSRConstant(max_sd_clk_freq)

        self.clock_domains.cd_sd = ClockDomain()
        self.clock_domains.cd_sd_fb = ClockDomain()

        # # #

        clk_sd_unbuffered = Signal()
        sd_progdata = Signal()
        sd_progen = Signal()
        sd_progdone = Signal()

        sd_locked = Signal()

        clkfx_md_max = max(2.0 / 4.0, max_sd_clk_freq / sys_clk_freq)
        self._clkfx_md_max_1000 = CSRConstant(clkfx_md_max * 1000.0)
        self.specials += Instance(
            "DCM_CLKGEN",
            # parameters
            p_SPREAD_SPECTRUM="NONE",
            p_STARTUP_WAIT="FALSE",

            # reset
            i_FREEZEDCM=0,
            i_RST=ResetSignal(),

            # input
            i_CLKIN=ClockSignal(),
            p_CLKIN_PERIOD=1e9 / sys_clk_freq,

            # output
            p_CLKFXDV_DIVIDE=2,
            p_CLKFX_MULTIPLY=2,
            p_CLKFX_DIVIDE=4,
            p_CLKFX_MD_MAX=clkfx_md_max,
            o_CLKFX=clk_sd_unbuffered,
            o_LOCKED=sd_locked,

            # programming interface
            i_PROGCLK=ClockSignal(),
            i_PROGDATA=sd_progdata,
            i_PROGEN=sd_progen,
            o_PROGDONE=sd_progdone)

        remaining_bits = Signal(max=11)
        transmitting = Signal()
        self.comb += transmitting.eq(remaining_bits != 0)
        sr = Signal(10)
        self.sync += [
            If(self._send_cmd_data.re, remaining_bits.eq(10),
               sr.eq(self._cmd_data.storage)).Elif(
                   transmitting, remaining_bits.eq(remaining_bits - 1),
                   sr.eq(sr[1:]))
        ]
        self.comb += [
            sd_progdata.eq(transmitting & sr[0]),
            sd_progen.eq(transmitting | self._send_go.re)
        ]

        # enforce gap between commands
        busy_counter = Signal(max=14)
        busy = Signal()
        self.comb += busy.eq(busy_counter != 0)
        self.sync += If(self._send_cmd_data.re, busy_counter.eq(13)).Elif(
            busy, busy_counter.eq(busy_counter - 1))

        self.comb += self._status.status.eq(Cat(busy, sd_progdone, sd_locked))

        self.specials += [
            Instance("BUFG", i_I=clk_sd_unbuffered, o_O=self.cd_sd.clk),
            AsyncResetSynchronizer(self.cd_sd, ~sd_locked)
        ]
Beispiel #16
0
    def __init__(self, pll, pads, mode="master"):
        self.tx_data = Signal(32)
        self.rx_data = Signal(32)

        self.tx_idle = Signal()
        self.tx_comma = Signal()
        self.rx_idle = Signal()
        self.rx_comma = Signal()

        self.rx_bitslip_value = Signal(6)
        self.rx_delay_rst = Signal()
        self.rx_delay_inc = Signal()
        self.rx_delay_ce = Signal()
        self.rx_delay_en_vtc = Signal()

        # # #

        self.submodules.encoder = ClockDomainsRenamer("serwb_serdes")(Encoder(
            4, True))
        self.decoders = [
            ClockDomainsRenamer("serwb_serdes")(Decoder(True))
            for _ in range(4)
        ]
        self.submodules += self.decoders

        # clocking:

        # In master mode:
        # - linerate/10 pll refclk provided by user
        # - linerate/10 slave refclk generated on clk_pads
        # In Slave mode:
        # - linerate/10 pll refclk provided by clk_pads
        self.clock_domains.cd_serwb_serdes = ClockDomain()
        self.clock_domains.cd_serwb_serdes_5x = ClockDomain()
        self.clock_domains.cd_serwb_serdes_20x = ClockDomain(reset_less=True)
        self.comb += [
            self.cd_serwb_serdes.clk.eq(pll.serwb_serdes_clk),
            self.cd_serwb_serdes_5x.clk.eq(pll.serwb_serdes_5x_clk),
            self.cd_serwb_serdes_20x.clk.eq(pll.serwb_serdes_20x_clk)
        ]
        self.specials += AsyncResetSynchronizer(self.cd_serwb_serdes,
                                                ~pll.lock)
        self.comb += self.cd_serwb_serdes_5x.rst.eq(self.cd_serwb_serdes.rst)

        # control/status cdc
        tx_idle = Signal()
        tx_comma = Signal()
        rx_idle = Signal()
        rx_comma = Signal()
        rx_bitslip_value = Signal(6)
        rx_delay_rst = Signal()
        rx_delay_inc = Signal()
        rx_delay_en_vtc = Signal()
        rx_delay_ce = Signal()
        self.specials += [
            MultiReg(self.tx_idle, tx_idle, "serwb_serdes"),
            MultiReg(self.tx_comma, tx_comma, "serwb_serdes"),
            MultiReg(rx_idle, self.rx_idle, "sys"),
            MultiReg(rx_comma, self.rx_comma, "sys"),
            MultiReg(self.rx_bitslip_value, rx_bitslip_value, "serwb_serdes"),
            MultiReg(self.rx_delay_inc, rx_delay_inc, "serwb_serdes_5x"),
            MultiReg(self.rx_delay_en_vtc, rx_delay_en_vtc, "serwb_serdes_5x")
        ]
        self.submodules.do_rx_delay_rst = PulseSynchronizer(
            "sys", "serwb_serdes_5x")
        self.comb += [
            rx_delay_rst.eq(self.do_rx_delay_rst.o),
            self.do_rx_delay_rst.i.eq(self.rx_delay_rst)
        ]
        self.submodules.do_rx_delay_ce = PulseSynchronizer(
            "sys", "serwb_serdes_5x")
        self.comb += [
            rx_delay_ce.eq(self.do_rx_delay_ce.o),
            self.do_rx_delay_ce.i.eq(self.rx_delay_ce)
        ]

        # tx clock (linerate/10)
        if mode == "master":
            self.submodules.tx_clk_gearbox = Gearbox(40, "serwb_serdes", 8,
                                                     "serwb_serdes_5x")
            self.comb += self.tx_clk_gearbox.i.eq((0b1111100000 << 30)
                                                  | (0b1111100000 << 20)
                                                  | (0b1111100000 << 10)
                                                  | (0b1111100000 << 0))
            clk_o = 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,
                         i_RST=ResetSignal("serwb_serdes"),
                         i_CLK=ClockSignal("serwb_serdes_20x"),
                         i_CLKDIV=ClockSignal("serwb_serdes_5x"),
                         i_D=self.tx_clk_gearbox.o),
                Instance("OBUFDS", i_I=clk_o, o_O=pads.clk_p, o_OB=pads.clk_n)
            ]

        # tx datapath
        # tx_data -> encoders -> gearbox -> serdes
        self.submodules.tx_gearbox = Gearbox(40, "serwb_serdes", 8,
                                             "serwb_serdes_5x")
        self.comb += [
            If(tx_comma, self.encoder.k[0].eq(1),
               self.encoder.d[0].eq(0xbc)).Else(
                   self.encoder.d[0].eq(self.tx_data[0:8]),
                   self.encoder.d[1].eq(self.tx_data[8:16]),
                   self.encoder.d[2].eq(self.tx_data[16:24]),
                   self.encoder.d[3].eq(self.tx_data[24:32]))
        ]
        self.sync.serwb_serdes += \
            If(tx_idle,
                self.tx_gearbox.i.eq(0)
            ).Else(
                self.tx_gearbox.i.eq(Cat(*[self.encoder.output[i] for i in range(4)]))
            )

        serdes_o = 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=serdes_o,
                     i_RST=ResetSignal("serwb_serdes"),
                     i_CLK=ClockSignal("serwb_serdes_20x"),
                     i_CLKDIV=ClockSignal("serwb_serdes_5x"),
                     i_D=self.tx_gearbox.o),
            Instance("OBUFDS", i_I=serdes_o, o_O=pads.tx_p, o_OB=pads.tx_n)
        ]

        # rx clock
        use_bufr = True
        if mode == "slave":
            clk_i = Signal()
            clk_i_bufg = Signal()
            self.specials += [
                Instance("IBUFDS", i_I=pads.clk_p, i_IB=pads.clk_n, o_O=clk_i)
            ]
            if use_bufr:
                clk_i_bufr = Signal()
                self.specials += [
                    Instance("BUFR", i_I=clk_i, o_O=clk_i_bufr),
                    Instance("BUFG", i_I=clk_i_bufr, o_O=clk_i_bufg)
                ]
            else:
                self.specials += Instance("BUFG", i_I=clk_i, o_O=clk_i_bufg)
            self.comb += pll.refclk.eq(clk_i_bufg)

        # rx datapath
        # serdes -> gearbox -> bitslip -> decoders -> rx_data
        self.submodules.rx_gearbox = Gearbox(8, "serwb_serdes_5x", 40,
                                             "serwb_serdes")
        self.submodules.rx_bitslip = ClockDomainsRenamer("serwb_serdes")(
            BitSlip(40))

        serdes_i_nodelay = Signal()
        self.specials += [
            Instance("IBUFDS_DIFF_OUT",
                     i_I=pads.rx_p,
                     i_IB=pads.rx_n,
                     o_O=serdes_i_nodelay)
        ]

        serdes_i_delayed = Signal()
        serdes_q = Signal(8)
        self.specials += [
            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="COUNT",
                     p_DELAY_SRC="IDATAIN",
                     p_DELAY_TYPE="VARIABLE",
                     p_DELAY_VALUE=0,
                     i_CLK=ClockSignal("serwb_serdes_5x"),
                     i_RST=rx_delay_rst,
                     i_LOAD=0,
                     i_INC=rx_delay_inc,
                     i_EN_VTC=rx_delay_en_vtc,
                     i_CE=rx_delay_ce,
                     i_IDATAIN=serdes_i_nodelay,
                     o_DATAOUT=serdes_i_delayed),
            Instance("ISERDESE3",
                     p_DATA_WIDTH=8,
                     i_D=serdes_i_delayed,
                     i_RST=ResetSignal("serwb_serdes"),
                     i_FIFO_RD_CLK=0,
                     i_FIFO_RD_EN=0,
                     i_CLK=ClockSignal("serwb_serdes_20x"),
                     i_CLK_B=~ClockSignal("serwb_serdes_20x"),
                     i_CLKDIV=ClockSignal("serwb_serdes_5x"),
                     o_Q=serdes_q)
        ]

        self.comb += [
            self.rx_gearbox.i.eq(serdes_q),
            self.rx_bitslip.value.eq(rx_bitslip_value),
            self.rx_bitslip.i.eq(self.rx_gearbox.o),
            self.decoders[0].input.eq(self.rx_bitslip.o[0:10]),
            self.decoders[1].input.eq(self.rx_bitslip.o[10:20]),
            self.decoders[2].input.eq(self.rx_bitslip.o[20:30]),
            self.decoders[3].input.eq(self.rx_bitslip.o[30:40]),
            self.rx_data.eq(Cat(*[self.decoders[i].d for i in range(4)])),
            rx_idle.eq(self.rx_bitslip.o == 0),
            rx_comma.eq(
                ((self.decoders[0].d == 0xbc) & (self.decoders[0].k == 1))
                & ((self.decoders[1].d == 0x00) & (self.decoders[1].k == 0))
                & ((self.decoders[2].d == 0x00) & (self.decoders[2].k == 0))
                & ((self.decoders[3].d == 0x00) & (self.decoders[3].k == 0)))
        ]
Beispiel #17
0
    def __init__(self, pll, pads, mode="master"):
        self.tx_data = Signal(32)
        self.rx_data = Signal(32)

        self.tx_idle = Signal()
        self.tx_comma = Signal()
        self.rx_idle = Signal()
        self.rx_comma = Signal()

        self.rx_bitslip_value = Signal(6)
        self.rx_delay_rst = Signal()
        self.rx_delay_inc = Signal()
        self.rx_delay_ce = Signal()

        # # #

        self.submodules.encoder = ClockDomainsRenamer("serwb_serdes")(Encoder(
            4, True))
        self.decoders = [
            ClockDomainsRenamer("serwb_serdes")(Decoder(True))
            for _ in range(4)
        ]
        self.submodules += self.decoders

        # clocking:

        # In master mode:
        # - linerate/10 pll refclk provided by user
        # - linerate/10 slave refclk generated on clk_pads
        # In Slave mode:
        # - linerate/10 pll refclk provided by clk_pads
        self.clock_domains.cd_serwb_serdes = ClockDomain()
        self.clock_domains.cd_serwb_serdes_5x = ClockDomain()
        self.clock_domains.cd_serwb_serdes_20x = ClockDomain(reset_less=True)
        self.comb += [
            self.cd_serwb_serdes.clk.eq(pll.serwb_serdes_clk),
            self.cd_serwb_serdes_5x.clk.eq(pll.serwb_serdes_5x_clk),
            self.cd_serwb_serdes_20x.clk.eq(pll.serwb_serdes_20x_clk)
        ]
        self.specials += AsyncResetSynchronizer(self.cd_serwb_serdes,
                                                ~pll.lock)
        self.comb += self.cd_serwb_serdes_5x.rst.eq(self.cd_serwb_serdes.rst)

        # control/status cdc
        tx_idle = Signal()
        tx_comma = Signal()
        rx_idle = Signal()
        rx_comma = Signal()
        rx_bitslip_value = Signal(6)
        self.specials += [
            MultiReg(self.tx_idle, tx_idle, "serwb_serdes"),
            MultiReg(self.tx_comma, tx_comma, "serwb_serdes"),
            MultiReg(rx_idle, self.rx_idle, "sys"),
            MultiReg(rx_comma, self.rx_comma, "sys")
        ]
        self.specials += MultiReg(self.rx_bitslip_value, rx_bitslip_value,
                                  "serwb_serdes"),

        # tx clock (linerate/10)
        if mode == "master":
            self.submodules.tx_clk_gearbox = Gearbox(40, "serwb_serdes", 8,
                                                     "serwb_serdes_5x")
            self.comb += self.tx_clk_gearbox.i.eq((0b1111100000 << 30)
                                                  | (0b1111100000 << 20)
                                                  | (0b1111100000 << 10)
                                                  | (0b1111100000 << 0))
            clk_o = 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=clk_o,
                         i_OCE=1,
                         i_RST=ResetSignal("serwb_serdes"),
                         i_CLK=ClockSignal("serwb_serdes_20x"),
                         i_CLKDIV=ClockSignal("serwb_serdes_5x"),
                         i_D1=self.tx_clk_gearbox.o[0],
                         i_D2=self.tx_clk_gearbox.o[1],
                         i_D3=self.tx_clk_gearbox.o[2],
                         i_D4=self.tx_clk_gearbox.o[3],
                         i_D5=self.tx_clk_gearbox.o[4],
                         i_D6=self.tx_clk_gearbox.o[5],
                         i_D7=self.tx_clk_gearbox.o[6],
                         i_D8=self.tx_clk_gearbox.o[7]),
                Instance("OBUFDS", i_I=clk_o, o_O=pads.clk_p, o_OB=pads.clk_n)
            ]

        # tx datapath
        # tx_data -> encoders -> gearbox -> serdes
        self.submodules.tx_gearbox = Gearbox(40, "serwb_serdes", 8,
                                             "serwb_serdes_5x")
        self.comb += [
            If(tx_comma, self.encoder.k[0].eq(1),
               self.encoder.d[0].eq(0xbc)).Else(
                   self.encoder.d[0].eq(self.tx_data[0:8]),
                   self.encoder.d[1].eq(self.tx_data[8:16]),
                   self.encoder.d[2].eq(self.tx_data[16:24]),
                   self.encoder.d[3].eq(self.tx_data[24:32]))
        ]
        self.sync.serwb_serdes += \
            If(tx_idle,
                self.tx_gearbox.i.eq(0)
            ).Else(
                self.tx_gearbox.i.eq(Cat(*[self.encoder.output[i] for i in range(4)]))
            )

        serdes_o = 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=serdes_o,
                     i_OCE=1,
                     i_RST=ResetSignal("serwb_serdes"),
                     i_CLK=ClockSignal("serwb_serdes_20x"),
                     i_CLKDIV=ClockSignal("serwb_serdes_5x"),
                     i_D1=self.tx_gearbox.o[0],
                     i_D2=self.tx_gearbox.o[1],
                     i_D3=self.tx_gearbox.o[2],
                     i_D4=self.tx_gearbox.o[3],
                     i_D5=self.tx_gearbox.o[4],
                     i_D6=self.tx_gearbox.o[5],
                     i_D7=self.tx_gearbox.o[6],
                     i_D8=self.tx_gearbox.o[7]),
            Instance("OBUFDS", i_I=serdes_o, o_O=pads.tx_p, o_OB=pads.tx_n)
        ]

        # rx clock
        use_bufr = True
        if mode == "slave":
            clk_i = Signal()
            clk_i_bufg = Signal()
            self.specials += [
                Instance("IBUFDS", i_I=pads.clk_p, i_IB=pads.clk_n, o_O=clk_i)
            ]
            if use_bufr:
                clk_i_bufr = Signal()
                self.specials += [
                    Instance("BUFR", i_I=clk_i, o_O=clk_i_bufr),
                    Instance("BUFG", i_I=clk_i_bufr, o_O=clk_i_bufg)
                ]
            else:
                self.specials += Instance("BUFG", i_I=clk_i, o_O=clk_i_bufg)
            self.comb += pll.refclk.eq(clk_i_bufg)

        # rx datapath
        # serdes -> gearbox -> bitslip -> decoders -> rx_data
        self.submodules.rx_gearbox = Gearbox(8, "serwb_serdes_5x", 40,
                                             "serwb_serdes")
        self.submodules.rx_bitslip = ClockDomainsRenamer("serwb_serdes")(
            BitSlip(40))

        serdes_i_nodelay = Signal()
        self.specials += [
            Instance("IBUFDS_DIFF_OUT",
                     i_I=pads.rx_p,
                     i_IB=pads.rx_n,
                     o_O=serdes_i_nodelay)
        ]

        serdes_i_delayed = Signal()
        serdes_q = Signal(8)
        self.specials += [
            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=0,
                     i_C=ClockSignal(),
                     i_LD=self.rx_delay_rst,
                     i_CE=self.rx_delay_ce,
                     i_LDPIPEEN=0,
                     i_INC=self.rx_delay_inc,
                     i_IDATAIN=serdes_i_nodelay,
                     o_DATAOUT=serdes_i_delayed),
            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=serdes_i_delayed,
                     i_CE1=1,
                     i_RST=ResetSignal("serwb_serdes"),
                     i_CLK=ClockSignal("serwb_serdes_20x"),
                     i_CLKB=~ClockSignal("serwb_serdes_20x"),
                     i_CLKDIV=ClockSignal("serwb_serdes_5x"),
                     i_BITSLIP=0,
                     o_Q8=serdes_q[0],
                     o_Q7=serdes_q[1],
                     o_Q6=serdes_q[2],
                     o_Q5=serdes_q[3],
                     o_Q4=serdes_q[4],
                     o_Q3=serdes_q[5],
                     o_Q2=serdes_q[6],
                     o_Q1=serdes_q[7])
        ]

        self.comb += [
            self.rx_gearbox.i.eq(serdes_q),
            self.rx_bitslip.value.eq(rx_bitslip_value),
            self.rx_bitslip.i.eq(self.rx_gearbox.o),
            self.decoders[0].input.eq(self.rx_bitslip.o[0:10]),
            self.decoders[1].input.eq(self.rx_bitslip.o[10:20]),
            self.decoders[2].input.eq(self.rx_bitslip.o[20:30]),
            self.decoders[3].input.eq(self.rx_bitslip.o[30:40]),
            self.rx_data.eq(Cat(*[self.decoders[i].d for i in range(4)])),
            rx_idle.eq(self.rx_bitslip.o == 0),
            rx_comma.eq(
                ((self.decoders[0].d == 0xbc) & (self.decoders[0].k == 1))
                & ((self.decoders[1].d == 0x00) & (self.decoders[1].k == 0))
                & ((self.decoders[2].d == 0x00) & (self.decoders[2].k == 0))
                & ((self.decoders[3].d == 0x00) & (self.decoders[3].k == 0)))
        ]
Beispiel #18
0
    def __init__(self, pads, clkin_freq=None):
        self._pll_reset = CSRStorage(reset=1)
        self._locked = CSRStatus()

        # DRP
        self._pll_adr = CSRStorage(5)
        self._pll_dat_r = CSRStatus(16)
        self._pll_dat_w = CSRStorage(16)
        self._pll_read = CSR()
        self._pll_write = CSR()
        self._pll_drdy = CSRStatus()

        self.locked = Signal()
        self.serdesstrobe = Signal()
        self.clock_domains._cd_pix = ClockDomain()
        self.clock_domains._cd_pix2x = ClockDomain()
        self.clock_domains._cd_pix10x = ClockDomain(reset_less=True)

        # # #

        self.clk_input = Signal()
        self.specials += Instance("IBUFDS",
                                  name="hdmi_in_ibufds",
                                  i_I=pads.clk_p,
                                  i_IB=pads.clk_n,
                                  o_O=self.clk_input)

        clkfbout = Signal()
        pll_locked = Signal()
        pll_clk0 = Signal()
        pll_clk1 = Signal()
        pll_clk2 = Signal()
        pll_drdy = Signal()
        self.sync += If(self._pll_read.re | self._pll_write.re,
                        self._pll_drdy.status.eq(0)).Elif(
                            pll_drdy, self._pll_drdy.status.eq(1))
        self.specials += [
            Instance(
                "PLL_ADV",
                name="hdmi_in_pll_adv",
                p_CLKFBOUT_MULT=10,
                p_CLKOUT0_DIVIDE=1,  # pix10x
                p_CLKOUT1_DIVIDE=5,  # pix2x
                p_CLKOUT2_DIVIDE=10,  # pix
                p_COMPENSATION="INTERNAL",
                i_CLKINSEL=1,
                i_CLKIN1=self.clk_input,
                o_CLKOUT0=pll_clk0,
                o_CLKOUT1=pll_clk1,
                o_CLKOUT2=pll_clk2,
                o_CLKFBOUT=clkfbout,
                i_CLKFBIN=clkfbout,
                o_LOCKED=pll_locked,
                i_RST=self._pll_reset.storage,
                i_DADDR=self._pll_adr.storage,
                o_DO=self._pll_dat_r.status,
                i_DI=self._pll_dat_w.storage,
                i_DEN=self._pll_read.re | self._pll_write.re,
                i_DWE=self._pll_write.re,
                o_DRDY=pll_drdy,
                i_DCLK=ClockSignal())
        ]

        locked_async = Signal()
        self.specials += [
            Instance("BUFPLL",
                     name="hdmi_in_bufpll",
                     p_DIVIDE=5,
                     i_PLLIN=pll_clk0,
                     i_GCLK=ClockSignal("pix2x"),
                     i_LOCKED=pll_locked,
                     o_IOCLK=self._cd_pix10x.clk,
                     o_LOCK=locked_async,
                     o_SERDESSTROBE=self.serdesstrobe),
            Instance("BUFG",
                     name="hdmi_in_pix2x_bufg",
                     i_I=pll_clk1,
                     o_O=self._cd_pix2x.clk),
            Instance("BUFG",
                     name="hdmi_in_pix_bufg",
                     i_I=pll_clk2,
                     o_O=self._cd_pix.clk),
            MultiReg(locked_async, self.locked, "sys")
        ]
        self.comb += self._locked.status.eq(self.locked)

        self.specials += [
            AsyncResetSynchronizer(self._cd_pix, ~locked_async),
            AsyncResetSynchronizer(self._cd_pix2x, ~locked_async),
        ]
    def __init__(self, platform, clk_freq):
        self.clock_domains.cd_sys = ClockDomain()
        self.clock_domains.cd_sys2x = ClockDomain()
        self.clock_domains.cd_sdram_half = ClockDomain()
        self.clock_domains.cd_sdram_full_wr = ClockDomain()
        self.clock_domains.cd_sdram_full_rd = ClockDomain()
        self.clock_domains.cd_base50 = ClockDomain()
        self.clock_domains.cd_encoder = ClockDomain()

        self.clk8x_wr_strb = Signal()
        self.clk8x_rd_strb = Signal()

        self.reset = Signal()

        f0 = 100 * 1000000
        clk100 = platform.request("clk100")
        clk100a = Signal()
        self.specials += Instance("IBUFG", i_I=clk100, o_O=clk100a)
        clk100b = Signal()
        self.specials += Instance("BUFIO2",
                                  p_DIVIDE=1,
                                  p_DIVIDE_BYPASS="******",
                                  p_I_INVERT="FALSE",
                                  i_I=clk100a,
                                  o_DIVCLK=clk100b)
        f = Fraction(int(clk_freq), int(f0))
        n, m = f.denominator, f.numerator
        assert f0 / n * m == clk_freq
        p = 8
        pll_lckd = Signal()
        pll_fb = Signal()
        pll = Signal(6)
        self.specials.pll = [
            Instance(
                "PLL_ADV",
                p_SIM_DEVICE="SPARTAN6",
                p_BANDWIDTH="OPTIMIZED",
                p_COMPENSATION="INTERNAL",
                p_REF_JITTER=.01,
                p_CLK_FEEDBACK="CLKFBOUT",
                i_DADDR=0,
                i_DCLK=0,
                i_DEN=0,
                i_DI=0,
                i_DWE=0,
                i_RST=0,
                i_REL=0,
                p_DIVCLK_DIVIDE=1,
                p_CLKFBOUT_MULT=m * p // n,
                p_CLKFBOUT_PHASE=0.,
                i_CLKIN1=clk100b,
                i_CLKIN2=0,
                i_CLKINSEL=1,
                p_CLKIN1_PERIOD=1e9 / f0,
                p_CLKIN2_PERIOD=0.,
                i_CLKFBIN=pll_fb,
                o_CLKFBOUT=pll_fb,
                o_LOCKED=pll_lckd,
                o_CLKOUT0=pll[0],
                p_CLKOUT0_DUTY_CYCLE=.5,
                o_CLKOUT1=pll[1],
                p_CLKOUT1_DUTY_CYCLE=.5,
                o_CLKOUT2=pll[2],
                p_CLKOUT2_DUTY_CYCLE=.5,
                o_CLKOUT3=pll[3],
                p_CLKOUT3_DUTY_CYCLE=.5,
                o_CLKOUT4=pll[4],
                p_CLKOUT4_DUTY_CYCLE=.5,
                o_CLKOUT5=pll[5],
                p_CLKOUT5_DUTY_CYCLE=.5,
                p_CLKOUT0_PHASE=0.,
                p_CLKOUT0_DIVIDE=p // 8,  # ddr3 wr/rd full clock
                p_CLKOUT1_PHASE=0.,
                p_CLKOUT1_DIVIDE=6,  # encoder (66MHz)
                p_CLKOUT2_PHASE=230.,
                p_CLKOUT2_DIVIDE=p // 4,  # ddr3 dqs adr ctrl off-chip
                p_CLKOUT3_PHASE=210.,
                p_CLKOUT3_DIVIDE=p // 4,  # ddr3 half clock
                p_CLKOUT4_PHASE=0.,
                p_CLKOUT4_DIVIDE=p // 2,  # 2x system clock
                p_CLKOUT5_PHASE=0.,
                p_CLKOUT5_DIVIDE=p // 1),  # system clock
            Instance("BUFG", i_I=pll[4], o_O=self.cd_sys2x.clk),
            Instance("BUFG", i_I=pll[5], o_O=self.cd_sys.clk)
        ]
        reset = ~platform.request("cpu_reset") | self.reset
        self.clock_domains.cd_por = ClockDomain()
        por = Signal(max=1 << 11, reset=(1 << 11) - 1)
        self.sync.por += If(por != 0, por.eq(por - 1))
        self.comb += self.cd_por.clk.eq(self.cd_sys.clk)
        self.specials += AsyncResetSynchronizer(self.cd_por, reset)
        self.specials += AsyncResetSynchronizer(self.cd_sys2x,
                                                ~pll_lckd | (por > 0))
        self.specials += AsyncResetSynchronizer(self.cd_sys,
                                                ~pll_lckd | (por > 0))
        self.specials += Instance("BUFG",
                                  i_I=pll[2],
                                  o_O=self.cd_sdram_half.clk)
        self.specials += Instance("BUFPLL",
                                  p_DIVIDE=4,
                                  i_PLLIN=pll[0],
                                  i_GCLK=self.cd_sys2x.clk,
                                  i_LOCKED=pll_lckd,
                                  o_IOCLK=self.cd_sdram_full_wr.clk,
                                  o_SERDESSTROBE=self.clk8x_wr_strb)
        self.comb += [
            self.cd_sdram_full_rd.clk.eq(self.cd_sdram_full_wr.clk),
            self.clk8x_rd_strb.eq(self.clk8x_wr_strb),
        ]
        clk_sdram_half_shifted = Signal()
        self.specials += Instance("BUFG",
                                  i_I=pll[3],
                                  o_O=clk_sdram_half_shifted)

        output_clk = Signal()
        clk = platform.request("ddram_clock")
        self.specials += Instance("ODDR2",
                                  p_DDR_ALIGNMENT="NONE",
                                  p_INIT=0,
                                  p_SRTYPE="SYNC",
                                  i_D0=1,
                                  i_D1=0,
                                  i_S=0,
                                  i_R=0,
                                  i_CE=1,
                                  i_C0=clk_sdram_half_shifted,
                                  i_C1=~clk_sdram_half_shifted,
                                  o_Q=output_clk)
        self.specials += Instance("OBUFDS",
                                  i_I=output_clk,
                                  o_O=clk.p,
                                  o_OB=clk.n)

        dcm_base50_locked = Signal()
        self.specials += [
            Instance("DCM_CLKGEN",
                     p_CLKFXDV_DIVIDE=2,
                     p_CLKFX_DIVIDE=4,
                     p_CLKFX_MD_MAX=1.0,
                     p_CLKFX_MULTIPLY=2,
                     p_CLKIN_PERIOD=10.0,
                     p_SPREAD_SPECTRUM="NONE",
                     p_STARTUP_WAIT="FALSE",
                     i_CLKIN=clk100a,
                     o_CLKFX=self.cd_base50.clk,
                     o_LOCKED=dcm_base50_locked,
                     i_FREEZEDCM=0,
                     i_RST=ResetSignal()),
            AsyncResetSynchronizer(self.cd_base50,
                                   self.cd_sys.rst | ~dcm_base50_locked)
        ]
        platform.add_period_constraint(self.cd_base50.clk, 20)

        self.specials += Instance("BUFG", i_I=pll[1],
                                  o_O=self.cd_encoder.clk)  # 66 MHz
        self.specials += AsyncResetSynchronizer(self.cd_encoder,
                                                self.cd_sys.rst)
Beispiel #20
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"),
        ]
Beispiel #21
0
    def __init__(self, pads, clkin_freq=148.5e6):
        self._mmcm_reset = CSRStorage(reset=1)
        self._locked = CSRStatus()

        # DRP
        self._mmcm_read = CSR()
        self._mmcm_read_o = CSR()
        self._mmcm_write = CSR()
        self._mmcm_write_o = CSR()
        self._mmcm_drdy = CSRStatus()
        self._mmcm_drdy_o = CSRStatus()
        self._mmcm_adr = CSRStorage(7)
        self._mmcm_dat_w = CSRStorage(16)
        self._mmcm_dat_r = CSRStatus(16)
        self._mmcm_dat_o_r = CSRStatus(16)

        self.locked = Signal()
        self.clock_domains.cd_pix = ClockDomain()
        self.clock_domains.cd_pix_o = ClockDomain()
        self.clock_domains.cd_pix1p25x = ClockDomain()
        self.clock_domains.cd_pix5x = ClockDomain(reset_less=True)
        self.clock_domains.cd_pix5x_o = ClockDomain(reset_less=True)

        # # #

        assert clkin_freq in [74.25e6, 148.5e6]
        self.clk_input = Signal()
        clk_input_bufr = Signal()
        if hasattr(pads.clk_p, "inverted"):
            self.specials += Instance("IBUFDS_DIFF_OUT",
                                      name="hdmi_in_ibufds",
                                      i_I=pads.clk_p,
                                      i_IB=pads.clk_n,
                                      o_OB=self.clk_input)
        else:
            self.specials += Instance("IBUFDS_DIFF_OUT",
                                      name="hdmi_in_ibufds",
                                      i_I=pads.clk_p,
                                      i_IB=pads.clk_n,
                                      o_O=self.clk_input)
        self.specials += Instance("BUFG",
                                  i_I=self.clk_input,
                                  o_O=clk_input_bufr)

        mmcm_fb = Signal()
        mmcm_fb_o = Signal()
        mmcm_locked = Signal()
        mmcm_locked_o = Signal()
        mmcm_clk0 = Signal()
        mmcm_clk1 = Signal()
        mmcm_clk2 = Signal()
        mmcm_clk2_o = Signal()
        mmcm_drdy = Signal()
        mmcm_drdy_o = Signal()

        self.specials += [
            Instance(
                "MMCME2_ADV",
                p_BANDWIDTH="OPTIMIZED",
                i_RST=self._mmcm_reset.storage,
                o_LOCKED=mmcm_locked,

                # VCO
                p_REF_JITTER1=0.01,
                p_CLKIN1_PERIOD=7.2,  #6.734
                p_CLKFBOUT_MULT_F=5.0,
                p_CLKFBOUT_PHASE=0.000,
                p_DIVCLK_DIVIDE=1,
                i_CLKIN1=clk_input_bufr,
                i_CLKFBIN=mmcm_fb_o,
                o_CLKFBOUT=mmcm_fb,

                # pix clk
                p_CLKOUT0_DIVIDE_F=5,
                p_CLKOUT0_PHASE=0.000,
                o_CLKOUT0=mmcm_clk0,
                # pix1p25x clk
                p_CLKOUT1_DIVIDE=4,
                p_CLKOUT1_PHASE=0.000,
                o_CLKOUT1=mmcm_clk1,
                # pix5x clk
                p_CLKOUT2_DIVIDE=1,
                p_CLKOUT2_PHASE=0.000,
                o_CLKOUT2=mmcm_clk2,

                # DRP
                i_DCLK=ClockSignal(),
                i_DWE=self._mmcm_write.re,
                i_DEN=self._mmcm_read.re | self._mmcm_write.re,
                o_DRDY=mmcm_drdy,
                i_DADDR=self._mmcm_adr.storage,
                i_DI=self._mmcm_dat_w.storage,
                o_DO=self._mmcm_dat_r.status),
            Instance("BUFG", i_I=mmcm_clk0, o_O=self.cd_pix.clk),
            Instance("BUFR", i_I=mmcm_clk1, o_O=self.cd_pix1p25x.clk),
            Instance("BUFIO", i_I=mmcm_clk2, o_O=self.cd_pix5x.clk),
            Instance(
                "BUFG", i_I=mmcm_fb, o_O=mmcm_fb_o
            ),  # compensate this delay to minimize phase offset with slave
        ]

        mmcm_fb_o = Signal()
        mmcm_clk0_o = Signal()
        self.specials += [
            Instance(
                "MMCME2_ADV",
                p_BANDWIDTH="LOW",
                i_RST=self._mmcm_reset.storage,
                o_LOCKED=mmcm_locked_o,

                # VCO
                p_REF_JITTER1=0.01,
                p_CLKIN1_PERIOD=6.734,
                p_CLKFBOUT_MULT_F=5.0,
                p_CLKFBOUT_PHASE=0.000,
                p_DIVCLK_DIVIDE=1,
                i_CLKIN1=
                mmcm_clk0,  # uncompesated delay for best phase match between master/slave
                i_CLKFBIN=mmcm_fb_o,
                o_CLKFBOUT=mmcm_fb_o,

                # pix clk
                p_CLKOUT0_DIVIDE_F=5,
                p_CLKOUT0_PHASE=0.000,
                o_CLKOUT0=mmcm_clk0_o,
                p_CLKOUT2_DIVIDE=1,
                p_CLKOUT2_PHASE=0.000,
                o_CLKOUT2=mmcm_clk2_o,

                # DRP
                i_DCLK=ClockSignal(),
                i_DWE=self._mmcm_write_o.re,
                i_DEN=self._mmcm_read_o.re | self._mmcm_write_o.re,
                o_DRDY=mmcm_drdy_o,
                i_DADDR=self._mmcm_adr.storage,
                i_DI=self._mmcm_dat_w.storage,
                o_DO=self._mmcm_dat_o_r.status),
            Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_pix_o.clk),
            Instance("BUFIO", i_I=mmcm_clk2_o, o_O=self.cd_pix5x_o.clk),
        ]

        self.sync += [
            If(self._mmcm_read.re | self._mmcm_write.re,
               self._mmcm_drdy.status.eq(0)).Elif(mmcm_drdy,
                                                  self._mmcm_drdy.status.eq(1))
        ]
        self.sync += [
            If(self._mmcm_read_o.re | self._mmcm_write_o.re,
               self._mmcm_drdy_o.status.eq(0)).Elif(
                   mmcm_drdy_o, self._mmcm_drdy_o.status.eq(1))
        ]
        self.specials += MultiReg(mmcm_locked, self.locked, "sys")
        self.comb += self._locked.status.eq(self.locked)

        self.specials += [
            AsyncResetSynchronizer(self.cd_pix, ~mmcm_locked),
            AsyncResetSynchronizer(self.cd_pix_o, ~mmcm_locked_o),
            AsyncResetSynchronizer(self.cd_pix1p25x, ~mmcm_locked),
        ]
Beispiel #22
0
    def __init__(self, pll, tx_pads, sys_clk_freq, polarity=0):
        self.prbs_config = Signal(2)

        self.produce_square_wave = CSRStorage()

        self.txdiffcttrl = CSRStorage(4, reset=0b1000)
        self.txmaincursor = CSRStorage(7, reset=80)
        self.txprecursor = CSRStorage(5)
        self.txpostcursor = CSRStorage(5)

        # # #

        use_cpll = isinstance(pll, GTXChannelPLL)
        use_qpll = isinstance(pll, GTXQuadPLL)

        self.submodules.init = GTXInit(sys_clk_freq, False)
        self.comb += [
            self.init.plllock.eq(pll.lock),
            pll.reset.eq(self.init.pllreset)
        ]

        nwords = 40 // 10

        txoutclk = Signal()
        txdata = Signal(40)
        self.specials += \
            Instance("GTXE2_CHANNEL",
                # PMA Attributes
                p_PMA_RSV=0x00018480,
                p_PMA_RSV2=0x2050,
                p_PMA_RSV3=0,
                p_PMA_RSV4=0,
                p_RX_BIAS_CFG=0b100,
                p_RX_CM_TRIM=0b010,
                p_RX_OS_CFG=0b10000000,
                p_RX_CLK25_DIV=5,
                p_TX_CLK25_DIV=5,

                # Power-Down Attributes
                p_PD_TRANS_TIME_FROM_P2=0x3c,
                p_PD_TRANS_TIME_NONE_P2=0x3c,
                p_PD_TRANS_TIME_TO_P2=0x64,

                # CPLL
                p_CPLL_CFG=0xBC07DC,
                p_CPLL_FBDIV=1 if use_qpll else pll.config["n2"],
                p_CPLL_FBDIV_45=4 if use_qpll else pll.config["n1"],
                p_CPLL_REFCLK_DIV=1 if use_qpll else pll.config["m"],
                p_RXOUT_DIV=pll.config["d"],
                p_TXOUT_DIV=pll.config["d"],
                i_CPLLRESET=0 if use_qpll else pll.reset,
                o_CPLLLOCK=Signal() if use_qpll else pll.lock,
                i_CPLLLOCKEN=1,
                i_CPLLREFCLKSEL=0b001,
                i_TSTIN=2**20-1,
                i_GTREFCLK0=0 if use_qpll else pll.refclk,

                # QPLL
                i_QPLLCLK=0 if use_cpll else pll.clk,
                i_QPLLREFCLK=0 if use_cpll else pll.refclk,

                # TX clock
                p_TXBUF_EN="FALSE",
                p_TX_XCLK_SEL="TXUSR",
                o_TXOUTCLK=txoutclk,
                i_TXSYSCLKSEL=0b11 if use_qpll else 0b00,
                i_TXOUTCLKSEL=0b11,

                # disable RX
                i_RXPD=0b11,

                # Startup/Reset
                i_GTTXRESET=self.init.gtXxreset,
                o_TXRESETDONE=self.init.Xxresetdone,
                i_TXDLYSRESET=self.init.Xxdlysreset,
                o_TXDLYSRESETDONE=self.init.Xxdlysresetdone,
                o_TXPHALIGNDONE=self.init.Xxphaligndone,
                i_TXUSERRDY=self.init.Xxuserrdy,

                # TX data
                p_TX_DATA_WIDTH=40,
                p_TX_INT_DATAWIDTH=1,
                i_TXCHARDISPMODE=Cat(*[txdata[10*i+9] for i in range(nwords)]),
                i_TXCHARDISPVAL=Cat(*[txdata[10*i+8] for i in range(nwords)]),
                i_TXDATA=Cat(*[txdata[10*i:10*i+8] for i in range(nwords)]),
                i_TXUSRCLK=ClockSignal("tx"),
                i_TXUSRCLK2=ClockSignal("tx"),

                # TX electrical
                i_TXBUFDIFFCTRL=0b100,
                i_TXDIFFCTRL=self.txdiffcttrl.storage,
                p_TX_MAINCURSOR_SEL=1,
                i_TXMAINCURSOR=self.txmaincursor.storage,
                i_TXPRECURSOR=self.txprecursor.storage,
                i_TXPOSTCURSOR=self.txpostcursor.storage,

                # Polarity
                i_TXPOLARITY=polarity,

                # Pads
                o_GTXTXP=tx_pads.txp,
                o_GTXTXN=tx_pads.txn
            )

        self.clock_domains.cd_tx = ClockDomain()
        self.specials += Instance("BUFH", i_I=txoutclk, o_O=self.cd_tx.clk)
        self.specials += AsyncResetSynchronizer(self.cd_tx, ~self.init.done)

        self.submodules.encoder = ClockDomainsRenamer("tx")(Encoder(
            nwords, True))
        self.submodules.prbs = ClockDomainsRenamer("tx")(PRBSTX(40, True))
        self.comb += [
            self.prbs.config.eq(self.prbs_config),
            self.prbs.i.eq(
                Cat(*[self.encoder.output[i] for i in range(nwords)])),
            If(
                self.produce_square_wave.storage,
                # square wave @ linerate/40 for scope observation
                txdata.eq(0b1111111111111111111100000000000000000000)).Else(
                    txdata.eq(self.prbs.o))
        ]
    def __init__(self,
                 platform,
                 usb_connector=0,
                 with_usb2=True,
                 with_usb2_analyzer=False,
                 with_usb3=True,
                 with_usb3_analyzer=False):
        BaseSoC.__init__(self, platform)

        # usb ios
        usb_reset_n = platform.request("usb_reset_n", usb_connector)
        if with_usb2:
            usb_ulpi = platform.request("usb_ulpi", usb_connector)
        if with_usb3:
            usb_pipe_ctrl = platform.request("usb_pipe_ctrl", usb_connector)
            usb_pipe_status = platform.request("usb_pipe_status",
                                               usb_connector)
            usb_pipe_data = platform.request("usb_pipe_data", usb_connector)

        usb2_reset_n = Signal(reset=1)
        usb3_reset_n = Signal(reset=1)
        self.comb += usb_reset_n.eq(usb2_reset_n & usb3_reset_n)

        # usb2 core
        if with_usb2:

            class USB2Control(Module, AutoCSR):
                def __init__(self):
                    self._phy_enable = CSRStorage()
                    self._core_enable = CSRStorage()

                    # probably not working but prevent synthesis optimizations
                    self._buf_in_addr = CSRStorage(9)
                    self._buf_in_data = CSRStorage(8)
                    self._buf_in_wren = CSR()
                    self._buf_in_ready = CSRStatus()
                    self._buf_in_commit = CSR()
                    self._buf_in_commit_len = CSRStorage(10)
                    self._buf_in_commit_ack = CSRStatus()

                    self._buf_out_addr = CSRStorage(9)
                    self._buf_out_q = CSRStatus(8)
                    self._buf_out_len = CSRStatus(10)
                    self._buf_out_hasdata = CSRStatus()
                    self._buf_out_arm = CSR()
                    self._buf_out_arm_ack = CSRStatus()

                    # # #

                    self.phy_enable = self._phy_enable.storage
                    self.core_enable = self._core_enable.storage

                    self.buf_in_addr = self._buf_in_addr.storage
                    self.buf_in_data = self._buf_in_data.storage
                    self.buf_in_wren = self._buf_in_wren.re & self._buf_in_wren.r
                    self.buf_in_ready = self._buf_in_ready.status
                    self.buf_in_commit = self._buf_in_commit.re & self._buf_in_commit.r
                    self.buf_in_commit_len = self._buf_in_commit_len.storage
                    self.buf_in_commit_ack = self._buf_in_commit_ack.status

                    self.buf_out_addr = self._buf_out_addr.storage
                    self.buf_out_q = self._buf_out_q.status
                    self.buf_out_len = self._buf_out_len.status
                    self.buf_out_hasdata = self._buf_out_hasdata.status
                    self.buf_out_arm = self._buf_out_arm.re & self._buf_out_arm.r
                    self.buf_out_arm_ack = self._buf_out_arm_ack.status

            self.submodules.usb2_control = USB2Control()

            self.clock_domains.cd_ulpi = ClockDomain()
            self.comb += self.cd_ulpi.clk.eq(usb_ulpi.clk)

            self.cd_ulpi.clk.attr.add("keep")
            self.platform.add_period_constraint(self.cd_ulpi.clk, 16.667)
            self.platform.add_false_path_constraints(self.crg.cd_sys.clk,
                                                     self.cd_ulpi.clk)

            stat_connected = Signal()
            stat_fs = Signal()
            stat_hs = Signal()
            stat_configured = Signal()

            vend_req_act = Signal()
            vend_req_request = Signal(8)
            vend_req_val = Signal(16)

            err_crc_pid = Signal()
            err_crc_tok = Signal()
            err_crc_pkt = Signal()
            err_pid_out_of_seq = Signal()
            err_setup_pkt = Signal()

            dbg_frame_num = Signal(11)
            dbg_linestate = Signal(2)

            self.comb += usb2_reset_n.eq(self.usb2_control.phy_enable)
            self.specials += Instance(
                "usb2_top",
                i_ext_clk=ClockSignal(),
                i_reset_n=self.usb2_control.core_enable,
                #o_reset_n_out=,
                i_phy_ulpi_clk=usb_ulpi.clk,
                io_phy_ulpi_d=usb_ulpi.data,
                i_phy_ulpi_dir=usb_ulpi.dir,
                o_phy_ulpi_stp=usb_ulpi.stp,
                i_phy_ulpi_nxt=usb_ulpi.nxt,
                i_opt_disable_all=0,
                i_opt_enable_hs=0,
                i_opt_ignore_vbus=0,
                o_stat_connected=stat_connected,
                o_stat_fs=stat_fs,
                o_stat_hs=stat_hs,
                o_stat_configured=stat_configured,
                i_buf_in_addr=self.usb2_control.buf_in_addr,
                i_buf_in_data=self.usb2_control.buf_in_data,
                i_buf_in_wren=self.usb2_control.buf_in_wren,
                o_buf_in_ready=self.usb2_control.buf_in_ready,
                i_buf_in_commit=self.usb2_control.buf_in_commit,
                i_buf_in_commit_len=self.usb2_control.buf_in_commit_len,
                o_buf_in_commit_ack=self.usb2_control.buf_in_commit_ack,
                i_buf_out_addr=self.usb2_control.buf_out_addr,
                o_buf_out_q=self.usb2_control.buf_out_q,
                o_buf_out_len=self.usb2_control.buf_out_len,
                o_buf_out_hasdata=self.usb2_control.buf_out_hasdata,
                i_buf_out_arm=self.usb2_control.buf_out_arm,
                o_buf_out_arm_ack=self.usb2_control.buf_out_arm_ack,
                o_vend_req_act=vend_req_act,
                o_vend_req_request=vend_req_request,
                o_vend_req_val=vend_req_val,
                o_err_crc_pid=err_crc_pid,
                o_err_crc_tok=err_crc_tok,
                o_err_crc_pkt=err_crc_pkt,
                o_err_pid_out_of_seq=err_pid_out_of_seq,
                o_err_setup_pkt=err_setup_pkt,
                o_dbg_frame_num=dbg_frame_num,
                o_dbg_linestate=dbg_linestate)
            platform.add_verilog_include_path(os.path.join("core"))
            platform.add_verilog_include_path(os.path.join("core", "usb2"))
            platform.add_source_dir(os.path.join("core", "usb2"))

            # usb2 debug
            if with_usb2_analyzer:
                analyzer_signals = [
                    dbg_frame_num, dbg_linestate, stat_connected, stat_fs,
                    stat_hs, stat_configured, vend_req_act, vend_req_request,
                    vend_req_val, err_crc_pid, err_crc_tok, err_crc_pkt,
                    err_pid_out_of_seq, err_setup_pkt
                ]
                self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals,
                                                             2048,
                                                             cd="ulpi")

        # usb3 core
        if with_usb3:

            class USB3Control(Module, AutoCSR):
                def __init__(self):
                    self._phy_enable = CSRStorage()
                    self._core_enable = CSRStorage()

                    # probably not working but prevent synthesis optimizations
                    self._buf_in_addr = CSRStorage(9)
                    self._buf_in_data = CSRStorage(32)
                    self._buf_in_wren = CSR()
                    self._buf_in_request = CSRStatus()
                    self._buf_in_ready = CSRStatus()
                    self._buf_in_commit = CSR()
                    self._buf_in_commit_len = CSRStorage(11)
                    self._buf_in_commit_ack = CSRStatus()

                    self._buf_out_addr = CSRStorage(9)
                    self._buf_out_q = CSRStatus(32)
                    self._buf_out_len = CSRStatus(11)
                    self._buf_out_hasdata = CSRStatus()
                    self._buf_out_arm = CSR()
                    self._buf_out_arm_ack = CSRStatus()

                    # # #

                    self.phy_enable = self._phy_enable.storage
                    self.core_enable = self._core_enable.storage

                    self.buf_in_addr = self._buf_in_addr.storage
                    self.buf_in_data = self._buf_in_data.storage
                    self.buf_in_wren = self._buf_in_wren.re & self._buf_in_wren.r
                    self.buf_in_request = self._buf_in_request.status
                    self.buf_in_ready = self._buf_in_ready.status
                    self.buf_in_commit = self._buf_in_commit.re & self._buf_in_commit.r
                    self.buf_in_commit_len = self._buf_in_commit_len.storage
                    self.buf_in_commit_ack = self._buf_in_commit_ack.status

                    self.buf_out_addr = self._buf_out_addr.storage
                    self.buf_out_q = self._buf_out_q.status
                    self.buf_out_len = self._buf_out_len.status
                    self.buf_out_hasdata = self._buf_out_hasdata.status
                    self.buf_out_arm = self._buf_out_arm.re & self._buf_out_arm.r
                    self.buf_out_arm_ack = self._buf_out_arm_ack.status

            self.submodules.usb3_control = USB3Control()

            phy_pipe_pll_locked = Signal()
            phy_pipe_pll_fb = Signal()

            phy_pipe_half_clk_pll = Signal()
            phy_pipe_half_clk_phase_pll = Signal()
            phy_pipe_quarter_clk_pll = Signal()
            phy_pipe_tx_clk_phase_pll = Signal()

            phy_pipe_half_clk = Signal()
            phy_pipe_half_clk_phase = Signal()
            phy_pipe_quarter_clk = Signal()
            phy_pipe_tx_clk_phase = Signal()

            self.specials += [
                Instance(
                    "PLLE2_BASE",
                    p_STARTUP_WAIT="FALSE",
                    o_LOCKED=phy_pipe_pll_locked,

                    # VCO @ 1GHz
                    p_REF_JITTER1=0.01,
                    p_CLKIN1_PERIOD=4.0,
                    p_CLKFBOUT_MULT=4,
                    p_DIVCLK_DIVIDE=1,
                    i_CLKIN1=usb_pipe_data.rx_clk,
                    i_CLKFBIN=phy_pipe_pll_fb,
                    o_CLKFBOUT=phy_pipe_pll_fb,

                    # 125MHz: 1/2 PCLK
                    p_CLKOUT0_DIVIDE=8,
                    p_CLKOUT0_PHASE=0.0,
                    o_CLKOUT0=phy_pipe_half_clk_pll,

                    # 125MHz: 1/2 PCLK, phase shift 90
                    p_CLKOUT1_DIVIDE=8,
                    p_CLKOUT1_PHASE=90.0,
                    o_CLKOUT1=phy_pipe_half_clk_phase_pll,

                    # 62.5MHz: 1/4 PCLK
                    p_CLKOUT2_DIVIDE=16,
                    p_CLKOUT2_PHASE=0.0,
                    o_CLKOUT2=phy_pipe_quarter_clk_pll,

                    # 250Mhz: TX CLK, phase shift 90
                    p_CLKOUT3_DIVIDE=4,
                    p_CLKOUT3_PHASE=90.0,
                    o_CLKOUT3=phy_pipe_tx_clk_phase_pll),
                Instance("BUFG",
                         i_I=phy_pipe_half_clk_pll,
                         o_O=phy_pipe_half_clk),
                Instance("BUFG",
                         i_I=phy_pipe_half_clk_phase_pll,
                         o_O=phy_pipe_half_clk_phase),
                Instance("BUFG",
                         i_I=phy_pipe_quarter_clk_pll,
                         o_O=phy_pipe_quarter_clk),
                Instance("BUFG",
                         i_I=phy_pipe_tx_clk_phase_pll,
                         o_O=phy_pipe_tx_clk_phase),
            ]

            self.clock_domains.cd_phy_pipe_half = ClockDomain()
            self.clock_domains.cd_phy_pipe_half_phase = ClockDomain()
            self.clock_domains.cd_phy_pipe_quarter = ClockDomain()
            self.clock_domains.cd_phy_pipe_tx_phase = ClockDomain()
            self.comb += [
                self.cd_phy_pipe_half.clk.eq(phy_pipe_half_clk),
                self.cd_phy_pipe_half_phase.clk.eq(phy_pipe_half_clk_phase),
                self.cd_phy_pipe_quarter.clk.eq(phy_pipe_quarter_clk),
                self.cd_phy_pipe_tx_phase.clk.eq(phy_pipe_tx_clk_phase)
            ]
            self.specials += [
                AsyncResetSynchronizer(self.cd_phy_pipe_half,
                                       ~phy_pipe_pll_locked),
                AsyncResetSynchronizer(self.cd_phy_pipe_half_phase,
                                       ~phy_pipe_pll_locked),
                AsyncResetSynchronizer(self.cd_phy_pipe_quarter,
                                       ~phy_pipe_pll_locked),
                AsyncResetSynchronizer(self.cd_phy_pipe_tx_phase,
                                       ~phy_pipe_pll_locked)
            ]
            self.cd_phy_pipe_half.clk.attr.add("keep")
            self.cd_phy_pipe_half_phase.clk.attr.add("keep")
            self.cd_phy_pipe_quarter.clk.attr.add("keep")
            self.cd_phy_pipe_tx_phase.clk.attr.add("keep")
            self.platform.add_period_constraint(self.cd_phy_pipe_half.clk, 8.0)
            self.platform.add_period_constraint(
                self.cd_phy_pipe_half_phase.clk, 8.0)
            self.platform.add_period_constraint(self.cd_phy_pipe_quarter.clk,
                                                16.0)
            self.platform.add_period_constraint(self.cd_phy_pipe_tx_phase.clk,
                                                4.0)
            self.platform.add_false_path_constraints(
                self.crg.cd_sys.clk, self.cd_phy_pipe_half.clk,
                self.cd_phy_pipe_half_phase.clk, self.cd_phy_pipe_quarter.clk,
                self.cd_phy_pipe_tx_phase.clk)

            phy_pipe_rx_data = Signal(32)
            phy_pipe_rx_datak = Signal(4)
            phy_pipe_rx_valid = Signal(2)

            phy_pipe_tx_data = Signal(32)
            phy_pipe_tx_datak = Signal(4)

            phy_rx_status = Signal(6)
            phy_phy_status = Signal(2)

            dbg_pipe_state = Signal(6)
            dbg_ltssm_state = Signal(5)

            usb_pipe_status_phy_status = Signal()
            self.specials += Tristate(usb_pipe_status.phy_status, 0,
                                      ~usb3_reset_n,
                                      usb_pipe_status_phy_status)

            self.comb += usb3_reset_n.eq(self.usb3_control.phy_enable)
            self.specials += Instance(
                "usb3_top",
                i_ext_clk=ClockSignal(),
                i_reset_n=self.usb3_control.core_enable,
                i_phy_pipe_half_clk=ClockSignal("phy_pipe_half"),
                i_phy_pipe_half_clk_phase=ClockSignal("phy_pipe_half_phase"),
                i_phy_pipe_quarter_clk=ClockSignal("phy_pipe_quarter"),
                i_phy_pipe_rx_data=phy_pipe_rx_data,
                i_phy_pipe_rx_datak=phy_pipe_rx_datak,
                i_phy_pipe_rx_valid=phy_pipe_rx_valid,
                o_phy_pipe_tx_data=phy_pipe_tx_data,
                o_phy_pipe_tx_datak=phy_pipe_tx_datak,

                #o_phy_reset_n=,
                #o_phy_out_enable=,
                o_phy_phy_reset_n=usb_pipe_ctrl.phy_reset_n,
                o_phy_tx_detrx_lpbk=usb_pipe_ctrl.tx_detrx_lpbk,
                o_phy_tx_elecidle=usb_pipe_ctrl.tx_elecidle,
                io_phy_rx_elecidle=usb_pipe_status.rx_elecidle,
                i_phy_rx_status=phy_rx_status,
                o_phy_power_down=usb_pipe_ctrl.power_down,
                i_phy_phy_status_i=phy_phy_status,
                #o_phy_phy_status_o=,
                i_phy_pwrpresent=usb_pipe_status.pwr_present,
                o_phy_tx_oneszeros=usb_pipe_ctrl.tx_oneszeros,
                o_phy_tx_deemph=usb_pipe_ctrl.tx_deemph,
                o_phy_tx_margin=usb_pipe_ctrl.tx_margin,
                o_phy_tx_swing=usb_pipe_ctrl.tx_swing,
                o_phy_rx_polarity=usb_pipe_ctrl.rx_polarity,
                o_phy_rx_termination=usb_pipe_ctrl.rx_termination,
                o_phy_rate=usb_pipe_ctrl.rate,
                o_phy_elas_buf_mode=usb_pipe_ctrl.elas_buf_mode,
                i_buf_in_addr=self.usb3_control.buf_in_addr,
                i_buf_in_data=self.usb3_control.buf_in_data,
                i_buf_in_wren=self.usb3_control.buf_in_wren,
                o_buf_in_request=self.usb3_control.buf_in_request,
                o_buf_in_ready=self.usb3_control.buf_in_ready,
                i_buf_in_commit=self.usb3_control.buf_in_commit,
                i_buf_in_commit_len=self.usb3_control.buf_in_commit_len,
                o_buf_in_commit_ack=self.usb3_control.buf_in_commit_ack,
                i_buf_out_addr=self.usb3_control.buf_out_addr,
                o_buf_out_q=self.usb3_control.buf_out_q,
                o_buf_out_len=self.usb3_control.buf_out_len,
                o_buf_out_hasdata=self.usb3_control.buf_out_hasdata,
                i_buf_out_arm=self.usb3_control.buf_out_arm,
                o_buf_out_arm_ack=self.usb3_control.buf_out_arm_ack,

                #o_vend_req_act=,
                #o_vend_req_request=,
                #o_vend_req_val=,
                o_dbg_pipe_state=dbg_pipe_state,
                o_dbg_ltssm_state=dbg_ltssm_state)
            platform.add_verilog_include_path(os.path.join("core"))
            platform.add_verilog_include_path(os.path.join("core", "usb3"))
            platform.add_source_dir(os.path.join("core", "usb3"))

            # ddr inputs
            self.specials += Instance(
                "IDDR",
                p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
                i_C=ClockSignal("phy_pipe_half"),
                i_CE=1,
                i_S=0,
                i_R=0,
                i_D=usb_pipe_data.rx_valid,
                o_Q1=phy_pipe_rx_valid[0],
                o_Q2=phy_pipe_rx_valid[1],
            )
            for i in range(16):
                self.specials += Instance(
                    "IDDR",
                    p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
                    i_C=ClockSignal("phy_pipe_half"),
                    i_CE=1,
                    i_S=0,
                    i_R=0,
                    i_D=usb_pipe_data.rx_data[i],
                    o_Q1=phy_pipe_rx_data[i],
                    o_Q2=phy_pipe_rx_data[16 + i],
                )
            for i in range(2):
                self.specials += Instance(
                    "IDDR",
                    p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
                    i_C=ClockSignal("phy_pipe_half"),
                    i_CE=1,
                    i_S=0,
                    i_R=0,
                    i_D=usb_pipe_data.rx_datak[i],
                    o_Q1=phy_pipe_rx_datak[i],
                    o_Q2=phy_pipe_rx_datak[2 + i],
                )
            for i in range(3):
                self.specials += Instance(
                    "IDDR",
                    p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
                    i_C=ClockSignal("phy_pipe_half"),
                    i_CE=1,
                    i_S=0,
                    i_R=0,
                    i_D=usb_pipe_status.rx_status[i],
                    o_Q1=phy_rx_status[i],
                    o_Q2=phy_rx_status[3 + i],
                )
            self.specials += Instance(
                "IDDR",
                p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
                i_C=ClockSignal("phy_pipe_half"),
                i_CE=1,
                i_S=0,
                i_R=0,
                i_D=usb_pipe_status_phy_status,
                o_Q1=phy_phy_status[0],
                o_Q2=phy_phy_status[1],
            )

            # ddr outputs
            self.specials += Instance(
                "ODDR",
                p_DDR_CLK_EDGE="SAME_EDGE",
                i_C=ClockSignal("phy_pipe_tx_phase"),
                i_CE=1,
                i_S=0,
                i_R=0,
                i_D1=1,
                i_D2=0,
                o_Q=usb_pipe_data.tx_clk,
            )
            for i in range(16):
                self.specials += Instance(
                    "ODDR",
                    p_DDR_CLK_EDGE="SAME_EDGE",
                    i_C=ClockSignal("phy_pipe_half_phase"),
                    i_CE=1,
                    i_S=0,
                    i_R=0,
                    i_D1=phy_pipe_tx_data[i],
                    i_D2=phy_pipe_tx_data[16 + i],
                    o_Q=usb_pipe_data.tx_data[i],
                )
            for i in range(2):
                self.specials += Instance(
                    "ODDR",
                    p_DDR_CLK_EDGE="SAME_EDGE",
                    i_C=ClockSignal("phy_pipe_half_phase"),
                    i_CE=1,
                    i_S=0,
                    i_R=0,
                    i_D1=phy_pipe_tx_datak[i],
                    i_D2=phy_pipe_tx_datak[2 + i],
                    o_Q=usb_pipe_data.tx_datak[i],
                )

            # usb3 debug
            if with_usb3_analyzer:
                analyzer_signals = [
                    dbg_pipe_state, dbg_ltssm_state,
                    usb_pipe_ctrl.tx_detrx_lpbk, usb_pipe_ctrl.tx_elecidle,
                    usb_pipe_status.rx_elecidle, usb_pipe_ctrl.power_down,
                    usb_pipe_status.phy_status, usb_pipe_status.pwr_present,
                    usb_pipe_ctrl.tx_oneszeros, usb_pipe_ctrl.tx_deemph,
                    usb_pipe_ctrl.tx_margin, usb_pipe_ctrl.tx_swing,
                    usb_pipe_ctrl.rx_polarity, usb_pipe_ctrl.rx_termination,
                    usb_pipe_ctrl.rate, usb_pipe_ctrl.elas_buf_mode,
                    phy_pipe_rx_valid, phy_pipe_rx_data, phy_pipe_rx_datak,
                    phy_pipe_tx_data, phy_pipe_tx_datak
                ]
                self.submodules.analyzer = LiteScopeAnalyzer(
                    analyzer_signals, 2048, cd="phy_pipe_half")
Beispiel #24
0
    def __init__(self,
                 pll,
                 tx_pads,
                 rx_pads,
                 sys_clk_freq,
                 dw=20,
                 mode="master"):
        assert (dw == 20) or (dw == 40)
        assert mode in ["master", "slave"]

        # # #

        nwords = dw // 10

        use_cpll = isinstance(pll, GTHChannelPLL)
        use_qpll0 = isinstance(pll,
                               GTHQuadPLL) and pll.config["qpll"] == "qpll0"
        use_qpll1 = isinstance(pll,
                               GTHQuadPLL) and pll.config["qpll"] == "qpll1"

        self.submodules.encoder = encoder = ClockDomainsRenamer("rtio_tx")(
            Encoder(nwords, True))
        self.submodules.decoders = decoders = [
            ClockDomainsRenamer("rtio_rx")((Decoder(True)))
            for _ in range(nwords)
        ]
        self.rx_ready = Signal()

        self.rtio_clk_freq = pll.config["linerate"] / dw

        # transceiver direct clock outputs
        # useful to specify clock constraints in a way palatable to Vivado
        self.txoutclk = Signal()
        self.rxoutclk = Signal()

        # # #

        # TX generates RTIO clock, init must be in system domain
        tx_init = GTHInit(sys_clk_freq, False)
        # RX receives restart commands from RTIO domain
        rx_init = ClockDomainsRenamer("rtio_tx")(GTHInit(
            self.rtio_clk_freq, True))
        self.submodules += tx_init, rx_init
        self.comb += [
            tx_init.plllock.eq(pll.lock),
            rx_init.plllock.eq(pll.lock)
        ]

        txdata = Signal(dw)
        rxdata = Signal(dw)
        rxphaligndone = Signal()
        self.specials += \
            Instance("GTHE3_CHANNEL",
                # Reset modes
                i_GTRESETSEL=0,
                i_RESETOVRD=0,

                # PMA Attributes
                p_PMA_RSV1=0xf800,
                p_RX_BIAS_CFG0=0x0AB4,
                p_RX_CM_TRIM=0b1010,
                p_RX_CLK25_DIV=5,
                p_TX_CLK25_DIV=5,

                # Power-Down Attributes
                p_PD_TRANS_TIME_FROM_P2=0x3c,
                p_PD_TRANS_TIME_NONE_P2=0x19,
                p_PD_TRANS_TIME_TO_P2=0x64,

                # CPLL
                p_CPLL_CFG0=0x67f8,
                p_CPLL_CFG1=0xa4ac,
                p_CPLL_CFG2=0xf007,
                p_CPLL_CFG3=0x0000,
                p_CPLL_FBDIV=1 if use_qpll0 or use_qpll1 else pll.config["n2"],
                p_CPLL_FBDIV_45=4 if use_qpll0 or use_qpll1 else pll.config["n1"],
                p_CPLL_REFCLK_DIV=1 if use_qpll0 or use_qpll1 else pll.config["m"],
                p_RXOUT_DIV=pll.config["d"],
                p_TXOUT_DIV=pll.config["d"],
                i_CPLLRESET=0,
                i_CPLLPD=0 if use_qpll0 or use_qpll1 else pll.reset,
                o_CPLLLOCK=Signal() if use_qpll0 or use_qpll1 else pll.lock,
                i_CPLLLOCKEN=1,
                i_CPLLREFCLKSEL=0b001,
                i_TSTIN=2**20-1,
                i_GTREFCLK0=0 if use_qpll0 or use_qpll1 else pll.refclk,

                # QPLL
                i_QPLL0CLK=0 if use_cpll or use_qpll1 else pll.clk,
                i_QPLL0REFCLK=0 if use_cpll or use_qpll1 else pll.refclk,
                i_QPLL1CLK=0 if use_cpll or use_qpll0 else pll.clk,
                i_QPLL1REFCLK=0 if use_cpll or use_qpll0 else pll.refclk,

                # TX clock
                p_TXBUF_EN="FALSE",
                p_TX_XCLK_SEL="TXUSR",
                o_TXOUTCLK=self.txoutclk,
                i_TXSYSCLKSEL=0b00 if use_cpll else 0b10 if use_qpll0 else 0b11,
                i_TXPLLCLKSEL=0b00 if use_cpll else 0b11 if use_qpll0 else 0b10,
                i_TXOUTCLKSEL=0b11,

                # TX Startup/Reset
                i_GTTXRESET=tx_init.gtXxreset,
                o_TXRESETDONE=tx_init.Xxresetdone,
                i_TXDLYSRESET=tx_init.Xxdlysreset,
                o_TXDLYSRESETDONE=tx_init.Xxdlysresetdone,
                o_TXPHALIGNDONE=tx_init.Xxphaligndone,
                i_TXUSERRDY=tx_init.Xxuserrdy,
                i_TXSYNCMODE=1,

                # TX data
                p_TX_DATA_WIDTH=dw,
                p_TX_INT_DATAWIDTH=dw == 40,
                i_TXCTRL0=Cat(*[txdata[10*i+8] for i in range(nwords)]),
                i_TXCTRL1=Cat(*[txdata[10*i+9] for i in range(nwords)]),
                i_TXDATA=Cat(*[txdata[10*i:10*i+8] for i in range(nwords)]),
                i_TXUSRCLK=ClockSignal("rtio_tx"),
                i_TXUSRCLK2=ClockSignal("rtio_tx"),

                # TX electrical
                i_TXPD=0b00,
                p_TX_CLKMUX_EN=1,
                i_TXBUFDIFFCTRL=0b000,
                i_TXDIFFCTRL=0b1100,

                # RX Startup/Reset
                i_GTRXRESET=rx_init.gtXxreset,
                o_RXRESETDONE=rx_init.Xxresetdone,
                i_RXDLYSRESET=rx_init.Xxdlysreset,
                o_RXPHALIGNDONE=rxphaligndone,
                i_RXSYNCALLIN=rxphaligndone,
                i_RXUSERRDY=rx_init.Xxuserrdy,
                i_RXSYNCIN=0,
                i_RXSYNCMODE=1,
                o_RXSYNCDONE=rx_init.Xxsyncdone,

                # RX AFE
                i_RXDFEAGCCTRL=1,
                i_RXDFEXYDEN=1,
                i_RXLPMEN=1,
                i_RXOSINTCFG=0xd,
                i_RXOSINTEN=1,

                # RX clock
                i_RXRATE=0,
                i_RXDLYBYPASS=0,
                p_RXBUF_EN="FALSE",
                p_RX_XCLK_SEL="RXUSR",
                i_RXSYSCLKSEL=0b00,
                i_RXOUTCLKSEL=0b010,
                i_RXPLLCLKSEL=0b00,
                o_RXOUTCLK=self.rxoutclk,
                i_RXUSRCLK=ClockSignal("rtio_rx"),
                i_RXUSRCLK2=ClockSignal("rtio_rx"),

                # RX Clock Correction Attributes
                p_CLK_CORRECT_USE="FALSE",
                p_CLK_COR_SEQ_1_1=0b0100000000,
                p_CLK_COR_SEQ_2_1=0b0100000000,
                p_CLK_COR_SEQ_1_ENABLE=0b1111,
                p_CLK_COR_SEQ_2_ENABLE=0b1111,

                # RX data
                p_RX_DATA_WIDTH=dw,
                p_RX_INT_DATAWIDTH=dw == 40,
                o_RXCTRL0=Cat(*[rxdata[10*i+8] for i in range(nwords)]),
                o_RXCTRL1=Cat(*[rxdata[10*i+9] for i in range(nwords)]),
                o_RXDATA=Cat(*[rxdata[10*i:10*i+8] for i in range(nwords)]),

                # RX electrical
                i_RXPD=0b00,
                p_RX_CLKMUX_EN=1,
                i_RXELECIDLEMODE=0b11,

                # Pads
                i_GTHRXP=rx_pads.p,
                i_GTHRXN=rx_pads.n,
                o_GTHTXP=tx_pads.p,
                o_GTHTXN=tx_pads.n
            )

        # tx clocking
        tx_reset_deglitched = Signal()
        tx_reset_deglitched.attr.add("no_retiming")
        self.sync += tx_reset_deglitched.eq(~tx_init.done)
        self.clock_domains.cd_rtio_tx = ClockDomain()
        if mode is "master":
            tx_bufg_div = pll.config["clkin"] / self.rtio_clk_freq
            assert tx_bufg_div == int(tx_bufg_div)
            self.specials += \
                Instance("BUFG_GT", i_I=self.txoutclk, o_O=self.cd_rtio_tx.clk,
                    i_DIV=int(tx_bufg_div)-1)
        self.specials += AsyncResetSynchronizer(self.cd_rtio_tx,
                                                tx_reset_deglitched)

        # rx clocking
        rx_reset_deglitched = Signal()
        rx_reset_deglitched.attr.add("no_retiming")
        self.sync.rtio_tx += rx_reset_deglitched.eq(~rx_init.done)
        self.clock_domains.cd_rtio_rx = ClockDomain()
        self.specials += [
            Instance("BUFG_GT", i_I=self.rxoutclk, o_O=self.cd_rtio_rx.clk),
            AsyncResetSynchronizer(self.cd_rtio_rx, rx_reset_deglitched)
        ]

        # tx data
        self.comb += txdata.eq(Cat(*[encoder.output[i]
                                     for i in range(nwords)]))

        # rx data
        for i in range(nwords):
            self.comb += decoders[i].input.eq(rxdata[10 * i:10 * (i + 1)])

        # clock alignment
        clock_aligner = BruteforceClockAligner(0b0101111100,
                                               self.rtio_clk_freq)
        self.submodules += clock_aligner
        self.comb += [
            clock_aligner.rxdata.eq(rxdata),
            rx_init.restart.eq(clock_aligner.restart),
            self.rx_ready.eq(clock_aligner.ready)
        ]
Beispiel #25
0
    def __init__(self, platform, clk_freq):
        # Clock domains for the system (soft CPU and related components run at).
        self.clock_domains.cd_sys = ClockDomain()
        self.clock_domains.cd_sys2x = ClockDomain()
        # Clock domains for the DDR interface.
        self.clock_domains.cd_sdram_half = ClockDomain()
        self.clock_domains.cd_sdram_full_wr = ClockDomain()
        self.clock_domains.cd_sdram_full_rd = ClockDomain()
        # Clock domain for peripherals (such as HDMI output).
        self.clock_domains.cd_base50 = ClockDomain()
        self.clock_domains.cd_encoder = ClockDomain()

        self.reset = Signal()

        # Input 100MHz clock
        f0 = 100 * 1000000
        clk100 = platform.request("clk100")
        clk100a = Signal()
        # Input 100MHz clock (buffered)
        self.specials += Instance("IBUFG", i_I=clk100, o_O=clk100a)
        clk100b = Signal()
        self.specials += Instance("BUFIO2",
                                  p_DIVIDE=1,
                                  p_DIVIDE_BYPASS="******",
                                  p_I_INVERT="FALSE",
                                  i_I=clk100a,
                                  o_DIVCLK=clk100b)

        f = Fraction(int(clk_freq), int(f0))
        n, m = f.denominator, f.numerator
        assert f0 / n * m == clk_freq
        p = 8

        # Unbuffered output signals from the PLL. They need to be buffered
        # before feeding into the fabric.
        unbuf_sdram_full = Signal()
        unbuf_sdram_half_a = Signal()
        unbuf_sdram_half_b = Signal()
        unbuf_encoder = Signal()
        unbuf_sys = Signal()
        unbuf_sys2x = Signal()

        # PLL signals
        pll_lckd = Signal()
        pll_fb = Signal()
        self.specials.pll = Instance(
            "PLL_ADV",
            name="crg_pll_adv",
            p_SIM_DEVICE="SPARTAN6",
            p_BANDWIDTH="OPTIMIZED",
            p_COMPENSATION="INTERNAL",
            p_REF_JITTER=.01,
            i_DADDR=0,
            i_DCLK=0,
            i_DEN=0,
            i_DI=0,
            i_DWE=0,
            i_RST=0,
            i_REL=0,
            p_DIVCLK_DIVIDE=1,
            # Input Clocks (100MHz)
            i_CLKIN1=clk100b,
            p_CLKIN1_PERIOD=1e9 / f0,
            i_CLKIN2=0,
            p_CLKIN2_PERIOD=0.,
            i_CLKINSEL=1,
            # Feedback
            i_CLKFBIN=pll_fb,
            o_CLKFBOUT=pll_fb,
            o_LOCKED=pll_lckd,
            p_CLK_FEEDBACK="CLKFBOUT",
            p_CLKFBOUT_MULT=m * p // n,
            p_CLKFBOUT_PHASE=0.,
            # (400MHz) ddr3 wr/rd full clock
            o_CLKOUT0=unbuf_sdram_full,
            p_CLKOUT0_DUTY_CYCLE=.5,
            p_CLKOUT0_PHASE=0.,
            p_CLKOUT0_DIVIDE=p // 8,
            # ( 66MHz) encoder
            o_CLKOUT1=unbuf_encoder,
            p_CLKOUT1_DUTY_CYCLE=.5,
            p_CLKOUT1_PHASE=0.,
            p_CLKOUT1_DIVIDE=6,
            # (200MHz) sdram_half - ddr3 dqs adr ctrl off-chip
            o_CLKOUT2=unbuf_sdram_half_a,
            p_CLKOUT2_DUTY_CYCLE=.5,
            p_CLKOUT2_PHASE=230.,
            p_CLKOUT2_DIVIDE=p // 4,
            # (200MHz) off-chip ddr - ddr3 half clock
            o_CLKOUT3=unbuf_sdram_half_b,
            p_CLKOUT3_DUTY_CYCLE=.5,
            p_CLKOUT3_PHASE=210.,
            p_CLKOUT3_DIVIDE=p // 4,
            # (100MHz) sys2x - 2x system clock
            o_CLKOUT4=unbuf_sys2x,
            p_CLKOUT4_DUTY_CYCLE=.5,
            p_CLKOUT4_PHASE=0.,
            p_CLKOUT4_DIVIDE=p // 2,
            # ( 50MHz) periph / sys - system clock
            o_CLKOUT5=unbuf_sys,
            p_CLKOUT5_DUTY_CYCLE=.5,
            p_CLKOUT5_PHASE=0.,
            p_CLKOUT5_DIVIDE=p // 1,
        )

        # power on reset?
        reset = ~platform.request("cpu_reset") | self.reset
        self.clock_domains.cd_por = ClockDomain()
        por = Signal(max=1 << 11, reset=(1 << 11) - 1)
        self.sync.por += If(por != 0, por.eq(por - 1))
        self.specials += AsyncResetSynchronizer(self.cd_por, reset)

        # System clock - 50MHz
        self.specials += Instance("BUFG",
                                  name="sys_bufg",
                                  i_I=unbuf_sys,
                                  o_O=self.cd_sys.clk)
        self.comb += self.cd_por.clk.eq(self.cd_sys.clk)
        self.specials += AsyncResetSynchronizer(self.cd_sys,
                                                ~pll_lckd | (por > 0))

        # sys2x
        self.specials += Instance("BUFG",
                                  name="sys2x_bufg",
                                  i_I=unbuf_sys2x,
                                  o_O=self.cd_sys2x.clk)
        self.specials += AsyncResetSynchronizer(self.cd_sys2x,
                                                ~pll_lckd | (por > 0))

        # SDRAM clocks
        # ------------------------------------------------------------------------------
        self.clk8x_wr_strb = Signal()
        self.clk8x_rd_strb = Signal()

        # sdram_full
        self.specials += Instance("BUFPLL",
                                  name="sdram_full_bufpll",
                                  p_DIVIDE=4,
                                  i_PLLIN=unbuf_sdram_full,
                                  i_GCLK=self.cd_sys2x.clk,
                                  i_LOCKED=pll_lckd,
                                  o_IOCLK=self.cd_sdram_full_wr.clk,
                                  o_SERDESSTROBE=self.clk8x_wr_strb)
        self.comb += [
            self.cd_sdram_full_rd.clk.eq(self.cd_sdram_full_wr.clk),
            self.clk8x_rd_strb.eq(self.clk8x_wr_strb),
        ]
        # sdram_half
        self.specials += Instance("BUFG",
                                  name="sdram_half_a_bufpll",
                                  i_I=unbuf_sdram_half_a,
                                  o_O=self.cd_sdram_half.clk)
        clk_sdram_half_shifted = Signal()
        self.specials += Instance("BUFG",
                                  name="sdram_half_b_bufpll",
                                  i_I=unbuf_sdram_half_b,
                                  o_O=clk_sdram_half_shifted)

        output_clk = Signal()
        clk = platform.request("ddram_clock")
        self.specials += Instance("ODDR2",
                                  p_DDR_ALIGNMENT="NONE",
                                  p_INIT=0,
                                  p_SRTYPE="SYNC",
                                  i_D0=1,
                                  i_D1=0,
                                  i_S=0,
                                  i_R=0,
                                  i_CE=1,
                                  i_C0=clk_sdram_half_shifted,
                                  i_C1=~clk_sdram_half_shifted,
                                  o_Q=output_clk)
        self.specials += Instance("OBUFDS",
                                  i_I=output_clk,
                                  o_O=clk.p,
                                  o_OB=clk.n)

        # Peripheral clock - 50MHz
        # ------------------------------------------------------------------------------
        # The peripheral clock is kept separate from the system clock to allow
        # the system clock to be increased in the future.
        dcm_base50_locked = Signal()
        self.specials += [
            Instance(
                "DCM_CLKGEN",
                name="crg_periph_dcm_clkgen",
                p_CLKIN_PERIOD=10.0,
                p_CLKFX_MULTIPLY=2,
                p_CLKFX_DIVIDE=4,
                p_CLKFX_MD_MAX=0.5,  # CLKFX_MULTIPLY/CLKFX_DIVIDE
                p_CLKFXDV_DIVIDE=2,
                p_SPREAD_SPECTRUM="NONE",
                p_STARTUP_WAIT="FALSE",
                i_CLKIN=clk100a,
                o_CLKFX=self.cd_base50.clk,
                o_LOCKED=dcm_base50_locked,
                i_FREEZEDCM=0,
                i_RST=ResetSignal(),
            ),
            AsyncResetSynchronizer(self.cd_base50,
                                   self.cd_sys.rst | ~dcm_base50_locked)
        ]
        platform.add_period_constraint(self.cd_base50.clk, 20)

        # Encoder clock - 66 MHz
        # ------------------------------------------------------------------------------
        self.specials += Instance("BUFG",
                                  name="encoder_bufg",
                                  i_I=unbuf_encoder,
                                  o_O=self.cd_encoder.clk)
        self.specials += AsyncResetSynchronizer(self.cd_encoder,
                                                self.cd_sys.rst)
Beispiel #26
0
    def __init__(self, platform):
        self.clock_domains.cd_sys = ClockDomain()
        self.clock_domains.cd_eth = ClockDomain(reset_less=True)

        clk100 = platform.request("clk100")
        rst = platform.request("cpu_reset")

        pll_locked = Signal()
        pll_fb = Signal()
        pll_sys = Signal()
        pll_eth = Signal()
        self.specials += [
            Instance(
                "PLLE2_BASE",
                p_STARTUP_WAIT="FALSE",
                o_LOCKED=pll_locked,

                # VCO @ 800 MHz
                p_REF_JITTER1=0.01,
                p_CLKIN1_PERIOD=10.0,
                p_CLKFBOUT_MULT=8,
                p_DIVCLK_DIVIDE=1,
                i_CLKIN1=clk100,
                i_CLKFBIN=pll_fb,
                o_CLKFBOUT=pll_fb,

                # 100 MHz
                p_CLKOUT0_DIVIDE=8,
                p_CLKOUT0_PHASE=0.0,
                o_CLKOUT0=pll_sys,

                # 25 MHz
                p_CLKOUT1_DIVIDE=32,
                p_CLKOUT1_PHASE=0.0,
                o_CLKOUT1=pll_eth,

                # 200 MHz
                p_CLKOUT2_DIVIDE=4,
                p_CLKOUT2_PHASE=0.0,
                #o_CLKOUT2=,

                # 200 MHz
                p_CLKOUT3_DIVIDE=4,
                p_CLKOUT3_PHASE=0.0,
                #o_CLKOUT3=,

                # 200MHz
                p_CLKOUT4_DIVIDE=4,
                p_CLKOUT4_PHASE=0.0,
                #o_CLKOUT4=
            ),
            Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk),
            Instance("BUFG", i_I=pll_eth, o_O=self.cd_eth.clk),
            AsyncResetSynchronizer(self.cd_sys, ~pll_locked | ~rst),
        ]

        self.specials += [
            Instance("ODDR2",
                     p_DDR_ALIGNMENT="NONE",
                     p_INIT=0,
                     p_SRTYPE="SYNC",
                     i_D0=0,
                     i_D1=1,
                     i_S=0,
                     i_R=0,
                     i_CE=1,
                     i_C0=self.cd_eth.clk,
                     i_C1=~self.cd_eth.clk,
                     o_Q=platform.request("eth_ref_clk"))
        ]