Exemple #1
0
    def __init__(self, nbits=11):
        self.valid_i = Signal()
        self.vsync = Signal()
        self.de = Signal()

        self._hres = CSRStatus(nbits)
        self._vres = CSRStatus(nbits)

        # # #

        # Detect DE transitions
        de_r = Signal()
        pn_de = Signal()
        self.sync.pix += de_r.eq(self.de)
        self.comb += pn_de.eq(~self.de & de_r)

        # HRES
        hcounter = Signal(nbits)
        self.sync.pix += \
            If(self.valid_i & self.de,
                hcounter.eq(hcounter + 1)
            ).Else(
                hcounter.eq(0)
            )

        hcounter_st = Signal(nbits)
        self.sync.pix += \
            If(self.valid_i,
                If(pn_de, hcounter_st.eq(hcounter))
            ).Else(
                hcounter_st.eq(0)
            )
        self.specials += MultiReg(hcounter_st, self._hres.status)

        # VRES
        vsync_r = Signal()
        p_vsync = Signal()
        self.sync.pix += vsync_r.eq(self.vsync),
        self.comb += p_vsync.eq(self.vsync & ~vsync_r)

        vcounter = Signal(nbits)
        self.sync.pix += \
            If(self.valid_i & p_vsync,
                vcounter.eq(0)
            ).Elif(pn_de,
                vcounter.eq(vcounter + 1)
            )

        vcounter_st = Signal(nbits)
        self.sync.pix += \
            If(self.valid_i,
                If(p_vsync, vcounter_st.eq(vcounter))
            ).Else(
                vcounter_st.eq(0)
            )
        self.specials += MultiReg(vcounter_st, self._vres.status)
Exemple #2
0
    def __init__(self, width, depth):
        _FIFOInterface.__init__(self, width, depth)

        ###

        depth_bits = log2_int(depth, True)

        produce = ClockDomainsRenamer("write")(GrayCounter(depth_bits + 1))
        consume = ClockDomainsRenamer("read")(GrayCounter(depth_bits + 1))
        self.submodules += produce, consume
        self.comb += [
            produce.ce.eq(self.writable & self.we),
            consume.ce.eq(self.readable & self.re)
        ]

        produce_rdomain = Signal(depth_bits + 1)
        self.specials += [
            NoRetiming(produce.q),
            MultiReg(produce.q, produce_rdomain, "read")
        ]
        consume_wdomain = Signal(depth_bits + 1)
        self.specials += [
            NoRetiming(consume.q),
            MultiReg(consume.q, consume_wdomain, "write")
        ]
        if depth_bits == 1:
            self.comb += self.writable.eq(
                (produce.q[-1] == consume_wdomain[-1])
                | (produce.q[-2] == consume_wdomain[-2]))
        else:
            self.comb += [
                self.writable.eq((produce.q[-1] == consume_wdomain[-1])
                                 | (produce.q[-2] == consume_wdomain[-2])
                                 | (produce.q[:-2] != consume_wdomain[:-2]))
            ]
        self.comb += self.readable.eq(consume.q != produce_rdomain)

        storage = Memory(self.width, depth)
        self.specials += storage
        wrport = storage.get_port(write_capable=True, clock_domain="write")
        self.specials += wrport
        self.comb += [
            wrport.adr.eq(produce.q_binary[:-1]),
            wrport.dat_w.eq(self.din),
            wrport.we.eq(produce.ce)
        ]
        rdport = storage.get_port(clock_domain="read")
        self.specials += rdport
        self.comb += [
            rdport.adr.eq(consume.q_next_binary[:-1]),
            self.dout.eq(rdport.dat_r)
        ]
Exemple #3
0
    def __init__(self, period, width=6):
        self.clk = Signal()
        self.value = CSRStatus(32)

        # # #

        self.clock_domains.cd_fmeter = ClockDomain(reset_less=True)
        self.comb += self.cd_fmeter.clk.eq(self.clk)

        # period generation
        period_done = Signal()
        period_counter = Signal(32)
        self.comb += period_done.eq(period_counter == period)
        self.sync += \
            If(period_done,
                period_counter.eq(0),
            ).Else(
                period_counter.eq(period_counter + 1)
            )

        # frequency measurement
        event_counter = ClockDomainsRenamer("fmeter")(GrayCounter(width))
        gray_decoder = GrayDecoder(width)
        sampler = Sampler(width)
        self.submodules += event_counter, gray_decoder, sampler

        self.specials += MultiReg(event_counter.q, gray_decoder.i)
        self.comb += [
            event_counter.ce.eq(1),
            sampler.latch.eq(period_done),
            sampler.i.eq(gray_decoder.o),
            self.value.status.eq(sampler.o)
        ]
Exemple #4
0
    def __init__(self, measure_clock, measure_period, 
            measure_width=6, counter_width=32):
        self.value = CSRStatus(counter_width)

        # # #

        # create measure clock domain
        self.clock_domains.cd_measure = ClockDomain(reset_less=True)
        self.comb += self.cd_measure.clk.eq(measure_clock)

        # mesure period
        period_done = Signal()
        period_counter = Signal(counter_width)
        self.comb += period_done.eq(period_counter == measure_period)
        self.sync += \
            If(period_done,
                period_counter.eq(0),
            ).Else(
                period_counter.eq(period_counter + 1)
            )

        # measurement
        event_counter = ClockDomainsRenamer("measure")(GrayCounter(measure_width))
        gray_decoder = GrayDecoder(measure_width)
        sampler = Sampler(measure_width, counter_width)
        self.submodules += event_counter, gray_decoder, sampler

        self.specials += MultiReg(event_counter.q, gray_decoder.i)
        self.comb += [
            event_counter.ce.eq(1),
            sampler.latch.eq(period_done),
            sampler.i.eq(gray_decoder.o),
            self.value.status.eq(sampler.value)
        ]
Exemple #5
0
    def __init__(self, dw, cd):
        self.sink = stream.Endpoint(core_layout(dw))
        self.source = stream.Endpoint(core_layout(dw))

        self.value = CSRStorage(16)

        # # #

        sync_cd = getattr(self.sync, cd)

        value = Signal(16)
        self.specials += MultiReg(self.value.storage, value, cd)

        counter = Signal(16)
        done = Signal()

        sync_cd += \
            If(self.source.ready,
                If(done,
                    counter.eq(0)
                ).Elif(self.sink.valid,
                    counter.eq(counter + 1)
                )
            )

        self.comb += [
            done.eq(counter == value),
            self.sink.connect(self.source, omit=set(["valid"])),
            self.source.valid.eq(self.sink.valid & done)
        ]
Exemple #6
0
    def __init__(self, required_controls=8):
        self.raw_data = Signal(10)
        self.synced = Signal()
        self.data = Signal(10)

        self._char_synced = CSRStatus()
        self._ctl_pos = CSRStatus(bits_for(9))

        # # #

        raw_data1 = Signal(10)
        self.sync.pix += raw_data1.eq(self.raw_data)
        raw = Signal(20)
        self.comb += raw.eq(Cat(raw_data1, self.raw_data))

        found_control = Signal()
        control_position = Signal(max=10)
        self.sync.pix += found_control.eq(0)
        for i in range(10):
            self.sync.pix += If(
                reduce(or_, [raw[i:i + 10] == t for t in control_tokens]),
                found_control.eq(1), control_position.eq(i))

        control_counter = Signal(max=required_controls)
        previous_control_position = Signal(max=10)
        word_sel = Signal(max=10)
        self.sync.pix += [
            If(
                found_control &
                (control_position == previous_control_position),
                If(control_counter == (required_controls - 1),
                   control_counter.eq(0), self.synced.eq(1),
                   word_sel.eq(control_position)).Else(
                       control_counter.eq(control_counter + 1))).Else(
                           control_counter.eq(0)),
            previous_control_position.eq(control_position)
        ]
        self.specials += [
            MultiReg(self.synced, self._char_synced.status),
            MultiReg(word_sel, self._ctl_pos.status)
        ]

        self.sync.pix += self.data.eq(raw >> word_sel)
Exemple #7
0
    def __init__(self, dw, cd):
        self.sink = stream.Endpoint(core_layout(dw))
        self.source = stream.Endpoint(core_layout(dw))

        self.value = CSRStorage(dw)
        self.mask = CSRStorage(dw)

        # # #

        value = Signal(dw)
        mask = Signal(dw)
        self.specials += [
            MultiReg(self.value.storage, value, cd),
            MultiReg(self.mask.storage, mask, cd)
        ]

        self.comb += [
            self.sink.connect(self.source),
            self.source.hit.eq((self.sink.data & mask) == value)
        ]
Exemple #8
0
    def __init__(self, pads):
        self.source = source = stream.Endpoint(eth_phy_description(8))

        # # #

        converter = stream.StrideConverter(converter_description(2),
                                           converter_description(8))
        converter = ResetInserter()(converter)
        self.submodules += converter

        converter_sink_valid = Signal()
        converter_sink_data = Signal(2)

        self.specials += [
            MultiReg(converter_sink_valid, converter.sink.valid, n=2),
            MultiReg(converter_sink_data, converter.sink.data, n=2)
        ]

        crs_dv = Signal()
        crs_dv_d = Signal()
        rx_data = Signal(2)
        self.sync += [
            crs_dv.eq(pads.crs_dv),
            crs_dv_d.eq(crs_dv),
            rx_data.eq(pads.rx_data)
        ]

        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act(
            "IDLE",
            If(crs_dv & (rx_data != 0b00), converter_sink_valid.eq(1),
               converter_sink_data.eq(rx_data),
               NextState("RECEIVE")).Else(converter.reset.eq(1)))
        fsm.act(
            "RECEIVE",
            converter_sink_valid.eq(1),
            converter_sink_data.eq(rx_data),
            # end of frame when 2 consecutives 0 on crs_dv
            If(~(crs_dv | crs_dv_d), converter.sink.last.eq(1),
               NextState("IDLE")))
        self.comb += converter.source.connect(source)
Exemple #9
0
    def __init__(self, core):
        self.enable = CSRStorage()
        self.ready = CSRStatus()

        self.prbs_config = CSRStorage(4)
        self.stpl_enable = CSRStorage()

        self.jsync = CSRStatus()

        self.restart_count_clear = CSR()
        self.restart_count = CSRStatus(8)

        # # #

        # core control/status
        self.comb += [
            core.enable.eq(self.enable.storage),
            core.prbs_config.eq(self.prbs_config.storage),
            core.stpl_enable.eq(self.stpl_enable.storage),
            self.ready.status.eq(core.ready)
        ]
        self.specials += MultiReg(core.jsync, self.jsync.status)

        # restart monitoring

        # restart is a slow signal so we simply pass it to sys_clk and
        # count rising edges
        restart = Signal()
        restart_d = Signal()
        restart_count = Signal(8)
        self.specials += MultiReg(core.restart, restart)
        self.sync += \
            If(self.restart_count_clear.re,
                restart_count.eq(0)
            ).Elif(restart & ~restart_d,
                # don't overflow when max is reached
                If(restart_count != (2**8-1),
                    restart_count.eq(restart_count + 1)
                )
            )
        self.comb += self.restart_count.status.eq(restart_count)
Exemple #10
0
    def __init__(self, platform, **kwargs):

        clk_freq = int(100e6)
        SoCCore.__init__(self, platform, clk_freq,
                         cpu_type=None,
                         **kwargs)

        self.platform = platform

        self.submodules.crg = CRG(platform)
        self.crg.cd_sys.clk.attr.add("keep")
        self.platform.add_period_constraint(self.crg.cd_sys.clk, period_ns(100e6))

        # common led
        self.sys_led = Signal()
        self.comb += platform.request("user_led", 0).eq(self.sys_led)

        self.aux_led = Signal()
        self.comb += platform.request("user_led", 1).eq(self.aux_led)

        # sys led
        sys_counter = Signal(32)
        self.sync += sys_counter.eq(sys_counter + 1)
        self.comb += self.sys_led.eq(sys_counter[26])

        sys_short_test = Signal(16)
        self.comb += sys_short_test.eq(sys_counter)
        self.comb += self.aux_led.eq(sys_short_test[15])

        self.bar_led = platform.request("user_led", 2)

        fred = ClockDomainsRenamer("clk100")(Flintstone())
        self.submodules += fred  ## if this isn't here, fred isn't instantiated

        self.dino = Signal(16)
        self.yoshi = Signal(8)
        self.specials += MultiReg(fred.wilma, self.dino, "clk100")
        self.specials += MultiReg(self.dino, self.yoshi, "clk200") # this takes dino into the yoshi clock domain
        self.comb += self.bar_led.eq(self.yoshi[7])
Exemple #11
0
    def __init__(self, nchan=3, depth=8):
        self.valid_i = Signal()
        self.chan_synced = Signal()

        self._channels_synced = CSRStatus()

        lst_control = []
        all_control = Signal()
        for i in range(nchan):
            name = "data_in" + str(i)
            data_in = Record(channel_layout, name=name)
            setattr(self, name, data_in)
            name = "data_out" + str(i)
            data_out = Record(channel_layout, name=name)
            setattr(self, name, data_out)

            # # #

            syncbuffer = _SyncBuffer(layout_len(channel_layout), depth)
            syncbuffer = ClockDomainsRenamer("pix")(syncbuffer)
            self.submodules += syncbuffer
            self.comb += [
                syncbuffer.din.eq(data_in.raw_bits()),
                data_out.raw_bits().eq(syncbuffer.dout)
            ]
            is_control = Signal()
            self.comb += [
                is_control.eq(~data_out.de),
                syncbuffer.re.eq(~is_control | all_control)
            ]
            lst_control.append(is_control)

        some_control = Signal()
        self.comb += [
            all_control.eq(reduce(and_, lst_control)),
            some_control.eq(reduce(or_, lst_control))
        ]
        self.sync.pix += \
            If(~self.valid_i,
                self.chan_synced.eq(0)
            ).Else(
                If(some_control,
                    If(all_control,
                        self.chan_synced.eq(1)
                    ).Else(
                        self.chan_synced.eq(0)
                    )
                )
            )
        self.specials += MultiReg(self.chan_synced,
                                  self._channels_synced.status)
Exemple #12
0
    def __init__(self, pads, tuning_word):
        self.source = stream.Endpoint([("data", 8)])

        # # #

        uart_clk_rxen = Signal()
        phase_accumulator_rx = Signal(32)

        rx = Signal()
        self.specials += MultiReg(pads.rx, rx)
        rx_r = Signal()
        rx_reg = Signal(8)
        rx_bitcount = Signal(4)
        rx_busy = Signal()
        rx_done = self.source.valid
        rx_data = self.source.data
        self.sync += [
            rx_done.eq(0),
            rx_r.eq(rx),
            If(
                ~rx_busy,
                If(
                    ~rx & rx_r,  # look for start bit
                    rx_busy.eq(1),
                    rx_bitcount.eq(0),
                )).Else(
                    If(
                        uart_clk_rxen,
                        rx_bitcount.eq(rx_bitcount + 1),
                        If(
                            rx_bitcount == 0,
                            If(
                                rx,  # verify start bit
                                rx_busy.eq(0))).Elif(
                                    rx_bitcount == 9,
                                    rx_busy.eq(0),
                                    If(
                                        rx,  # verify stop bit
                                        rx_data.eq(rx_reg),
                                        rx_done.eq(1))).Else(
                                            rx_reg.eq(Cat(rx_reg[1:], rx)))))
        ]
        self.sync += \
                If(rx_busy,
                    Cat(phase_accumulator_rx, uart_clk_rxen).eq(phase_accumulator_rx + tuning_word)
                ).Else(
                    Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31)
                )
Exemple #13
0
    def __init__(self, pads):
        self._w = CSRStorage(3, name="w")
        self._r = CSRStatus(1, name="r")

        # # #

        data_w = Signal()
        data_oe = Signal()
        data_r = Signal()
        self.comb += [
            pads.mdc.eq(self._w.storage[0]),
            data_oe.eq(self._w.storage[1]),
            data_w.eq(self._w.storage[2])
        ]
        self.specials += [
            MultiReg(data_r, self._r.status[0]),
            Tristate(pads.mdio, data_w, data_oe, data_r)
        ]
Exemple #14
0
    def __init__(self, width, reverse=False):
        self.i = Signal(width)
        self.config = Signal(2)
        self.errors = Signal(32)

        # # #

        config = Signal(2)

        # optional bits reversing
        prbs_data = self.i
        if reverse:
            new_prbs_data = Signal(width)
            self.comb += new_prbs_data.eq(prbs_data[::-1])
            prbs_data = new_prbs_data

        # checkers
        self.specials += MultiReg(self.config, config)
        prbs7 = PRBS7Checker(width)
        prbs15 = PRBS15Checker(width)
        prbs31 = PRBS31Checker(width)
        self.submodules += prbs7, prbs15, prbs31
        self.comb += [
            prbs7.i.eq(prbs_data),
            prbs15.i.eq(prbs_data),
            prbs31.i.eq(prbs_data)
        ]

        # errors count
        self.sync += \
            If(config == 0,
                self.errors.eq(0)
            ).Elif(self.errors != (2**32-1),
                If(config == 0b01,
                    self.errors.eq(self.errors + (prbs7.errors != 0))
                ).Elif(config == 0b10,
                    self.errors.eq(self.errors + (prbs15.errors != 0))
                ).Elif(config == 0b11,
                    self.errors.eq(self.errors + (prbs31.errors != 0))
                )
            )
Exemple #15
0
    def __init__(self, width, reverse=False):
        self.config = Signal(2)
        self.i = Signal(width)
        self.o = Signal(width)

        # # #

        config = Signal(2)

        # generators
        self.specials += MultiReg(self.config, config)
        prbs7 = PRBS7Generator(width)
        prbs15 = PRBS15Generator(width)
        prbs31 = PRBS31Generator(width)
        self.submodules += prbs7, prbs15, prbs31

        # select
        prbs_data = Signal(width)
        self.comb += \
            If(config == 0b11,
                prbs_data.eq(prbs31.o)
            ).Elif(config == 0b10,
                prbs_data.eq(prbs15.o)
            ).Else(
                prbs_data.eq(prbs7.o)
            )

        # optional bits reversing
        if reverse:
            new_prbs_data = Signal(width)
            self.comb += new_prbs_data.eq(prbs_data[::-1])
            prbs_data = new_prbs_data

        # prbs / data mux
        self.comb += \
            If(config == 0,
                self.o.eq(self.i)
            ).Else(
                self.o.eq(prbs_data)
            )
Exemple #16
0
    def __init__(self, phys, jesd_settings, converter_data_width):
        self.enable = Signal()
        self.jsync = Signal()
        self.ready = Signal()
        self.restart = Signal()

        self.prbs_config = Signal(4)
        self.stpl_enable = Signal()

        self.sink = Record([("converter" + str(i), converter_data_width)
                            for i in range(jesd_settings.nconverters)])

        # # #

        # restart when disabled or on re-synchronization request
        self.comb += self.restart.eq(~self.enable | self.ready & ~self.jsync)

        # transport layer
        transport = LiteJESD204BTransportTX(jesd_settings,
                                            converter_data_width)
        self.submodules.transport = transport

        # stpl
        stpl = LiteJESD204BSTPLGenerator(jesd_settings, converter_data_width)
        self.submodules += stpl
        stpl_enable = Signal()
        self.specials += \
            MultiReg(self.stpl_enable, stpl_enable)
        self.comb += \
            If(stpl_enable,
                transport.sink.eq(stpl.source)
            ).Else(
                transport.sink.eq(self.sink)
            )

        links = []
        for n, (phy, lane) in enumerate(zip(phys, transport.source.flatten())):
            phy_name = "phy{}".format(n)
            phy_cd = phy_name + "_tx"

            # claim the phy
            setattr(self.submodules, phy_name, phy)

            ebuf = ElasticBuffer(len(phy.data), 4, "sys", phy_cd)
            setattr(self.submodules, "ebuf{}".format(n), ebuf)

            link = LiteJESD204BLinkTX(len(phy.data), jesd_settings, n)
            link = ClockDomainsRenamer(phy_cd)(link)
            links.append(link)
            self.comb += link.jsync.eq(self.jsync)
            self.submodules += link

            # connect data
            self.comb += [
                ebuf.din.eq(lane),
                link.sink.data.eq(ebuf.dout),
                phy.data.eq(link.source.data),
                phy.ctrl.eq(link.source.ctrl)
            ]

            # connect control
            self.comb += phy.transmitter.init.restart.eq(
                self.restart & (self.prbs_config == 0))

            self.specials += MultiReg(self.prbs_config,
                                      phy.transmitter.prbs_config, phy_cd)
        ready = Signal()
        self.comb += ready.eq(reduce(and_, [link.ready for link in links]))
        self.specials += MultiReg(ready, self.ready)
    def __init__(self, sys_clk_freq, rx):
        self.done = Signal()
        self.restart = Signal()

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

        # # #

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

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

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

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

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

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

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

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

        # Wait 2 rising edges of Xxphaligndone
        # (from UG576 in TX Buffer Bypass in Single-Lane Auto Mode)
        startup_fsm.act(
            "WAIT_FIRST_ALIGN_DONE", Xxuserrdy.eq(1),
            If(Xxphaligndone_rising, NextState("WAIT_SECOND_ALIGN_DONE")))
        startup_fsm.act("WAIT_SECOND_ALIGN_DONE", Xxuserrdy.eq(1),
                        If(Xxphaligndone_rising, NextState("READY")))
        startup_fsm.act("READY", Xxuserrdy.eq(1), self.done.eq(1),
                        If(self.restart, NextState("RESET_ALL")))
Exemple #18
0
    def __init__(self,
                 pads,
                 clk_freq,
                 fifo_depth=32,
                 read_time=128,
                 write_time=128):
        dw = len(pads.data)
        self.clk_freq = clk_freq

        # timings
        tRD = self.ns(30)  # RD# active pulse width (t4)
        tRDDataSetup = self.ns(14)  # RD# to DATA (t3)
        tWRDataSetup = self.ns(5)  # DATA to WR# active setup time (t8)
        tWR = self.ns(30)  # WR# active pulse width (t10)
        tMultiReg = 2

        # read fifo (FTDI --> SoC)
        read_fifo = stream.SyncFIFO(phy_description(8), fifo_depth)

        # write fifo (SoC --> FTDI)
        write_fifo = stream.SyncFIFO(phy_description(8), fifo_depth)

        self.submodules += read_fifo, write_fifo

        # sink / source interfaces
        self.sink = write_fifo.sink
        self.source = read_fifo.source

        # read / write arbitration
        wants_write = Signal()
        wants_read = Signal()

        txe_n = Signal()
        rxf_n = Signal()

        self.specials += [
            MultiReg(pads.txe_n, txe_n),
            MultiReg(pads.rxf_n, rxf_n)
        ]

        self.comb += [
            wants_write.eq(~txe_n & write_fifo.source.valid),
            wants_read.eq(~rxf_n & read_fifo.sink.ready),
        ]

        read_time_en, max_read_time = anti_starvation(self, read_time)
        write_time_en, max_write_time = anti_starvation(self, write_time)

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

        read_done = Signal()
        write_done = Signal()
        commuting = Signal()

        fsm.act(
            "READ", read_time_en.eq(1),
            If(
                wants_write & read_done,
                If(~wants_read | max_read_time, commuting.eq(1),
                   NextState("RTW"))))
        fsm.act("RTW", NextState("WRITE"))
        fsm.act(
            "WRITE", write_time_en.eq(1),
            If(
                wants_read & write_done,
                If(~wants_write | max_write_time, commuting.eq(1),
                   NextState("WTR"))))
        fsm.act("WTR", NextState("READ"))

        # databus tristate
        data_w = Signal(dw)
        data_r_async = Signal(dw)
        data_r = Signal(dw)
        data_oe = Signal()
        self.specials += [
            Tristate(pads.data, data_w, data_oe, data_r_async),
            MultiReg(data_r_async, data_r)
        ]

        # read actions
        pads.rd_n.reset = 1

        read_fsm = FSM(reset_state="IDLE")
        self.submodules += read_fsm
        read_counter = Signal(8)
        read_counter_reset = Signal()
        read_counter_ce = Signal()
        self.sync += \
            If(read_counter_reset,
                read_counter.eq(0)
            ).Elif(read_counter_ce,
                read_counter.eq(read_counter + 1)
            )

        read_fsm.act(
            "IDLE", read_done.eq(1), read_counter_reset.eq(1),
            If(
                fsm.ongoing("READ") & wants_read,
                If(~commuting, NextState("PULSE_RD_N"))))
        read_fsm.act(
            "PULSE_RD_N", pads.rd_n.eq(0), read_counter_ce.eq(1),
            If(read_counter == max((tRD - 1), (tRDDataSetup + tMultiReg - 1)),
               NextState("ACQUIRE_DATA")))
        read_fsm.act("ACQUIRE_DATA", read_fifo.sink.valid.eq(1),
                     read_fifo.sink.data.eq(data_r), NextState("WAIT_RXF_N"))
        read_fsm.act("WAIT_RXF_N", If(rxf_n, NextState("IDLE")))

        # write actions
        pads.wr_n.reset = 1

        write_fsm = FSM(reset_state="IDLE")
        self.submodules += write_fsm
        write_counter = Signal(8)
        write_counter_reset = Signal()
        write_counter_ce = Signal()
        self.sync += \
            If(write_counter_reset,
                write_counter.eq(0)
            ).Elif(write_counter_ce,
                write_counter.eq(write_counter + 1)
            )

        write_fsm.act(
            "IDLE", write_done.eq(1), write_counter_reset.eq(1),
            If(
                fsm.ongoing("WRITE") & wants_write,
                If(~commuting, NextState("SET_DATA"))))
        write_fsm.act(
            "SET_DATA", data_oe.eq(1), data_w.eq(write_fifo.source.data),
            write_counter_ce.eq(1),
            If(write_counter == (tWRDataSetup - 1), write_counter_reset.eq(1),
               NextState("PULSE_WR_N")))
        write_fsm.act("PULSE_WR_N", data_oe.eq(1),
                      data_w.eq(write_fifo.source.data), pads.wr_n.eq(0),
                      write_counter_ce.eq(1),
                      If(write_counter == (tWR - 1), NextState("WAIT_TXE_N")))
        write_fsm.act(
            "WAIT_TXE_N",
            If(txe_n, write_fifo.source.ready.eq(1), NextState("IDLE")))
Exemple #19
0
    def __init__(self, phy):
        self.sink = stream.Endpoint([("data", 32)])
        self.source = stream.Endpoint([("data", 32)])

        self.argument = CSRStorage(32)
        self.command = CSRStorage(32)
        self.response = CSRStatus(120)

        self.cmdevt = CSRStatus(32)
        self.dataevt = CSRStatus(32)

        self.blocksize = CSRStorage(16)
        self.blockcount = CSRStorage(32)

        self.datatimeout = CSRStorage(32, reset=2**16)
        self.cmdtimeout = CSRStorage(32, reset=2**16)

        self.datawcrcclear = CSRStorage()
        self.datawcrcvalids = CSRStatus(32)
        self.datawcrcerrors = CSRStatus(32)

        # # #

        argument = Signal(32)
        command = Signal(32)
        response = Signal(120)
        cmdevt = Signal(32)
        dataevt = Signal(32)
        blocksize = Signal(16)
        blockcount = Signal(32)
        datatimeout = Signal(32)
        cmdtimeout = Signal(32)

        # sys to sd cdc
        self.specials += [
            MultiReg(self.argument.storage, argument, "sd"),
            MultiReg(self.command.storage, command, "sd"),
            MultiReg(self.blocksize.storage, blocksize, "sd"),
            MultiReg(self.blockcount.storage, blockcount, "sd"),
            MultiReg(self.datatimeout.storage, datatimeout, "sd"),
            MultiReg(self.cmdtimeout.storage, cmdtimeout, "sd")
        ]

        # sd to sys cdc
        response_cdc = BusSynchronizer(120, "sd", "sys")
        cmdevt_cdc = BusSynchronizer(32, "sd", "sys")
        dataevt_cdc = BusSynchronizer(32, "sd", "sys")
        self.submodules += response_cdc, cmdevt_cdc, dataevt_cdc
        self.comb += [
            response_cdc.i.eq(response),
            self.response.status.eq(response_cdc.o),
            cmdevt_cdc.i.eq(cmdevt),
            self.cmdevt.status.eq(cmdevt_cdc.o),
            dataevt_cdc.i.eq(dataevt),
            self.dataevt.status.eq(dataevt_cdc.o)
        ]

        self.submodules.new_command = PulseSynchronizer("sys", "sd")
        self.comb += self.new_command.i.eq(self.command.re)

        self.comb += [
            phy.cfg.blocksize.eq(blocksize),
            phy.cfg.datatimeout.eq(datatimeout),
            phy.cfg.cmdtimeout.eq(cmdtimeout),
            phy.dataw.crc_clear.eq(self.datawcrcclear.storage),
            self.datawcrcvalids.status.eq(phy.dataw.crc_valids),
            self.datawcrcerrors.status.eq(phy.dataw.crc_errors)
        ]

        self.submodules.crc7inserter = ClockDomainsRenamer("sd")(CRC(9, 7, 40))
        self.submodules.crc7checker = ClockDomainsRenamer("sd")(CRCChecker(
            9, 7, 120))
        self.submodules.crc16inserter = ClockDomainsRenamer("sd")(
            CRCUpstreamInserter())
        self.submodules.crc16checker = ClockDomainsRenamer("sd")(
            CRCDownstreamChecker())

        self.submodules.upstream_cdc = ClockDomainsRenamer({
            "write": "sys",
            "read": "sd"
        })(stream.AsyncFIFO(self.sink.description, 4))
        self.submodules.downstream_cdc = ClockDomainsRenamer({
            "write": "sd",
            "read": "sys"
        })(stream.AsyncFIFO(self.source.description, 4))

        self.submodules.upstream_converter = ClockDomainsRenamer("sd")(
            stream.StrideConverter([('data', 32)], [('data', 8)],
                                   reverse=True))
        self.submodules.downstream_converter = ClockDomainsRenamer("sd")(
            stream.StrideConverter([('data', 8)], [('data', 32)],
                                   reverse=True))

        self.comb += [
            self.sink.connect(self.upstream_cdc.sink),
            self.upstream_cdc.source.connect(self.upstream_converter.sink),
            self.upstream_converter.source.connect(self.crc16inserter.sink),
            self.crc16checker.source.connect(self.downstream_converter.sink),
            self.downstream_converter.source.connect(self.downstream_cdc.sink),
            self.downstream_cdc.source.connect(self.source)
        ]

        self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM())

        csel = Signal(max=6)
        waitresp = Signal(2)
        dataxfer = Signal(2)
        cmddone = Signal(reset=1)
        datadone = Signal(reset=1)
        blkcnt = Signal(32)
        pos = Signal(2)

        cerrtimeout = Signal()
        cerrcrc_en = Signal()
        derrtimeout = Signal()
        derrwrite = Signal()
        derrread_en = Signal()

        self.comb += [
            waitresp.eq(command[0:2]),
            dataxfer.eq(command[5:7]),
            cmdevt.eq(
                Cat(cmddone, C(0, 1), cerrtimeout,
                    cerrcrc_en & ~self.crc7checker.valid)),
            dataevt.eq(
                Cat(datadone, derrwrite, derrtimeout,
                    derrread_en & ~self.crc16checker.valid)),
            self.crc7inserter.val.eq(Cat(argument, command[8:14], 1, 0)),
            self.crc7inserter.clr.eq(1),
            self.crc7inserter.enable.eq(1),
            self.crc7checker.val.eq(response)
        ]

        ccases = {}  # To send command and CRC
        ccases[0] = phy.sink.data.eq(Cat(command[8:14], 1, 0))
        for i in range(4):
            ccases[i + 1] = phy.sink.data.eq(argument[24 - 8 * i:32 - 8 * i])
        ccases[5] = [
            phy.sink.data.eq(Cat(1, self.crc7inserter.crc)),
            phy.sink.last.eq(waitresp == SDCARD_CTRL_RESPONSE_NONE)
        ]

        fsm.act(
            "IDLE", NextValue(pos, 0),
            If(self.new_command.o, NextValue(cmddone, 0),
               NextValue(cerrtimeout, 0), NextValue(cerrcrc_en, 0),
               NextValue(datadone, 0), NextValue(derrtimeout, 0),
               NextValue(derrwrite, 0), NextValue(derrread_en, 0),
               NextValue(response, 0), NextState("SEND_CMD")))

        fsm.act(
            "SEND_CMD", phy.sink.valid.eq(1), phy.sink.cmd_data_n.eq(1),
            phy.sink.rd_wr_n.eq(0), Case(csel, ccases),
            If(
                phy.sink.valid & phy.sink.ready,
                If(csel < 5, NextValue(csel, csel + 1)).Else(
                    NextValue(csel, 0),
                    If(waitresp == SDCARD_CTRL_RESPONSE_NONE,
                       NextValue(cmddone, 1),
                       NextState("IDLE")).Else(NextValue(cerrcrc_en, 1),
                                               NextState("RECV_RESP")))))

        fsm.act(
            "RECV_RESP",
            phy.sink.valid.eq(1),
            phy.sink.cmd_data_n.eq(1),
            phy.sink.rd_wr_n.eq(1),
            phy.sink.last.eq(dataxfer == SDCARD_CTRL_DATA_TRANSFER_NONE),
            If(
                waitresp == SDCARD_CTRL_RESPONSE_SHORT,
                phy.sink.data.eq(5)  # (5+1)*8 == 48bits
            ).Elif(
                waitresp == SDCARD_CTRL_RESPONSE_LONG,
                phy.sink.data.eq(16)  # (16+1)*8 == 136bits
            ),
            If(
                phy.source.valid,  # Wait for resp or timeout coming from phy
                phy.source.ready.eq(1),
                If(phy.source.status == SDCARD_STREAM_STATUS_TIMEOUT,
                   NextValue(cerrtimeout, 1), NextValue(cmddone, 1),
                   NextValue(datadone, 1), NextState("IDLE")).Elif(
                       phy.source.last,
                       # Check response CRC
                       NextValue(self.crc7checker.check, phy.source.data[1:8]),
                       NextValue(cmddone, 1),
                       If(dataxfer == SDCARD_CTRL_DATA_TRANSFER_READ,
                          NextValue(derrread_en, 1),
                          NextState("RECV_DATA")).Elif(
                              dataxfer == SDCARD_CTRL_DATA_TRANSFER_WRITE,
                              NextState("SEND_DATA")).Else(
                                  NextValue(datadone, 1), NextState("IDLE")),
                   ).Else(
                       NextValue(response, Cat(phy.source.data,
                                               response[0:112])))))

        fsm.act(
            "RECV_DATA",
            phy.sink.valid.eq(1),
            phy.sink.cmd_data_n.eq(0),
            phy.sink.rd_wr_n.eq(1),
            phy.sink.last.eq(blkcnt == (blockcount - 1)),
            phy.sink.data.eq(0),  # Read 1 block
            If(
                phy.source.valid,
                phy.source.ready.eq(1),
                If(
                    phy.source.status == SDCARD_STREAM_STATUS_OK,
                    self.crc16checker.sink.data.eq(
                        phy.source.data),  # Manual connect streams except ctrl
                    self.crc16checker.sink.valid.eq(phy.source.valid),
                    self.crc16checker.sink.last.eq(phy.source.last),
                    phy.source.ready.eq(self.crc16checker.sink.ready),
                    If(
                        phy.source.last & phy.source.ready,  # End of block
                        If(blkcnt < (blockcount - 1),
                           NextValue(blkcnt,
                                     blkcnt + 1), NextState("RECV_DATA")).Else(
                                         NextValue(blkcnt, 0),
                                         NextValue(datadone, 1),
                                         NextState("IDLE")))).Elif(
                                             phy.source.status ==
                                             SDCARD_STREAM_STATUS_TIMEOUT,
                                             NextValue(derrtimeout, 1),
                                             NextValue(blkcnt, 0),
                                             NextValue(datadone, 1),
                                             phy.source.ready.eq(1),
                                             NextState("IDLE"))))

        fsm.act(
            "SEND_DATA", phy.sink.valid.eq(self.crc16inserter.source.valid),
            phy.sink.cmd_data_n.eq(0), phy.sink.rd_wr_n.eq(0),
            phy.sink.last.eq(self.crc16inserter.source.last),
            phy.sink.data.eq(self.crc16inserter.source.data),
            self.crc16inserter.source.ready.eq(phy.sink.ready),
            If(
                self.crc16inserter.source.valid
                & self.crc16inserter.source.last
                & self.crc16inserter.source.ready,
                If(blkcnt < (blockcount - 1),
                   NextValue(blkcnt, blkcnt + 1)).Else(NextValue(blkcnt, 0),
                                                       NextValue(datadone, 1),
                                                       NextState("IDLE"))),
            If(
                phy.source.valid, phy.source.ready.eq(1),
                If(phy.source.status != SDCARD_STREAM_STATUS_DATAACCEPTED,
                   NextValue(derrwrite, 1))))
Exemple #20
0
    def __init__(self, cfg):
        self.pads = pads = _sdpads()
        self.sink = sink = stream.Endpoint([("data", 8)])
        self.source = source = stream.Endpoint([("data", 8), ("status", 3)])

        # # #

        cmdrfb_reset = Signal()

        self.submodules.cmdrfb = SDPHYRFB(pads.cmd.i, False)
        self.submodules.fifo = ClockDomainsRenamer({
            "write": "sd_fb",
            "read": "sd"
        })(stream.AsyncFIFO(self.cmdrfb.source.description, 4))
        self.comb += self.cmdrfb.source.connect(self.fifo.sink)

        ctimeout = Signal(32)

        cread = Signal(10)
        ctoread = Signal(10)
        cnt = Signal(8)

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

        fsm.act(
            "IDLE",
            If(sink.valid, NextValue(ctimeout, 0), NextValue(cread, 0),
               NextValue(ctoread, sink.data), NextState("CMD_READSTART")).Else(
                   cmdrfb_reset.eq(1),
                   self.fifo.source.ready.eq(1),
               ))
        self.specials += MultiReg(cmdrfb_reset, self.cmdrfb.reset, "sd_fb")

        fsm.act(
            "CMD_READSTART", pads.cmd.oe.eq(0), pads.clk.eq(1),
            NextValue(ctimeout, ctimeout + 1),
            If(self.fifo.source.valid,
               NextState("CMD_READ")).Elif(ctimeout > cfg.cmdtimeout,
                                           NextState("TIMEOUT")))

        fsm.act(
            "CMD_READ", pads.cmd.oe.eq(0), pads.clk.eq(1),
            source.valid.eq(self.fifo.source.valid),
            source.data.eq(self.fifo.source.data),
            source.status.eq(SDCARD_STREAM_STATUS_OK),
            source.last.eq(cread == ctoread),
            self.fifo.source.ready.eq(source.ready),
            If(
                source.valid & source.ready, NextValue(cread, cread + 1),
                If(
                    cread == ctoread,
                    If(sink.last,
                       NextState("CMD_CLK8")).Else(sink.ready.eq(1),
                                                   NextState("IDLE")))))

        fsm.act(
            "CMD_CLK8",
            If(cnt < 7, NextValue(cnt, cnt + 1),
               pads.clk.eq(1)).Else(NextValue(cnt, 0), sink.ready.eq(1),
                                    NextState("IDLE")))

        fsm.act(
            "TIMEOUT", source.valid.eq(1), source.data.eq(0),
            source.status.eq(SDCARD_STREAM_STATUS_TIMEOUT), source.last.eq(1),
            If(source.valid & source.ready, sink.ready.eq(1),
               NextState("IDLE")))
Exemple #21
0
    def __init__(self,
                 platform,
                 pads,
                 data_width=64,
                 bar0_size=1 * MB,
                 cd="sys",
                 pll1=None):
        self.sink = stream.Endpoint(phy_layout(data_width))
        self.source = stream.Endpoint(phy_layout(data_width))
        self.msi = stream.Endpoint(msi_layout())

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

        self.data_width = data_width

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

        # # #

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

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

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

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

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

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

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

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

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

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

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

            #o_cfg_to_turnoff=,
            o_cfg_bus_number=bus_number,
            o_cfg_device_number=device_number,
            o_cfg_function_number=function_number,
            o_cfg_command=command,
            o_cfg_dcommand=dcommand,
            o_cfg_interrupt_msienable=msienable,
            i_cfg_interrupt=cfg_msi.valid,
            o_cfg_interrupt_rdy=cfg_msi.ready,
            i_cfg_interrupt_di=cfg_msi.dat,
            p_QPLL_PLL1_FBDIV=4 if pll1 is None else pll1.config["n2"],
            p_QPLL_PLL1_FBDIV_45=4 if pll1 is None else pll1.config["n1"],
            p_QPLL_PLL1_REFCLK_DIV=1 if pll1 is None else pll1.config["m"],
            i_QPLL_GTGREFCLK1=0 if pll1 is None else pll1.gtgrefclk,
            i_QPLL_GTREFCLK1=0 if pll1 is None else pll1.gtrefclk,
            i_QPLL_PLL1LOCKEN=1,
            i_QPLL_PLL1PD=1 if pll1 is None else 0,
            i_QPLL_PLL1REFCLKSEL=0b001 if pll1 is None else pll1.refclksel,
            i_QPLL_PLL1RESET=1 if pll1 is None else pll1.reset,
            o_QPLL_PLL1LOCK=Signal() if pll1 is None else pll1.lock,
            o_QPLL_PLL1OUTCLK=Signal() if pll1 is None else pll1.clk,
            o_QPLL_PLL1OUTREFCLK=Signal() if pll1 is None else pll1.refclk)
        litepcie_phy_path = os.path.abspath(os.path.dirname(__file__))
        platform.add_source_dir(
            os.path.join(litepcie_phy_path, "xilinx", "7-series", "common"))
        if platform.device[:4] == "xc7k":
            platform.add_source_dir(
                os.path.join(litepcie_phy_path, "xilinx", "7-series",
                             "kintex7"))
        elif platform.device[:4] == "xc7a":
            platform.add_source_dir(
                os.path.join(litepcie_phy_path, "xilinx", "7-series",
                             "artix7"))
Exemple #22
0
    def __init__(self, pads, revision, dw=16):
    # Common signals
        self.dw = dw
        if dw not in [16, 32]:
            raise ValueError("Unsupported datawidth")

        # control
        self.tx_idle = Signal()         #i

        self.tx_cominit_stb = Signal()  #i
        self.tx_cominit_ack = Signal()  #o
        self.tx_comwake_stb = Signal()  #i
        self.tx_comwake_ack = Signal()  #o

        self.rx_idle = Signal()         #o
        self.rx_cdrhold = Signal()      #i

        self.rx_cominit_stb = Signal()  #o
        self.rx_comwake_stb = Signal()  #o

        self.rxdisperr = Signal(dw//8)      #o
        self.rxnotintable = Signal(dw//8)   #o

        # datapath
        self.sink = stream.Endpoint(phy_description(dw))
        self.source = stream.Endpoint(phy_description(dw))

    # K7 specific signals
        # Channel - Ref Clock Ports
        self.gtrefclk0 = Signal()

        # Channel PLL
        self.cplllock = Signal()
        self.cpllreset = Signal()

        # Receive Ports
        self.rxuserrdy = Signal()

        # Receive Ports - 8b10b Decoder
        self.rxcharisk = Signal(dw//8)

        # Receive Ports - RX Data Path interface
        self.gtrxreset = Signal()
        self.rxdata = Signal(dw)
        self.rxoutclk = Signal()
        self.rxusrclk = Signal()
        self.rxusrclk2 = Signal()

        # Receive Ports - RX PLL Ports
        self.rxresetdone = Signal()
        self.rxdlyreset = Signal()
        self.rxdlyresetdone = Signal()
        self.rxphaligndone = Signal()

        # Receive Ports - RX Ports for SATA
        self.rxcominitdet = Signal()
        self.rxcomwakedet = Signal()

        # Transmit Ports
        self.txuserrdy = Signal()

        # Transmit Ports - 8b10b Encoder Control Ports
        self.txcharisk = Signal(dw//8)

        # Transmit Ports - TX Data Path interface
        self.gttxreset = Signal()
        self.txdata = Signal(dw)
        self.txoutclk = Signal()
        self.txusrclk = Signal()
        self.txusrclk2 = Signal()

        # Transmit Ports - TX PLL Ports
        self.txresetdone = Signal()
        self.txdlyreset = Signal()
        self.txdlyresetdone = Signal()
        self.txphaligndone = Signal()

        # Transmit Ports - TX Ports for PCI Express
        self.txelecidle = Signal(reset=1)

        # Transmit Ports - TX Ports for SATA
        self.txcomfinish = Signal()
        self.txcominit = Signal()
        self.txcomwake = Signal()

        # DRP port
        self.drpaddr = Signal(9)
        self.drpclk  = Signal()
        self.drpdi   = Signal(16)
        self.drpdo   = Signal(16)
        self.drpen   = Signal()
        self.drprdy  = Signal()
        self.drpwe   = Signal()

        # Power-down signals
        self.cpllpd = Signal()
        self.rxpd   = Signal()
        self.txpd   = Signal()

    # Config at startup
        div_config = {
            "sata_gen1": 4,
            "sata_gen2": 2,
            "sata_gen3": 1
            }
        rxout_div = div_config[revision]
        txout_div = div_config[revision]

        cdr_config = {
            "sata_gen1": 0x0380008BFF40100008,
            "sata_gen2": 0x0388008BFF40200008,
            "sata_gen3": 0x0380008BFF10200010
        }
        rxcdr_cfg = cdr_config[revision]

    # Specific / Generic signals encoding/decoding
        self.comb += [
            self.txelecidle.eq(self.tx_idle | self.txpd),
            self.tx_cominit_ack.eq(self.tx_cominit_stb & self.txcomfinish),
            self.tx_comwake_ack.eq(self.tx_comwake_stb & self.txcomfinish),
            self.rx_cominit_stb.eq(self.rxcominitdet),
            self.rx_comwake_stb.eq(self.rxcomwakedet),
        ]
        self.submodules += [
            _RisingEdge(self.tx_cominit_stb, self.txcominit),
            _RisingEdge(self.tx_comwake_stb, self.txcomwake),
        ]

        self.sync.sata_rx += [
            self.source.valid.eq(1),
            self.source.charisk.eq(self.rxcharisk),
            self.source.data.eq(self.rxdata)
        ]

        self.sync.sata_tx += [
            self.txcharisk.eq(self.sink.charisk),
            self.txdata.eq(self.sink.data),
            self.sink.ready.eq(1),
        ]
    # Internals and clock domain crossing
        # sys_clk --> sata_tx clk
        txuserrdy = Signal()
        txelecidle = Signal(reset=1)
        txcominit = Signal()
        txcomwake = Signal()
        txdlyreset = Signal()
        txdlyresetdone = Signal()
        txphaligndone = Signal()
        gttxreset = Signal()

        self.specials += [
            MultiReg(self.txuserrdy, txuserrdy, "sata_tx"),
            MultiReg(self.txelecidle, txelecidle, "sata_tx"),
            MultiReg(self.gttxreset, gttxreset, "sata_tx")
        ]
        self.submodules += [
            _PulseSynchronizer(self.txcominit, "sys", txcominit, "sata_tx"),
            _PulseSynchronizer(self.txcomwake, "sys", txcomwake, "sata_tx"),
            _PulseSynchronizer(self.txdlyreset, "sys", txdlyreset, "sata_tx")
        ]

        # sata_tx clk --> sys clk
        txresetdone = Signal()
        txcomfinish = Signal()

        self.specials += [
            MultiReg(txresetdone, self.txresetdone, "sys"),
            MultiReg(txdlyresetdone, self.txdlyresetdone, "sys"),
            MultiReg(txphaligndone, self.txphaligndone, "sys")
        ]

        self.submodules += [
            _PulseSynchronizer(txcomfinish, "sata_tx", self.txcomfinish, "sys")
        ]

        # sys clk --> sata_rx clk
        rxuserrdy = Signal()
        rxdlyreset = Signal()

        self.specials += [
            MultiReg(self.rxuserrdy, rxuserrdy, "sata_rx")
        ]

        self.submodules += [
            _PulseSynchronizer(self.rxdlyreset, "sys", rxdlyreset, "sata_rx")
        ]

        # sata_rx clk --> sys clk
        rxresetdone = Signal()
        rxcominitdet = Signal()
        rxcomwakedet = Signal()
        rxratedone = Signal()
        rxdlyresetdone = Signal()
        rxphaligndone = Signal()
        rxdisperr = Signal(dw//8)
        rxnotintable = Signal(dw//8)

        self.specials += [
            MultiReg(rxresetdone, self.rxresetdone, "sys"),
            MultiReg(rxcominitdet, self.rxcominitdet, "sys"),
            MultiReg(rxcomwakedet, self.rxcomwakedet, "sys"),
            MultiReg(rxdlyresetdone, self.rxdlyresetdone, "sys"),
            MultiReg(rxphaligndone, self.rxphaligndone, "sys"),
            MultiReg(rxdisperr, self.rxdisperr, "sys"),
            MultiReg(rxnotintable, self.rxnotintable, "sys")
        ]

    # QPLL input clock
        self.qpllclk = Signal()
        self.qpllrefclk = Signal()

    # OOB clock (75MHz)
        oobclk = Signal()
        self.specials += \
            Instance("FDPE", p_INIT=1, i_CE=1,  i_PRE=0,
                     i_C=self.gtrefclk0, i_D=~oobclk, o_Q=oobclk)

    # Instance
        gtxe2_channel_parameters = {
                # Simulation-Only Attributes
                    "p_SIM_RECEIVER_DETECT_PASS": "******",
                    "p_SIM_TX_EIDLE_DRIVE_LEVEL": "X",
                    "p_SIM_RESET_SPEEDUP": "TRUE",
                    "p_SIM_CPLLREFCLK_SEL": 0b001,
                    "p_SIM_VERSION": "4.0",

                # RX Byte and Word Alignment Attributes
                    "p_ALIGN_COMMA_DOUBLE": "FALSE",
                    "p_ALIGN_COMMA_ENABLE": ones(10),
                    "p_ALIGN_COMMA_WORD": 1,
                    "p_ALIGN_MCOMMA_DET": "TRUE",
                    "p_ALIGN_MCOMMA_VALUE": 0b1010000011,
                    "p_ALIGN_PCOMMA_DET": "TRUE",
                    "p_ALIGN_PCOMMA_VALUE": 0b0101111100,
                    "p_SHOW_REALIGN_COMMA": "FALSE",
                    "p_RXSLIDE_AUTO_WAIT": 7,
                    "p_RXSLIDE_MODE": "PCS",
                    "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": "FALSE",

                # 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 if dw == 16 else 19,
                    "p_CLK_COR_MIN_LAT": 7 if dw == 16 else 15,
                    "p_CLK_COR_PRECEDENCE": "TRUE",
                    "p_CLK_COR_REPEAT_WAIT": 0,
                    "p_CLK_COR_SEQ_LEN": 1,
                    "p_CLK_COR_SEQ_1_ENABLE": ones(4),
                    "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": ones(4),
                    "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": 0,
                    "p_CHAN_BOND_SEQ_1_1": 0,
                    "p_CHAN_BOND_SEQ_1_2": 0,
                    "p_CHAN_BOND_SEQ_1_3": 0,
                    "p_CHAN_BOND_SEQ_1_4": 0,
                    "p_CHAN_BOND_SEQ_1_ENABLE": ones(4),
                    "p_CHAN_BOND_SEQ_2_1": 0,
                    "p_CHAN_BOND_SEQ_2_2": 0,
                    "p_CHAN_BOND_SEQ_2_3": 0,
                    "p_CHAN_BOND_SEQ_2_4": 0,
                    "p_CHAN_BOND_SEQ_2_ENABLE": ones(4),
                    "p_CHAN_BOND_SEQ_2_USE": "FALSE",
                    "p_FTS_DESKEW_SEQ_ENABLE": ones(4),
                    "p_FTS_LANE_DESKEW_CFG": ones(4),
                    "p_FTS_LANE_DESKEW_EN": "FALSE",

                # RX Margin Analysis Attributes
                    "p_ES_CONTROL": 0,
                    "p_ES_ERRDET_EN": "FALSE",
                    "p_ES_EYE_SCAN_EN": "TRUE",
                    "p_ES_HORZ_OFFSET": 0,
                    "p_ES_PMA_CFG": 0,
                    "p_ES_PRESCALE": 0,
                    "p_ES_QUALIFIER": 0,
                    "p_ES_QUAL_MASK": 0,
                    "p_ES_SDATA_MASK": 0,
                    "p_ES_VERT_OFFSET": 0,

                # FPGA RX Interface Attributes
                    "p_RX_DATA_WIDTH": 20 if dw == 16 else 40,

                # PMA Attributes
                    "p_OUTREFCLK_SEL_INV": 0b11,
                    "p_PMA_RSV": 0x00018480,
                    "p_PMA_RSV2": 0x2050,
                    "p_PMA_RSV3": 0,
                    "p_PMA_RSV4": 0,
                    "p_RX_BIAS_CFG": 0b100,
                    "p_DMONITOR_CFG": 0xA00,
                    "p_RX_CM_SEL": 0b11,
                    "p_RX_CM_TRIM": 0b010,
                    "p_RX_DEBUG_CFG": 0,
                    "p_RX_OS_CFG": 0b10000000,
                    "p_TERM_RCAL_CFG": 0b10000,
                    "p_TERM_RCAL_OVRD": 0,
                    "p_TST_RSV": 0,
                    "p_RX_CLK25_DIV": 6,
                    "p_TX_CLK25_DIV": 6,
                    "p_UCODEER_CLR": 0,

                # PCI Express Attributes
                    "p_PCS_PCIE_EN": "FALSE",

                # PCS Attributes
                    "p_PCS_RSVD_ATTR": 0x108 if revision == "sata_gen1" else 0x100,

                # RX Buffer Attributes
                    "p_RXBUF_ADDR_MODE": "FAST",
                    "p_RXBUF_EIDLE_HI_CNT": 0b1000,
                    "p_RXBUF_EIDLE_LO_CNT": 0b0000,
                    "p_RXBUF_EN": "FALSE",
                    "p_RX_BUFFER_CFG": 0,
                    "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": 1,
                    "p_RXBUF_THRESH_OVFLW": 61,
                    "p_RXBUF_THRESH_OVRD": "FALSE",
                    "p_RXBUF_THRESH_UNDFLW": 4,
                    "p_RXDLY_CFG": 0x1f,
                    "p_RXDLY_LCFG": 0x30,
                    "p_RXDLY_TAP_CFG": 0,
                    "p_RXPH_CFG": 0,
                    "p_RXPHDLY_CFG": 0x084020,
                    "p_RXPH_MONITOR_SEL": 0,
                    "p_RX_XCLK_SEL": "RXUSR",
                    "p_RX_DDI_SEL": 0,
                    "p_RX_DEFER_RESET_BUF_EN": "TRUE",

                # CDR Attributes
                    "p_RXCDR_CFG": rxcdr_cfg,
                    "p_RXCDR_FR_RESET_ON_EIDLE": 0,
                    "p_RXCDR_HOLD_DURING_EIDLE": 0,
                    "p_RXCDR_PH_RESET_ON_EIDLE": 0,
                    "p_RXCDR_LOCK_CFG": 0b010101,

                # RX Initialization and Reset Attributes
                    "p_RXCDRFREQRESET_TIME": 1,
                    "p_RXCDRPHRESET_TIME": 1,
                    "p_RXISCANRESET_TIME": 1,
                    "p_RXPCSRESET_TIME": 1,
                    "p_RXPMARESET_TIME": 3,

                # RX OOB Signaling Attributes
                    "p_RXOOB_CFG": 0b0000110,

                # RX Gearbox Attributes
                    "p_RXGEARBOX_EN": "FALSE",
                    "p_GEARBOX_MODE": 0,

                # PRBS Detection Attribute
                    "p_RXPRBS_ERR_LOOPBACK": 0,

                # 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": "FALSE",
                    "p_TXBUF_RESET_ON_RATE_CHANGE": "FALSE",
                    "p_TXDLY_CFG": 0x1f,
                    "p_TXDLY_LCFG": 0x030,
                    "p_TXDLY_TAP_CFG": 0,
                    "p_TXPH_CFG": 0x0780,
                    "p_TXPHDLY_CFG": 0x084020,
                    "p_TXPH_MONITOR_SEL": 0,
                    "p_TX_XCLK_SEL": "TXUSR",

                # FPGA TX Interface Attributes
                    "p_TX_DATA_WIDTH": 20 if dw ==16 else 40,

                # TX Configurable Driver Attributes
                    "p_TX_DEEMPH0": 0,
                    "p_TX_DEEMPH1": 0,
                    "p_TX_EIDLE_ASSERT_DELAY": 0b110,
                    "p_TX_EIDLE_DEASSERT_DELAY": 0b100,
                    "p_TX_LOOPBACK_DRIVE_HIZ": "FALSE",
                    "p_TX_MAINCURSOR_SEL": 0,
                    "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": 1,
                    "p_TXPMARESET_TIME": 1,

                # TX Receiver Detection Attributes
                    "p_TX_RXDETECT_CFG": 0x1832,
                    "p_TX_RXDETECT_REF": 0b100,

                # CPLL Attributes
                    "p_CPLL_CFG": 0xBC07DC,
                    "p_CPLL_FBDIV": 4,
                    "p_CPLL_FBDIV_45": 5,
                    "p_CPLL_INIT_CFG": 0x00001e,
                    "p_CPLL_LOCK_CFG": 0x01e8,
                    "p_CPLL_REFCLK_DIV": 1,
                    "p_RXOUT_DIV": rxout_div,
                    "p_TXOUT_DIV": txout_div,
                    "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": 1,
                    "p_RX_DFE_UT_CFG": 0b10001111000000000,
                    "p_RX_DFE_VP_CFG": 0b00011111100000011,

                # Power-Down Attributes
                    "p_RX_CLKMUX_PD": 1,
                    "p_TX_CLKMUX_PD": 1,

                # FPGA RX Interface Attribute
                    "p_RX_INT_DATAWIDTH": 0 if dw == 16 else 1,

                # FPGA TX Interface Attribute
                    "p_TX_INT_DATAWIDTH": 0 if dw == 16 else 1,

                # TX Configurable Driver Attributes
                    "p_TX_QPI_STATUS_EN": 0,

                # RX Equalizer Attributes
                    "p_RX_DFE_KL_CFG2": 0b00110011000100000001100000001100,
                    "p_RX_DFE_XYD_CFG": 0b0000000000000,

                # TX Configurable Driver Attributes
                    "p_TX_PREDRIVER_MODE": 0,
            }

        self.specials += \
            Instance("GTXE2_CHANNEL",
                # CPLL Ports
                    #o_CPLLFBCLKLOST=,
                    o_CPLLLOCK=self.cplllock,
                    i_CPLLLOCKDETCLK=0,
                    i_CPLLLOCKEN=1,
                    i_CPLLPD=self.cpllpd,
                    #o_CPLLREFCLKLOST=0,
                    i_CPLLREFCLKSEL=0b001,
                    i_CPLLRESET=self.cpllreset,
                    i_GTRSVD=0,
                    i_PCSRSVDIN=0,
                    i_PCSRSVDIN2=0,
                    i_PMARSVDIN=0,
                    i_PMARSVDIN2=0,
                    i_TSTIN=ones(20),
                    #o_TSTOUT=,

                # Channel
                    i_CLKRSVD=oobclk,

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

                # Channel - DRP Ports
                    i_DRPADDR=self.drpaddr,
                    i_DRPCLK=self.drpclk,
                    i_DRPDI=self.drpdi,
                    o_DRPDO=self.drpdo,
                    i_DRPEN=self.drpen,
                    o_DRPRDY=self.drprdy,
                    i_DRPWE=self.drpwe,

                # Clocking Ports
                    #o_GTREFCLKMONITOR=,
                    i_QPLLCLK=self.qpllclk,
                    i_QPLLREFCLK=self.qpllrefclk,
                    i_RXSYSCLKSEL=0b00,
                    i_TXSYSCLKSEL=0b00,

                # Digital Monitor Ports
                    #o_DMONITOROUT=,

                # FPGA TX Interface Datapath Configuration
                    i_TX8B10BEN=1,

                # Loopback Ports
                    i_LOOPBACK=0,

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

                # Power-Down Ports
                    i_RXPD=Replicate(self.rxpd, 2),
                    i_TXPD=Replicate(self.txpd, 2),

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

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

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

                # Receive Ports - CDR Ports
                    i_RXCDRFREQRESET=0,
                    i_RXCDRHOLD=self.rx_cdrhold,
                    #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=1,

                # Receive Ports - FPGA RX Interface Ports
                    i_RXUSRCLK=self.rxusrclk,
                    i_RXUSRCLK2=self.rxusrclk2,

                # Receive Ports - FPGA RX interface Ports
                    o_RXDATA=self.rxdata,

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

                # 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
                    o_RXDISPERR=rxdisperr,
                    o_RXNOTINTABLE=rxnotintable,

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

                # Receive Ports - RX Buffer Bypass Ports
                    i_RXBUFRESET=0,
                    #o_RXBUFSTATUS=,
                    i_RXDDIEN=1,
                    i_RXDLYBYPASS=0,
                    i_RXDLYEN=0,
                    i_RXDLYOVRDEN=0,
                    i_RXDLYSRESET=rxdlyreset,
                    o_RXDLYSRESETDONE=rxdlyresetdone,
                    i_RXPHALIGN=0,
                    o_RXPHALIGNDONE=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=0,
                    i_RXCHBONDMASTER=0,
                    #o_RXCHBONDO=,
                    i_RXCHBONDSLAVE=0,

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

                # Receive Ports - RX Equalizer Ports
                    i_RXDFEAGCHOLD=0,
                    i_RXDFEAGCOVRDEN=0,
                    i_RXDFECM1EN=0,
                    i_RXDFELFHOLD=0,
                    i_RXDFELFOVRDEN=0,
                    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=0b00,
                    i_RXOSHOLD=0,
                    i_RXOSOVRDEN=0,

                # Receive Ports - RX Equilizer Ports
                    i_RXLPMHFHOLD=0,
                    i_RXLPMHFOVRDEN=0,
                    i_RXLPMLFHOLD=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=self.gtrxreset,
                    i_RXOOBRESET=0,
                    i_RXPCSRESET=0,
                    i_RXPMARESET=0,

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

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

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

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

                # 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=self.rxcharisk,

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

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

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

                # TX Buffer Bypass Ports
                    i_TXPHDLYTSTCLK=0,

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

                # TX Initialization and Reset Ports
                    i_CFGRESET=0,
                    i_GTTXRESET=gttxreset,
                    #o_PCSRSVDOUT=,
                    i_TXUSERRDY=txuserrdy,

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

                # Transmit Ports - 8b10b Encoder Control Ports
                    i_TXCHARDISPMODE=0,
                    i_TXCHARDISPVAL=0,

                # Transmit Ports - FPGA TX Interface Ports
                    i_TXUSRCLK=self.txusrclk,
                    i_TXUSRCLK2=self.txusrclk2,

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

                # Transmit Ports - Pattern Generator Ports
                    i_TXPRBSFORCEERR=0,

                # Transmit Ports - TX Buffer Bypass Ports
                    i_TXDLYBYPASS=0,
                    i_TXDLYEN=0,
                    i_TXDLYHOLD=0,
                    i_TXDLYOVRDEN=0,
                    i_TXDLYSRESET=txdlyreset,
                    o_TXDLYSRESETDONE=txdlyresetdone,
                    i_TXDLYUPDOWN=0,
                    i_TXPHALIGN=0,
                    o_TXPHALIGNDONE=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=0,
                    i_TXPISOPD=0,

                # Transmit Ports - TX Data Path interface
                    i_TXDATA=self.txdata,

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

                # Transmit Ports - TX Fabric Clock Output Control Ports
                    o_TXOUTCLK=self.txoutclk,
                    #o_TXOUTCLKFABRIC=,
                    #o_TXOUTCLKPCS=,
                    i_TXOUTCLKSEL=0b11,
                    #o_TXRATEDONE=,
                # Transmit Ports - TX Gearbox Ports
                    i_TXCHARISK=self.txcharisk,
                    #o_TXGEARBOXREADY=,
                    i_TXHEADER=0,
                    i_TXSEQUENCE=0,
                    i_TXSTARTSEQ=0,

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

                # Transmit Ports - TX OOB signalling Ports
                    o_TXCOMFINISH=txcomfinish,
                    i_TXCOMINIT=txcominit,
                    i_TXCOMSAS=0,
                    i_TXCOMWAKE=txcomwake,
                    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=0,

                # Transmit Ports - pattern Generator Ports
                    i_TXPRBSSEL=0,

                # Tx Configurable Driver  Ports
                    #o_TXQPISENN=,
                    #o_TXQPISENP=,

                    **gtxe2_channel_parameters
            )
Exemple #23
0
 def __init__(self, signal):
     self._in = CSRStatus(len(signal))
     self.specials += MultiReg(signal, self._in.status)
Exemple #24
0
    def __init__(self, dram_port, mode="rgb", fifo_depth=512):
        try:
            dw = modes_dw[mode]
        except:
            raise ValueError("Unsupported {} video mode".format(mode))
        assert dram_port.dw >= dw
        assert dram_port.dw == 2**log2_int(dw, need_pow2=False)
        self.source = source = stream.Endpoint(video_out_layout(dw))

        self.underflow_enable = CSRStorage()
        self.underflow_update = CSR()
        self.underflow_counter = CSRStatus(32)

        # # #

        cd = dram_port.cd

        self.submodules.initiator = initiator = Initiator(cd)
        self.submodules.timing = timing = ClockDomainsRenamer(cd)(
            TimingGenerator())
        self.submodules.dma = dma = ClockDomainsRenamer(cd)(DMAReader(
            dram_port, fifo_depth))

        # ctrl path
        self.comb += [
            # dispatch initiator parameters to timing & dma
            timing.sink.valid.eq(initiator.source.valid),
            dma.sink.valid.eq(initiator.source.valid),
            initiator.source.ready.eq(timing.sink.ready),

            # combine timing and dma
            source.valid.eq(timing.source.valid
                            & (~timing.source.de | dma.source.valid)),
            # flush dma/timing when disabled
            If(~initiator.source.valid, timing.source.ready.eq(1),
               dma.source.ready.eq(1)).Elif(
                   source.valid & source.ready, timing.source.ready.eq(1),
                   dma.source.ready.eq(timing.source.de | (mode == "raw")))
        ]

        # data path
        self.comb += [
            # dispatch initiator parameters to timing & dma
            initiator.source.connect(
                timing.sink, keep=list_signals(frame_parameter_layout)),
            initiator.source.connect(dma.sink,
                                     keep=list_signals(frame_dma_layout)),

            # combine timing and dma
            source.de.eq(timing.source.de),
            source.hsync.eq(timing.source.hsync),
            source.vsync.eq(timing.source.vsync),
            source.data.eq(dma.source.data)
        ]

        # underflow detection
        underflow_enable = Signal()
        underflow_update = Signal()
        underflow_counter = Signal(32)
        self.specials += MultiReg(self.underflow_enable.storage,
                                  underflow_enable)
        underflow_update_synchronizer = PulseSynchronizer("sys", cd)
        self.submodules += underflow_update_synchronizer
        self.comb += [
            underflow_update_synchronizer.i.eq(self.underflow_update.re),
            underflow_update.eq(underflow_update_synchronizer.o)
        ]
        sync = getattr(self.sync, cd)
        sync += [
            If(underflow_enable,
               If(~source.valid,
                  underflow_counter.eq(underflow_counter + 1))).Else(
                      underflow_counter.eq(0)),
            If(underflow_update,
               self.underflow_counter.status.eq(underflow_counter))
        ]
Exemple #25
0
    def __init__(self, pads, external_clocking, max_pix_clk=100e6):
        if external_clocking is None:
            self._cmd_data = CSRStorage(10)
            self._send_cmd_data = CSR()
            self._send_go = CSR()
            self._status = CSRStatus(4)
            self._max_pix_clk = CSRConstant(max_pix_clk)

            self.clock_domains.cd_pix = ClockDomain(reset_less=True)
            self._pll_reset = CSRStorage()
            self._pll_adr = CSRStorage(5)
            self._pll_dat_r = CSRStatus(16)
            self._pll_dat_w = CSRStorage(16)
            self._pll_read = CSR()
            self._pll_write = CSR()
            self._pll_drdy = CSRStatus()

            self.clock_domains.cd_pix2x = ClockDomain(reset_less=True)
            self.clock_domains.cd_pix10x = ClockDomain(reset_less=True)
            self.serdesstrobe = Signal()

            # # #

            # Generate 1x pixel clock
            clk_pix_unbuffered = Signal()
            pix_progdata = Signal()
            pix_progen = Signal()
            pix_progdone = Signal()

            pix_locked = Signal()

            clkfx_md_max = max(2.0 / 4.0, max_pix_clk / 50e6)
            self._clkfx_md_max_1000 = CSRConstant(clkfx_md_max * 1000.0)
            self.specials += Instance(
                "DCM_CLKGEN",
                name="hdmi_out_dcm_clkgen",

                # parameters
                p_SPREAD_SPECTRUM="NONE",
                p_STARTUP_WAIT="FALSE",

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

                # input
                i_CLKIN=ClockSignal("base50"),
                p_CLKIN_PERIOD=20.0,

                # output
                p_CLKFXDV_DIVIDE=2,
                p_CLKFX_MULTIPLY=2,
                p_CLKFX_DIVIDE=4,
                p_CLKFX_MD_MAX=clkfx_md_max,
                o_CLKFX=clk_pix_unbuffered,
                o_LOCKED=pix_locked,

                # programming interface
                i_PROGCLK=ClockSignal(),
                i_PROGDATA=pix_progdata,
                i_PROGEN=pix_progen,
                o_PROGDONE=pix_progdone)

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

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

            mult_locked = Signal()
            self.comb += self._status.status.eq(
                Cat(busy, pix_progdone, pix_locked, mult_locked))

            # Clock multiplication and buffering
            # Route unbuffered 1x pixel clock to PLL
            # Generate 1x, 2x and 10x IO pixel clocks
            clkfbout = Signal()
            pll_locked = Signal()
            pll0_pix10x = Signal()
            pll1_pix2x = Signal()
            pll2_pix = Signal()
            locked_async = Signal()
            pll_drdy = Signal()
            self.sync += If(self._pll_read.re | self._pll_write.re,
                            self._pll_drdy.status.eq(0)).Elif(
                                pll_drdy, self._pll_drdy.status.eq(1))
            self.specials += [
                Instance(
                    "PLL_ADV",
                    name="hdmi_out_pll_adv",
                    p_CLKFBOUT_MULT=10,
                    p_CLKOUT0_DIVIDE=1,  # pix10x
                    p_CLKOUT1_DIVIDE=5,  # pix2x
                    p_CLKOUT2_DIVIDE=10,  # pix
                    p_COMPENSATION="INTERNAL",
                    i_CLKINSEL=1,
                    i_CLKIN1=clk_pix_unbuffered,
                    o_CLKOUT0=pll0_pix10x,
                    o_CLKOUT1=pll1_pix2x,
                    o_CLKOUT2=pll2_pix,
                    o_CLKFBOUT=clkfbout,
                    i_CLKFBIN=clkfbout,
                    o_LOCKED=pll_locked,
                    i_RST=~pix_locked | self._pll_reset.storage,
                    i_DADDR=self._pll_adr.storage,
                    o_DO=self._pll_dat_r.status,
                    i_DI=self._pll_dat_w.storage,
                    i_DEN=self._pll_read.re | self._pll_write.re,
                    i_DWE=self._pll_write.re,
                    o_DRDY=pll_drdy,
                    i_DCLK=ClockSignal()),
                Instance("BUFPLL",
                         name="hdmi_out_bufpll",
                         p_DIVIDE=5,
                         i_PLLIN=pll0_pix10x,
                         i_GCLK=ClockSignal("pix2x"),
                         i_LOCKED=pll_locked,
                         o_IOCLK=self.cd_pix10x.clk,
                         o_LOCK=locked_async,
                         o_SERDESSTROBE=self.serdesstrobe),
                Instance("BUFG",
                         name="hdmi_out_pix2x_bufg",
                         i_I=pll1_pix2x,
                         o_O=self.cd_pix2x.clk),
                Instance("BUFG",
                         name="hdmi_out_pix_bufg",
                         i_I=pll2_pix,
                         o_O=self.cd_pix.clk),
                MultiReg(locked_async, mult_locked, "sys")
            ]

            self.pll0_pix10x = pll0_pix10x
            self.pll1_pix2x = pll1_pix2x
            self.pll2_pix = pll2_pix
            self.pll_locked = pll_locked

        else:
            self.clock_domains.cd_pix = ClockDomain(reset_less=True)
            self.specials += Instance("BUFG",
                                      name="hdmi_out_pix_bufg",
                                      i_I=external_clocking.pll2_pix,
                                      o_O=self.cd_pix.clk)
            self.clock_domains.cd_pix2x = ClockDomain(reset_less=True)
            self.clock_domains.cd_pix10x = ClockDomain(reset_less=True)
            self.serdesstrobe = Signal()
            self.specials += [
                Instance("BUFG",
                         name="hdmi_out_pix2x_bufg",
                         i_I=external_clocking.pll1_pix2x,
                         o_O=self.cd_pix2x.clk),
                Instance("BUFPLL",
                         name="hdmi_out_bufpll",
                         p_DIVIDE=5,
                         i_PLLIN=external_clocking.pll0_pix10x,
                         i_GCLK=self.cd_pix2x.clk,
                         i_LOCKED=external_clocking.pll_locked,
                         o_IOCLK=self.cd_pix10x.clk,
                         o_SERDESSTROBE=self.serdesstrobe),
            ]

        # Drive HDMI clock pads
        hdmi_clk_se = Signal()
        self.specials += Instance("ODDR2",
                                  p_DDR_ALIGNMENT="NONE",
                                  p_INIT=0,
                                  p_SRTYPE="SYNC",
                                  o_Q=hdmi_clk_se,
                                  i_C0=ClockSignal("pix"),
                                  i_C1=~ClockSignal("pix"),
                                  i_CE=1,
                                  i_D0=not hasattr(pads.clk_p, "inverted"),
                                  i_D1=hasattr(pads.clk_p, "inverted"),
                                  i_R=0,
                                  i_S=0)
        if hasattr(pads, "clk_p"):
            self.specials += Instance("OBUFDS",
                                      i_I=hdmi_clk_se,
                                      o_O=pads.clk_p,
                                      o_OB=pads.clk_n)
        else:
            self.comb += pads.clk.eq(hdmi_clk_se)
Exemple #26
0
    def __init__(self, word_width, fifo_depth):
        # in pix clock domain
        self.valid_i = Signal()
        self.vsync = Signal()
        self.de = Signal()
        self.r = Signal(8)
        self.g = Signal(8)
        self.b = Signal(8)

        # in sys clock domain
        word_layout = [("sof", 1), ("pixels", word_width)]
        self.frame = stream.Endpoint(word_layout)
        self.busy = Signal()

        self._overflow = CSR()

        # # #

        de_r = Signal()
        self.sync.pix += de_r.eq(self.de)

        rgb2ycbcr = RGB2YCbCr()
        self.submodules += ClockDomainsRenamer("pix")(rgb2ycbcr)
        chroma_downsampler = YCbCr444to422()
        self.submodules += ClockDomainsRenamer("pix")(chroma_downsampler)
        self.comb += [
            rgb2ycbcr.sink.valid.eq(self.valid_i),
            rgb2ycbcr.sink.r.eq(self.r),
            rgb2ycbcr.sink.g.eq(self.g),
            rgb2ycbcr.sink.b.eq(self.b),
            rgb2ycbcr.source.connect(chroma_downsampler.sink),
            chroma_downsampler.source.ready.eq(1),
            chroma_downsampler.datapath.first.eq(self.de & ~de_r) # XXX need clean up
        ]
        # XXX need clean up
        de = self.de
        vsync = self.vsync
        for i in range(rgb2ycbcr.latency + chroma_downsampler.latency):
            next_de = Signal()
            next_vsync = Signal()
            self.sync.pix += [
                next_de.eq(de),
                next_vsync.eq(vsync)
            ]
            de = next_de
            vsync = next_vsync

        # start of frame detection
        vsync_r = Signal()
        new_frame = Signal()
        self.comb += new_frame.eq(vsync & ~vsync_r)
        self.sync.pix += vsync_r.eq(vsync)

        # pack pixels into words
        cur_word = Signal(word_width)
        cur_word_valid = Signal()
        encoded_pixel = Signal(16)
        self.comb += encoded_pixel.eq(Cat(chroma_downsampler.source.y,
                                          chroma_downsampler.source.cb_cr)),
        pack_factor = word_width//16
        assert(pack_factor & (pack_factor - 1) == 0)  # only support powers of 2
        pack_counter = Signal(max=pack_factor)
        self.sync.pix += [
            cur_word_valid.eq(0),
            If(new_frame,
                cur_word_valid.eq(pack_counter == (pack_factor - 1)),
                pack_counter.eq(0),
            ).Elif(chroma_downsampler.source.valid & de,
                [If(pack_counter == (pack_factor-i-1),
                    cur_word[16*i:16*(i+1)].eq(encoded_pixel)) for i in range(pack_factor)],
                cur_word_valid.eq(pack_counter == (pack_factor - 1)),
                pack_counter.eq(pack_counter + 1)
            )
        ]

        # FIFO
        fifo = stream.AsyncFIFO(word_layout, fifo_depth)
        fifo = ClockDomainsRenamer({"write": "pix", "read": "sys"})(fifo)
        self.submodules += fifo
        self.comb += [
            fifo.sink.pixels.eq(cur_word),
            fifo.sink.valid.eq(cur_word_valid)
        ]
        self.sync.pix += \
            If(new_frame,
                fifo.sink.sof.eq(1)
            ).Elif(cur_word_valid,
                fifo.sink.sof.eq(0)
            )

        self.comb += [
            fifo.source.connect(self.frame),
            self.busy.eq(0)
        ]

        # overflow detection
        pix_overflow = Signal()
        pix_overflow_reset = Signal()
        self.sync.pix += [
            If(fifo.sink.valid & ~fifo.sink.ready,
                pix_overflow.eq(1)
            ).Elif(pix_overflow_reset,
                pix_overflow.eq(0)
            )
        ]

        sys_overflow = Signal()
        self.specials += MultiReg(pix_overflow, sys_overflow)
        self.submodules.overflow_reset = PulseSynchronizer("sys", "pix")
        self.submodules.overflow_reset_ack = PulseSynchronizer("pix", "sys")
        self.comb += [
            pix_overflow_reset.eq(self.overflow_reset.o),
            self.overflow_reset_ack.i.eq(pix_overflow_reset)
        ]

        overflow_mask = Signal()
        self.comb += [
            self._overflow.w.eq(sys_overflow & ~overflow_mask),
            self.overflow_reset.i.eq(self._overflow.re)
        ]
        self.sync += \
            If(self._overflow.re,
                overflow_mask.eq(1)
            ).Elif(self.overflow_reset_ack.o,
                overflow_mask.eq(0)
            )
Exemple #27
0
    def __init__(self, clock_pads_or_refclk, pads, gtx, revision, clk_freq):
        self.tx_reset = Signal()
        self.rx_reset = Signal()
        self.ready = Signal()
        self.cplllock = Signal()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

        # Reset for SATA TX/RX clock domains
        self.specials += [
            AsyncResetSynchronizer(self.cd_sata_tx, ~(gtx.cplllock & mmcm_locked) | self.tx_reset),
            AsyncResetSynchronizer(self.cd_sata_rx, ~gtx.cplllock | self.rx_reset),
            MultiReg(gtx.cplllock, self.cplllock, "sys"),
        ]
Exemple #28
0
    def __init__(self, cfg):
        self.pads = pads = _sdpads()
        self.sink = sink = stream.Endpoint([("data", 8)])
        self.source = source = stream.Endpoint([("data", 8), ("status", 3)])

        # # #

        datarfb_reset = Signal()

        self.submodules.datarfb = SDPHYRFB(pads.data.i, True)
        self.submodules.cdc = ClockDomainsRenamer({
            "write": "sd_fb",
            "read": "sd"
        })(stream.AsyncFIFO(self.datarfb.source.description, 4))
        self.submodules.buffer = ClockDomainsRenamer("sd")(stream.Buffer(
            self.datarfb.source.description))
        self.comb += self.datarfb.source.connect(self.buffer.sink)

        dtimeout = Signal(32)

        read = Signal(10)
        toread = Signal(10)
        cnt = Signal(8)

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

        fsm.act(
            "IDLE",
            pads.data.oe.eq(0),
            pads.clk.eq(1),
            datarfb_reset.eq(1),
            self.buffer.source.ready.eq(1),
            If(
                sink.valid,
                NextValue(dtimeout, 0),
                NextValue(read, 0),
                # Read 1 block + 8*8 == 64 bits CRC
                NextValue(toread, cfg.blocksize + 8),
                NextState("DATA_READSTART")))

        self.specials += MultiReg(datarfb_reset, self.datarfb.reset, "sd_fb")

        fsm.act(
            "DATA_READSTART", pads.data.oe.eq(0), pads.clk.eq(1),
            NextValue(dtimeout, dtimeout + 1),
            If(self.buffer.source.valid,
               NextState("DATA_READ")).Elif(dtimeout > cfg.datatimeout,
                                            NextState("TIMEOUT")))

        fsm.act(
            "DATA_READ", pads.data.oe.eq(0), pads.clk.eq(1),
            source.valid.eq(self.buffer.source.valid),
            source.data.eq(self.buffer.source.data),
            source.status.eq(SDCARD_STREAM_STATUS_OK),
            source.last.eq(read == (toread - 1)),
            self.buffer.source.ready.eq(source.ready),
            If(
                source.valid & source.ready, NextValue(read, read + 1),
                If(
                    read == (toread - 1),
                    If(sink.last, NextState("DATA_CLK40")).Else(
                        sink.ready.eq(1), NextState("DATA_FLUSH")))))

        fsm.act(
            "DATA_FLUSH", pads.data.oe.eq(0), datarfb_reset.eq(1),
            self.buffer.source.ready.eq(1),
            If(
                cnt < 5,
                NextValue(cnt, cnt + 1),
            ).Else(NextValue(cnt, 0), NextState("IDLE")))

        fsm.act(
            "DATA_CLK40", pads.data.oe.eq(1), pads.data.o.eq(0xf),
            If(cnt < 40, NextValue(cnt, cnt + 1),
               pads.clk.eq(1)).Else(NextValue(cnt, 0), sink.ready.eq(1),
                                    NextState("IDLE")))

        fsm.act(
            "TIMEOUT", source.valid.eq(1), source.data.eq(0),
            source.status.eq(SDCARD_STREAM_STATUS_TIMEOUT), source.last.eq(1),
            If(source.valid & source.ready, sink.ready.eq(1),
               NextState("IDLE")))
Exemple #29
0
    def __init__(self, pll, pads, mode="master"):
        self.tx_data = Signal(32)
        self.rx_data = Signal(32)

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

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

        # # #

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

        # clocking:

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

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

        # tx clock (linerate/10)
        if mode == "master":
            self.submodules.tx_clk_gearbox = Gearbox(40, "serwb_serdes", 8,
                                                     "serwb_serdes_5x")
            self.comb += self.tx_clk_gearbox.i.eq((0b1111100000 << 30)
                                                  | (0b1111100000 << 20)
                                                  | (0b1111100000 << 10)
                                                  | (0b1111100000 << 0))
            clk_o = Signal()
            self.specials += [
                Instance("OSERDESE3",
                         p_DATA_WIDTH=8,
                         p_INIT=0,
                         p_IS_CLK_INVERTED=0,
                         p_IS_CLKDIV_INVERTED=0,
                         p_IS_RST_INVERTED=0,
                         o_OQ=clk_o,
                         i_RST=ResetSignal("serwb_serdes"),
                         i_CLK=ClockSignal("serwb_serdes_20x"),
                         i_CLKDIV=ClockSignal("serwb_serdes_5x"),
                         i_D=self.tx_clk_gearbox.o),
                Instance("OBUFDS", i_I=clk_o, o_O=pads.clk_p, o_OB=pads.clk_n)
            ]

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

        serdes_o = Signal()
        self.specials += [
            Instance("OSERDESE3",
                     p_DATA_WIDTH=8,
                     p_INIT=0,
                     p_IS_CLK_INVERTED=0,
                     p_IS_CLKDIV_INVERTED=0,
                     p_IS_RST_INVERTED=0,
                     o_OQ=serdes_o,
                     i_RST=ResetSignal("serwb_serdes"),
                     i_CLK=ClockSignal("serwb_serdes_20x"),
                     i_CLKDIV=ClockSignal("serwb_serdes_5x"),
                     i_D=self.tx_gearbox.o),
            Instance("OBUFDS", i_I=serdes_o, o_O=pads.tx_p, o_OB=pads.tx_n)
        ]

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

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

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

        serdes_i_delayed = Signal()
        serdes_q = Signal(8)
        self.specials += [
            Instance("IDELAYE3",
                     p_CASCADE="NONE",
                     p_UPDATE_MODE="ASYNC",
                     p_REFCLK_FREQUENCY=200.0,
                     p_IS_CLK_INVERTED=0,
                     p_IS_RST_INVERTED=0,
                     p_DELAY_FORMAT="COUNT",
                     p_DELAY_SRC="IDATAIN",
                     p_DELAY_TYPE="VARIABLE",
                     p_DELAY_VALUE=0,
                     i_CLK=ClockSignal("serwb_serdes_5x"),
                     i_RST=rx_delay_rst,
                     i_LOAD=0,
                     i_INC=rx_delay_inc,
                     i_EN_VTC=rx_delay_en_vtc,
                     i_CE=rx_delay_ce,
                     i_IDATAIN=serdes_i_nodelay,
                     o_DATAOUT=serdes_i_delayed),
            Instance("ISERDESE3",
                     p_DATA_WIDTH=8,
                     i_D=serdes_i_delayed,
                     i_RST=ResetSignal("serwb_serdes"),
                     i_FIFO_RD_CLK=0,
                     i_FIFO_RD_EN=0,
                     i_CLK=ClockSignal("serwb_serdes_20x"),
                     i_CLK_B=~ClockSignal("serwb_serdes_20x"),
                     i_CLKDIV=ClockSignal("serwb_serdes_5x"),
                     o_Q=serdes_q)
        ]

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

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

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

        # # #

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

        # clocking:

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

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

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

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

        serdes_o = Signal()
        self.specials += [
            Instance("OSERDESE2",
                     p_DATA_WIDTH=8,
                     p_TRISTATE_WIDTH=1,
                     p_DATA_RATE_OQ="DDR",
                     p_DATA_RATE_TQ="BUF",
                     p_SERDES_MODE="MASTER",
                     o_OQ=serdes_o,
                     i_OCE=1,
                     i_RST=ResetSignal("serwb_serdes"),
                     i_CLK=ClockSignal("serwb_serdes_20x"),
                     i_CLKDIV=ClockSignal("serwb_serdes_5x"),
                     i_D1=self.tx_gearbox.o[0],
                     i_D2=self.tx_gearbox.o[1],
                     i_D3=self.tx_gearbox.o[2],
                     i_D4=self.tx_gearbox.o[3],
                     i_D5=self.tx_gearbox.o[4],
                     i_D6=self.tx_gearbox.o[5],
                     i_D7=self.tx_gearbox.o[6],
                     i_D8=self.tx_gearbox.o[7]),
            Instance("OBUFDS", i_I=serdes_o, o_O=pads.tx_p, o_OB=pads.tx_n)
        ]

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

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

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

        serdes_i_delayed = Signal()
        serdes_q = Signal(8)
        self.specials += [
            Instance("IDELAYE2",
                     p_DELAY_SRC="IDATAIN",
                     p_SIGNAL_PATTERN="DATA",
                     p_CINVCTRL_SEL="FALSE",
                     p_HIGH_PERFORMANCE_MODE="TRUE",
                     p_REFCLK_FREQUENCY=200.0,
                     p_PIPE_SEL="FALSE",
                     p_IDELAY_TYPE="VARIABLE",
                     p_IDELAY_VALUE=0,
                     i_C=ClockSignal(),
                     i_LD=self.rx_delay_rst,
                     i_CE=self.rx_delay_ce,
                     i_LDPIPEEN=0,
                     i_INC=self.rx_delay_inc,
                     i_IDATAIN=serdes_i_nodelay,
                     o_DATAOUT=serdes_i_delayed),
            Instance("ISERDESE2",
                     p_DATA_WIDTH=8,
                     p_DATA_RATE="DDR",
                     p_SERDES_MODE="MASTER",
                     p_INTERFACE_TYPE="NETWORKING",
                     p_NUM_CE=1,
                     p_IOBDELAY="IFD",
                     i_DDLY=serdes_i_delayed,
                     i_CE1=1,
                     i_RST=ResetSignal("serwb_serdes"),
                     i_CLK=ClockSignal("serwb_serdes_20x"),
                     i_CLKB=~ClockSignal("serwb_serdes_20x"),
                     i_CLKDIV=ClockSignal("serwb_serdes_5x"),
                     i_BITSLIP=0,
                     o_Q8=serdes_q[0],
                     o_Q7=serdes_q[1],
                     o_Q6=serdes_q[2],
                     o_Q5=serdes_q[3],
                     o_Q4=serdes_q[4],
                     o_Q3=serdes_q[5],
                     o_Q2=serdes_q[6],
                     o_Q1=serdes_q[7])
        ]

        self.comb += [
            self.rx_gearbox.i.eq(serdes_q),
            self.rx_bitslip.value.eq(rx_bitslip_value),
            self.rx_bitslip.i.eq(self.rx_gearbox.o),
            self.decoders[0].input.eq(self.rx_bitslip.o[0:10]),
            self.decoders[1].input.eq(self.rx_bitslip.o[10:20]),
            self.decoders[2].input.eq(self.rx_bitslip.o[20:30]),
            self.decoders[3].input.eq(self.rx_bitslip.o[30:40]),
            self.rx_data.eq(Cat(*[self.decoders[i].d for i in range(4)])),
            rx_idle.eq(self.rx_bitslip.o == 0),
            rx_comma.eq(
                ((self.decoders[0].d == 0xbc) & (self.decoders[0].k == 1))
                & ((self.decoders[1].d == 0x00) & (self.decoders[1].k == 0))
                & ((self.decoders[2].d == 0x00) & (self.decoders[2].k == 0))
                & ((self.decoders[3].d == 0x00) & (self.decoders[3].k == 0)))
        ]