Example #1
0
    def __init__(self, domain,
                 req_stb, req_ack, req_data,
                 srv_stb, srv_ack, srv_data):
        dsync = getattr(self.sync, domain)

        request = PulseSynchronizer("sys", domain)
        reply = PulseSynchronizer(domain, "sys")
        self.submodules += request, reply

        ongoing = Signal()
        self.comb += request.i.eq(~ongoing & req_stb)
        self.sync += [
            req_ack.eq(reply.o),
            If(req_stb, ongoing.eq(1)),
            If(req_ack, ongoing.eq(0))
        ]
        if req_data is not None:
            req_data_r = Signal.like(req_data)
            req_data_r.attr.add("no_retiming")
            self.sync += If(req_stb, req_data_r.eq(req_data))
        dsync += [
            If(request.o, srv_stb.eq(1)),
            If(srv_ack, srv_stb.eq(0))
        ]
        if req_data is not None:
            dsync += If(request.o, srv_data.eq(req_data_r))
        self.comb += reply.i.eq(srv_stb & srv_ack)
    def __init__(self, idata):
        self.start = Signal()
        self.valid = Signal()
        self.error = Signal()

        # # #

        counter = Signal(2)
        shift = Signal()
        data = Signal(3)

        valid = Signal()
        error = Signal()

        self.submodules.fsm = fsm = ClockDomainsRenamer("sd_fb")(FSM(reset_state="IDLE"))

        self.sync.sd_fb += If(shift, data.eq(Cat(idata, data)))

        self.submodules.pulse_start = PulseSynchronizer("sd", "sd_fb")
        self.comb += self.pulse_start.i.eq(self.start)

        fsm.act("IDLE",
            If(self.pulse_start.o,
                NextState("START")
            )
        )
        fsm.act("START",
            If(idata == 0,
                NextValue(counter, 0),
                NextState("RECEIVE")
            )
        )
        fsm.act("RECEIVE",
            shift.eq(1),
            If(counter == 2,
                NextState("CHECK")
            ).Else(
                NextValue(counter, counter + 1)
            )
        )
        fsm.act("CHECK",
            If(data == 0b101,
                valid.eq(0),
                error.eq(1),
            ).Else(
                valid.eq(1),
                error.eq(0)
            ),
            NextState("IDLE")
        )

        self.submodules.pulse_valid = PulseSynchronizer("sd_fb", "sd")
        self.submodules.pulse_error = PulseSynchronizer("sd_fb", "sd")
        self.comb += [
            self.pulse_valid.i.eq(valid),
            self.valid.eq(self.pulse_valid.o),
            self.pulse_error.i.eq(error),
            self.error.eq(self.pulse_error.o)
        ]
Example #3
0
    def __init__(self, dram_port, random=True):
        ashift = log2_int(dram_port.dw // 8)
        awidth = dram_port.aw + ashift
        self.reset = CSR()
        self.start = CSR()
        self.base = CSRStorage(awidth)
        self.length = CSRStorage(awidth)
        self.done = CSRStatus()
        self.ticks = CSRStatus(32)
        self.errors = CSRStatus(32)

        # # #

        cd = dram_port.cd

        core = _LiteDRAMBISTChecker(dram_port, random)
        core = ClockDomainsRenamer(cd)(core)
        self.submodules += core

        reset_sync = PulseSynchronizer("sys", cd)
        start_sync = PulseSynchronizer("sys", cd)
        self.submodules += reset_sync, start_sync
        self.comb += [
            reset_sync.i.eq(self.reset.re),
            core.reset.eq(reset_sync.o),
            start_sync.i.eq(self.start.re),
            core.start.eq(start_sync.o)
        ]

        done_sync = BusSynchronizer(1, cd, "sys")
        self.submodules += done_sync
        self.comb += [
            done_sync.i.eq(core.done),
            self.done.status.eq(done_sync.o)
        ]

        base_sync = BusSynchronizer(awidth, "sys", cd)
        length_sync = BusSynchronizer(awidth, "sys", cd)
        self.submodules += base_sync, length_sync
        self.comb += [
            base_sync.i.eq(self.base.storage),
            core.base.eq(base_sync.o),
            length_sync.i.eq(self.length.storage),
            core.length.eq(length_sync.o)
        ]

        ticks_sync = BusSynchronizer(32, cd, "sys")
        self.submodules += ticks_sync
        self.comb += [
            ticks_sync.i.eq(core.ticks),
            self.ticks.status.eq(ticks_sync.o)
        ]

        errors_sync = BusSynchronizer(32, cd, "sys")
        self.submodules += errors_sync
        self.comb += [
            errors_sync.i.eq(core.errors),
            self.errors.status.eq(errors_sync.o)
        ]
Example #4
0
    def __init__(self, platform):
        # instantiate the clock module
        crg = CRG(platform, sim_config)
        self.submodules += crg


        # instantiate the DUT
        pulse_in = Signal()
        pulse_out = Signal()
        self.submodules.pulsesync = PulseSynchronizer("sys", "adc")
        self.comb += self.pulsesync.i.eq(pulse_in)
        self.comb += pulse_out.eq(self.pulsesync.o)

        # connect test vectors to DUT
        mult = Signal(4) # allow each element in pulse_vect to be repeated "mult" times
        count = Signal(4) # counter variable to implement mult
        self.comb += mult.eq(5)  # in this case, 5

        index = Signal(4) # tracks the index of the vector we are in
        self.sync.sys += [  # generate vector index based on count/multiply params
            count.eq(count + 1),
            If(count == mult,
               index.eq(index + 1),
               count.eq(0),
            )
        ]
        # now assign vector to DUT signal(s)
        for k, i in enumerate(pulse_vect):
            self.sync.sys += [
                If( (count == 0) & (k == index),
                    pulse_in.eq(i)
                )
            ]
Example #5
0
    def __init__(self, period_bits=24):
        self.data = Signal(10)
        self._update = CSR()
        self._value = CSRStatus(period_bits)

        ###
        # (pipeline stage 1)
        # We ignore the 10th (inversion) bit, as it is independent of the
        # transition minimization.
        data_r = Signal(9)
        self.sync.pix += data_r.eq(self.data[:9])

        # (pipeline stage 2)
        # Count the number of transitions in the TMDS word.
        transitions = Signal(8)
        self.comb += [
            transitions[i].eq(data_r[i] ^ data_r[i + 1]) for i in range(8)
        ]
        transition_count = Signal(max=9)
        self.sync.pix += transition_count.eq(
            optree("+", [transitions[i] for i in range(8)]))

        # Control data characters are designed to have a large number (7) of
        # transitions to help the receiver synchronize its clock with the
        # transmitter clock.
        is_control = Signal()
        self.sync.pix += is_control.eq(
            optree("|", [data_r == ct for ct in control_tokens]))

        # (pipeline stage 3)
        # The TMDS characters selected to represent pixel data contain five or
        # fewer transitions.
        is_error = Signal()
        self.sync.pix += is_error.eq((transition_count > 4) & ~is_control)

        # counter
        period_counter = Signal(period_bits)
        period_done = Signal()
        self.sync.pix += Cat(period_counter,
                             period_done).eq(period_counter + 1)

        wer_counter = Signal(period_bits)
        wer_counter_r = Signal(period_bits)
        wer_counter_r_updated = Signal()
        self.sync.pix += [
            wer_counter_r_updated.eq(period_done),
            If(period_done, wer_counter_r.eq(wer_counter),
               wer_counter.eq(0)).Elif(is_error,
                                       wer_counter.eq(wer_counter + 1))
        ]

        # sync to system clock domain
        wer_counter_sys = Signal(period_bits)
        self.submodules.ps_counter = PulseSynchronizer("pix", "sys")
        self.comb += self.ps_counter.i.eq(wer_counter_r_updated)
        self.sync += If(self.ps_counter.o, wer_counter_sys.eq(wer_counter_r))

        # register interface
        self.sync += If(self._update.re,
                        self._value.status.eq(wer_counter_sys))
Example #6
0
    def __init__(self, comma, sys_clk_freq, check_period=6e-3):
        self.rxdata = Signal(20)
        self.restart = Signal()

        check_max_val = ceil(check_period*sys_clk_freq)
        check_counter = Signal(max=check_max_val+1)
        check = Signal()
        self.sync += [
            check.eq(0),
            If(check_counter == 0,
                check.eq(1),
                check_counter.eq(check_max_val)
            ).Else(
                check_counter.eq(check_counter-1)
            )
        ]

        comma_n = ~comma & 0b1111111111
        comma_seen_rxclk = Signal()
        comma_seen = Signal()
        self.specials += MultiReg(comma_seen_rxclk, comma_seen)
        comma_seen_reset = PulseSynchronizer("sys", "rx")
        self.submodules += comma_seen_reset
        self.sync.rx += \
            If(comma_seen_reset.o,
                comma_seen_rxclk.eq(0)
            ).Elif((self.rxdata[:10] == comma) | (self.rxdata[:10] == comma_n),
                comma_seen_rxclk.eq(1)
            )

        self.comb += \
            If(check,
                If(~comma_seen, self.restart.eq(1)),
                comma_seen_reset.i.eq(1)
            )
Example #7
0
    def __init__(self, with_csr=True, simulation=False):
        self.addr = Signal(5)
        self.data = Signal(32)
        self.send = Signal()
        self.done = Signal()

        # # #

        # Create slow icap clk (sys_clk/16) ---------------------------------------------------------
        self.clock_domains.cd_icap = ClockDomain()
        icap_clk_counter = Signal(4)
        self.sync += icap_clk_counter.eq(icap_clk_counter + 1)
        self.sync += self.cd_icap.clk.eq(icap_clk_counter[3])

        # Resynchronize send pulse to icap domain ---------------------------------------------------
        ps_send = PulseSynchronizer("sys", "icap")
        self.submodules += ps_send
        self.comb += ps_send.i.eq(self.send)

        # Generate icap bitstream write sequence
        self._csib = _csib = Signal(reset=1)
        self._i = _i = Signal(32)
        _addr = self.addr << 13
        _data = self.data
        self.sync.icap += [
            _i.eq(0xffffffff),  # dummy
            timeline(
                ps_send.o,
                [
                    (1, [_csib.eq(1), self.done.eq(0)]),
                    (2, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (3, [_csib.eq(0), _i.eq(0xaa995566)]),  # sync word
                    (4, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (5, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (6, [_csib.eq(0), _i.eq(0x30000001 | _addr)
                         ]),  # write command
                    (7, [_csib.eq(0), _i.eq(_data)]),  # write value
                    (8, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (9, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (10, [_csib.eq(0), _i.eq(0x30008001)
                          ]),  # write to cmd register
                    (11, [_csib.eq(0), _i.eq(0x0000000d)]),  # desync command
                    (12, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (13, [_csib.eq(0), _i.eq(0x20000000)]),  # noop
                    (14, [_csib.eq(1), self.done.eq(1)]),
                ])
        ]

        # ICAP instance
        if not simulation:
            self.specials += [
                Instance(
                    "ICAPE2",
                    p_ICAP_WIDTH="X32",
                    i_CLK=ClockSignal("icap"),
                    i_CSIB=_csib,
                    i_RDWRB=0,
                    i_I=Cat(*[_i[8 * i:8 * (i + 1)][::-1] for i in range(4)]),
                )
            ]
Example #8
0
    def __init__(self, clk_freq):
        self.mode = Signal()
        self._mode = CSRStatus()

        # # #

        mode = Signal()
        update_mode = Signal()
        self.sync += \
            If(update_mode,
                self.mode.eq(mode)
            )
        self.comb += self._mode.status.eq(self.mode)

        # Principle:
        #  sys_clk >= 125MHz
        #  eth_rx <= 125Mhz
        # We generate ticks every 1024 clock cycles in eth_rx domain
        # and measure ticks period in sys_clk domain.

        # Generate a tick every 1024 clock cycles (eth_rx clock domain)
        eth_tick = Signal()
        eth_counter = Signal(10, reset_less=True)
        self.sync.eth_rx += eth_counter.eq(eth_counter + 1)
        self.comb += eth_tick.eq(eth_counter == 0)

        # Synchronize tick (sys clock domain)
        sys_tick = Signal()
        eth_ps = PulseSynchronizer("eth_rx", "sys")
        self.comb += [eth_ps.i.eq(eth_tick), sys_tick.eq(eth_ps.o)]
        self.submodules += eth_ps

        # sys_clk domain counter
        sys_counter = Signal(24, reset_less=True)
        sys_counter_reset = Signal()
        sys_counter_ce = Signal()
        self.sync += [
            If(sys_counter_reset,
               sys_counter.eq(0)).Elif(sys_counter_ce,
                                       sys_counter.eq(sys_counter + 1))
        ]

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

        fsm.act("IDLE", sys_counter_reset.eq(1),
                If(sys_tick, NextState("COUNT")))
        fsm.act("COUNT", sys_counter_ce.eq(1),
                If(sys_tick, NextState("DETECTION")))
        fsm.act(
            "DETECTION",
            update_mode.eq(1),
            # if freq < 125MHz-5% use MII mode
            If(sys_counter > int((clk_freq / 125000000) * 1024 * 1.05),
               mode.eq(1)
               # if freq >= 125MHz-5% use GMII mode
               ).Else(mode.eq(0)),
            NextState("IDLE"))
Example #9
0
 def cdc(i):
     o = Signal()
     psync = PulseSynchronizer("sys", "sys2x")
     self.submodules += psync
     self.comb += [
         psync.i.eq(i),
         o.eq(psync.o),
     ]
     return o
Example #10
0
 def csr_cdc(self, i):
     o = Signal()
     psync = PulseSynchronizer("sys", self.internal_cd)
     self.submodules += psync
     self.comb += [
         psync.i.eq(i),
         o.eq(psync.o),
     ]
     return o
Example #11
0
    def __init__(self, period_bits=24):
        self.data = Signal(10)
        self._update = CSR()
        self._value = CSRStatus(period_bits)

        ###

        # pipeline stage 1
        # we ignore the 10th (inversion) bit, as it is independent of the transition minimization
        data_r = Signal(9)
        self.sync.pix += data_r.eq(self.data[:9])

        # pipeline stage 2
        transitions = Signal(8)
        self.comb += [
            transitions[i].eq(data_r[i] ^ data_r[i + 1]) for i in range(8)
        ]
        transition_count = Signal(max=9)
        self.sync.pix += transition_count.eq(
            reduce(add, [transitions[i] for i in range(8)]))

        is_control = Signal()
        self.sync.pix += is_control.eq(
            reduce(or_, [data_r == ct for ct in control_tokens]))

        # pipeline stage 3
        is_error = Signal()
        self.sync.pix += is_error.eq((transition_count > 4) & ~is_control)

        # counter
        period_counter = Signal(period_bits)
        period_done = Signal()
        self.sync.pix += Cat(period_counter,
                             period_done).eq(period_counter + 1)

        wer_counter = Signal(period_bits)
        wer_counter_r = Signal(period_bits)
        wer_counter_r_updated = Signal()
        self.sync.pix += [
            wer_counter_r_updated.eq(period_done),
            If(period_done, wer_counter_r.eq(wer_counter),
               wer_counter.eq(0)).Elif(is_error,
                                       wer_counter.eq(wer_counter + 1))
        ]

        # sync to system clock domain
        wer_counter_sys = Signal(period_bits)
        self.submodules.ps_counter = PulseSynchronizer("pix", "sys")
        self.comb += self.ps_counter.i.eq(wer_counter_r_updated)
        self.sync += If(self.ps_counter.o, wer_counter_sys.eq(wer_counter_r))

        # register interface
        self.sync += If(self._update.re,
                        self._value.status.eq(wer_counter_sys))
Example #12
0
            def add_preamble(self):
                rx_preamble = preamble.LiteEthMACPreambleChecker(datapath_dw)
                rx_preamble = ClockDomainsRenamer(cd_rx)(rx_preamble)
                self.submodules += rx_preamble
                self.pipeline.append(rx_preamble)

                ps = PulseSynchronizer(cd_rx, "sys")
                self.submodules += ps
                self.comb += ps.i.eq(rx_preamble.error)
                self.sync += If(
                    ps.o,
                    self.preamble_errors.status.eq(
                        self.preamble_errors.status + 1))
Example #13
0
    def __init__(self, domain, emi_stb, emi_data, rec_stb, rec_ack, rec_data):
        emi_data_r = Signal.like(emi_data)
        emi_data_r.attr.add("no_retiming")
        dsync = getattr(self.sync, domain)
        dsync += If(emi_stb, emi_data_r.eq(emi_data))

        ps = PulseSynchronizer(domain, "sys")
        self.submodules += ps
        self.comb += ps.i.eq(emi_stb)
        self.sync += [
            If(rec_ack, rec_stb.eq(0)),
            If(ps.o, rec_data.eq(emi_data_r), rec_stb.eq(1))
        ]
Example #14
0
    def create_insert_logic(self):
        self.arm = Signal()
        self.pending = Signal()
        self.data = Signal.like(self.target)

        buf = Signal.like(self.target)
        buf.attr.add("no_retiming")
        self.specials += MultiReg(buf, self.data, "microscope")

        ps_arm = PulseSynchronizer("microscope", self.clock_domain)
        ps_done = PulseSynchronizer(self.clock_domain, "microscope")
        self.submodules += ps_arm, ps_done
        self.comb += ps_arm.i.eq(self.arm)
        self.sync.microscope += [
            If(ps_done.o, self.pending.eq(0)),
            If(self.arm, self.pending.eq(1))
        ]

        sync = getattr(self.sync, self.clock_domain)
        sync += [
            ps_done.i.eq(0),
            If(ps_arm.o, buf.eq(self.target), ps_done.i.eq(1))
        ]
Example #15
0
            def add_crc(self):
                rx_crc = crc.LiteEthMACCRC32Checker(
                    eth_phy_description(datapath_dw))
                rx_crc = BufferizeEndpoints({"sink": DIR_SINK})(
                    rx_crc)  # FIXME: Still required?
                rx_crc = ClockDomainsRenamer(cd_rx)(rx_crc)
                self.submodules += rx_crc
                self.pipeline.append(rx_crc)

                ps = PulseSynchronizer(cd_rx, "sys")
                self.submodules += ps
                self.comb += ps.i.eq(rx_crc.error),
                self.sync += If(
                    ps.o,
                    self.crc_errors.status.eq(self.crc_errors.status + 1))
Example #16
0
    def create_insert_logic(self):
        self.arm = Signal()
        self.pending = Signal()
        self.address = Signal(max=self.depth)
        self.data = Signal(len(self.target))
        self.specials.memory = Memory(len(self.target), self.depth)

        rdport = self.memory.get_port(clock_domain="microscope")
        self.specials += rdport
        self.comb += [rdport.adr.eq(self.address), self.data.eq(rdport.dat_r)]

        ps_arm = PulseSynchronizer("microscope", self.clock_domain)
        ps_done = PulseSynchronizer(self.clock_domain, "microscope")
        self.submodules += ps_arm, ps_done
        self.comb += ps_arm.i.eq(self.arm)
        self.sync.microscope += [
            If(ps_done.o, self.pending.eq(0)),
            If(self.arm, self.pending.eq(1))
        ]

        port = self.memory.get_port(write_capable=True,
                                    clock_domain=self.clock_domain)
        self.specials += port

        running = Signal()
        wait_trigger = Signal()
        sync = getattr(self.sync, self.clock_domain)
        sync += [
            ps_done.i.eq(0),
            If(running, port.adr.eq(port.adr + 1),
               If(port.adr == self.depth - 1, running.eq(0), ps_done.i.eq(1))),
            If(wait_trigger & self.trigger, running.eq(1), wait_trigger.eq(0)),
            If(ps_arm.o, wait_trigger.eq(1))
        ]
        self.comb += port.we.eq(running)
        sync += port.dat_w.eq(self.target)
Example #17
0
    def _register_trigger_in(self, signal, label, cd="rio_phy"):
        if isinstance(cd, str):
            cd = cd
        elif isinstance(cd, ClockDomain):
            cd = cd.name
        else:
            raise ValueError("Invalid clock domain")

        if cd == "rio_phy":
            trigger_in_rio_phy = signal
        else:
            trigger_in_rio_phy = Signal()
            cdc = PulseSynchronizer(cd, "rio_phy")
            self.submodules += cdc
            self.comb += [cdc.i.eq(signal), trigger_in_rio_phy.eq(cdc.o)]

        self.trigger_in_signals.append(trigger_in_rio_phy)
        self.trigger_in_labels.append(label)
Example #18
0
def csr_helper(obj, name, regs, cdc=False, pulsed=False, **kwargs):
    '''
    handle csr + optional clock domain crossing (cdc) from sys to sample

    obj: the object where the csr will be pushed into

    cdc:    add a pulse synchronizer to move the csr write strobe to the
            sample domain, then use the strobe to latch csr.storage

    pulsed: instead of latching csr.storage in the sample clock domain,
            make its value valid only for one cycle and zero otherwise
    '''
    if type(regs) not in (list, tuple):
        regs = [regs]
    for i, reg in enumerate(regs):
        name_ = name
        if len(regs) > 1:
            name_ += str(i)
        if 'reset' not in kwargs:
            try:
                kwargs['reset'] = reg.reset
            except AttributeError:
                print('csr_helper(): could not extract reset value from',
                      name_, reg)
        csr = CSRStorage(len(reg), name=name_, **kwargs)
        print('CSR: {} len({}) reset({})'.format(csr.name, len(csr.storage),
                                                 csr.storage.reset.value))
        setattr(obj, name_, csr)
        if cdc:
            # csr.storage is fully latched and stable when csr.re is pulsed
            # hence we only need to cross the csr.re pulse into the sample
            # clock domain and then latch csr.storage there once more
            ps = PulseSynchronizer('sys', 'sample')
            setattr(obj.submodules, name_ + '_sync', ps)
            obj.comb += ps.i.eq(csr.re)
            if pulsed:
                obj.sync.sample += reg.eq(Mux(ps.o, csr.storage, 0))
            else:
                obj.sync.sample += If(ps.o, reg.eq(csr.storage))
        else:
            if pulsed:
                obj.comb += reg.eq(Mux(csr.re, csr.storage, 0))
            else:
                obj.comb += reg.eq(csr.storage)
Example #19
0
    def __init__(self, roi_engines):
        counts_in = [roi_engine.out.count for roi_engine in roi_engines]

        # This assumes all ROI engines update at the same time.
        self.update = Signal()
        # stays valid until the next frame after self.update is pulsed.
        self.counts = [Signal.like(count) for count in counts_in]

        # # #

        for count in counts_in:
            count.attr.add("no_retiming")
        counts_rtio = [Signal.like(count) for count in counts_in]
        self.specials += [MultiReg(i, o, "rtio") for i, o in zip(counts_in, self.counts)]

        ps = PulseSynchronizer("cl", "rtio")
        self.submodules += ps
        self.comb += ps.i.eq(roi_engines[0].out.update)
        self.sync.rtio += self.update.eq(ps.o)
Example #20
0
 def __init__(self, width, depth, port, **kwargs):
     self.adc_data = adc_data = Signal(width)
     acq_start, acq_start_x = Signal(reset=0), Signal(reset=0)
     self._buf_full = CSRStatus(
         fields=[CSRField("acq_complete", size=1, offset=0)])
     self._acq_start = CSRStorage(
         fields=[CSRField("acq_start", size=1, offset=0, pulse=True)])
     w_addr = Signal(16, reset=0)
     self.comb += [
         self._buf_full.fields.acq_complete.eq(w_addr == depth),
         acq_start.eq(self._acq_start.fields.acq_start),
         port.adr.eq(w_addr),
         port.dat_w.eq(adc_data),
         port.we.eq(w_addr != depth)
     ]
     self.submodules.ps = PulseSynchronizer("sys", "sample")
     self.comb += [self.ps.i.eq(acq_start), acq_start_x.eq(self.ps.o)]
     self.sync.sample += [
         If(acq_start_x & (w_addr == depth),
            w_addr.eq(0)).Elif(w_addr != depth, w_addr.eq(w_addr + 1))
     ]
Example #21
0
    def __init__(self, dma):
        self.enable = CSRStorage()
        self.slot0_base = CSRStorage(32)
        self.slot1_base = CSRStorage(32)
        self.length = CSRStorage(32)

        self.start = CSR()
        self.idle = CSRStatus()
        self.slot = CSRStatus()

        # # #

        self.specials += [
            MultiReg(self.enable.storage, dma.enable, dma.cd),
            MultiReg(self.slot0_base.storage, dma.slot0_base, dma.cd),
            MultiReg(self.slot1_base.storage, dma.slot1_base, dma.cd),
            MultiReg(self.length.storage, dma.length, dma.cd),
            MultiReg(dma.idle, self.idle.status),
            MultiReg(dma.slot, self.slot.status),
        ]

        start_sync = PulseSynchronizer("sys", dma.cd)
        self.submodules += start_sync
        self.comb += [
            start_sync.i.eq(self.start.re),
            dma.start.eq(start_sync.o)
        ]

        if hasattr(dma, "source"):
            self.underflows = CSRStatus(32)
            self.sync.pix += [
                If(~dma.source.valid,
                   self.underflows.status.eq(self.underflows.status + 1))
            ]
        if hasattr(dma, "sink"):
            self.overflows = CSRStatus(32)
            self.sync.pix += [
                If(~dma.sink.ready,
                   self.overflows.status.eq(self.overflows.status + 1))
            ]
Example #22
0
    def __init__(self, counter, input_signal):
        self.arm = CSR()
        self.tag = CSRStatus(len(counter))

        # in helper clock domain
        self.h_tag = Signal(len(counter))
        self.h_tag_update = Signal()

        # # #

        deglitcher = DDMTDDeglitcherFirstEdge(input_signal)
        self.submodules += deglitcher

        self.sync.helper += [
            self.h_tag_update.eq(0),
            If(deglitcher.detect, self.h_tag_update.eq(1),
               self.h_tag.eq(counter + deglitcher.tag_correction))
        ]

        tag_update_ps = PulseSynchronizer("helper", "sys")
        self.submodules += tag_update_ps
        self.comb += tag_update_ps.i.eq(self.h_tag_update)
        tag_update = Signal()
        self.sync += tag_update.eq(tag_update_ps.o)

        tag = Signal(len(counter))
        self.h_tag.attr.add("no_retiming")
        self.specials += MultiReg(self.h_tag, tag)

        self.sync += [
            If(self.arm.re & self.arm.r, self.arm.w.eq(1)),
            If(
                tag_update,
                If(self.arm.w, self.tag.status.eq(tag)),
                self.arm.w.eq(0),
            )
        ]
Example #23
0
    def __init__(self,
                 endpoint,
                 count_width=32,
                 clock_domain="sys",
                 with_tokens=False,
                 with_overflows=False,
                 with_underflows=False):

        self.reset = CSR()
        self.latch = CSR()
        if with_tokens:
            self.tokens = CSRStatus(count_width)
        if with_overflows:
            self.overflows = CSRStatus(count_width)
        if with_underflows:
            self.underflows = CSRStatus(count_width)

        # # #

        reset = Signal()
        latch = Signal()
        if clock_domain == "sys":
            self.comb += reset.eq(self.reset.re)
            self.comb += latch.eq(self.latch.re)
        else:
            reset_ps = PulseSynchronizer("sys", clock_domain)
            latch_ps = PulseSynchronizer("sys", clock_domain)
            self.submodules += reset_ps, latch_ps
            self.comb += reset_ps.i.eq(self.reset.re)
            self.comb += reset.eq(reset_ps.o)
            self.comb += latch_ps.i.eq(self.latch.re)
            self.comb += latch.eq(latch_ps.o)

        # Generic Monitor Counter ------------------------------------------------------------------
        class MonitorCounter(Module):
            def __init__(self, reset, latch, enable, count):
                _count = Signal.like(count)
                _count_latched = Signal.like(count)
                _sync = getattr(self.sync, clock_domain)
                _sync += [
                    If(
                        reset,
                        _count.eq(0),
                        _count_latched.eq(0),
                    ).Elif(
                        enable,
                        If(_count != (2**len(count) - 1),
                           _count.eq(_count + 1))),
                    If(latch, _count_latched.eq(_count))
                ]
                self.specials += MultiReg(_count_latched, count)

        # Tokens Count -----------------------------------------------------------------------------
        if with_tokens:
            tokens_counter = MonitorCounter(reset, latch,
                                            endpoint.valid & endpoint.ready,
                                            self.tokens.status)
            self.submodules += token_counter

        # Overflows Count (only useful when endpoint is expected to always be ready) ---------------
        if with_overflows:
            overflow_counter = MonitorCounter(reset, latch,
                                              endpoint.valid & ~endpoint.ready,
                                              self.overflows.status)
            self.submodules += overflow_counter

        # Underflows Count (only useful when endpoint is expected to always be valid) --------------
        if with_underflows:
            underflow_counter = MonitorCounter(
                reset, latch, ~endpoint.valid & endpoint.ready,
                self.underflows.status)
            self.submodules += underflow_counter
Example #24
0
    def __init__(self, refclk_or_clk_pads, data_pads, sys_clk_freq):
        pcs = PCS(lsb_first=True)
        self.submodules += pcs

        self.sink = pcs.sink
        self.source = pcs.source
        self.link_up = pcs.link_up

        self.clock_domains.cd_eth_tx = ClockDomain()
        self.clock_domains.cd_eth_rx = ClockDomain()
        self.clock_domains.cd_eth_tx_half = ClockDomain(reset_less=True)
        self.clock_domains.cd_eth_rx_half = ClockDomain(reset_less=True)

        # for specifying clock constraints. 62.5MHz clocks.
        self.txoutclk = Signal()
        self.rxoutclk = Signal()

        # # #

        if isinstance(refclk_or_clk_pads, Signal):
            refclk = refclk_or_clk_pads
        else:
            refclk = Signal()
            self.specials += Instance("IBUFDS_GTE2",
                                      i_I=refclk_or_clk_pads.p,
                                      i_IB=refclk_or_clk_pads.n,
                                      i_CEB=0,
                                      o_O=refclk)

        # GTX transceiver
        tx_reset = Signal()
        tx_mmcm_locked = Signal()
        tx_data = Signal(20)
        tx_reset_done = Signal()

        rx_reset = Signal()
        rx_mmcm_locked = Signal()
        rx_data = Signal(20)
        rx_reset_done = Signal()

        pll = GTXChannelPLL(refclk, 200e6, 1.25e9)
        self.submodules.pll = pll

        # Work around Python's 255 argument limitation.
        gtx_params = dict(
            # Simulation-Only Attributes
            p_SIM_RECEIVER_DETECT_PASS="******",
            p_SIM_TX_EIDLE_DRIVE_LEVEL="X",
            p_SIM_RESET_SPEEDUP="FALSE",
            p_SIM_CPLLREFCLK_SEL="FALSE",
            p_SIM_VERSION="4.0",

            # RX Byte and Word Alignment Attributes
            p_ALIGN_COMMA_DOUBLE="FALSE",
            p_ALIGN_COMMA_ENABLE=0b1111111111,
            p_ALIGN_COMMA_WORD=2,
            p_ALIGN_MCOMMA_DET="TRUE",
            p_ALIGN_MCOMMA_VALUE=0b1010000011,
            p_ALIGN_PCOMMA_DET="TRUE",
            p_ALIGN_PCOMMA_VALUE=0b0101111100,
            p_SHOW_REALIGN_COMMA="TRUE",
            p_RXSLIDE_AUTO_WAIT=7,
            p_RXSLIDE_MODE="OFF",
            p_RX_SIG_VALID_DLY=10,

            # RX 8B/10B Decoder Attributes
            p_RX_DISPERR_SEQ_MATCH="TRUE",
            p_DEC_MCOMMA_DETECT="TRUE",
            p_DEC_PCOMMA_DETECT="TRUE",
            p_DEC_VALID_COMMA_ONLY="TRUE",

            # RX Clock Correction Attributes
            p_CBCC_DATA_SOURCE_SEL="DECODED",
            p_CLK_COR_SEQ_2_USE="FALSE",
            p_CLK_COR_KEEP_IDLE="FALSE",
            p_CLK_COR_MAX_LAT=9,
            p_CLK_COR_MIN_LAT=7,
            p_CLK_COR_PRECEDENCE="TRUE",
            p_CLK_COR_REPEAT_WAIT=0,
            p_CLK_COR_SEQ_LEN=1,
            p_CLK_COR_SEQ_1_ENABLE=0b1111,
            p_CLK_COR_SEQ_1_1=0b0100000000,
            p_CLK_COR_SEQ_1_2=0b0000000000,
            p_CLK_COR_SEQ_1_3=0b0000000000,
            p_CLK_COR_SEQ_1_4=0b0000000000,
            p_CLK_CORRECT_USE="FALSE",
            p_CLK_COR_SEQ_2_ENABLE=0b1111,
            p_CLK_COR_SEQ_2_1=0b0100000000,
            p_CLK_COR_SEQ_2_2=0b0000000000,
            p_CLK_COR_SEQ_2_3=0b0000000000,
            p_CLK_COR_SEQ_2_4=0b0000000000,

            # RX Channel Bonding Attributes
            p_CHAN_BOND_KEEP_ALIGN="FALSE",
            p_CHAN_BOND_MAX_SKEW=1,
            p_CHAN_BOND_SEQ_LEN=1,
            p_CHAN_BOND_SEQ_1_1=0b0000000000,
            p_CHAN_BOND_SEQ_1_2=0b0000000000,
            p_CHAN_BOND_SEQ_1_3=0b0000000000,
            p_CHAN_BOND_SEQ_1_4=0b0000000000,
            p_CHAN_BOND_SEQ_1_ENABLE=0b1111,
            p_CHAN_BOND_SEQ_2_1=0b0000000000,
            p_CHAN_BOND_SEQ_2_2=0b0000000000,
            p_CHAN_BOND_SEQ_2_3=0b0000000000,
            p_CHAN_BOND_SEQ_2_4=0b0000000000,
            p_CHAN_BOND_SEQ_2_ENABLE=0b1111,
            p_CHAN_BOND_SEQ_2_USE="FALSE",
            p_FTS_DESKEW_SEQ_ENABLE=0b1111,
            p_FTS_LANE_DESKEW_CFG=0b1111,
            p_FTS_LANE_DESKEW_EN="FALSE",

            # RX Margin Analysis Attributes
            p_ES_CONTROL=0b000000,
            p_ES_ERRDET_EN="FALSE",
            p_ES_EYE_SCAN_EN="TRUE",
            p_ES_HORZ_OFFSET=0x000,
            p_ES_PMA_CFG=0b0000000000,
            p_ES_PRESCALE=0b00000,
            p_ES_QUALIFIER=0x00000000000000000000,
            p_ES_QUAL_MASK=0x00000000000000000000,
            p_ES_SDATA_MASK=0x00000000000000000000,
            p_ES_VERT_OFFSET=0b000000000,

            # FPGA RX Interface Attributes
            p_RX_DATA_WIDTH=20,

            # PMA Attributes
            p_OUTREFCLK_SEL_INV=0b11,
            p_PMA_RSV=0x001e7080,
            p_PMA_RSV2=0x2050,
            p_PMA_RSV3=0b00,
            p_PMA_RSV4=0x00000000,
            p_RX_BIAS_CFG=0b000000000100,
            p_DMONITOR_CFG=0x000A00,
            p_RX_CM_SEL=0b11,
            p_RX_CM_TRIM=0b010,
            p_RX_DEBUG_CFG=0b000000000000,
            p_RX_OS_CFG=0b0000010000000,
            p_TERM_RCAL_CFG=0b10000,
            p_TERM_RCAL_OVRD=0b0,
            p_TST_RSV=0x00000000,
            p_RX_CLK25_DIV=5,
            p_TX_CLK25_DIV=5,
            p_UCODEER_CLR=0b0,

            # PCI Express Attributes
            p_PCS_PCIE_EN="FALSE",

            # PCS Attributes
            p_PCS_RSVD_ATTR=0x000000000000,

            # RX Buffer Attributes
            p_RXBUF_ADDR_MODE="FAST",
            p_RXBUF_EIDLE_HI_CNT=0b1000,
            p_RXBUF_EIDLE_LO_CNT=0b0000,
            p_RXBUF_EN="TRUE",
            p_RX_BUFFER_CFG=0b000000,
            p_RXBUF_RESET_ON_CB_CHANGE="TRUE",
            p_RXBUF_RESET_ON_COMMAALIGN="FALSE",
            p_RXBUF_RESET_ON_EIDLE="FALSE",
            p_RXBUF_RESET_ON_RATE_CHANGE="TRUE",
            p_RXBUFRESET_TIME=0b00001,
            p_RXBUF_THRESH_OVFLW=61,
            p_RXBUF_THRESH_OVRD="FALSE",
            p_RXBUF_THRESH_UNDFLW=4,
            p_RXDLY_CFG=0x001F,
            p_RXDLY_LCFG=0x030,
            p_RXDLY_TAP_CFG=0x0000,
            p_RXPH_CFG=0x000000,
            p_RXPHDLY_CFG=0x084020,
            p_RXPH_MONITOR_SEL=0b00000,
            p_RX_XCLK_SEL="RXREC",
            p_RX_DDI_SEL=0b000000,
            p_RX_DEFER_RESET_BUF_EN="TRUE",

            # CDR Attributes
            p_RXCDR_CFG=0x03000023ff10100020,
            p_RXCDR_FR_RESET_ON_EIDLE=0b0,
            p_RXCDR_HOLD_DURING_EIDLE=0b0,
            p_RXCDR_PH_RESET_ON_EIDLE=0b0,
            p_RXCDR_LOCK_CFG=0b010101,

            # RX Initialization and Reset Attributes
            p_RXCDRFREQRESET_TIME=0b00001,
            p_RXCDRPHRESET_TIME=0b00001,
            p_RXISCANRESET_TIME=0b00001,
            p_RXPCSRESET_TIME=0b00001,
            p_RXPMARESET_TIME=0b00011,

            # RX OOB Signaling Attributes
            p_RXOOB_CFG=0b0000110,

            # RX Gearbox Attributes
            p_RXGEARBOX_EN="FALSE",
            p_GEARBOX_MODE=0b000,

            # PRBS Detection Attribute
            p_RXPRBS_ERR_LOOPBACK=0b0,

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

            # RX OOB Signaling Attributes
            p_SAS_MAX_COM=64,
            p_SAS_MIN_COM=36,
            p_SATA_BURST_SEQ_LEN=0b0101,
            p_SATA_BURST_VAL=0b100,
            p_SATA_EIDLE_VAL=0b100,
            p_SATA_MAX_BURST=8,
            p_SATA_MAX_INIT=21,
            p_SATA_MAX_WAKE=7,
            p_SATA_MIN_BURST=4,
            p_SATA_MIN_INIT=12,
            p_SATA_MIN_WAKE=4,

            # RX Fabric Clock Output Control Attributes
            p_TRANS_TIME_RATE=0x0E,

            # TX Buffer Attributes
            p_TXBUF_EN="TRUE",
            p_TXBUF_RESET_ON_RATE_CHANGE="TRUE",
            p_TXDLY_CFG=0x001F,
            p_TXDLY_LCFG=0x030,
            p_TXDLY_TAP_CFG=0x0000,
            p_TXPH_CFG=0x0780,
            p_TXPHDLY_CFG=0x084020,
            p_TXPH_MONITOR_SEL=0b00000,
            p_TX_XCLK_SEL="TXOUT",

            # FPGA TX Interface Attributes
            p_TX_DATA_WIDTH=20,

            # TX Configurable Driver Attributes
            p_TX_DEEMPH0=0b00000,
            p_TX_DEEMPH1=0b00000,
            p_TX_EIDLE_ASSERT_DELAY=0b110,
            p_TX_EIDLE_DEASSERT_DELAY=0b100,
            p_TX_LOOPBACK_DRIVE_HIZ="FALSE",
            p_TX_MAINCURSOR_SEL=0b0,
            p_TX_DRIVE_MODE="DIRECT",
            p_TX_MARGIN_FULL_0=0b1001110,
            p_TX_MARGIN_FULL_1=0b1001001,
            p_TX_MARGIN_FULL_2=0b1000101,
            p_TX_MARGIN_FULL_3=0b1000010,
            p_TX_MARGIN_FULL_4=0b1000000,
            p_TX_MARGIN_LOW_0=0b1000110,
            p_TX_MARGIN_LOW_1=0b1000100,
            p_TX_MARGIN_LOW_2=0b1000010,
            p_TX_MARGIN_LOW_3=0b1000000,
            p_TX_MARGIN_LOW_4=0b1000000,

            # TX Gearbox Attributes
            p_TXGEARBOX_EN="FALSE",

            # TX Initialization and Reset Attributes
            p_TXPCSRESET_TIME=0b00001,
            p_TXPMARESET_TIME=0b00001,

            # TX Receiver Detection Attributes
            p_TX_RXDETECT_CFG=0x1832,
            p_TX_RXDETECT_REF=0b100,

            # CPLL Attributes
            p_CPLL_CFG=0xBC07DC,
            p_CPLL_FBDIV=pll.config["n2"],
            p_CPLL_FBDIV_45=pll.config["n1"],
            p_CPLL_INIT_CFG=0x00001E,
            p_CPLL_LOCK_CFG=0x01E8,
            p_CPLL_REFCLK_DIV=pll.config["m"],
            p_RXOUT_DIV=pll.config["d"],
            p_TXOUT_DIV=pll.config["d"],
            p_SATA_CPLL_CFG="VCO_3000MHZ",

            # RX Initialization and Reset Attributes
            p_RXDFELPMRESET_TIME=0b0001111,

            # RX Equalizer Attributes
            p_RXLPM_HF_CFG=0b00000011110000,
            p_RXLPM_LF_CFG=0b00000011110000,
            p_RX_DFE_GAIN_CFG=0x020FEA,
            p_RX_DFE_H2_CFG=0b000000000000,
            p_RX_DFE_H3_CFG=0b000001000000,
            p_RX_DFE_H4_CFG=0b00011110000,
            p_RX_DFE_H5_CFG=0b00011100000,
            p_RX_DFE_KL_CFG=0b0000011111110,
            p_RX_DFE_LPM_CFG=0x0954,
            p_RX_DFE_LPM_HOLD_DURING_EIDLE=0b0,
            p_RX_DFE_UT_CFG=0b10001111000000000,
            p_RX_DFE_VP_CFG=0b00011111100000011,

            # Power-Down Attributes
            p_RX_CLKMUX_PD=0b1,
            p_TX_CLKMUX_PD=0b1,

            # FPGA RX Interface Attribute
            p_RX_INT_DATAWIDTH=0,

            # FPGA TX Interface Attribute
            p_TX_INT_DATAWIDTH=0,

            # TX Configurable Driver Attributes
            p_TX_QPI_STATUS_EN=0b0,

            # RX Equalizer Attributes
            p_RX_DFE_KL_CFG2=0x301148AC,
            p_RX_DFE_XYD_CFG=0b0000000000000,

            # TX Configurable Driver Attributes
            p_TX_PREDRIVER_MODE=0b0)
        gtx_params.update(
            # CPLL Ports
            #o_CPLLFBCLKLOST                  =,
            o_CPLLLOCK=pll.lock,
            i_CPLLLOCKDETCLK=ClockSignal(),
            i_CPLLLOCKEN=1,
            i_CPLLPD=0,
            #o_CPLLREFCLKLOST                 =,
            i_CPLLREFCLKSEL=0b001,
            i_CPLLRESET=pll.reset,
            i_GTRSVD=0b0000000000000000,
            i_PCSRSVDIN=0b0000000000000000,
            i_PCSRSVDIN2=0b00000,
            i_PMARSVDIN=0b00000,
            i_PMARSVDIN2=0b00000,
            i_TSTIN=0b11111111111111111111,
            #o_TSTOUT                         =,

            # Channel
            i_CLKRSVD=0b0000,

            # Channel - Clocking Ports
            i_GTGREFCLK=0,
            i_GTNORTHREFCLK0=0,
            i_GTNORTHREFCLK1=0,
            i_GTREFCLK0=pll.refclk,
            i_GTREFCLK1=0,
            i_GTSOUTHREFCLK0=0,
            i_GTSOUTHREFCLK1=0,

            # Channel - DRP Ports
            i_DRPADDR=0,
            i_DRPCLK=0,
            i_DRPDI=0,
            #o_DRPDO                          =,
            i_DRPEN=0,
            #o_DRPRDY                         =,
            i_DRPWE=0,

            # Clocking Ports
            #o_GTREFCLKMONITOR                =,
            i_QPLLCLK=0,
            i_QPLLREFCLK=0,
            i_RXSYSCLKSEL=0b00,
            i_TXSYSCLKSEL=0b00,

            # Digital Monitor Ports
            #o_DMONITOROUT                    =,

            # FPGA TX Interface Datapath Configuration
            i_TX8B10BEN=0,

            # Loopback Ports
            i_LOOPBACK=0b000,

            # PCI Express Ports
            #o_PHYSTATUS                      =,
            i_RXRATE=0b000,
            #o_RXVALID                        =,

            # Power-Down Ports
            i_RXPD=0b00,
            i_TXPD=0b00,

            # RX 8B/10B Decoder Ports
            i_SETERRSTATUS=0,

            # RX Initialization and Reset Ports
            i_EYESCANRESET=0,
            i_RXUSERRDY=rx_mmcm_locked,

            # RX Margin Analysis Ports
            #o_EYESCANDATAERROR               =,
            i_EYESCANMODE=0,
            i_EYESCANTRIGGER=0,

            # Receive Ports - CDR Ports
            i_RXCDRFREQRESET=0,
            i_RXCDRHOLD=0,
            #o_RXCDRLOCK                      =,
            i_RXCDROVRDEN=0,
            i_RXCDRRESET=0,
            i_RXCDRRESETRSV=0,

            # Receive Ports - Clock Correction Ports
            #o_RXCLKCORCNT                    =,

            # Receive Ports - FPGA RX Interface Datapath Configuration
            i_RX8B10BEN=0,

            # Receive Ports - FPGA RX Interface Ports
            i_RXUSRCLK=ClockSignal("eth_rx_half"),
            i_RXUSRCLK2=ClockSignal("eth_rx_half"),

            # Receive Ports - FPGA RX interface Ports
            o_RXDATA=Cat(*[rx_data[10 * i:10 * i + 8] for i in range(2)]),

            # Receive Ports - Pattern Checker Ports
            #o_RXPRBSERR                      =,
            i_RXPRBSSEL=0b000,

            # Receive Ports - Pattern Checker ports
            i_RXPRBSCNTRESET=0,

            # Receive Ports - RX  Equalizer Ports
            i_RXDFEXYDEN=1,
            i_RXDFEXYDHOLD=0,
            i_RXDFEXYDOVRDEN=0,

            # Receive Ports - RX 8B/10B Decoder Ports
            i_RXDISPERR=Cat(*[rx_data[10 * i + 9] for i in range(2)]),
            #o_RXNOTINTABLE                   =,

            # Receive Ports - RX AFE
            i_GTXRXP=data_pads.rxp,
            # Receive Ports - RX AFE Ports
            i_GTXRXN=data_pads.rxn,

            # Receive Ports - RX Buffer Bypass Ports
            i_RXBUFRESET=0,
            #o_RXBUFSTATUS                    =,
            i_RXDDIEN=0,
            i_RXDLYBYPASS=1,
            i_RXDLYEN=0,
            i_RXDLYOVRDEN=0,
            i_RXDLYSRESET=0,
            #o_RXDLYSRESETDONE                =,
            i_RXPHALIGN=0,
            #o_RXPHALIGNDONE                  =,
            i_RXPHALIGNEN=0,
            i_RXPHDLYPD=0,
            i_RXPHDLYRESET=0,
            #o_RXPHMONITOR                    =,
            i_RXPHOVRDEN=0,
            #o_RXPHSLIPMONITOR                =,
            #o_RXSTATUS                       =,

            # Receive Ports - RX Byte and Word Alignment Ports
            #o_RXBYTEISALIGNED                =,
            #o_RXBYTEREALIGN                  =,
            #o_RXCOMMADET                     =,
            i_RXCOMMADETEN=1,
            i_RXMCOMMAALIGNEN=1,
            i_RXPCOMMAALIGNEN=1,

            # Receive Ports - RX Channel Bonding Ports
            #o_RXCHANBONDSEQ                  =,
            i_RXCHBONDEN=0,
            i_RXCHBONDLEVEL=0b000,
            i_RXCHBONDMASTER=0,
            #o_RXCHBONDO                      =,
            i_RXCHBONDSLAVE=0,

            # Receive Ports - RX Channel Bonding Ports
            #o_RXCHANISALIGNED                =,
            #o_RXCHANREALIGN                  =,

            # Receive Ports - RX Equailizer Ports
            i_RXLPMHFHOLD=0,
            i_RXLPMHFOVRDEN=0,
            i_RXLPMLFHOLD=0,

            # Receive Ports - RX Equalizer Ports
            i_RXDFEAGCHOLD=0,
            i_RXDFEAGCOVRDEN=0,
            i_RXDFECM1EN=0,
            i_RXDFELFHOLD=0,
            i_RXDFELFOVRDEN=1,
            i_RXDFELPMRESET=0,
            i_RXDFETAP2HOLD=0,
            i_RXDFETAP2OVRDEN=0,
            i_RXDFETAP3HOLD=0,
            i_RXDFETAP3OVRDEN=0,
            i_RXDFETAP4HOLD=0,
            i_RXDFETAP4OVRDEN=0,
            i_RXDFETAP5HOLD=0,
            i_RXDFETAP5OVRDEN=0,
            i_RXDFEUTHOLD=0,
            i_RXDFEUTOVRDEN=0,
            i_RXDFEVPHOLD=0,
            i_RXDFEVPOVRDEN=0,
            i_RXDFEVSEN=0,
            i_RXLPMLFKLOVRDEN=0,
            #o_RXMONITOROUT                   =
            i_RXMONITORSEL=0,
            i_RXOSHOLD=0,
            i_RXOSOVRDEN=0,

            # Receive Ports - RX Fabric ClocK Output Control Ports
            #o_RXRATEDONE                     =,

            # Receive Ports - RX Fabric Output Control Ports
            o_RXOUTCLK=self.rxoutclk,
            #o_RXOUTCLKFABRIC                 =,
            #o_RXOUTCLKPCS                    =,
            i_RXOUTCLKSEL=0b010,

            # Receive Ports - RX Gearbox Ports
            #o_RXDATAVALID                    =,
            #o_RXHEADER                       =,
            #o_RXHEADERVALID                  =,
            #o_RXSTARTOFSEQ                   =,

            # Receive Ports - RX Gearbox Ports
            i_RXGEARBOXSLIP=0,

            # Receive Ports - RX Initialization and Reset Ports
            i_GTRXRESET=rx_reset,
            i_RXOOBRESET=0,
            i_RXPCSRESET=0,
            i_RXPMARESET=0,

            # Receive Ports - RX Margin Analysis ports
            i_RXLPMEN=0,

            # Receive Ports - RX OOB Signaling ports
            #o_RXCOMSASDET                    =,
            #o_RXCOMWAKEDET                   =,

            # Receive Ports - RX OOB Signaling ports
            #o_RXCOMINITDET                   =,

            # Receive Ports - RX OOB signalling Ports
            #o_RXELECIDLE                     =,
            i_RXELECIDLEMODE=0b11,

            # Receive Ports - RX Polarity Control Ports
            i_RXPOLARITY=0,

            # Receive Ports - RX gearbox ports
            i_RXSLIDE=0,

            # Receive Ports - RX8B/10B Decoder Ports
            #o_RXCHARISCOMMA                  =,
            o_RXCHARISK=Cat(*[rx_data[10 * i + 8] for i in range(2)]),

            # Receive Ports - Rx Channel Bonding Ports
            i_RXCHBONDI=0b00000,

            # Receive Ports -RX Initialization and Reset Ports
            o_RXRESETDONE=rx_reset_done,

            # Rx AFE Ports
            i_RXQPIEN=0,
            #o_RXQPISENN                      =,
            #o_RXQPISENP                      =,

            # TX Buffer Bypass Ports
            i_TXPHDLYTSTCLK=0,

            # TX Configurable Driver Ports
            i_TXPOSTCURSOR=0b00000,
            i_TXPOSTCURSORINV=0,
            i_TXPRECURSOR=0b00000,
            i_TXPRECURSORINV=0,
            i_TXQPIBIASEN=0,
            i_TXQPISTRONGPDOWN=0,
            i_TXQPIWEAKPUP=0,

            # TX Initialization and Reset Ports
            i_CFGRESET=0,
            i_GTTXRESET=tx_reset,
            #o_PCSRSVDOUT                     =,
            i_TXUSERRDY=tx_mmcm_locked,

            # Transceiver Reset Mode Operation
            i_GTRESETSEL=0,
            i_RESETOVRD=0,

            # Transmit Ports - 8b10b Encoder Control Ports
            i_TXCHARDISPMODE=Cat(*[tx_data[10 * i + 9] for i in range(2)]),
            i_TXCHARDISPVAL=Cat(*[tx_data[10 * i + 8] for i in range(2)]),

            # Transmit Ports - FPGA TX Interface Ports
            i_TXUSRCLK=ClockSignal("eth_tx_half"),
            i_TXUSRCLK2=ClockSignal("eth_tx_half"),

            # Transmit Ports - PCI Express Ports
            i_TXELECIDLE=0,
            i_TXMARGIN=0b000,
            i_TXRATE=0b000,
            i_TXSWING=0,

            # Transmit Ports - Pattern Generator Ports
            i_TXPRBSFORCEERR=0,

            # Transmit Ports - TX Buffer Bypass Ports
            i_TXDLYBYPASS=1,
            i_TXDLYEN=0,
            i_TXDLYHOLD=0,
            i_TXDLYOVRDEN=0,
            i_TXDLYSRESET=0,
            #o_TXDLYSRESETDONE                =,
            i_TXDLYUPDOWN=0,
            i_TXPHALIGN=0,
            #o_TXPHALIGNDONE                  =,
            i_TXPHALIGNEN=0,
            i_TXPHDLYPD=0,
            i_TXPHDLYRESET=0,
            i_TXPHINIT=0,
            #o_TXPHINITDONE                   =,
            i_TXPHOVRDEN=0,

            # Transmit Ports - TX Buffer Ports
            #o_TXBUFSTATUS                    =,

            # Transmit Ports - TX Configurable Driver Ports
            i_TXBUFDIFFCTRL=0b100,
            i_TXDEEMPH=0,
            i_TXDIFFCTRL=0b1000,
            i_TXDIFFPD=0,
            i_TXINHIBIT=0,
            i_TXMAINCURSOR=0b0000000,
            i_TXPISOPD=0,

            # Transmit Ports - TX Data Path interface
            i_TXDATA=Cat(*[tx_data[10 * i:10 * i + 8] for i in range(2)]),

            # Transmit Ports - TX Driver and OOB signaling
            o_GTXTXN=data_pads.txn,
            o_GTXTXP=data_pads.txp,

            # Transmit Ports - TX Fabric Clock Output Control Ports
            o_TXOUTCLK=self.txoutclk,
            #o_TXOUTCLKFABRIC                 =,
            #o_TXOUTCLKPCS                    =,
            i_TXOUTCLKSEL=0b010,
            #o_TXRATEDONE                     =,

            # Transmit Ports - TX Gearbox Ports
            i_TXCHARISK=0b00000000,
            #o_TXGEARBOXREADY                 =,
            i_TXHEADER=0b000,
            i_TXSEQUENCE=0b0000000,
            i_TXSTARTSEQ=0,

            # Transmit Ports - TX Initialization and Reset Ports
            i_TXPCSRESET=0,
            i_TXPMARESET=0,
            o_TXRESETDONE=tx_reset_done,

            # Transmit Ports - TX OOB signaling Ports
            #o_TXCOMFINISH                    =,
            i_TXCOMINIT=0,
            i_TXCOMSAS=0,
            i_TXCOMWAKE=0,
            i_TXPDELECIDLEMODE=0,

            # Transmit Ports - TX Polarity Control Ports
            i_TXPOLARITY=0,

            # Transmit Ports - TX Receiver Detection Ports
            i_TXDETECTRX=0,

            # Transmit Ports - TX8b/10b Encoder Ports
            i_TX8B10BBYPASS=0b00000000,

            # Transmit Ports - pattern Generator Ports
            i_TXPRBSSEL=0b000,

            # Tx Configurable Driver  Ports
            #o_TXQPISENN                      =,
            #o_TXQPISENP                      =,
        )
        self.specials += Instance("GTXE2_CHANNEL", **gtx_params)

        # Get 125MHz clocks back - the GTX is outputting 62.5MHz.
        txoutclk_rebuffer = Signal()
        self.specials += Instance("BUFH",
                                  i_I=self.txoutclk,
                                  o_O=txoutclk_rebuffer)
        rxoutclk_rebuffer = Signal()
        self.specials += Instance("BUFG",
                                  i_I=self.rxoutclk,
                                  o_O=rxoutclk_rebuffer)

        tx_mmcm_fb = Signal()
        tx_mmcm_reset = Signal(reset=1)
        clk_tx_unbuf = Signal()
        clk_tx_half_unbuf = Signal()
        self.specials += [
            Instance(
                "MMCME2_BASE",
                p_CLKIN1_PERIOD=16.0,
                i_CLKIN1=txoutclk_rebuffer,
                i_RST=tx_mmcm_reset,
                o_CLKFBOUT=tx_mmcm_fb,
                i_CLKFBIN=tx_mmcm_fb,
                p_CLKFBOUT_MULT_F=16,
                o_LOCKED=tx_mmcm_locked,
                p_DIVCLK_DIVIDE=1,
                p_CLKOUT0_DIVIDE_F=16,
                o_CLKOUT0=clk_tx_half_unbuf,
                p_CLKOUT1_DIVIDE=8,
                o_CLKOUT1=clk_tx_unbuf,
            ),
            Instance("BUFH",
                     i_I=clk_tx_half_unbuf,
                     o_O=self.cd_eth_tx_half.clk),
            Instance("BUFH", i_I=clk_tx_unbuf, o_O=self.cd_eth_tx.clk),
            AsyncResetSynchronizer(self.cd_eth_tx, ~tx_mmcm_locked)
        ]

        rx_mmcm_fb = Signal()
        rx_mmcm_reset = Signal(reset=1)
        clk_rx_unbuf = Signal()
        clk_rx_half_unbuf = Signal()
        self.specials += [
            Instance(
                "MMCME2_BASE",
                p_CLKIN1_PERIOD=16.0,
                i_CLKIN1=rxoutclk_rebuffer,
                i_RST=rx_mmcm_reset,
                o_CLKFBOUT=rx_mmcm_fb,
                i_CLKFBIN=rx_mmcm_fb,
                p_CLKFBOUT_MULT_F=16,
                o_LOCKED=rx_mmcm_locked,
                p_DIVCLK_DIVIDE=1,
                p_CLKOUT0_DIVIDE_F=16,
                o_CLKOUT0=clk_rx_half_unbuf,
                p_CLKOUT1_DIVIDE=8,
                o_CLKOUT1=clk_rx_unbuf,
            ),
            Instance("BUFG",
                     i_I=clk_rx_half_unbuf,
                     o_O=self.cd_eth_rx_half.clk),
            Instance("BUFG", i_I=clk_rx_unbuf, o_O=self.cd_eth_rx.clk),
            AsyncResetSynchronizer(self.cd_eth_rx, ~rx_mmcm_locked)
        ]

        # Transceiver init
        tx_init = GTXTXInit(sys_clk_freq, buffer_enable=True)
        self.comb += [
            pll.reset.eq(tx_init.pllreset),
            tx_init.plllock.eq(pll.lock),
            tx_reset.eq(tx_init.gtXxreset)
        ]
        self.sync += tx_mmcm_reset.eq(~pll.lock)
        tx_mmcm_reset.attr.add("no_retiming")

        rx_init = ResetInserter()(GTXRXInit(sys_clk_freq, buffer_enable=True))
        self.submodules += rx_init
        self.comb += [
            rx_init.reset.eq(~tx_init.done),
            rx_reset.eq(rx_init.gtXxreset)
        ]
        ps_restart = PulseSynchronizer("eth_tx", "sys")
        self.submodules += ps_restart
        self.comb += [
            ps_restart.i.eq(pcs.restart),
            rx_init.restart.eq(ps_restart.o)
        ]

        # Unlike CDRs from serious vendors, Xilinx CDRs can't tell you
        # when they are locked. Assume CDR lock time is 50,000 UI,
        # as per DS183. The Xilinx "wizards" also assume that.
        cdr_lock_time = round(sys_clk_freq * 50e3 / 1.25e9)
        cdr_lock_counter = Signal(max=cdr_lock_time + 1)
        cdr_locked = Signal()
        self.sync += [
            If(rx_reset, cdr_locked.eq(0), cdr_lock_counter.eq(0)).Elif(
                cdr_lock_counter != cdr_lock_time,
                cdr_lock_counter.eq(cdr_lock_counter + 1)).Else(
                    cdr_locked.eq(1)),
            rx_mmcm_reset.eq(~cdr_locked)
        ]
        rx_mmcm_reset.attr.add("no_retiming")

        # Gearbox and PCS connection
        gearbox = Gearbox()
        self.submodules += gearbox

        self.comb += [
            tx_data.eq(gearbox.tx_data_half),
            gearbox.rx_data_half.eq(rx_data),
            gearbox.tx_data.eq(pcs.tbi_tx),
            pcs.tbi_rx.eq(gearbox.rx_data)
        ]
Example #25
0
    def __init__(self, link_layer, min_mem_dw):
        ll_dw = len(link_layer.tx_aux_data)
        mem_dw = max(min_mem_dw, ll_dw)

        self.aux_tx_length = CSRStorage(bits_for(max_packet),
                                        alignment_bits=log2_int(mem_dw//8))
        self.aux_tx = CSR()
        self.specials.mem = Memory(mem_dw, max_packet//(mem_dw//8))

        converter = ClockDomainsRenamer("rtio")(
            stream.Converter(mem_dw, ll_dw))
        self.submodules += converter

        # when continuously fed, the Converter outputs data continuously
        self.comb += [
            converter.source.ack.eq(link_layer.tx_aux_ack),
            link_layer.tx_aux_frame.eq(converter.source.stb),
            link_layer.tx_aux_data.eq(converter.source.data)
        ]

        seen_eop_rst = Signal()
        frame_r = Signal()
        seen_eop = Signal()
        self.sync.rtio += [
            If(link_layer.tx_aux_ack,
                frame_r.eq(link_layer.tx_aux_frame),
                If(frame_r & ~link_layer.tx_aux_frame, seen_eop.eq(1))
            ),
            If(seen_eop_rst, seen_eop.eq(0))
        ]

        mem_port = self.mem.get_port(clock_domain="rtio")
        self.specials += mem_port

        self.aux_tx_length.storage.attr.add("no_retiming")
        tx_length = Signal(bits_for(max_packet))
        self.specials += MultiReg(self.aux_tx_length.storage, tx_length, "rtio")

        frame_counter_nbits = bits_for(max_packet) - log2_int(mem_dw//8)
        frame_counter = Signal(frame_counter_nbits)
        frame_counter_next = Signal(frame_counter_nbits)
        frame_counter_ce = Signal()
        frame_counter_rst = Signal()
        self.comb += [
            frame_counter_next.eq(frame_counter),
            If(frame_counter_rst,
                frame_counter_next.eq(0)
            ).Elif(frame_counter_ce,
                frame_counter_next.eq(frame_counter + 1)
            ),
            mem_port.adr.eq(frame_counter_next),
            converter.sink.data.eq(mem_port.dat_r)
        ]
        self.sync.rtio += frame_counter.eq(frame_counter_next)

        start_tx = PulseSynchronizer("sys", "rtio")
        tx_done = PulseSynchronizer("rtio", "sys")
        self.submodules += start_tx, tx_done
        self.comb += start_tx.i.eq(self.aux_tx.re)
        self.sync += [
            If(tx_done.o, self.aux_tx.w.eq(0)),
            If(self.aux_tx.re, self.aux_tx.w.eq(1))
        ]

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

        fsm.act("IDLE",
            frame_counter_rst.eq(1),
            seen_eop_rst.eq(1),
            If(start_tx.o, NextState("TRANSMIT"))
        )
        fsm.act("TRANSMIT",
            converter.sink.stb.eq(1),
            If(converter.sink.ack,
                frame_counter_ce.eq(1)
            ),
            If(frame_counter_next == tx_length, NextState("WAIT_INTERFRAME"))
        )
        fsm.act("WAIT_INTERFRAME",
            If(seen_eop,
                tx_done.i.eq(1),
                NextState("IDLE")
            )
        )
Example #26
0
    def __init__(self, link_layer, min_mem_dw):
        self.aux_rx_length = CSRStatus(bits_for(max_packet))
        self.aux_rx_present = CSR()
        self.aux_rx_error = CSR()

        ll_dw = len(link_layer.rx_aux_data)
        mem_dw = max(min_mem_dw, ll_dw)
        self.specials.mem = Memory(mem_dw, max_packet//(mem_dw//8))

        converter = ClockDomainsRenamer("rtio_rx")(
            stream.Converter(ll_dw, mem_dw))
        self.submodules += converter

        # when continuously drained, the Converter accepts data continuously
        frame_r = Signal()
        self.sync.rtio_rx += [
            If(link_layer.rx_aux_stb,
                frame_r.eq(link_layer.rx_aux_frame),
                converter.sink.data.eq(link_layer.rx_aux_data)
            )
        ]
        self.comb += [
            converter.sink.stb.eq(link_layer.rx_aux_stb & frame_r),
            converter.sink.eop.eq(converter.sink.stb & ~link_layer.rx_aux_frame)
        ]

        mem_port = self.mem.get_port(write_capable=True, clock_domain="rtio_rx")
        self.specials += mem_port

        frame_counter_nbits = bits_for(max_packet) - log2_int(mem_dw//8)
        frame_counter = Signal(frame_counter_nbits)
        self.comb += [
            mem_port.adr.eq(frame_counter),
            mem_port.dat_w.eq(converter.source.data),
            converter.source.ack.eq(1)
        ]

        frame_counter.attr.add("no_retiming")
        frame_counter_sys = Signal(frame_counter_nbits)
        self.specials += MultiReg(frame_counter, frame_counter_sys)
        self.comb += self.aux_rx_length.status.eq(frame_counter_sys << log2_int(mem_dw//8))

        signal_frame = PulseSynchronizer("rtio_rx", "sys")
        frame_ack = PulseSynchronizer("sys", "rtio_rx")
        signal_error = PulseSynchronizer("rtio_rx", "sys")
        self.submodules += signal_frame, frame_ack, signal_error
        self.sync += [
            If(self.aux_rx_present.re, self.aux_rx_present.w.eq(0)),
            If(signal_frame.o, self.aux_rx_present.w.eq(1)),
            If(self.aux_rx_error.re, self.aux_rx_error.w.eq(0)),
            If(signal_error.o, self.aux_rx_error.w.eq(1))
        ]
        self.comb += frame_ack.i.eq(self.aux_rx_present.re)

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

        sop = Signal(reset=1)
        self.sync.rtio_rx += \
            If(converter.source.stb,
                If(converter.source.eop,
                    sop.eq(1)
                ).Else(
                    sop.eq(0)
                )
            )

        fsm.act("IDLE",
            If(converter.source.stb & sop,
                NextValue(frame_counter, frame_counter + 1),
                mem_port.we.eq(1),
                If(converter.source.eop,
                    NextState("SIGNAL_FRAME")
                ).Else(
                    NextState("FRAME")
                )
            ).Else(
                NextValue(frame_counter, 0)
            )
        )
        fsm.act("FRAME",
            If(converter.source.stb,
                NextValue(frame_counter, frame_counter + 1),
                mem_port.we.eq(1),
                If(frame_counter == max_packet,
                    mem_port.we.eq(0),
                    signal_error.i.eq(1),
                    NextState("IDLE")  # discard the rest of the frame
                ),
                If(converter.source.eop,
                    NextState("SIGNAL_FRAME")
                )
            )
        )
        fsm.act("SIGNAL_FRAME",
            signal_frame.i.eq(1),
            NextState("WAIT_ACK"),
            If(converter.source.stb, signal_error.i.eq(1))
        )
        fsm.act("WAIT_ACK",
            If(frame_ack.o,
                NextValue(frame_counter, 0), 
                NextState("IDLE")
            ),
            If(converter.source.stb, signal_error.i.eq(1))
        )
Example #27
0
    def __init__(self, lsb_first=False, check_period=6e-3, more_ack_time=10e-3):
        self.submodules.tx = ClockDomainsRenamer("eth_tx")(
            TransmitPath(lsb_first=lsb_first))
        self.submodules.rx = ClockDomainsRenamer("eth_rx")(
            ReceivePath(lsb_first=lsb_first))

        self.tbi_tx = self.tx.encoder.output[0]
        self.tbi_rx = self.rx.decoder.input
        self.sink = stream.Endpoint(eth_phy_description(8))
        self.source = stream.Endpoint(eth_phy_description(8))
        
        self.link_up = Signal()
        self.restart = Signal()

        # # #
        
        # endpoint interface
        self.comb += [
            self.tx.tx_stb.eq(self.sink.valid),
            self.sink.ready.eq(self.tx.tx_ack),
            self.tx.tx_data.eq(self.sink.data),
        ]

        rx_en_d = Signal()
        self.sync.eth_rx += [
            rx_en_d.eq(self.rx.rx_en),
            self.source.valid.eq(self.rx.rx_en),
            self.source.data.eq(self.rx.rx_data)
        ]
        self.comb += self.source.last.eq(~self.rx.rx_en & rx_en_d)

        # main module
        seen_valid_ci = PulseSynchronizer("eth_rx", "eth_tx")
        self.submodules += seen_valid_ci
        self.comb += seen_valid_ci.i.eq(self.rx.seen_valid_ci)

        checker_max_val = ceil(check_period*125e6)
        checker_counter = Signal(max=checker_max_val+1)
        checker_tick = Signal()
        checker_ok = Signal()
        self.sync.eth_tx += [
            checker_tick.eq(0),
            If(checker_counter == 0,
                checker_tick.eq(1),
                checker_counter.eq(checker_max_val)
            ).Else(
                checker_counter.eq(checker_counter-1)
            ),
            If(seen_valid_ci.o, checker_ok.eq(1)),
            If(checker_tick, checker_ok.eq(0))
        ]

        autoneg_ack = Signal()
        self.comb += self.tx.config_reg.eq((1 << 5) | (autoneg_ack << 14))

        rx_config_reg = PulseSynchronizer("eth_rx", "eth_tx")
        rx_config_reg_ack = PulseSynchronizer("eth_rx", "eth_tx")
        self.submodules += rx_config_reg, rx_config_reg_ack

        more_ack_timer = ClockDomainsRenamer("eth_tx")(
            WaitTimer(ceil(more_ack_time*125e6)))
        self.submodules += more_ack_timer

        fsm = ClockDomainsRenamer("eth_tx")(FSM())
        self.submodules += fsm

        fsm.act("AUTONEG_WAIT_CONFIG_REG",
            self.tx.config_stb.eq(1),
            If(rx_config_reg.o|rx_config_reg_ack.o,
                NextState("AUTONEG_WAIT_ACK")
            ),
            If(checker_tick & ~checker_ok,
                self.restart.eq(1),
                NextState("AUTONEG_WAIT_CONFIG_REG")
            )
        )
        fsm.act("AUTONEG_WAIT_ACK",
            self.tx.config_stb.eq(1),
            autoneg_ack.eq(1),
            If(rx_config_reg_ack.o,
                NextState("AUTONEG_SEND_MORE_ACK")
            ),
            If(checker_tick & ~checker_ok,
                self.restart.eq(1),
                NextState("AUTONEG_WAIT_CONFIG_REG")
            )
        )
        fsm.act("AUTONEG_SEND_MORE_ACK",
            self.tx.config_stb.eq(1),
            autoneg_ack.eq(1),
            more_ack_timer.wait.eq(1),
            If(more_ack_timer.done,
                NextState("RUNNING")
            ),
            If(checker_tick & ~checker_ok,
                self.restart.eq(1),
                NextState("AUTONEG_WAIT_CONFIG_REG")
            )
        )
        fsm.act("RUNNING",
            self.link_up.eq(1),
            If(checker_tick & ~checker_ok,
                self.restart.eq(1),
                NextState("AUTONEG_WAIT_CONFIG_REG")
            )
        )

        c_counter = Signal(max=5)
        previous_config_reg = Signal(16)
        self.sync.eth_rx += [
            If(self.rx.seen_config_reg,
                c_counter.eq(4)
            ).Elif(c_counter != 0,
                c_counter.eq(c_counter - 1)
            ),

            rx_config_reg_ack.i.eq(0),
            rx_config_reg.i.eq(0),
            If(self.rx.seen_config_reg,
                previous_config_reg.eq(self.rx.config_reg),
                # two identical config_reg in immediate succession
                If((c_counter == 1) & (previous_config_reg == self.rx.config_reg),
                    If(previous_config_reg[14],
                        rx_config_reg_ack.i.eq(1)
                    ).Else(
                        rx_config_reg.i.eq(1)
                    )
                )
            )
        ]
Example #28
0
    def __init__(self,
                 lsb_first=False,
                 check_period=6e-3,
                 more_ack_time=10e-3):
        self.submodules.tx = ClockDomainsRenamer("eth_tx")(
            TransmitPath(lsb_first=lsb_first))
        self.submodules.rx = ClockDomainsRenamer("eth_rx")(
            ReceivePath(lsb_first=lsb_first))

        self.tbi_tx = self.tx.encoder.output[0]
        self.tbi_rx = self.rx.decoder.input
        self.sink = stream.Endpoint(eth_phy_layout(8))
        self.source = stream.Endpoint(eth_phy_layout(8))

        self.link_up = Signal()
        self.restart = Signal()

        self.lp_abi = BusSynchronizer(16, "eth_rx", "eth_tx")
        self.submodules += self.lp_abi

        # # #

        # endpoint interface
        self.comb += [
            self.tx.tx_stb.eq(self.sink.stb),
            self.sink.ack.eq(self.tx.tx_ack),
            self.tx.tx_data.eq(self.sink.data),
        ]

        rx_en_d = Signal()
        self.sync.eth_rx += [
            rx_en_d.eq(self.rx.rx_en),
            self.source.stb.eq(self.rx.sample_en),
            self.source.data.eq(self.rx.rx_data)
        ]
        self.comb += self.source.eop.eq(~self.rx.rx_en & rx_en_d)

        # main module
        seen_valid_ci = PulseSynchronizer("eth_rx", "eth_tx")
        self.submodules += seen_valid_ci
        self.comb += seen_valid_ci.i.eq(self.rx.seen_valid_ci)

        checker_max_val = ceil(check_period * 125e6)
        checker_counter = Signal(max=checker_max_val + 1)
        checker_tick = Signal()
        checker_ok = Signal()
        self.sync.eth_tx += [
            checker_tick.eq(0),
            If(checker_counter == 0, checker_tick.eq(1),
               checker_counter.eq(checker_max_val)).Else(
                   checker_counter.eq(checker_counter - 1)),
            If(seen_valid_ci.o, checker_ok.eq(1)),
            If(checker_tick, checker_ok.eq(0))
        ]

        # Control if tx_config_reg should be empty
        tx_config_empty = Signal()
        # Detections in SGMII mode
        is_sgmii = Signal()
        linkdown = Signal()
        self.comb += [
            is_sgmii.eq(self.lp_abi.o[0]),
            # Detect that link is down:
            # - 1000BASE-X: linkup can be inferred by non-empty reg
            # - SGMII: linkup is indicated with bit 15
            linkdown.eq((self.lp_abi.o[0] & ~self.lp_abi.o[15])
                        | (self.lp_abi.o == 0)),
            self.tx.sgmii_speed.eq(
                Mux(self.lp_abi.o[0], self.lp_abi.o[10:12], 0b10)),
            self.rx.sgmii_speed.eq(
                Mux(self.lp_abi.i[0], self.lp_abi.i[10:12], 0b10))
        ]
        autoneg_ack = Signal()
        self.comb += [
            self.tx.config_reg.eq(
                Mux(
                    tx_config_empty,
                    0,
                    (is_sgmii) |  # SGMII: SGMII in-use
                    (~is_sgmii << 5) |  # 1000BASE-X: Full-duplex
                    (
                        Mux(
                            self.lp_abi.o[0],  # SGMII: Speed
                            self.lp_abi.o[10:12],
                            0) << 10) | (is_sgmii << 12)
                    |  # SGMII: Full-duplex
                    (autoneg_ack << 14) |  # SGMII/1000BASE-X: Acknowledge Bit
                    (is_sgmii & self.link_up)  # SGMII: Link-up
                ))
        ]

        rx_config_reg_abi = PulseSynchronizer("eth_rx", "eth_tx")
        rx_config_reg_ack = PulseSynchronizer("eth_rx", "eth_tx")
        self.submodules += [rx_config_reg_abi, rx_config_reg_ack]

        more_ack_timer = ClockDomainsRenamer("eth_tx")(WaitTimer(
            ceil(more_ack_time * 125e6)))
        # SGMII: use 1.6ms link_timer
        sgmii_ack_timer = ClockDomainsRenamer("eth_tx")(WaitTimer(
            ceil(1.6e-3 * 125e6)))
        self.submodules += more_ack_timer, sgmii_ack_timer

        fsm = ClockDomainsRenamer("eth_tx")(FSM())
        self.submodules += fsm

        # AN_ENABLE
        fsm.act("AUTONEG_BREAKLINK", self.tx.config_stb.eq(1),
                tx_config_empty.eq(1), more_ack_timer.wait.eq(1),
                If(more_ack_timer.done, NextState("AUTONEG_WAIT_ABI")))
        # ABILITY_DETECT
        fsm.act(
            "AUTONEG_WAIT_ABI", self.tx.config_stb.eq(1),
            If(rx_config_reg_abi.o, NextState("AUTONEG_WAIT_ACK")),
            If(checker_tick & ~checker_ok, self.restart.eq(1),
               NextState("AUTONEG_BREAKLINK")))
        # ACKNOWLEDGE_DETECT
        fsm.act(
            "AUTONEG_WAIT_ACK", self.tx.config_stb.eq(1), autoneg_ack.eq(1),
            If(rx_config_reg_ack.o, NextState("AUTONEG_SEND_MORE_ACK")),
            If(checker_tick & ~checker_ok, self.restart.eq(1),
               NextState("AUTONEG_BREAKLINK")))
        # COMPLETE_ACKNOWLEDGE
        fsm.act(
            "AUTONEG_SEND_MORE_ACK", self.tx.config_stb.eq(1),
            autoneg_ack.eq(1), more_ack_timer.wait.eq(~is_sgmii),
            sgmii_ack_timer.wait.eq(is_sgmii),
            If((is_sgmii & sgmii_ack_timer.done) |
               (~is_sgmii & more_ack_timer.done), NextState("RUNNING")),
            If(checker_tick & ~checker_ok, self.restart.eq(1),
               NextState("AUTONEG_BREAKLINK")))
        # LINK_OK
        fsm.act(
            "RUNNING", self.link_up.eq(1),
            If((checker_tick & ~checker_ok) | linkdown, self.restart.eq(1),
               NextState("AUTONEG_BREAKLINK")))

        c_counter = Signal(max=5)
        prev_config_reg = Signal(16)
        self.sync.eth_rx += [
            # Restart consistency counter
            If(self.rx.seen_config_reg,
               c_counter.eq(4)).Elif(c_counter != 0,
                                     c_counter.eq(c_counter - 1)),
            rx_config_reg_abi.i.eq(0),
            rx_config_reg_ack.i.eq(0),
            If(
                self.rx.seen_config_reg,
                # Record current config_reg for comparison in the next clock cycle
                prev_config_reg.eq(self.rx.config_reg),
                # Compare consecutive values of config_reg
                If(
                    (c_counter == 1) &
                    (prev_config_reg & 0xbfff == self.rx.config_reg & 0xbfff),
                    # Acknowledgement/Consistency match
                    If(
                        prev_config_reg[14] & self.rx.config_reg[14],
                        rx_config_reg_ack.i.eq(1),
                    )
                    # Ability match
                    .Else(rx_config_reg_abi.i.eq(1), )),
                # Record advertised ability of link partner
                self.lp_abi.i.eq(self.rx.config_reg))
        ]
Example #29
0
    def __init__(self,
                 lsb_first=False,
                 check_period=6e-3,
                 more_ack_time=10e-3):
        self.submodules.tx = ClockDomainsRenamer("eth_tx")(
            TransmitPath(lsb_first=lsb_first))
        self.submodules.rx = ClockDomainsRenamer("eth_rx")(
            ReceivePath(lsb_first=lsb_first))

        self.tbi_tx = self.tx.encoder.output[0]
        self.tbi_rx = self.rx.decoder.input
        self.sink = stream.Endpoint(eth_phy_description(8))
        self.source = stream.Endpoint(eth_phy_description(8))

        self.link_up = Signal()
        self.restart = Signal()

        # SGMII Speed Adaptation
        is_sgmii = Signal()
        self.link_partner_adv_ability = Signal(16)

        # # #

        # endpoint interface
        self.comb += [
            self.tx.tx_stb.eq(self.sink.valid),
            self.sink.ready.eq(self.tx.tx_ack),
            self.tx.tx_data.eq(self.sink.data),
        ]

        rx_en_d = Signal()
        self.sync.eth_rx += [
            rx_en_d.eq(self.rx.rx_en),
            self.source.valid.eq(self.rx.sample_en),
            self.source.data.eq(self.rx.rx_data)
        ]
        self.comb += self.source.last.eq(~self.rx.rx_en & rx_en_d)

        # main module
        seen_valid_ci = PulseSynchronizer("eth_rx", "eth_tx")
        self.submodules += seen_valid_ci
        self.comb += seen_valid_ci.i.eq(self.rx.seen_valid_ci)

        checker_max_val = ceil(check_period * 125e6)
        checker_counter = Signal(max=checker_max_val + 1)
        checker_tick = Signal()
        checker_ok = Signal()
        self.sync.eth_tx += [
            checker_tick.eq(0),
            If(checker_counter == 0, checker_tick.eq(1),
               checker_counter.eq(checker_max_val)).Else(
                   checker_counter.eq(checker_counter - 1)),
            If(seen_valid_ci.o, checker_ok.eq(1)),
            If(checker_tick, checker_ok.eq(0))
        ]

        autoneg_ack = Signal()
        self.comb += self.tx.config_reg.eq((is_sgmii) |  # SGMII-specific
                                           (~is_sgmii << 5) |  # Full-duplex
                                           (autoneg_ack << 14)  # ACK
                                           )

        rx_config_reg_abi = PulseSynchronizer("eth_rx", "eth_tx")
        rx_config_reg_ack = PulseSynchronizer("eth_rx", "eth_tx")
        self.submodules += [rx_config_reg_abi, rx_config_reg_ack]

        more_ack_timer = ClockDomainsRenamer("eth_tx")(WaitTimer(
            ceil(more_ack_time * 125e6)))
        self.submodules += more_ack_timer

        fsm_inited = Signal()
        config_reg_empty = Signal()

        fsm = ClockDomainsRenamer("eth_tx")(FSM())
        self.submodules += fsm

        fsm.act(
            "AUTONEG_WAIT_ABI", self.tx.config_stb.eq(fsm_inited),
            If(rx_config_reg_abi.o, NextValue(fsm_inited, 1),
               NextState("AUTONEG_WAIT_ACK")),
            If(checker_tick & ~checker_ok, self.restart.eq(1),
               NextState("AUTONEG_WAIT_ABI")))
        fsm.act(
            "AUTONEG_WAIT_ACK", self.tx.config_stb.eq(1), autoneg_ack.eq(1),
            If(rx_config_reg_ack.o, NextState("AUTONEG_SEND_MORE_ACK")),
            If(checker_tick & ~checker_ok, self.restart.eq(1),
               NextState("AUTONEG_WAIT_ABI")))
        # COMPLETE_ACKNOWLEDGE
        fsm.act(
            "AUTONEG_SEND_MORE_ACK", self.tx.config_stb.eq(1),
            autoneg_ack.eq(1), more_ack_timer.wait.eq(1),
            If(more_ack_timer.done, NextState("RUNNING")),
            If(checker_tick & ~checker_ok, self.restart.eq(1),
               NextState("AUTONEG_WAIT_ABI")))
        # LINK_OK
        fsm.act(
            "RUNNING", self.link_up.eq(1),
            If((checker_tick & ~checker_ok) | config_reg_empty,
               self.restart.eq(1), NextState("AUTONEG_WAIT_ABI")))

        c_counter = Signal(max=5)
        previous_config_reg = Signal(16)
        preack_config_reg = Signal(16)
        self.sync.eth_rx += [
            # Restart consistency counter
            If(self.rx.seen_config_reg,
               c_counter.eq(4)).Elif(c_counter != 0,
                                     c_counter.eq(c_counter - 1)),
            rx_config_reg_abi.i.eq(0),
            rx_config_reg_ack.i.eq(0),
            If(
                self.rx.seen_config_reg,
                previous_config_reg.eq(self.rx.config_reg),
                If(
                    (c_counter == 1) & ((previous_config_reg | 0x4000)
                                        == (self.rx.config_reg | 0x4000)) &
                    ((self.rx.config_reg | 1) != 1),
                    # Ability match
                    rx_config_reg_abi.i.eq(1),
                    preack_config_reg.eq(previous_config_reg),
                    # Acknowledgement/Consistency match
                    If((previous_config_reg[14] & self.rx.config_reg[14]) &
                       ((preack_config_reg | 0x4000)
                        == (self.rx.config_reg | 0x4000)),
                       rx_config_reg_ack.i.eq(1))),
                # Record advertised ability of link partner
                self.link_partner_adv_ability.eq(self.rx.config_reg))
        ]

        # Speed detection via SGMII
        sgmii_speed = Mux(is_sgmii, self.link_partner_adv_ability[10:12], 0b10)
        self.comb += [
            is_sgmii.eq(self.link_partner_adv_ability[0]),
            self.tx.sgmii_speed.eq(sgmii_speed),
            self.rx.sgmii_speed.eq(sgmii_speed)
        ]

        # Detect that config_reg is empty
        self.comb += [
            config_reg_empty.eq((self.link_partner_adv_ability | 1) == 1)
        ]
Example #30
0
    def __init__(self, pads):
        self.gpio_enable = CSRStorage(reset=1)
        self.gpio_in = CSRStatus(2)
        self.gpio_out = CSRStorage(2)
        self.gpio_oe = CSRStorage(2)

        self.i2c_divider = CSRStorage(16)
        self.i2c_address = CSRStorage(7)
        self.errors = CSR(2)

        # in helper clock domain
        self.adpll = Signal(24)
        self.adpll_stb = Signal()

        # # #

        programmer = ClockDomainsRenamer("helper")(ADPLLProgrammer())
        self.submodules += programmer

        self.i2c_divider.storage.attr.add("no_retiming")
        self.i2c_address.storage.attr.add("no_retiming")
        self.specials += [
            MultiReg(self.i2c_divider.storage, programmer.i2c_divider,
                     "helper"),
            MultiReg(self.i2c_address.storage, programmer.i2c_address,
                     "helper")
        ]
        self.comb += [
            programmer.adpll.eq(self.adpll),
            programmer.adpll_stb.eq(self.adpll_stb)
        ]

        self.gpio_enable.storage.attr.add("no_retiming")
        self.gpio_out.storage.attr.add("no_retiming")
        self.gpio_oe.storage.attr.add("no_retiming")

        # SCL GPIO and mux
        ts_scl = TSTriple(1)
        self.specials += ts_scl.get_tristate(pads.scl)

        status = Signal()
        self.comb += self.gpio_in.status[0].eq(status)

        self.specials += MultiReg(ts_scl.i, status)
        self.comb += [
            If(self.gpio_enable.storage, ts_scl.o.eq(self.gpio_out.storage[0]),
               ts_scl.oe.eq(self.gpio_oe.storage[0])).Else(
                   ts_scl.o.eq(programmer.scl), ts_scl.oe.eq(1))
        ]

        # SDA GPIO and mux
        ts_sda = TSTriple(1)
        self.specials += ts_sda.get_tristate(pads.sda)

        status = Signal()
        self.comb += self.gpio_in.status[1].eq(status)

        self.specials += MultiReg(ts_sda.i, status)
        self.comb += [
            If(self.gpio_enable.storage, ts_sda.o.eq(self.gpio_out.storage[1]),
               ts_sda.oe.eq(self.gpio_oe.storage[1])).Else(
                   ts_sda.o.eq(0), ts_sda.oe.eq(~programmer.sda_o))
        ]
        self.specials += MultiReg(ts_sda.i, programmer.sda_i, "helper")

        # Error reporting
        collision_cdc = BlindTransfer("helper", "sys")
        self.submodules += collision_cdc
        self.comb += collision_cdc.i.eq(programmer.stb & programmer.busy)

        nack_cdc = PulseSynchronizer("helper", "sys")
        self.submodules += nack_cdc
        self.comb += nack_cdc.i.eq(programmer.nack)

        for n, trig in enumerate([collision_cdc.o, nack_cdc.o]):
            self.sync += [
                If(self.errors.re & self.errors.r[n], self.errors.w[n].eq(0)),
                If(trig, self.errors.w[n].eq(1))
            ]