Exemplo n.º 1
0
    def __init__(self, data_clk_i, frame_signals_i, data_signals_i):

        # Outputs
        # ==========================================

        self.data_clk_o = Signal(name="data_clk_o")
        self.data_o = []
        self.data_stb_o = []

        # Design
        # ==========================================

        data_clk_to_bufr = Signal()
        self.clock_domains.cd_dclk = cd_dclk = ClockDomain()  # !!!! Inverted!

        self.specials += DifferentialInput(data_clk_i.p, data_clk_i.n, data_clk_to_bufr)
        self.specials += Instance("BUFG", i_I=~data_clk_to_bufr, o_O=cd_dclk.clk)  # !!!! Inverted!
        # platform.add_period_constraint(cd_dclk.clk, 4.)

        self.specials += [AsyncResetSynchronizer(cd_dclk, ResetSignal("sys"))]

        self.phy_channels = []
        for channel, (frame, data) in enumerate(zip(frame_signals_i, data_signals_i)):
            frame_se = Signal()
            data_se = Signal()
            self.specials += DifferentialInput(frame.p, frame.n, frame_se)
            self.specials += DifferentialInput(data.p, data.n, data_se)

            channel_phy = ClockDomainsRenamer("dclk")(TdcGpx2ChannelPhy(frame_i=frame_se, data_i=data_se))
            self.phy_channels.append(channel_phy)
            setattr(self.submodules, "channel{}".format(channel), channel_phy)
            self.data_o.append(channel_phy.data_o)
            self.data_stb_o.append(channel_phy.stb_o)
Exemplo n.º 2
0
    def __init__(self, platform, eem):
        self.sck_en = Signal()
        self.cnv = Signal()
        self.clkout = Signal()

        spip = platform.request("{}_adc_spi_p".format(eem))
        spin = platform.request("{}_adc_spi_n".format(eem))
        cnv = platform.request("{}_cnv".format(eem))
        sdr = platform.request("{}_sdr".format(eem))
        dp = platform.request("{}_adc_data_p".format(eem))
        dn = platform.request("{}_adc_data_n".format(eem))

        clkout_se = Signal()
        clkout_inv = Signal()
        sck = Signal()

        self.specials += [
            DifferentialOutput(self.cnv, cnv.p, cnv.n),
            DifferentialOutput(1, sdr.p, sdr.n),
            DDROutput(self.sck_en, 0, sck, ClockSignal("sys")),
            DifferentialOutput(sck, spip.clk, spin.clk),
            DifferentialInput(dp.clkout, dn.clkout, clkout_se),
            # FIXME (hardware): CLKOUT is inverted
            # (Sampler v2.0, v2.1) out on rising, in on falling
            Instance("BUFR", i_I=clkout_se, o_O=clkout_inv)
        ]

        self.comb += self.clkout.eq(~clkout_inv)

        # define clock here before the input delays below
        self.clkout_p = dp.clkout  # available for false paths
        platform.add_platform_command(
            "create_clock -name {clk} -period 8 [get_nets {clk}]",
            clk=dp.clkout)
        # platform.add_period_constraint(sampler_pads.clkout_p, 8.)
        for i in "abcd":
            sdo = Signal()
            setattr(self, "sdo{}".format(i), sdo)
            if i != "a":
                # FIXME (hardware): sdob, sdoc, sdod are inverted
                # (Sampler v2.0, v2.1)
                sdo, sdo_inv = Signal(), sdo
                self.comb += sdo_inv.eq(~sdo)
            sdop = getattr(dp, "sdo{}".format(i))
            sdon = getattr(dn, "sdo{}".format(i))
            self.specials += [
                DifferentialInput(sdop, sdon, sdo),
            ]
            # -0+1.5 hold (t_HSDO_SDR), -0.5+0.5 skew
            platform.add_platform_command(
                "set_input_delay -clock {clk} -max 2 [get_ports {port}]\n"
                "set_input_delay -clock {clk} -min -0.5 [get_ports {port}]",
                clk=dp.clkout,
                port=sdop)
Exemplo n.º 3
0
    def __init__(self, pad, pad_n=None):
        self.rtlink = rtlink.Interface(rtlink.OInterface(2, 2),
                                       rtlink.IInterface(1))
        self.overrides = []
        self.probes = []

        # # #

        sensitivity = Signal(2)

        sample = Signal()
        self.sync.rio += [
            sample.eq(0),
            If(self.rtlink.o.stb & self.rtlink.o.address[1],
               sensitivity.eq(self.rtlink.o.data),
               If(self.rtlink.o.address[0], sample.eq(1)))
        ]

        i = Signal()
        i_d = Signal(reset_less=True)
        pad_i = Signal()
        if pad_n is None:
            self.comb += pad_i.eq(pad)
        else:
            self.specials += DifferentialInput(pad, pad_n, pad_i)
        self.specials += MultiReg(pad_i, i, "rio_phy")
        self.sync.rio_phy += i_d.eq(i)
        self.comb += [
            self.rtlink.i.stb.eq(sample | (sensitivity[0] & (i & ~i_d))
                                 | (sensitivity[1] & (~i & i_d))),
            self.rtlink.i.data.eq(i)
        ]

        self.probes += [i]
Exemplo n.º 4
0
    def __init__(self, pad, pad_n=None, name="external_trigger"):
        super().__init__(name)

        # Outputs
        self.trigger_re = Signal()  # CD: sys
        self.trigger_fe = Signal()  # CD: sys

        # FIXME: Revise trigger registration
        self.register_trigger(self.trigger_re, "re", "rio_phy")
        self.register_trigger(self.trigger_fe, "fe", "rio_phy")

        # # #

        if pad_n is not None:
            external_trigger = Signal()
            self.specials += DifferentialInput(pad, pad_n, external_trigger)
        else:
            external_trigger = pad

        trigger_ext_d = Signal()
        trigger_ext_prev = Signal()
        self.sync += [
            trigger_ext_prev.eq(trigger_ext_d),
            trigger_ext_d.eq(external_trigger)
        ]
        self.comb += [
            self.trigger_re.eq(~trigger_ext_prev & trigger_ext_d),
            self.trigger_fe.eq(trigger_ext_prev & ~trigger_ext_d)
        ]
Exemplo n.º 5
0
 def register_jref(self, jref):
     self.jref_registered = True
     if isinstance(jref, Signal):
         self.comb += self.jref.eq(jref)
     elif isinstance(jref, Record):
         self.specials += DifferentialInput(jref.p, jref.n, self.jref)
     else:
         raise ValueError
Exemplo n.º 6
0
 def register_jsync(self, jsync):
     self.jsync_registered = True
     if isinstance(jsync, Signal):
         self.comb += self.jsync.eq(jsync)
     elif isinstance(jsync, Record):
         self.specials += DifferentialInput(jsync.p, jsync.n, self.jsync)
     else:
         raise ValueError
Exemplo n.º 7
0
    def __init__(self, platform, eem):
        self.sck_en = Signal()
        self.cnv = Signal()
        self.clkout = Signal()

        spip = platform.request("{}_adc_spi_p".format(eem))
        spin = platform.request("{}_adc_spi_n".format(eem))
        cnv = platform.request("{}_cnv".format(eem))
        sdr = platform.request("{}_sdr".format(eem))
        dp = platform.request("{}_adc_data_p".format(eem))
        dn = platform.request("{}_adc_data_n".format(eem))

        clkout_se = Signal()
        sck = Signal()

        self.specials += [
                DifferentialOutput(self.cnv, cnv.p, cnv.n),
                DifferentialOutput(1, sdr.p, sdr.n),
                DDROutput(0, self.sck_en, sck, ClockSignal("rio_phy")),
                DifferentialOutput(sck, spip.clk, spin.clk),
                DifferentialInput(dp.clkout, dn.clkout, clkout_se),
                Instance("BUFR", i_I=clkout_se, o_O=self.clkout)
        ]

        # here to be early before the input delays below to have the clock
        # available
        self.clkout_p = dp.clkout  # availabel for false paths
        platform.add_platform_command(
                "create_clock -name {clk} -period 8 [get_nets {clk}]",
                clk=dp.clkout)
        # platform.add_period_constraint(sampler_pads.clkout_p, 8.)
        for i in "abcd":
            sdo = Signal()
            setattr(self, "sdo{}".format(i), sdo)
            sdop = getattr(dp, "sdo{}".format(i))
            sdon = getattr(dn, "sdo{}".format(i))
            self.specials += [
                DifferentialInput(sdop, sdon, sdo),
            ]
            # 8, -0+1.5 hold (t_HSDO_DDR), -0.5+0.5 skew
            platform.add_platform_command(
                "set_input_delay -clock {clk} "
                "-max 2 [get_ports {port}] -clock_fall\n"
                "set_input_delay -clock {clk} "
                "-min -0.5 [get_ports {port}] -clock_fall",
                clk=dp.clkout, port=sdop)
Exemplo n.º 8
0
Arquivo: clock.py Projeto: zakgi/litex
 def register_clkin(self, clkin, freq):
     self.clkin = Signal()
     if isinstance(clkin, (Signal, ClockSignal)):
         self.comb += self.clkin.eq(clkin)
     elif isinstance(clkin, Record):
         self.specials += DifferentialInput(clkin.p, clkin.n, self.clkin)
     else:
         raise ValueError
     self.clkin_freq = freq
 def __init__(self, p, sys_clk_freq, f_sample_tx=None):
     # ----------------------------
     #  Clock and Reset Generation
     # ----------------------------
     xtal_pads = p.request(p.default_clk_name)
     xtal = Signal()
     self.specials += DifferentialInput(xtal_pads.p, xtal_pads.n, xtal)
     xtal_f = 1e9 / p.default_clk_period
     rst = p.request("cpu_reset")
     cds = [("cd_sys", sys_clk_freq)]
     if f_sample_tx is not None:
         cds.append(("cd_sample_tx", f_sample_tx))
     for cd, f in cds:
         setattr(self.clock_domains, cd, ClockDomain(cd))
         pll = S6PLL(speedgrade=-3)
         self.comb += pll.reset.eq(rst)
         pll.register_clkin(xtal, xtal_f)
         pll.create_clkout(getattr(self, cd), f)
         self.submodules += pll
     if f_sample_tx is not None:
         # Provide a ENC clock signal on SMA_GPIO
         enc_out = Signal()
         self.specials += Instance(
             "ODDR2",
             o_Q=enc_out,
             i_C0=ClockSignal("sample_tx"),
             i_C1=~ClockSignal("sample_tx"),
             i_CE=1,
             i_D0=1,
             i_D1=0
         )
         p.add_extension(
             # Connect GPIO_SMA on SP605 with CLK input on 1525A
             [("ENC_CLK", 0,
                 Subsignal("p", Pins("SMA_GPIO:P")),
                 Subsignal("n", Pins("SMA_GPIO:N")),
                 # Note: the LTC eval board needs to be modded
                 # to accept a differential clock
                 IOStandard("LVDS_25")
             )]
         )
         gpio_pads = p.request("ENC_CLK")
         self.specials += DifferentialOutput(enc_out, gpio_pads.p, gpio_pads.n)
Exemplo n.º 10
0
    def __init__(self, pins, pins_n):
        self.data = [Signal(2) for _ in range(2 + len(pins.mosi))]

        for d, pp, pn in zip(self.data,
                             [pins.clk] + list(pins.mosi),
                             [pins_n.clk] + list(pins_n.mosi)):
            ddr = Signal()
            self.specials += [
                # d1 closer to q
                DDROutput(d[1], d[0], ddr, ClockSignal("rio_phy")),
                DifferentialOutput(ddr, pp, pn),
            ]
        ddr = Signal()
        self.specials += [
            DifferentialInput(pins.miso, pins_n.miso, ddr),
            # q1 closer to d
            DDRInput(ddr, self.data[-1][0], self.data[-1][1],
                     ClockSignal("rio_phy")),
        ]
Exemplo n.º 11
0
    def __init__(self, platform):
        self.jreset = CSRStorage(reset=1)
        self.jref = Signal()

        self.refclk = Signal()
        refclk2 = Signal()
        self.clock_domains.cd_jesd = ClockDomain()
        refclk_pads = platform.request("dac_refclk", 0)

        platform.add_period_constraint(refclk_pads.p, 1e9/self.refclk_freq)
        self.specials += [
            Instance("IBUFDS_GTE3", i_CEB=0, p_REFCLK_HROW_CK_SEL=0b00,
                     i_I=refclk_pads.p, i_IB=refclk_pads.n,
                     o_O=self.refclk, o_ODIV2=refclk2),
            Instance("BUFG_GT", i_I=refclk2, o_O=self.cd_jesd.clk),
            AsyncResetSynchronizer(self.cd_jesd, self.jreset.storage),
        ]

        jref = platform.request("dac_sysref")
        self.specials += DifferentialInput(jref.p, jref.n, self.jref)
Exemplo n.º 12
0
    def __init__(self, platform, eem):

        self.sdi = Signal()
        self.ldac = Signal()
        self.busy = Signal(reset=1)
        self.syncr = Signal(reset=1)
        self.rst = Signal(reset=1)
        self.clr = Signal(reset=1)
        self.sclk = Signal()

        spip = platform.request("{}_spi_p".format(eem))
        spin = platform.request("{}_spi_n".format(eem))
        ldacn = platform.request("{}_ldac_n".format(eem))
        busy = platform.request("{}_busy".format(eem))
        clrn = platform.request("{}_clr_n".format(eem))

        self.specials += [
            DifferentialOutput(self.ldac, ldacn.p, ldacn.n),
            DifferentialOutput(self.sdi, spip.mosi, spin.mosi),
            DifferentialOutput(self.sclk, spip.clk, spin.clk),
            DifferentialOutput(self.syncr, spip.cs_n, spin.cs_n),
            DifferentialOutput(self.clr, clrn.p, clrn.n),
            DifferentialInput(busy.p, busy.n, self.busy),
        ]
Exemplo n.º 13
0
    def __init__(self, adclk_i, lclk_i, dat_i):
        """ADS5296A ADC phy for Xilinx Series 7

        Args:
            adclk_i (differential signal): frame clock
            lclk_i (differential signal): bit clock
            dat_i (array of differential signals): data lines
        """

        # Module constants
        # ==========================================

        DAT_O_LEN = 10
        BUFR_DIVIDE = 5
        VALID_FRAME_OUT = 0b1111100000

        # Outputs
        # ==========================================

        self.data_clk_o = Signal()
        self.bitslip_done = Signal()
        self.data_o = [Signal(DAT_O_LEN, name="data_{}_o".format(i)) for i in range(9)]

        # RTLink Control Status Registers
        # ==========================================

        regs = [
            *[("data{}_delay_value".format(x), 5) for x in range(9)],
            ("adclk_delay_value", 5),
            ("phy_reset", 1, 1),
            ("bitslip_done", 1, 0, "ro")
        ]

        csr = RtLinkCSR(regs, "ads5296a_phy")
        self.submodules.csr = csr
        
        # Design
        # ==========================================

        input_lines = [*dat_i, adclk_i]
        lines_delayed = [Signal(name="line_delayed_{}".format(i)) for i in range(9)]
        # 0 - data[0]
        # 1 - data[1]
        # ...
        # 7 - data[7]
        # 8 - adclk
        for idx, (input_line, line_delayed) in enumerate(zip(input_lines, lines_delayed)):
            line_buffer = Signal()
            self.specials += DifferentialInput(i_p=input_line.p,
                                               i_n=input_line.n,
                                               o=line_buffer)
            self.submodules += XilinxIdelayE2(
                data_i=line_buffer,
                data_o=line_delayed,
                delay_value_i=getattr(csr, regs[idx][0]),
                delay_value_ld_i=getattr(csr, regs[idx][0]+"_ld")
            )

        # Clocking
        lclk_ibuf = Signal()
        lclk_bufg = Signal()
        self.lclk = lclk_bufg
        self.lclk_bufio = lclk_bufio = Signal()

        self.clock_domains.cd_adclk_clkdiv = cd_adclk_clkdiv = ClockDomain()
        self.specials += [AsyncResetSynchronizer(cd_adclk_clkdiv, csr.phy_reset)]

        self.specials += DifferentialInput(i_p=lclk_i.p,
                                           i_n=lclk_i.n,
                                           o=lclk_ibuf)
        self.specials += Instance("BUFIO",
                                  i_I=lclk_ibuf,
                                  o_O=lclk_bufio)
        self.specials += Instance("BUFR",
                                  p_BUFR_DIVIDE=str(BUFR_DIVIDE),
                                  i_I=lclk_ibuf,
                                  i_CE=1,
                                  i_CLR=0,
                                  o_O=lclk_bufg)
        self.specials += Instance("BUFG",
                                  i_I=lclk_bufg,
                                  o_O=cd_adclk_clkdiv.clk)

        # Bitslip logic
        bitslip = Signal()
        bitslip_cnt = Signal(4)

        self.sync.adclk_clkdiv += [
            bitslip.eq(0),
            bitslip_cnt.eq(bitslip_cnt + 1),
            self.bitslip_done.eq(self.data_o[8] == VALID_FRAME_OUT),
            If(bitslip_cnt == 0x0,
               If(~self.bitslip_done,
                  bitslip.eq(1))),
        ]

        self.specials += MultiReg(i=self.bitslip_done, o=csr.bitslip_done, odomain="rio_phy")

        # ISERDES
        # For 10b deserialization we'll be using two ISERDES modules connected in MASTER-SLAVE mode.

        self.specials += Instance("BUFG", i_I=cd_adclk_clkdiv.clk, o_O=self.data_clk_o)

        for idx, (line_delayed, dat_o) in enumerate(zip(lines_delayed, self.data_o)):
            shift1 = Signal(name="shift1_{}".format(idx))
            shift2 = Signal(name="shift2_{}".format(idx))
            self.specials += Instance("ISERDESE2",
                                      p_DATA_RATE="DDR",
                                      p_DATA_WIDTH=10,
                                      p_INTERFACE_TYPE="NETWORKING",
                                      p_NUM_CE=1,
                                      p_SERDES_MODE="MASTER",
                                      p_IOBDELAY="BOTH",
                                      o_Q1=dat_o[0], o_Q2=dat_o[1], o_Q3=dat_o[2], o_Q4=dat_o[3],
                                      o_Q5=dat_o[4], o_Q6=dat_o[5], o_Q7=dat_o[6], o_Q8=dat_o[7],
                                      o_SHIFTOUT1=shift1,
                                      o_SHIFTOUT2=shift2,
                                      o_O=Signal(name="output_test_master_{}".format(idx)),
                                      i_DDLY=line_delayed,
                                      i_CLK=lclk_bufio,
                                      i_CLKB=~lclk_bufio,
                                      i_CE1=1,
                                      i_RST=ResetSignal("adclk_clkdiv"),
                                      i_CLKDIV=lclk_bufg,
                                      i_CLKDIVP=0,
                                      i_BITSLIP=bitslip,
                                      i_DYNCLKDIVSEL=0,
                                      i_DYNCLKSEL=0)
            self.specials += Instance("ISERDESE2",
                                      p_DATA_RATE="DDR",
                                      p_DATA_WIDTH=10,
                                      p_INTERFACE_TYPE="NETWORKING",
                                      p_NUM_CE=1,
                                      p_SERDES_MODE="SLAVE",
                                      p_IOBDELAY="BOTH",
                                      o_Q3=dat_o[8], o_Q4=dat_o[9],
                                      i_SHIFTIN1=shift1,
                                      i_SHIFTIN2=shift2,
                                      i_CLK=lclk_bufio,
                                      i_CLKB=~lclk_bufio,
                                      i_CE1=1,
                                      i_RST=ResetSignal("adclk_clkdiv"),
                                      i_CLKDIV=lclk_bufg,
                                      i_CLKDIVP=0,
                                      i_BITSLIP=bitslip,
                                      i_DYNCLKDIVSEL=0,
                                      i_DYNCLKSEL=0)
Exemplo n.º 14
0
    def __init__(self, platform):
        self.jreset = CSRStorage(reset=1)
        self.jsync = CSRStatus()

        ps = JESD204BPhysicalSettings(l=4, m=4, n=16, np=16)
        ts = JESD204BTransportSettings(f=2, s=1, k=16, cs=1)
        settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5)
        linerate = 6e9
        refclk_freq = 150e6
        fabric_freq = 150 * 1000 * 1000

        refclk = Signal()
        self.clock_domains.cd_jesd = ClockDomain()
        refclk_pads = platform.request("ad9154_refclk")

        self.specials += [
            Instance("IBUFDS_GTE2",
                     i_CEB=0,
                     i_I=refclk_pads.p,
                     i_IB=refclk_pads.n,
                     o_O=refclk),
            Instance("BUFG", i_I=refclk, o_O=self.cd_jesd.clk),
            AsyncResetSynchronizer(self.cd_jesd, self.jreset.storage),
        ]
        self.cd_jesd.clk.attr.add("keep")
        platform.add_period_constraint(self.cd_jesd.clk, 1e9 / refclk_freq)

        qpll = GTXQuadPLL(refclk, refclk_freq, linerate)
        self.submodules += qpll
        self.phys = []
        for i in range(4):
            phy = JESD204BPhyTX(qpll, platform.request("ad9154_jesd", i),
                                fabric_freq)
            phy.gtx.cd_tx.clk.attr.add("keep")
            platform.add_period_constraint(phy.gtx.cd_tx.clk,
                                           40 * 1e9 / linerate)
            platform.add_false_path_constraints(self.cd_jesd.clk,
                                                phy.gtx.cd_tx.clk)
            self.phys.append(phy)
        to_jesd = ClockDomainsRenamer("jesd")
        self.submodules.core = to_jesd(
            JESD204BCoreTX(self.phys, settings, converter_data_width=32))
        self.submodules.control = to_jesd(JESD204BCoreTXControl(self.core))

        sync_pads = platform.request("ad9154_sync")
        jsync = Signal()
        self.specials += [
            DifferentialInput(sync_pads.p, sync_pads.n, jsync),
            MultiReg(jsync, self.jsync.status)
        ]

        self.comb += [
            platform.request("ad9154_txen", 0).eq(1),
            platform.request("ad9154_txen", 1).eq(1),
            self.core.start.eq(jsync),
            platform.request("user_led", 3).eq(jsync),
        ]

        # blinking leds for transceiver reset status
        for i in range(4):
            counter = Signal(max=fabric_freq)
            self.comb += platform.request("user_led", 4 + i).eq(counter[-1])
            sync = getattr(self.sync, "phy{}_tx".format(i))
            sync += [
                counter.eq(counter - 1),
                If(counter == 0, counter.eq(fabric_freq - 1))
            ]
Exemplo n.º 15
0
    def __init__(self,
                 S,
                 D,
                 MIRROR_BITS,
                 BITSLIPS,
                 idelay_overrides={},
                 iserdes_overrides={}):
        """
        Generates all logic necessary for the data lanes, calibration
        and phase detection / adjustment
        Does not do anything related to clocking.
        Inherit and add you own clock.
        """
        # LVDS DDR bit clock
        self.dco_p = Signal()
        self.dco_n = Signal()

        # data lanes
        self.lvds_data_p = Signal(D)
        self.lvds_data_n = Signal(D)

        # Control signals (on sample clock domain)
        self.bitslip = Signal()  # Pulse to rotate

        # Phase detector readout (on sample clock domain)
        # input for number of sample clock cycles to integrate
        self.pd_int_period = Signal(32, reset=2**23)
        # outputs integrated Phase detector values (int32)
        self.pd_int_phases = [Signal((32, True)) for i in range(D)]
        # input to enable auto increment / decrement IDELAY based on PD value
        self.id_auto_control = Signal()

        # Idelay control inputs (on sample clock domain)
        self.id_mux = Signal(max=D + 1)  # select a LVDS lane
        self.id_inc = Signal(1)
        self.id_dec = Signal(1)

        # parallel data out, S-bit serdes on D-lanes (on sample clock domain)
        self.data_outs = [Signal(S) for i in range(D)]

        # Async Reset for clock generation and `sample` clock domain
        self.reset = Signal(reset=1)

        ###

        # Common internal signals which must be driven by child
        self.clock_domains.sample = ClockDomain(
            "sample")  # received ADC sample clock
        self.ioclk_p = Signal()
        self.ioclk_n = Signal()
        self.serdesstrobe = Signal()

        # -----------------------------
        #  IDELAY calibration
        # -----------------------------
        self.idelay_rst = Signal()
        self.idelay_cal_m = Signal()
        self.idelay_cal_s = Signal()
        # High when IDELAY initialization complete
        self.initial_tl_done = Signal()
        bitslip_initial = Signal()
        self.sync.sample += [
            self.idelay_cal_m.eq(0),
            self.idelay_cal_s.eq(0),
            self.idelay_rst.eq(0),
            bitslip_initial.eq(0)
        ]
        # Initially calibrate and reset all IDELAY2s
        tl = [
            (20, [self.idelay_cal_m.eq(1),
                  self.idelay_cal_s.eq(1)]),
            (40, [self.idelay_rst.eq(1)]),
            (60, [self.initial_tl_done.eq(1)]),
            # Add initial bitslips starting from clk 100. Have I gone too far?
            *zip([100 + i * 10 for i in range(BITSLIPS)],
                 [[bitslip_initial.eq(1)]] * BITSLIPS)
        ]
        # print(tl)
        self.sync.sample += timeline(~self.initial_tl_done, tl)
        # Periodically re-calibrate all slave IDELAY2s
        self.sync.sample += timeline(
            self.initial_tl_done,
            [(2**26, [self.idelay_cal_s.eq(1)])  # every 0.54 s at 125 MHz
             ])

        # Accumulator regs for phase detector
        pd_int_accus = [Signal.like(s) for s in self.pd_int_phases]
        pd_int_cnt = Signal(32)
        self.sync.sample += [
            If(
                pd_int_cnt >= self.pd_int_period,
                pd_int_cnt.eq(0),
            ).Elif(
                self.
                initial_tl_done,  # only start counting when idelays are calibrated
                pd_int_cnt.eq(pd_int_cnt + 1))
        ]

        # -----------------------------
        #  Default block parameters
        # -----------------------------
        self.idelay_default = {
            "p_SIM_TAPDELAY_VALUE": 49,
            "p_IDELAY_VALUE": 0,  # A faire: make CSR
            "p_IDELAY2_VALUE": 0,
            "p_ODELAY_VALUE": 0,
            "p_IDELAY_MODE": "NORMAL",
            "p_COUNTER_WRAPAROUND": "WRAPAROUND",
            "p_DELAY_SRC": "IDATAIN",
            "i_T": 1,
            "i_ODATAIN": 0,
            "i_IOCLK0": self.ioclk_p,
            "i_IOCLK1": self.ioclk_n,
            "i_CLK": ClockSignal("sample"),
            "i_RST": self.idelay_rst
        }
        self.idelay_default.update(idelay_overrides)
        self.iserdes_default = {
            "p_DATA_WIDTH": S,
            "p_BITSLIP_ENABLE": "TRUE",
            "p_INTERFACE_TYPE": "RETIMED",
            "i_CE0": 1,
            "i_CLK0": self.ioclk_p,
            "i_CLK1": self.ioclk_n,
            "i_IOCE": self.serdesstrobe,
            "i_RST": ~self.initial_tl_done,
            "i_CLKDIV": ClockSignal("sample"),
            "i_BITSLIP": self.bitslip | bitslip_initial
        }
        self.iserdes_default.update(iserdes_overrides)

        for i in range(D):
            lvds_data = Signal()
            lvds_data_m = Signal()
            lvds_data_s = Signal()
            id_CE = Signal()
            id_INC = Signal()
            # -------------------------------------
            #  Idelay control (auto / manual)
            # -------------------------------------
            self.sync.sample += [
                # Mux the IDELAY control inputs
                If(
                    self.id_auto_control,
                    id_CE.
                    eq((pd_int_cnt == 1) &
                       # Adjust IDELAYS at end of each accumulator cycle
                       (self.pd_int_phases[i] != 0)
                       # Adjust IDELAYs when consistently early / late
                       # during _all_ accumulator cycles
                       # ((self.pd_int_phases[i] >= self.pd_int_period) |
                       # (self.pd_int_phases[i] <= -self.pd_int_period))
                       ),
                    id_INC.eq(self.pd_int_phases[i] < 0)).Else(
                        id_CE.eq((self.id_mux == i)
                                 & (self.id_inc ^ self.id_dec)),
                        id_INC.eq(self.id_inc))
            ]
            self.specials += DifferentialInput(self.lvds_data_p[i],
                                               self.lvds_data_n[i], lvds_data)
            self.specials += Instance("IODELAY2",
                                      p_SERDES_MODE="MASTER",
                                      p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
                                      i_IDATAIN=lvds_data,
                                      i_CAL=self.idelay_cal_m,
                                      i_CE=id_CE,
                                      i_INC=id_INC,
                                      o_DATAOUT=lvds_data_m,
                                      **self.idelay_default)
            self.specials += Instance("IODELAY2",
                                      p_SERDES_MODE="SLAVE",
                                      p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
                                      i_IDATAIN=lvds_data,
                                      i_CAL=self.idelay_cal_s,
                                      i_CE=id_CE,
                                      i_INC=id_INC,
                                      o_DATAOUT=lvds_data_s,
                                      **self.idelay_default)
            cascade_up = Signal()
            cascade_down = Signal()
            tempData = Signal(8)
            pdValid = Signal()
            pdInc = Signal()
            pdAcc = pd_int_accus[i]
            self.specials += Instance(
                "ISERDES2",
                p_SERDES_MODE="MASTER",
                i_D=lvds_data_m,
                i_SHIFTIN=cascade_up,
                o_Q4=tempData[7],
                o_Q3=tempData[6],
                o_Q2=tempData[5],
                o_Q1=tempData[4],
                o_SHIFTOUT=cascade_down,
                # The phase detector outputs
                o_VALID=pdValid,
                o_INCDEC=pdInc,
                **self.iserdes_default)
            # Accumulate increment / decrement pulses
            self.sync.sample += [
                If(
                    pd_int_cnt >= self.pd_int_period,
                    # Latch accumulator value into output registers
                    self.pd_int_phases[i].eq(pdAcc),
                    # Reset accumulators
                    pdAcc.eq(0)).Elif(
                        pdValid & self.initial_tl_done,
                        # Accumulate
                        If(pdInc,
                           pdAcc.eq(pdAcc - 1)).Else(pdAcc.eq(pdAcc + 1)))
            ]
            self.specials += Instance("ISERDES2",
                                      p_SERDES_MODE="SLAVE",
                                      i_D=lvds_data_s,
                                      i_SHIFTIN=cascade_down,
                                      o_Q4=tempData[3],
                                      o_Q3=tempData[2],
                                      o_Q2=tempData[1],
                                      o_Q1=tempData[0],
                                      o_SHIFTOUT=cascade_up,
                                      **self.iserdes_default)
            if MIRROR_BITS:
                self.comb += self.data_outs[i].eq(tempData[::-1])
            else:
                self.comb += self.data_outs[i].eq(tempData)
Exemplo n.º 16
0
    def __init__(self, pins, pins_n):
        n_bits = 16  # bits per dac data word
        n_channels = 32  # channels per fastino
        n_div = 7  # bits per lane and word
        assert n_div == 7
        n_frame = 14  # word per frame
        n_lanes = len(pins.mosi)  # number of data lanes
        n_checksum = 12  # checksum bits
        n_addr = 4  # readback address bits
        n_word = n_lanes*n_div
        n_body = n_word*n_frame - (n_frame//2 + 1) - n_checksum

        # dac data words
        self.dacs = [Signal(n_bits) for i in range(n_channels)]
        # dac update enable
        self.enable = Signal(n_channels)
        # configuration word
        self.cfg = Signal(20)
        # readback data
        self.dat_r = Signal(n_frame//2*(1 << n_addr))
        # data load synchronization event
        self.stb = Signal()

        # # #

        # crc-12 telco
        self.submodules.crc = LiteEthMACCRCEngine(
            data_width=2*n_lanes, width=n_checksum, polynom=0x80f)

        addr = Signal(4)
        body_ = Cat(self.cfg, addr, self.enable, self.dacs)
        assert len(body_) == n_body
        body = Signal(n_body)
        self.comb += body.eq(body_)

        words_ = []
        j = 0
        for i in range(n_frame):  # iterate over words
            if i == 0:  # data and checksum
                k = n_word - n_checksum
            elif i == 1:  # marker
                words_.append(C(1))
                k = n_word - 1
            elif i < n_frame//2 + 2:  # marker
                words_.append(C(0))
                k = n_word - 1
            else:  # full word
                k = n_word
            # append corresponding frame body bits
            words_.append(body[j:j + k])
            j += k
        words_ = Cat(words_)
        assert len(words_) == n_frame*n_word - n_checksum
        words = Signal(len(words_))
        self.comb += words.eq(words_)

        clk = Signal(n_div, reset=0b1100011)
        clk_stb = Signal()
        i_frame = Signal(max=n_div*n_frame//2)  # DDR
        frame_stb = Signal()
        sr = [Signal(n_frame*n_div - n_checksum//n_lanes, reset_less=True)
                for i in range(n_lanes)]
        assert len(Cat(sr)) == len(words)
        # DDR bits for each register
        ddr_data = Cat([sri[-2] for sri in sr], [sri[-1] for sri in sr])
        self.comb += [
            # assert one cycle ahead
            clk_stb.eq(~clk[0] & clk[-1]),
            # double period because of DDR
            frame_stb.eq(i_frame == n_div*n_frame//2 - 1),

            # LiteETHMACCRCEngine takes data LSB first
            self.crc.data[::-1].eq(ddr_data),
            self.stb.eq(frame_stb & clk_stb),
        ]
        miso = Signal()
        miso_sr = Signal(n_frame, reset_less=True)
        self.sync.rio_phy += [
            # shift 7 bit clock pattern by two bits each DDR cycle
            clk.eq(Cat(clk[-2:], clk)),
            [sri[2:].eq(sri) for sri in sr],
            self.crc.last.eq(self.crc.next),
            If(clk[:2] == 0,  # TODO: tweak MISO sampling
                miso_sr.eq(Cat(miso, miso_sr)),
            ),
            If(~frame_stb,
                i_frame.eq(i_frame + 1),
            ),
            If(frame_stb & clk_stb,
                i_frame.eq(0),
                self.crc.last.eq(0),
                # transpose, load
                Cat(sr).eq(Cat(words[mm::n_lanes] for mm in range(n_lanes))),
                Array([self.dat_r[i*n_frame//2:(i + 1)*n_frame//2]
                    for i in range(1 << len(addr))])[addr].eq(miso_sr),
                addr.eq(addr + 1),
            ),
            If(i_frame == n_div*n_frame//2 - 2,
                # inject crc
                ddr_data.eq(self.crc.next),
            ),
        ]

        clk_ddr = Signal()
        miso0 = Signal()
        self.specials += [
            DDROutput(clk[-1], clk[-2], clk_ddr, ClockSignal("rio_phy")),
            DifferentialOutput(clk_ddr, pins.clk, pins_n.clk),
            DifferentialInput(pins.miso, pins_n.miso, miso0),
            MultiReg(miso0, miso, "rio_phy"),
        ]
        for sri, ddr, mp, mn in zip(
                sr, Signal(n_lanes), pins.mosi, pins_n.mosi):
            self.specials += [
                DDROutput(sri[-1], sri[-2], ddr, ClockSignal("rio_phy")),
                DifferentialOutput(ddr, mp, mn),
            ]