Beispiel #1
0
    def __init__(self, dram_port, random=True):
        ashift = log2_int(dram_port.dw // 8)
        awidth = dram_port.aw + ashift
        self.reset = CSR()
        self.start = CSR()
        self.base = CSRStorage(awidth)
        self.length = CSRStorage(awidth)
        self.done = CSRStatus()
        self.ticks = CSRStatus(32)
        self.errors = CSRStatus(32)

        # # #

        cd = dram_port.cd

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

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

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

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

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

        errors_sync = BusSynchronizer(32, cd, "sys")
        self.submodules += errors_sync
        self.comb += [
            errors_sync.i.eq(core.errors),
            self.errors.status.eq(errors_sync.o)
        ]
Beispiel #2
0
    def __init__(self, dram_port, random=True):
        self.reset = CSR()
        self.start = CSR()

        self.base = CSRStorage(dram_port.aw)
        self.length = CSRStorage(dram_port.aw)

        self.done = CSRStatus()
        self.err_count = CSRStatus(32)

        # # #

        cd = dram_port.cd

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

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

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

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

        err_count_sync = BusSynchronizer(32, cd, "sys")
        self.submodules += err_count_sync
        self.comb += [
            err_count_sync.i.eq(core.err_count),
            self.err_count.status.eq(err_count_sync.o),
        ]
Beispiel #3
0
    def __init__(self, period_bits=24):
        self.data = Signal(10)
        self._update = CSR()
        self._value = CSRStatus(period_bits)

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

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

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

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

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

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

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

        # register interface
        self.sync += If(self._update.re,
                        self._value.status.eq(wer_counter_sys))
Beispiel #4
0
    def __init__(self, clk_freq):
        self.mode = Signal()
        self._mode = CSRStatus()

        # # #

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

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

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

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

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

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

        fsm.act("IDLE", sys_counter_reset.eq(1),
                If(sys_tick, NextState("COUNT")))
        fsm.act("COUNT", sys_counter_ce.eq(1),
                If(sys_tick, NextState("DETECTION")))
        fsm.act(
            "DETECTION",
            update_mode.eq(1),
            # if freq < 125MHz-5% use MII mode
            If(sys_counter > int((clk_freq / 125000000) * 1024 * 1.05),
               mode.eq(1)
               # if freq >= 125MHz-5% use GMII mode
               ).Else(mode.eq(0)),
            NextState("IDLE"))
Beispiel #5
0
    def __init__(self, idata):
        self.start = Signal()
        self.valid = Signal()
        self.error = Signal()

        # # #

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

        valid = Signal()
        error = Signal()

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

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

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

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

        self.submodules.pulse_valid = PulseSynchronizer("sd_fb", "sd")
        self.submodules.pulse_error = PulseSynchronizer("sd_fb", "sd")
        self.comb += [
            self.pulse_valid.i.eq(valid),
            self.valid.eq(self.pulse_valid.o),
            self.pulse_error.i.eq(error),
            self.error.eq(self.pulse_error.o)
        ]
Beispiel #6
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)
            )
Beispiel #7
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))))
Beispiel #8
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))
        ]
Beispiel #9
0
    def __init__(self, pll, pads, mode="master"):
        self.tx_data = Signal(32)
        self.rx_data = Signal(32)

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

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

        # # #

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

        # clocking:

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

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

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

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

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

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

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

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

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

        self.comb += [
            self.rx_gearbox.i.eq(serdes_q),
            self.rx_bitslip.value.eq(rx_bitslip_value),
            self.rx_bitslip.i.eq(self.rx_gearbox.o),
            self.decoders[0].input.eq(self.rx_bitslip.o[0:10]),
            self.decoders[1].input.eq(self.rx_bitslip.o[10:20]),
            self.decoders[2].input.eq(self.rx_bitslip.o[20:30]),
            self.decoders[3].input.eq(self.rx_bitslip.o[30:40]),
            self.rx_data.eq(Cat(*[self.decoders[i].d for i in range(4)])),
            rx_idle.eq(self.rx_bitslip.o == 0),
            rx_comma.eq(
                ((self.decoders[0].d == 0xbc) & (self.decoders[0].k == 1))
                & ((self.decoders[1].d == 0x00) & (self.decoders[1].k == 0))
                & ((self.decoders[2].d == 0x00) & (self.decoders[2].k == 0))
                & ((self.decoders[3].d == 0x00) & (self.decoders[3].k == 0)))
        ]
Beispiel #10
0
    def __init__(self, phy, dw, endianness="big",
            with_preamble_crc=True,
            with_padding=True):
        if dw < phy.dw:
            raise ValueError("Core data width({}) must be larger than PHY data width({})".format(dw, phy.dw))

        rx_pipeline = [phy]
        tx_pipeline = [phy]

        # Interpacket gap
        tx_gap_inserter = gap.LiteEthMACGap(phy.dw)
        rx_gap_checker = gap.LiteEthMACGap(phy.dw, ack_on_gap=True)
        self.submodules += ClockDomainsRenamer("eth_tx")(tx_gap_inserter)
        self.submodules += ClockDomainsRenamer("eth_rx")(rx_gap_checker)

        tx_pipeline += [tx_gap_inserter]
        rx_pipeline += [rx_gap_checker]

        # Preamble / CRC
        if isinstance(phy, LiteEthPHYModel):
            # In simulation, avoid CRC/Preamble to enable direct connection
            # to the Ethernet tap.
            self._preamble_crc = CSRStatus(reset=1)
        elif with_preamble_crc:
            self._preamble_crc = CSRStatus(reset=1)
            self.crc_errors = CSRStatus(32)

            # Preamble insert/check
            preamble_inserter = preamble.LiteEthMACPreambleInserter(phy.dw)
            preamble_checker = preamble.LiteEthMACPreambleChecker(phy.dw)
            self.submodules += ClockDomainsRenamer("eth_tx")(preamble_inserter)
            self.submodules += ClockDomainsRenamer("eth_rx")(preamble_checker)

            # CRC insert/check
            crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_phy_description(phy.dw))
            crc32_checker = crc.LiteEthMACCRC32Checker(eth_phy_description(phy.dw))
            self.submodules += ClockDomainsRenamer("eth_tx")(crc32_inserter)
            self.submodules += ClockDomainsRenamer("eth_rx")(crc32_checker)

            tx_pipeline += [preamble_inserter, crc32_inserter]
            rx_pipeline += [preamble_checker, crc32_checker]

            # CRC error counter
            self.submodules.ps_crc_error = PulseSynchronizer("eth_rx", "sys")

            self.comb += self.ps_crc_error.i.eq(crc32_checker.crc_error)
            self.sync += [
                If(self.ps_crc_error.o,
                    self.crc_errors.status.eq(self.crc_errors.status + 1))]

        # Padding
        if with_padding:
            padding_inserter = padding.LiteEthMACPaddingInserter(phy.dw, 60)
            padding_checker = padding.LiteEthMACPaddingChecker(phy.dw, 60)
            self.submodules += ClockDomainsRenamer("eth_tx")(padding_inserter)
            self.submodules += ClockDomainsRenamer("eth_rx")(padding_checker)

            tx_pipeline += [padding_inserter]
            rx_pipeline += [padding_checker]

        # Delimiters
        if dw != 8:
            tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw)
            rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw)
            self.submodules += ClockDomainsRenamer("eth_tx")(tx_last_be)
            self.submodules += ClockDomainsRenamer("eth_rx")(rx_last_be)

            tx_pipeline += [tx_last_be]
            rx_pipeline += [rx_last_be]

        # Converters
        if dw != phy.dw:
            reverse = endianness == "big"
            tx_converter = stream.StrideConverter(eth_phy_description(dw),
                                                  eth_phy_description(phy.dw),
                                                 reverse=reverse)
            rx_converter = stream.StrideConverter(eth_phy_description(phy.dw),
                                                  eth_phy_description(dw),
                                                  reverse=reverse)
            self.submodules += ClockDomainsRenamer("eth_tx")(tx_converter)
            self.submodules += ClockDomainsRenamer("eth_rx")(rx_converter)

            tx_pipeline += [tx_converter]
            rx_pipeline += [rx_converter]

        # Cross Domain Crossing
        tx_cdc = stream.AsyncFIFO(eth_phy_description(dw), 64)
        rx_cdc = stream.AsyncFIFO(eth_phy_description(dw), 64)
        self.submodules += ClockDomainsRenamer({"write": "sys", "read": "eth_tx"})(tx_cdc)
        self.submodules += ClockDomainsRenamer({"write": "eth_rx", "read": "sys"})(rx_cdc)

        tx_pipeline += [tx_cdc]
        rx_pipeline += [rx_cdc]

        # Graph
        self.submodules.tx_pipeline = stream.Pipeline(*reversed(tx_pipeline))
        self.submodules.rx_pipeline = stream.Pipeline(*rx_pipeline)

        self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
Beispiel #11
0
 def __init__(self, i, idomain, o, odomain):
     PulseSynchronizer.__init__(self, idomain, odomain)
     self.comb += [
         self.i.eq(i),
         o.eq(self.o)
     ]
Beispiel #12
0
 def __init__(self, i, idomain, o, odomain):
     PulseSynchronizer.__init__(self, idomain, odomain)
     self.comb += [
         self.i.eq(i),
         o.eq(self.o)
     ]
Beispiel #13
0
    def __init__(self, pad_p, pad_n, ntbits=8):
        self.serdesstrobe = Signal()
        self.d = Signal(10)

        self._dly_ctl = CSR(6)
        self._dly_busy = CSRStatus(2)
        self._phase = CSRStatus(2)
        self._phase_reset = CSR()

        # # #

        # IO
        pad_se = Signal()
        self.specials += Instance("IBUFDS", i_I=pad_p, i_IB=pad_n, o_O=pad_se)

        pad_delayed_master = Signal()
        pad_delayed_slave = Signal()
        delay_inc = Signal()
        delay_ce = Signal()
        delay_master_cal = Signal()
        delay_master_rst = Signal()
        delay_master_busy = Signal()
        delay_slave_cal = Signal()
        delay_slave_rst = Signal()
        delay_slave_busy = Signal()
        self.specials += [
            Instance("IODELAY2",
                     p_SERDES_MODE="MASTER",
                     p_DELAY_SRC="IDATAIN",
                     p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
                     p_COUNTER_WRAPAROUND="STAY_AT_LIMIT",
                     p_DATA_RATE="SDR",
                     i_IDATAIN=pad_se,
                     o_DATAOUT=pad_delayed_master,
                     i_CLK=ClockSignal("pix2x"),
                     i_IOCLK0=ClockSignal("pix10x"),
                     i_INC=delay_inc,
                     i_CE=delay_ce,
                     i_CAL=delay_master_cal,
                     i_RST=delay_master_rst,
                     o_BUSY=delay_master_busy,
                     i_T=1),
            Instance("IODELAY2",
                     p_SERDES_MODE="SLAVE",
                     p_DELAY_SRC="IDATAIN",
                     p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
                     p_COUNTER_WRAPAROUND="WRAPAROUND",
                     p_DATA_RATE="SDR",
                     i_IDATAIN=pad_se,
                     o_DATAOUT=pad_delayed_slave,
                     i_CLK=ClockSignal("pix2x"),
                     i_IOCLK0=ClockSignal("pix10x"),
                     i_INC=delay_inc,
                     i_CE=delay_ce,
                     i_CAL=delay_slave_cal,
                     i_RST=delay_slave_rst,
                     o_BUSY=delay_slave_busy,
                     i_T=1)
        ]

        dsr2 = Signal(5)
        pd_valid = Signal()
        pd_incdec = Signal()
        pd_edge = Signal()
        pd_cascade = Signal()
        self.specials += [
            Instance("ISERDES2",
                     p_SERDES_MODE="MASTER",
                     p_BITSLIP_ENABLE="FALSE",
                     p_DATA_RATE="SDR",
                     p_DATA_WIDTH=5,
                     p_INTERFACE_TYPE="RETIMED",
                     i_D=pad_delayed_master,
                     o_Q4=dsr2[4],
                     o_Q3=dsr2[3],
                     o_Q2=dsr2[2],
                     o_Q1=dsr2[1],
                     i_BITSLIP=0,
                     i_CE0=1,
                     i_RST=0,
                     i_CLK0=ClockSignal("pix10x"),
                     i_CLKDIV=ClockSignal("pix2x"),
                     i_IOCE=self.serdesstrobe,
                     o_VALID=pd_valid,
                     o_INCDEC=pd_incdec,
                     i_SHIFTIN=pd_edge,
                     o_SHIFTOUT=pd_cascade),
            Instance("ISERDES2",
                     p_SERDES_MODE="SLAVE",
                     p_BITSLIP_ENABLE="FALSE",
                     p_DATA_RATE="SDR",
                     p_DATA_WIDTH=5,
                     p_INTERFACE_TYPE="RETIMED",
                     i_D=pad_delayed_slave,
                     o_Q4=dsr2[0],
                     i_BITSLIP=0,
                     i_CE0=1,
                     i_RST=0,
                     i_CLK0=ClockSignal("pix10x"),
                     i_CLKDIV=ClockSignal("pix2x"),
                     i_IOCE=self.serdesstrobe,
                     i_SHIFTIN=pd_cascade,
                     o_SHIFTOUT=pd_edge)
        ]

        # Phase error accumulator
        lateness = Signal(ntbits, reset=2**(ntbits - 1))
        too_late = Signal()
        too_early = Signal()
        reset_lateness = Signal()
        self.comb += [
            too_late.eq(lateness == (2**ntbits - 1)),
            too_early.eq(lateness == 0)
        ]
        self.sync.pix2x += [
            If(reset_lateness, lateness.eq(2**(ntbits - 1))).Elif(
                ~delay_master_busy & ~delay_slave_busy & ~too_late
                & ~too_early,
                If(pd_valid & pd_incdec, lateness.eq(lateness - 1)),
                If(pd_valid & ~pd_incdec, lateness.eq(lateness + 1)))
        ]

        # Delay control
        self.submodules.delay_master_done = PulseSynchronizer("pix2x", "sys")
        delay_master_pending = Signal()
        self.sync.pix2x += [
            self.delay_master_done.i.eq(0),
            If(~delay_master_pending,
               If(delay_master_cal | delay_ce,
                  delay_master_pending.eq(1))).Else(
                      If(~delay_master_busy, self.delay_master_done.i.eq(1),
                         delay_master_pending.eq(0)))
        ]
        self.submodules.delay_slave_done = PulseSynchronizer("pix2x", "sys")
        delay_slave_pending = Signal()
        self.sync.pix2x += [
            self.delay_slave_done.i.eq(0),
            If(~delay_slave_pending,
               If(delay_slave_cal | delay_ce, delay_slave_pending.eq(1))).Else(
                   If(~delay_slave_busy, self.delay_slave_done.i.eq(1),
                      delay_slave_pending.eq(0)))
        ]

        self.submodules.do_delay_master_cal = PulseSynchronizer("sys", "pix2x")
        self.submodules.do_delay_master_rst = PulseSynchronizer("sys", "pix2x")
        self.submodules.do_delay_slave_cal = PulseSynchronizer("sys", "pix2x")
        self.submodules.do_delay_slave_rst = PulseSynchronizer("sys", "pix2x")
        self.submodules.do_delay_inc = PulseSynchronizer("sys", "pix2x")
        self.submodules.do_delay_dec = PulseSynchronizer("sys", "pix2x")
        self.comb += [
            delay_master_cal.eq(self.do_delay_master_cal.o),
            delay_master_rst.eq(self.do_delay_master_rst.o),
            delay_slave_cal.eq(self.do_delay_slave_cal.o),
            delay_slave_rst.eq(self.do_delay_slave_rst.o),
            delay_inc.eq(self.do_delay_inc.o),
            delay_ce.eq(self.do_delay_inc.o | self.do_delay_dec.o),
        ]

        sys_delay_master_pending = Signal()
        self.sync += [
            If(
                self.do_delay_master_cal.i | self.do_delay_inc.i
                | self.do_delay_dec.i, sys_delay_master_pending.eq(1)).Elif(
                    self.delay_master_done.o, sys_delay_master_pending.eq(0))
        ]
        sys_delay_slave_pending = Signal()
        self.sync += [
            If(
                self.do_delay_slave_cal.i | self.do_delay_inc.i
                | self.do_delay_dec.i, sys_delay_slave_pending.eq(1)).Elif(
                    self.delay_slave_done.o, sys_delay_slave_pending.eq(0))
        ]

        self.comb += [
            self.do_delay_master_cal.i.eq(self._dly_ctl.re
                                          & self._dly_ctl.r[0]),
            self.do_delay_master_rst.i.eq(self._dly_ctl.re
                                          & self._dly_ctl.r[1]),
            self.do_delay_slave_cal.i.eq(self._dly_ctl.re
                                         & self._dly_ctl.r[2]),
            self.do_delay_slave_rst.i.eq(self._dly_ctl.re
                                         & self._dly_ctl.r[3]),
            self.do_delay_inc.i.eq(self._dly_ctl.re & self._dly_ctl.r[4]),
            self.do_delay_dec.i.eq(self._dly_ctl.re & self._dly_ctl.r[5]),
            self._dly_busy.status.eq(
                Cat(sys_delay_master_pending, sys_delay_slave_pending))
        ]

        # Phase detector control
        self.specials += MultiReg(Cat(too_late, too_early), self._phase.status)
        self.submodules.do_reset_lateness = PulseSynchronizer("sys", "pix2x")
        self.comb += [
            reset_lateness.eq(self.do_reset_lateness.o),
            self.do_reset_lateness.i.eq(self._phase_reset.re)
        ]

        # 5:10 deserialization
        dsr = Signal(10)
        self.sync.pix2x += dsr.eq(Cat(dsr[5:], dsr2))
        if hasattr(pad_p, "inverted"):
            self.sync.pix += self.d.eq(~dsr)
        else:
            self.sync.pix += self.d.eq(dsr)
Beispiel #14
0
    def __init__(self, pad_p, pad_n, ntbits=8):
        self.d = Signal(10)

        self._dly_ctl = CSR(5)
        self._phase = CSRStatus(2)
        self._phase_reset = CSR()

        # # #

        # use 2 serdes for phase detection: master & slave
        serdes_m_i_nodelay = Signal()
        serdes_s_i_nodelay = Signal()
        self.specials += [
            Instance(
                "IBUFDS_DIFF_OUT",
                i_I=pad_p,
                i_IB=pad_n,
                o_O=serdes_m_i_nodelay,
                o_OB=serdes_s_i_nodelay,
            )
        ]

        delay_rst = Signal()
        delay_master_inc = Signal()
        delay_master_ce = Signal()
        delay_slave_inc = Signal()
        delay_slave_ce = Signal()

        # master serdes
        serdes_m_i_delayed = Signal()
        serdes_m_q = Signal(8)
        serdes_m_d = 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("pix1p25x"),
                     i_LD=delay_rst,
                     i_CE=delay_master_ce,
                     i_LDPIPEEN=0,
                     i_INC=delay_master_inc,
                     i_IDATAIN=serdes_m_i_nodelay,
                     o_DATAOUT=serdes_m_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_m_i_delayed,
                     i_CE1=1,
                     i_RST=ResetSignal("pix1p25x"),
                     i_CLK=ClockSignal("pix5x"),
                     i_CLKB=~ClockSignal("pix5x"),
                     i_CLKDIV=ClockSignal("pix1p25x"),
                     i_BITSLIP=0,
                     o_Q8=serdes_m_q[0],
                     o_Q7=serdes_m_q[1],
                     o_Q6=serdes_m_q[2],
                     o_Q5=serdes_m_q[3],
                     o_Q4=serdes_m_q[4],
                     o_Q3=serdes_m_q[5],
                     o_Q2=serdes_m_q[6],
                     o_Q1=serdes_m_q[7]),
        ]

        # slave serdes
        # idelay_value must be preloaded with a 90° phase shift but we
        # do it dynamically by software to support all resolutions
        serdes_s_i_delayed = Signal()
        serdes_s_q = Signal(8)
        serdes_s_d = 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("pix1p25x"),
                     i_LD=delay_rst,
                     i_CE=delay_slave_ce,
                     i_LDPIPEEN=0,
                     i_INC=delay_slave_inc,
                     i_IDATAIN=serdes_s_i_nodelay,
                     o_DATAOUT=serdes_s_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_s_i_delayed,
                     i_CE1=1,
                     i_RST=ResetSignal("pix1p25x"),
                     i_CLK=ClockSignal("pix5x"),
                     i_CLKB=~ClockSignal("pix5x"),
                     i_CLKDIV=ClockSignal("pix1p25x"),
                     i_BITSLIP=0,
                     o_Q8=serdes_s_q[0],
                     o_Q7=serdes_s_q[1],
                     o_Q6=serdes_s_q[2],
                     o_Q5=serdes_s_q[3],
                     o_Q4=serdes_s_q[4],
                     o_Q3=serdes_s_q[5],
                     o_Q2=serdes_s_q[6],
                     o_Q1=serdes_s_q[7]),
        ]

        # polarity
        if hasattr(pad_p, "inverted"):
            self.comb += [
                serdes_m_d.eq(~serdes_m_q),
                serdes_s_d.eq(serdes_s_q)
            ]
        else:
            self.comb += [
                serdes_m_d.eq(serdes_m_q),
                serdes_s_d.eq(~serdes_s_q)
            ]

        # datapath
        self.submodules.gearbox = Gearbox(8, "pix1p25x", 10, "pix")
        self.comb += [self.gearbox.i.eq(serdes_m_d), self.d.eq(self.gearbox.o)]

        # phase detector
        self.submodules.phase_detector = ClockDomainsRenamer("pix1p25x")(
            S7PhaseDetector())
        self.comb += [
            self.phase_detector.mdata.eq(serdes_m_d),
            self.phase_detector.sdata.eq(serdes_s_d)
        ]

        # phase error accumulator
        lateness = Signal(ntbits, reset=2**(ntbits - 1))
        too_late = Signal()
        too_early = Signal()
        reset_lateness = Signal()
        self.comb += [
            too_late.eq(lateness == (2**ntbits - 1)),
            too_early.eq(lateness == 0)
        ]
        self.sync.pix1p25x += [
            If(reset_lateness, lateness.eq(2**(ntbits - 1))).Elif(
                ~too_late & ~too_early,
                If(self.phase_detector.dec, lateness.eq(lateness + 1)),
                If(self.phase_detector.inc, lateness.eq(lateness - 1)))
        ]

        # delay control
        self.submodules.do_delay_rst = PulseSynchronizer("sys", "pix1p25x")
        self.submodules.do_delay_master_inc = PulseSynchronizer(
            "sys", "pix1p25x")
        self.submodules.do_delay_master_dec = PulseSynchronizer(
            "sys", "pix1p25x")
        self.submodules.do_delay_slave_inc = PulseSynchronizer(
            "sys", "pix1p25x")
        self.submodules.do_delay_slave_dec = PulseSynchronizer(
            "sys", "pix1p25x")
        self.comb += [
            delay_rst.eq(self.do_delay_rst.o),
            delay_master_inc.eq(self.do_delay_master_inc.o),
            delay_master_ce.eq(self.do_delay_master_inc.o
                               | self.do_delay_master_dec.o),
            delay_slave_inc.eq(self.do_delay_slave_inc.o),
            delay_slave_ce.eq(self.do_delay_slave_inc.o
                              | self.do_delay_slave_dec.o)
        ]

        self.comb += [
            self.do_delay_rst.i.eq(self._dly_ctl.re & self._dly_ctl.r[0]),
            self.do_delay_master_inc.i.eq(self._dly_ctl.re
                                          & self._dly_ctl.r[1]),
            self.do_delay_master_dec.i.eq(self._dly_ctl.re
                                          & self._dly_ctl.r[2]),
            self.do_delay_slave_inc.i.eq(self._dly_ctl.re
                                         & self._dly_ctl.r[3]),
            self.do_delay_slave_dec.i.eq(self._dly_ctl.re & self._dly_ctl.r[4])
        ]

        # phase detector control
        self.specials += MultiReg(Cat(too_late, too_early), self._phase.status)
        self.submodules.do_reset_lateness = PulseSynchronizer(
            "sys", "pix1p25x")
        self.comb += [
            reset_lateness.eq(self.do_reset_lateness.o),
            self.do_reset_lateness.i.eq(self._phase_reset.re)
        ]
Beispiel #15
0
    def __init__(self, comma, tx_clk_freq, check_period=6e-3):
        self.rxdata = Signal(20)
        self.restart = Signal()

        self.ready = Signal()

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

        checks_reset = PulseSynchronizer("rtio_tx", "rtio_rx")
        self.submodules += checks_reset

        comma_n = ~comma & 0b1111111111
        comma_seen_rxclk = Signal()
        comma_seen = Signal()
        comma_seen_rxclk.attr.add("no_retiming")
        self.specials += MultiReg(comma_seen_rxclk, comma_seen)
        self.sync.rtio_rx += \
            If(checks_reset.o,
                comma_seen_rxclk.eq(0)
            ).Elif((self.rxdata[:10] == comma) | (self.rxdata[:10] == comma_n),
                comma_seen_rxclk.eq(1)
            )

        error_seen_rxclk = Signal()
        error_seen = Signal()
        error_seen_rxclk.attr.add("no_retiming")
        self.specials += MultiReg(error_seen_rxclk, error_seen)
        rx1cnt = Signal(max=11)
        self.sync.rtio_rx += [
            rx1cnt.eq(reduce(add, [self.rxdata[i] for i in range(10)])),
            If(checks_reset.o, error_seen_rxclk.eq(0)).Elif(
                (rx1cnt != 4) & (rx1cnt != 5) & (rx1cnt != 6),
                error_seen_rxclk.eq(1))
        ]

        fsm = ClockDomainsRenamer("rtio_tx")(FSM(reset_state="WAIT_COMMA"))
        self.submodules += fsm

        fsm.act(
            "WAIT_COMMA",
            If(
                check,
                # Errors are still OK at this stage, as the transceiver
                # has just been reset and may output garbage data.
                If(comma_seen,
                   NextState("WAIT_NOERROR")).Else(self.restart.eq(1)),
                checks_reset.i.eq(1)))
        fsm.act(
            "WAIT_NOERROR",
            If(
                check,
                If(comma_seen & ~error_seen,
                   NextState("READY")).Else(self.restart.eq(1),
                                            NextState("WAIT_COMMA")),
                checks_reset.i.eq(1)))
        fsm.act(
            "READY", reset_check_counter.eq(1), self.ready.eq(1),
            If(error_seen, checks_reset.i.eq(1), self.restart.eq(1),
               NextState("WAIT_COMMA")))