Ejemplo n.º 1
0
    def elaborate(self, platform):
        pins = self.pins
        leds = self.leds
        mode = self.mode
        count = self.count

        m = Module()

        m.domains += ClockDomain("clk100")
        m.d.comb += ClockSignal(domain="clk100").eq(pins.clk)

        fifo_width = 16
        depth = 1024 * 2 + 1

        m.submodules.fifo_rx = fifo_rx = AsyncFIFOBuffered(
            width=fifo_width,
            depth=depth,
            exact_depth=True,
            w_domain="clk100",
            r_domain="clk100",
        )

        m.submodules.fifo_tx = fifo_tx = AsyncFIFOBuffered(
            width=fifo_width,
            depth=depth,
            exact_depth=True,
            w_domain="clk100",
            r_domain="clk100",
        )

        debug = leds[-3:]
        m.submodules.ft600 = DomainRenamer("clk100")(FT600(
            pins, fifo_rx, fifo_tx, debug))

        if mode == SOURCE:
            # Test TX only
            counter = Signal(SOURCE_COUNTER_BITS)
            with m.If(fifo_tx.w_rdy):
                m.d.comb += [
                    fifo_tx.w_data.eq(Cat(counter[8:], counter[:8])),
                    fifo_tx.w_en.eq(1),
                ]
                m.d.clk100 += counter.eq(counter + 1)
        elif mode == SINK:
            # Test RX only
            counter = Signal(32)
            m.d.comb += fifo_rx.r_en.eq(counter == 0)

            with m.If(counter == count):
                m.d.clk100 += counter.eq(0)
            with m.Else():
                m.d.clk100 += counter.eq(counter + 1)
        elif mode == LOOPBACK:
            # Loopback
            m.d.comb += fifo_tx.w_data.eq(fifo_rx.r_data),
            with m.If(fifo_tx.w_rdy & fifo_rx.r_rdy):
                m.d.comb += fifo_tx.w_en.eq(1)
                m.d.comb += fifo_rx.r_en.eq(1)

        return m
Ejemplo n.º 2
0
        def elaborate(self, platform: Platform) -> Module:
            m = Module()

            # Setup two clock domains
            m.submodules.pll = pll = Ecp5Pll(
                platform.default_clk_frequency,
                [
                    PllClock(dvi_mode.pixel_clock * 5,
                             error_weight=100.0,
                             tolerance=0.01),  # TMDS 2 bits
                    PllClock(dvi_mode.pixel_clock,
                             tolerance=(1e-20, 1.0)),  # Pixel clock
                ])

            m.domains.tmds_2bit = ClockDomain("tmds_2bit")
            m.domains.pixel = ClockDomain("pixel")
            m.d.comb += [
                pll.i_clk.eq(ClockSignal()),
                ClockSignal("tmds_2bit").eq(pll.o_clk[0]),
                ClockSignal("pixel").eq(pll.o_clk[1]),
            ]

            use_fifo = True

            if use_fifo:
                m.submodules.fifo = fifo = \
                    AsyncFIFOBuffered(width=3*10, depth=4, r_domain="tmds_2bit", w_domain="pixel")

                m.submodules.pixel_gen = pixel_gen = \
                    DomainRenamer("pixel")(EnableInserter(fifo.w_rdy)(PixelGenerator()))
            else:
                m.submodules.pixel_gen = pixel_gen = \
                    DomainRenamer("pixel")(PixelGenerator())

            m.submodules.tmds_shifter = tmds_shifter = \
                DomainRenamer("tmds_2bit")(TmdsShifter())

            hdmi = platform.request("hdmi")

            if use_fifo:
                m.d.comb += [
                    tmds_shifter.i_packed.eq(fifo.r_data),
                    hdmi.d.eq(tmds_shifter.o_data),
                    hdmi.clk.eq(tmds_shifter.o_clk),
                    fifo.r_en.eq(tmds_shifter.o_read),
                    fifo.w_data.eq(pixel_gen.o_packed),
                    fifo.w_en.eq(1),
                ]
            else:
                m.d.pixel += tmds_shifter.i_packed.eq(pixel_gen.o_packed),
                m.d.comb += [
                    hdmi.d.eq(tmds_shifter.o_data),
                    hdmi.clk.eq(tmds_shifter.o_clk),
                ]

            return m
Ejemplo n.º 3
0
 def __init__(self, data_width):
     # instantiate submodules
     self.producer = DomainRenamer("producer")\
         (Producer(data_width))
     self.consumer = DomainRenamer("consumer")\
         (Consumer(data_width))
     self.fifo = AsyncFIFOBuffered(width=data_width,
                                   depth=data_width,
                                   w_domain="producer",
                                   r_domain="consumer")
Ejemplo n.º 4
0
    def elaborate(self, platform: Platform):
        led1 = platform.request("led", 0)
        led2 = platform.request("led", 1)
        led3 = platform.request("led", 2)
        led4 = platform.request("led", 3)

        ft600_resource = platform.request("ft600")

        m = Module()

        # Connect pseudo power pins for the FT600 and DDR3 banks
        pseudo_power = platform.request("pseudo_power")
        m.d.comb += pseudo_power.ddr.o.eq(Repl(1, len(pseudo_power.ddr)))
        m.d.comb += pseudo_power.ft.o.eq(Repl(1, len(pseudo_power.ft)))

        m.submodules.pll = ECP5PLL(clock_signal_name="pll_clk25",
                                   clock_config=[
                                       ECP5PLLConfig("sync", 25),
                                   ])

        m.domains += ClockDomain("ft600")
        m.d.comb += ClockSignal("ft600").eq(ft600_resource.clk)

        m.submodules.ft600 = ft600 = DomainRenamer("ft600")(FT600(
            ft600_resource, ))

        m.submodules.fifo = fifo = AsyncFIFOBuffered(width=16,
                                                     depth=2048,
                                                     r_domain="ft600",
                                                     w_domain="sync")

        # FT to Write FIFO
        m.d.comb += ft600.input_payload.eq(fifo.r_data)
        m.d.comb += fifo.r_en.eq(ft600.input_ready)
        m.d.comb += ft600.input_valid.eq(fifo.r_rdy)

        # Write data into FIFO
        m.d.comb += fifo.w_data.eq(0xABCD)
        m.d.comb += fifo.w_en.eq(1)

        led_counter = Signal(10)

        with m.If(fifo.w_rdy):
            m.d.sync += led_counter.eq(led_counter + 1)

        # Connect LEDs
        m.d.comb += led1.o.eq(ft600_resource.write)
        m.d.comb += led2.o.eq(ft600_resource.txe)
        m.d.comb += led3.o.eq(fifo.w_level > 2000)
        m.d.comb += led4.o.eq(led_counter[-1])

        return m
Ejemplo n.º 5
0
    def elaborate(self, platform):
        m = Module()

        width_in = self.width_in
        width_out = self.width_out
        depth = self.depth
        domain_in = self.domain_in
        domain_out = self.domain_out

        data_in = self.data_in
        data_out = self.data_out

        ctr_in = self.ctr_in
        ctr_out = self.ctr_out

        fifo_width = width_in * width_out

        fifo_data_in = Signal(fifo_width)
        fifo_data_out = Signal(fifo_width)

        m.submodules.fifo = fifo = AsyncFIFOBuffered(
            width=fifo_width,
            depth=depth,
            exact_depth=True,
            w_domain=domain_in,
            r_domain=domain_out,
        )

        with m.If(ctr_in == (width_out - 1)):
            m.d[domain_in] += ctr_in.eq(0)
        with m.Else():
            m.d[domain_in] += ctr_in.eq(ctr_in + 1)

        with m.If(ctr_out == (width_in - 1)):
            m.d[domain_out] += ctr_out.eq(0)
        with m.Else():
            m.d[domain_out] += ctr_out.eq(ctr_out + 1)

        m.d.comb += fifo.w_data.eq(fifo_data_in)
        m.d[domain_in] += fifo.w_en.eq(fifo.w_rdy & (ctr_in == (width_out - 1)))
        m.d[domain_in] += fifo_data_in.eq(Cat(fifo_data_in[width_in:], data_in))

        m.d[domain_out] += fifo.r_en.eq(fifo.r_rdy & (ctr_out == (width_in - 1)))
        with m.If(ctr_out == 0):
            m.d[domain_out] += fifo_data_out.eq(fifo.r_data)
        with m.Else():
            m.d[domain_out] += fifo_data_out.eq(fifo_data_out[width_out:])

        m.d.comb += data_out.eq(fifo_data_out[:width_out])

        return m
Ejemplo n.º 6
0
        def elaborate(self, platform: Platform) -> Module:
            m = Module()

            m.submodules.plla = plla = Ecp5Pll(platform.default_clk_frequency, [
                PllClock(100.0*MHz, error_weight=10.0), # 100MHz helper clock for accurate shift clock
                PllClock(dvi_mode.pixel_clock, tolerance=(1e-20, 0.1)), # Pixel clock
            ])

            m.submodules.pllb = pllb = Ecp5Pll(plla.config.clko_hzs[0], [
                PllClock(dvi_mode.pixel_clock * 5, tolerance=0.001), # TMDS 2 bits per clock
            ])

            m.submodules.div = div = Ecp5ClockDiv2(pllb.config.clko_hzs[0])

            m.domains.tmds_eclk = ClockDomain("tmds_eclk")
            m.domains.tmds_sclk = ClockDomain("tmds_sclk")
            m.domains.pixel = ClockDomain("pixel")
            m.d.comb += [
                plla.i_clk.eq(ClockSignal()),
                pllb.i_clk.eq(plla.o_clk[0]),
                div.i.eq(pllb.o_clk[0]),
                ClockSignal("pixel").eq(plla.o_clk[1]),
                ClockSignal("tmds_eclk").eq(pllb.o_clk[0]),
                ClockSignal("tmds_sclk").eq(div.o),
            ]

            m.submodules.fifo = fifo = \
                AsyncFIFOBuffered(width=3*10, depth=4, r_domain="tmds_sclk", w_domain="pixel")

            m.submodules.pixel_gen = pixel_gen = \
                DomainRenamer("pixel")(EnableInserter(fifo.w_rdy)(PixelGenerator()))

            m.submodules.tmds_shifter = tmds_shifter = \
                DomainRenamer({ "eclk": "tmds_eclk", "sclk": "tmds_sclk" })(TmdsShifter())

            hdmi = platform.request("hdmi")

            m.d.comb += [
                tmds_shifter.i_packed.eq(fifo.r_data),
                hdmi.d.eq(tmds_shifter.o_data),
                hdmi.clk.eq(tmds_shifter.o_clk),
                fifo.r_en.eq(tmds_shifter.o_read),
                fifo.w_data.eq(pixel_gen.o_packed),
                fifo.w_en.eq(1),
            ]

            return m
Ejemplo n.º 7
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        # Do TX CDC
        # FFSynchronizer
        if False:
            m.submodules += FFSynchronizer(Cat(self.tx_symbol, self.tx_set_disp, self.tx_disp, self.tx_e_idle), Cat(self.__lane.tx_symbol, self.__lane.tx_set_disp, self.__lane.tx_disp, self.__lane.tx_e_idle), o_domain="tx", stages=4)
        
        # No CDC
        if False:
            m.d.comb += Cat(self.__lane.tx_symbol, self.__lane.tx_set_disp, self.__lane.tx_disp, self.__lane.tx_e_idle).eq(
                Cat(self.tx_symbol, self.tx_set_disp, self.tx_disp, self.tx_e_idle))

        # AsyncFIFOBuffered
        if True:
            tx_fifo = m.submodules.tx_fifo = AsyncFIFOBuffered(width=24, depth=10, r_domain="tx", w_domain="rx")
            m.d.comb += tx_fifo.w_data.eq(Cat(self.tx_symbol, self.tx_set_disp, self.tx_disp, self.tx_e_idle))
            m.d.comb += Cat(self.__lane.tx_symbol, self.__lane.tx_set_disp, self.__lane.tx_disp, self.__lane.tx_e_idle).eq(tx_fifo.r_data)
            m.d.comb += tx_fifo.r_en.eq(1)
            m.d.comb += tx_fifo.w_en.eq(1)

        # Testing symbols
        if False:
            m.d.comb += self.__lane.tx_symbol.eq(Cat(Ctrl.COM, D(10, 2)))


        self.slip = SymbolSlip(symbol_size=10, word_size=self.__lane.ratio, comma=Cat(Ctrl.COM, 1))
        m.submodules += self.slip
        
        m.d.comb += [
            self.slip.en.eq(self.rx_align),
            self.slip.i.eq(Cat(
                (self.__lane.rx_symbol.word_select(n, 9), self.__lane.rx_valid[n])
                for n in range(self.__lane.ratio)
            )),
            self.rx_symbol.eq(Cat(
                Part(self.slip.o, 10 * n, 9)
                for n in range(self.__lane.ratio)
            )),
            self.rx_valid.eq(Cat(
                self.slip.o[10 * n + 9]
                for n in range(self.__lane.ratio)
            )),
        ]
        return m
Ejemplo n.º 8
0
    def elaborate(self, platform: Platform):
        led1 = platform.request("led", 0)
        led4 = platform.request("led", 3)

        timer1 = Signal(25)
        fifo_buf = Signal(16)

        m = Module()

        # Connect pseudo power pins for the FT600 and DDR3 banks
        pseudo_power = platform.request("pseudo_power")
        m.d.comb += pseudo_power.ddr.o.eq(Repl(1, len(pseudo_power.ddr)))
        m.d.comb += pseudo_power.ft.o.eq(Repl(1, len(pseudo_power.ft)))

        m.submodules.pll = ECP5PLL(clock_signal_name="pll_clk25",
                                   clock_config=[
                                       ECP5PLLConfig("sync", 25),
                                       ECP5PLLConfig("fast", 100, error=0),
                                       ECP5PLLConfig("fast2", 100, error=0),
                                       ECP5PLLConfig("fast3", 150, error=0),
                                   ])

        m.submodules.fifo = fifo = AsyncFIFOBuffered(width=16,
                                                     depth=1024,
                                                     r_domain="fast",
                                                     w_domain="sync")

        # Write the FIFO using the timer data
        m.d.sync += timer1.eq(timer1 + 1)
        with m.If(fifo.w_rdy):
            m.d.comb += fifo.w_data.eq(timer1[9:25])
        m.d.comb += fifo.w_en.eq(1)

        # Read the FIFO in the `fast` domain, the LEDs should blink at the same time
        with m.If(fifo.r_rdy):
            m.d.fast += fifo_buf.eq(fifo.r_data)

        m.d.comb += fifo.r_en.eq(1)

        # Combinatorial logic
        m.d.comb += led1.o.eq(timer1[-1])
        m.d.comb += led4.o.eq(fifo_buf[-1])

        return m
Ejemplo n.º 9
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        m.submodules.serdes = serdes = LatticeECP5PCIeSERDES(1)
        m.submodules += self.lane

        m.domains.rxf = ClockDomain()
        m.domains.txf = ClockDomain()
        m.d.comb += [
            #ClockSignal("sync").eq(serdes.refclk),
            ClockSignal("rxf").eq(serdes.rx_clk),
            ClockSignal("txf").eq(serdes.tx_clk),
        ]

        platform.add_clock_constraint(
            self.rx_clk, 125e6
        )  # For NextPNR, set the maximum clock frequency such that errors are given
        platform.add_clock_constraint(self.tx_clk, 125e6)

        m.submodules.lane = lane = PCIeSERDESInterface(2)

        self.lane.frequency = int(125e6)

        # IF SOMETHING IS BROKE: Check if the TX actually transmits good data and not order-swapped data
        m.d.rxf += self.rx_clk.eq(~self.rx_clk)
        with m.If(~self.rx_clk):
            m.d.rxf += lane.rx_symbol[9:18].eq(serdes.lane.rx_symbol)
            m.d.rxf += lane.rx_valid[1].eq(serdes.lane.rx_valid)
        with m.Else():
            m.d.rxf += lane.rx_symbol[0:9].eq(serdes.lane.rx_symbol)
            m.d.rxf += lane.rx_valid[0].eq(serdes.lane.rx_valid)

            # To ensure that it outputs consistent data
            # m.d.rxf += self.lane.rx_symbol.eq(lane.rx_symbol)
            # m.d.rxf += self.lane.rx_valid.eq(lane.rx_valid)

        m.d.txf += self.tx_clk.eq(~self.tx_clk)
        # Do NOT add an invert here! It works, checked with x1 gearing. If you do, a "COM SKP SKP SKP" will turn into a "SKP COM SKP SKP"
        #with m.If(self.tx_clk):
        #    m.d.txf += serdes.lane.tx_symbol    .eq(lane.tx_symbol[9:18])
        #    m.d.txf += serdes.lane.tx_disp      .eq(lane.tx_disp[1])
        #    m.d.txf += serdes.lane.tx_set_disp  .eq(lane.tx_set_disp[1])
        #    m.d.txf += serdes.lane.tx_e_idle    .eq(lane.tx_e_idle[1])
        #with m.Else():
        #    m.d.txf += serdes.lane.tx_symbol    .eq(lane.tx_symbol[0:9])
        #    m.d.txf += serdes.lane.tx_disp      .eq(lane.tx_disp[0])
        #    m.d.txf += serdes.lane.tx_set_disp  .eq(lane.tx_set_disp[0])
        #    m.d.txf += serdes.lane.tx_e_idle    .eq(lane.tx_e_idle[0])

        # To ensure that it inputs consistent data
        # m.d.rxf += lane.tx_symbol.eq(self.lane.tx_symbol)
        # m.d.rxf += lane.tx_disp.eq(self.lane.tx_disp)
        # m.d.rxf += lane.tx_set_disp.eq(self.lane.tx_set_disp)
        # m.d.rxf += lane.tx_e_idle.eq(self.lane.tx_e_idle)

        m.d.txf += serdes.lane.tx_symbol.eq(
            Mux(self.tx_clk, lane.tx_symbol[9:18], lane.tx_symbol[0:9]))
        m.d.txf += serdes.lane.tx_disp.eq(
            Mux(self.tx_clk, lane.tx_disp[1], lane.tx_disp[0]))
        m.d.txf += serdes.lane.tx_set_disp.eq(
            Mux(self.tx_clk, lane.tx_set_disp[1], lane.tx_set_disp[0]))
        m.d.txf += serdes.lane.tx_e_idle.eq(
            Mux(self.tx_clk, lane.tx_e_idle[1], lane.tx_e_idle[0]))

        # CDC
        rx_fifo = m.submodules.rx_fifo = AsyncFIFOBuffered(width=20,
                                                           depth=4,
                                                           r_domain="rx",
                                                           w_domain="rxf")
        m.d.rxf += rx_fifo.w_data.eq(Cat(lane.rx_symbol, lane.rx_valid))
        m.d.comb += Cat(self.lane.rx_symbol,
                        self.lane.rx_valid).eq(rx_fifo.r_data)
        m.d.comb += rx_fifo.r_en.eq(1)
        m.d.rxf += rx_fifo.w_en.eq(self.rx_clk)

        tx_fifo = m.submodules.tx_fifo = AsyncFIFOBuffered(width=24,
                                                           depth=4,
                                                           r_domain="txf",
                                                           w_domain="tx")
        m.d.comb += tx_fifo.w_data.eq(
            Cat(self.lane.tx_symbol, self.lane.tx_set_disp, self.lane.tx_disp,
                self.lane.tx_e_idle))
        m.d.txf += Cat(lane.tx_symbol, lane.tx_set_disp, lane.tx_disp,
                       lane.tx_e_idle).eq(tx_fifo.r_data)
        m.d.txf += tx_fifo.r_en.eq(self.tx_clk)
        m.d.comb += tx_fifo.w_en.eq(1)
        #m.d.txf  += Cat(lane.tx_symbol, lane.tx_set_disp, lane.tx_disp, lane.tx_e_idle).eq(Cat(self.lane.tx_symbol, self.lane.tx_set_disp, self.lane.tx_disp, self.lane.tx_e_idle))

        serdes.lane.rx_invert = self.lane.rx_invert
        serdes.lane.rx_align = self.lane.rx_align
        serdes.lane.rx_aligned = self.lane.rx_aligned
        serdes.lane.rx_locked = self.lane.rx_locked
        serdes.lane.rx_present = self.lane.rx_present

        serdes.lane.det_enable = self.lane.det_enable
        serdes.lane.det_valid = self.lane.det_valid
        serdes.lane.det_status = self.lane.det_status
        serdes.slip = self.slip

        return m
Ejemplo n.º 10
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        uart = self.uart
        words = self.words
        depth = self.depth
        data = self.data
        if (self.timeout >= 0):
            timer = Signal(range(self.timeout + 1), reset=self.timeout)
        word_sel = Signal(range(2 * words), reset=2 * words - 1)
        fifo = AsyncFIFOBuffered(width=8 * words,
                                 depth=depth,
                                 r_domain="sync",
                                 w_domain=self.data_domain)
        m.submodules += fifo

        m.d.comb += fifo.w_data.eq(data)

        def sendByteFSM(byte, nextState):
            sent = Signal(reset=0)
            with m.If(uart.tx.rdy):
                with m.If(sent == 0):
                    m.d.sync += uart.tx.data.eq(byte)
                    m.d.sync += uart.tx.ack.eq(1)
                    m.d.sync += sent.eq(1)
                with m.If(sent == 1):
                    m.d.sync += uart.tx.ack.eq(0)
                    m.d.sync += sent.eq(0)
                    m.next = nextState

        with m.FSM():
            with m.State("Wait"):
                m.d.sync += uart.rx.ack.eq(1)
                with m.If(uart.rx.rdy):
                    m.d.sync += uart.rx.ack.eq(0)
                    if self.timeout >= 0:
                        m.d.sync += timer.eq(self.timeout)
                    m.next = "Pre-Collect"
            with m.State("Pre-Collect"):
                sendByteFSM(ord('\n'), "Collect")
            with m.State("Collect"):
                with m.If(~fifo.w_rdy
                          | ((timer == 0) if self.timeout >= 0 else 0)):
                    m.d.comb += fifo.w_en.eq(0)
                    m.next = "Transmit-1"
                with m.Else():
                    m.d.comb += fifo.w_en.eq(self.enable)
                    if self.timeout >= 0:
                        m.d.sync += timer.eq(timer - 1)
            with m.State("Transmit-1"):
                with m.If(fifo.r_rdy):
                    m.d.sync += fifo.r_en.eq(1)
                    m.next = "Transmit-2"
                with m.Else():
                    m.next = "Wait"
            with m.State("Transmit-2"):
                m.d.sync += fifo.r_en.eq(0)
                m.next = "TransmitByte"
            with m.State("TransmitByte"):
                sent = Signal(reset=0)
                with m.If(uart.tx.rdy):
                    with m.If(sent == 0):
                        hexNumber = HexNumber(
                            fifo.r_data.word_select(word_sel, 4), Signal(8))
                        m.submodules += hexNumber
                        m.d.sync += uart.tx.data.eq(hexNumber.ascii)
                        m.d.sync += uart.tx.ack.eq(1)
                        m.d.sync += sent.eq(1)
                    with m.If(sent == 1):
                        m.d.sync += uart.tx.ack.eq(0)
                        m.d.sync += sent.eq(0)
                        with m.If(word_sel == 0):
                            m.d.sync += word_sel.eq(word_sel.reset)
                            m.next = "Separator"
                        with m.Else():
                            m.d.sync += word_sel.eq(word_sel - 1)
                with m.Else():
                    m.d.sync += uart.tx.ack.eq(0)
            with m.State("Separator"):
                sendByteFSM(ord('\n'), "Transmit-1")
        return m
Ejemplo n.º 11
0
    def elaborate(self, platform):
        m = Module()

        # Buffer our stream inputs here to improve timing.
        stream_in_data = Signal.like(self.sink.data)
        stream_in_ctrl = Signal.like(self.sink.ctrl)
        stream_in_valid = Signal.like(self.sink.valid)
        m.d.sync += [
            stream_in_data.eq(self.sink.data),
            stream_in_ctrl.eq(self.sink.ctrl),
            stream_in_valid.eq(self.sink.valid),
        ]

        # Aliases.
        stream_in = self.sink
        if self._flip_bytes:
            stream_in_data = stream_in.data.rotate_right(
                (self._words_in // 2) * 8)
            stream_in_ctrl = stream_in.ctrl.rotate_right(self._words_in // 2)
        else:
            stream_in_data = stream_in.data
            stream_in_ctrl = stream_in.ctrl

        # If our output domain is the same as our input domain, we'll directly drive our output stream.
        # Otherwise, we'll drive an internal signal; and then cross that into our output domain.
        if self._output_domain == self._input_domain:
            stream_out = self.source
        else:
            stream_out = USBRawSuperSpeedStream()

        # Create proxies that allow us access to the upper and lower halves of our output data stream.
        data_out_halves = Array(
            stream_out.data.word_select(i, self._data_bits_in)
            for i in range(2))
        ctrl_out_halves = Array(
            stream_out.ctrl.word_select(i, self._ctrl_bits_in)
            for i in range(2))

        # Word select -- selects whether we're targeting the upper or lower half of the output word.
        # Toggles every input-domain cycle.
        targeting_upper_half = Signal(reset=1 if self._flip_bytes else 0)
        m.d.sync += targeting_upper_half.eq(~targeting_upper_half)

        # Pass through our data and control every cycle.
        m.d.sync += [
            data_out_halves[targeting_upper_half].eq(stream_in_data),
            ctrl_out_halves[targeting_upper_half].eq(stream_in_ctrl),
        ]

        # Set our valid signal high only if both the current and previously captured word are valid.
        m.d.comb += [
            stream_out.valid.eq(
                stream_in.valid
                & Past(stream_in.valid, domain=self._input_domain))
        ]

        if self._input_domain != self._output_domain:
            in_domain_signals = Cat(stream_out.data, stream_out.ctrl,
                                    stream_out.valid)
            out_domain_signals = Cat(self.source.data, self.source.ctrl,
                                     self.source.valid)

            # Create our async FIFO...
            m.submodules.cdc = fifo = AsyncFIFOBuffered(
                width=len(in_domain_signals),
                depth=8,
                w_domain="sync",
                r_domain=self._output_domain)

            m.d.comb += [
                # ... fill it from our in-domain stream...
                fifo.w_data.eq(in_domain_signals),
                fifo.w_en.eq(targeting_upper_half),

                # ... and output it into our output stream.
                out_domain_signals.eq(fifo.r_data),
                self.source.valid.eq(fifo.r_level > 2),
                fifo.r_en.eq(1),
            ]

        # If our source domain isn't `sync`, translate `sync` to the proper domain name.
        if self._input_domain != "sync":
            m = DomainRenamer({'sync': self._input_domain})(m)

        return m
Ejemplo n.º 12
0
    def elaborate(self, platform):
        m = Module()

        # If we're receiving data from an domain other than our output domain,
        # cross it over nicely.
        if self._input_domain != self._output_domain:
            stream_in = USBRawSuperSpeedStream(payload_words=self._words_in)
            in_domain_signals = Cat(
                self.sink.data,
                self.sink.ctrl,
            )
            out_domain_signals = Cat(
                stream_in.data,
                stream_in.ctrl,
            )

            # Advance our FIFO only ever other cycle.
            advance_fifo = Signal()
            m.d.tx += advance_fifo.eq(~advance_fifo)

            # Create our async FIFO...
            m.submodules.cdc = fifo = AsyncFIFOBuffered(
                width=len(in_domain_signals),
                depth=8,
                w_domain=self._input_domain,
                r_domain="tx")

            m.d.comb += [
                # ... fill it from our in-domain stream...
                fifo.w_data.eq(in_domain_signals),
                fifo.w_en.eq(1),
                self.sink.ready.eq(1),

                # ... and output it into our output stream.
                out_domain_signals.eq(fifo.r_data),
                stream_in.valid.eq(fifo.r_rdy),
                fifo.r_en.eq(advance_fifo),
            ]

        # Otherwise, use our data-stream directly.
        else:
            stream_in = self.sink
            m.d.comb += self.sink.ready.eq(1)

        # Word select -- selects whether we're targeting the upper or lower half of the input word.
        # Toggles every input-domain cycle.
        next_half_targeted = Signal()
        targeting_upper_half = Signal()

        # If our data has just changed, we should always be targeting the upper word.
        # This "locks" us to the data's changes.
        data_changed = stream_in.data != Past(stream_in.data, domain="tx")
        ctrl_changed = stream_in.ctrl != Past(stream_in.ctrl, domain="tx")
        with m.If(data_changed | ctrl_changed):
            m.d.comb += targeting_upper_half.eq(1 if self._flip_bytes else 0)
            m.d.tx += next_half_targeted.eq(0 if self._flip_bytes else 1)
        with m.Else():
            m.d.comb += targeting_upper_half.eq(next_half_targeted)
            m.d.tx += next_half_targeted.eq(~next_half_targeted)

        # If we're flipping the bytes in our output stream (e.g. to maintain endianness),
        # create a flipped version; otherwise, use our output stream directly.
        stream_out = self.source

        # Create proxies that allow us access to the upper and lower halves of our input data stream.
        data_in_halves = Array(
            stream_in.data.word_select(i,
                                       len(stream_in.data) // 2)
            for i in range(2))
        ctrl_in_halves = Array(
            stream_in.ctrl.word_select(i,
                                       len(stream_in.ctrl) // 2)
            for i in range(2))

        # Pass through our data and control every cycle.
        # This is registered to loosen timing.
        if self._flip_bytes:
            stream_out_data = data_in_halves[targeting_upper_half]
            stream_out_ctrl = ctrl_in_halves[targeting_upper_half]
            m.d.tx += [
                stream_out.data.eq(
                    stream_out_data.rotate_right(len(stream_out_data) // 2)),
                stream_out.ctrl.eq(
                    stream_out_ctrl.rotate_right(len(stream_out_ctrl) // 2)),
                stream_out.valid.eq(1),
            ]
        else:
            m.d.tx += [
                stream_out.data.eq(data_in_halves[targeting_upper_half]),
                stream_out.ctrl.eq(ctrl_in_halves[targeting_upper_half]),
                stream_out.valid.eq(1),
            ]

        # If our output domain isn't `sync`, translate `sync` to the proper domain name.
        if self._output_domain != "tx":
            m = DomainRenamer({'tx': self._output_domain})(m)

        return m
Ejemplo n.º 13
0
def main():
    # parser = main_parser()
    # args = parser.parse_args()

    m = Module()

    m.submodules.ft = ft = FT600()
    m.submodules.wfifo = wfifo = AsyncFIFOBuffered(
        width=16, depth=1024, r_domain="sync", w_domain="sync")
    m.submodules.rfifo = rfifo = AsyncFIFOBuffered(
        width=16, depth=1024, r_domain="sync", w_domain="sync")

    ft_oe = Signal()
    ft_be = Signal()
    ft_txe = Signal()

    # FT control
    m.d.comb += ft_oe.eq(ft.ft_oe)
    m.d.comb += ft_be.eq(ft.ft_be)
    m.d.comb += ft_txe.eq(ft.ft_txe)

    # FT to Write FIFO
    m.d.comb += ft.input_payload.eq(wfifo.r_data)
    m.d.comb += wfifo.r_en.eq(ft.input_ready)
    m.d.comb += ft.input_valid.eq(wfifo.r_rdy)

    # FT to Read FIFO
    m.d.comb += rfifo.w_data.eq(ft.output_payload)
    m.d.comb += rfifo.w_en.eq(ft.output_valid)
    m.d.comb += ft.output_ready.eq(rfifo.w_rdy)

    sim = Simulator(m)
    sim.add_clock(1e-7, domain="sync")      # 10 MHz FPGA clock

    def process():
        yield wfifo.w_en.eq(1)
        yield wfifo.w_data.eq(1)
        yield Tick(domain="sync")
        yield wfifo.w_data.eq(2)
        yield Tick(domain="sync")
        yield wfifo.w_data.eq(3)
        yield Tick(domain="sync")
        yield wfifo.w_data.eq(4)
        yield Tick(domain="sync")
        yield wfifo.w_data.eq(5)
        yield Tick(domain="sync")
        yield wfifo.w_data.eq(6)
        yield Tick(domain="sync")
        yield wfifo.w_data.eq(7)
        yield Tick(domain="sync")
        yield wfifo.w_en.eq(0)
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield ft.ft_txe.eq(1)
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield ft.ft_txe.eq(0)
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield ft.ft_txe.eq(1)
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield ft.ft_rxf.eq(1)
        yield Tick(domain="sync")
        yield ft.ft_override.eq(1)
        yield Tick(domain="sync")
        yield ft.ft_override.eq(2)
        yield Tick(domain="sync")
        yield ft.ft_override.eq(3)
        yield Tick(domain="sync")
        yield ft.ft_rxf.eq(0)
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield Tick(domain="sync")
        yield Tick(domain="sync")

    sim.add_sync_process(process)
    with sim.write_vcd("test.vcd", "test.gtkw", traces=[]):
        sim.run()
Ejemplo n.º 14
0
Archivo: ila.py Proyecto: zyp/luna
    def elaborate(self, platform):
        m = Module()
        m.submodules.ila = ila = self.ila

        if self._o_domain == self.domain:
            in_domain_stream = self.stream
        else:
            in_domain_stream = StreamInterface(
                payload_width=self.bits_per_sample)

        # Count where we are in the current transmission.
        current_sample_number = Signal(range(0, ila.sample_depth))

        # Always present the current sample number to our ILA, and the current
        # sample value to the UART.
        m.d.comb += [
            ila.captured_sample_number.eq(current_sample_number),
            in_domain_stream.payload.eq(ila.captured_sample)
        ]

        with m.FSM():

            # IDLE -- we're currently waiting for a trigger before capturing samples.
            with m.State("IDLE"):

                # Always allow triggering, as we're ready for the data.
                m.d.comb += self.ila.trigger.eq(self.trigger)

                # Once we're triggered, move onto the SAMPLING state.
                with m.If(self.trigger):
                    m.next = "SAMPLING"

            # SAMPLING -- the internal ILA is sampling; we're now waiting for it to
            # complete. This state is similar to IDLE; except we block triggers in order
            # to cleanly avoid a race condition.
            with m.State("SAMPLING"):

                # Once our ILA has finished sampling, prepare to read out our samples.
                with m.If(self.ila.complete):
                    m.d.sync += [
                        current_sample_number.eq(0),
                        in_domain_stream.first.eq(1)
                    ]
                    m.next = "SENDING"

            # SENDING -- we now have a valid buffer of samples to send up to the host;
            # we'll transmit them over our stream interface.
            with m.State("SENDING"):
                m.d.comb += [
                    # While we're sending, we're always providing valid data to the UART.
                    in_domain_stream.valid.eq(1),

                    # Indicate when we're on the last sample.
                    in_domain_stream.last.eq(
                        current_sample_number == (self.sample_depth - 1))
                ]

                # Each time the UART accepts a valid word, move on to the next one.
                with m.If(in_domain_stream.ready):
                    m.d.sync += [
                        current_sample_number.eq(current_sample_number + 1),
                        in_domain_stream.first.eq(0)
                    ]

                    # If this was the last sample, we're done! Move back to idle.
                    with m.If(self.stream.last):
                        m.next = "IDLE"

        # If we're not streaming out of the same domain we're capturing from,
        # we'll add some clock-domain crossing hardware.
        if self._o_domain != self.domain:
            in_domain_signals = Cat(in_domain_stream.first,
                                    in_domain_stream.payload,
                                    in_domain_stream.last)
            out_domain_signals = Cat(self.stream.first, self.stream.payload,
                                     self.stream.last)

            # Create our async FIFO...
            m.submodules.cdc = fifo = AsyncFIFOBuffered(
                width=len(in_domain_signals),
                depth=16,
                w_domain="sync",
                r_domain=self._o_domain)

            m.d.comb += [
                # ... fill it from our in-domain stream...
                fifo.w_data.eq(in_domain_signals),
                fifo.w_en.eq(in_domain_stream.valid),
                in_domain_stream.ready.eq(fifo.w_rdy),

                # ... and output it into our outupt stream.
                out_domain_signals.eq(fifo.r_data),
                self.stream.valid.eq(fifo.r_rdy),
                fifo.r_en.eq(self.stream.ready)
            ]

        # Convert our sync domain to the domain requested by the user, if necessary.
        if self.domain != "sync":
            m = DomainRenamer({"sync": self.domain})(m)

        return m
Ejemplo n.º 15
0
    def elaborate(self, platform):
        m = Module()

        #
        # Clock/Data recovery.
        #
        clock_data_recovery = RxClockDataRecovery(self.i_usbp, self.i_usbn)
        m.submodules.clock_data_recovery = clock_data_recovery
        m.d.comb += self.o_bit_strobe.eq(clock_data_recovery.line_state_valid)

        #
        # NRZI decoding
        #
        m.submodules.nrzi = nrzi = RxNRZIDecoder()
        m.d.comb += [
            nrzi.i_valid.eq(self.o_bit_strobe),
            nrzi.i_dj.eq(clock_data_recovery.line_state_dj),
            nrzi.i_dk.eq(clock_data_recovery.line_state_dk),
            nrzi.i_se0.eq(clock_data_recovery.line_state_se0),
        ]

        #
        # Packet boundary detection.
        #
        m.submodules.detect = detect = RxPacketDetect()
        m.d.comb += [
            detect.i_valid.eq(nrzi.o_valid),
            detect.i_se0.eq(nrzi.o_se0),
            detect.i_data.eq(nrzi.o_data),
        ]

        #
        # Bitstuff remover.
        #
        m.submodules.bitstuff = bitstuff = \
            ResetInserter(~detect.o_pkt_active)(RxBitstuffRemover())
        m.d.comb += [
            bitstuff.i_valid.eq(nrzi.o_valid),
            bitstuff.i_data.eq(nrzi.o_data),
            self.o_receive_error.eq(bitstuff.o_error)
        ]

        #
        # 1bit->8bit (1byte) gearing
        #
        m.submodules.shifter = shifter = RxShifter(width=8)
        m.d.comb += [
            shifter.reset.eq(detect.o_pkt_end),
            shifter.i_data.eq(bitstuff.o_data),
            shifter.i_valid.eq(~bitstuff.o_stall
                               & Past(detect.o_pkt_active, domain="usb_io")),
        ]

        #
        # Clock domain crossing.
        #
        flag_start = Signal()
        flag_end = Signal()
        flag_valid = Signal()
        m.submodules.payload_fifo = payload_fifo = AsyncFIFOBuffered(
            width=8, depth=4, r_domain="usb", w_domain="usb_io")
        m.d.comb += [
            payload_fifo.w_data.eq(shifter.o_data[::-1]),
            payload_fifo.w_en.eq(shifter.o_put),
            self.o_data_payload.eq(payload_fifo.r_data),
            self.o_data_strobe.eq(payload_fifo.r_rdy),
            payload_fifo.r_en.eq(1)
        ]

        m.submodules.flags_fifo = flags_fifo = AsyncFIFOBuffered(
            width=2, depth=4, r_domain="usb", w_domain="usb_io")
        m.d.comb += [
            flags_fifo.w_data[1].eq(detect.o_pkt_start),
            flags_fifo.w_data[0].eq(detect.o_pkt_end),
            flags_fifo.w_en.eq(detect.o_pkt_start | detect.o_pkt_end),
            flag_start.eq(flags_fifo.r_data[1]),
            flag_end.eq(flags_fifo.r_data[0]),
            flag_valid.eq(flags_fifo.r_rdy),
            flags_fifo.r_en.eq(1),
        ]

        # Packet flag signals (in 12MHz domain)
        m.d.comb += [
            self.o_pkt_start.eq(flag_start & flag_valid),
            self.o_pkt_end.eq(flag_end & flag_valid),
        ]

        with m.If(self.o_pkt_start):
            m.d.usb += self.o_pkt_in_progress.eq(1)
        with m.Elif(self.o_pkt_end):
            m.d.usb += self.o_pkt_in_progress.eq(0)

        return m