Example #1
0
    def elaborate(self, platform):
        m = Module()

        with m.If(self.i_hlclk):
            m.d.sync += [
                self.r_hline.eq(self.r_hline + 1),
                self.r_hline_count.eq(self.r_hline_count + 1),
            ]

            with m.FSM() as fsm:
                with m.State("SYNC"):
                    with m.If(self.r_hline_count == self.syncv_vs):
                        m.d.sync += self.r_hline_count.eq(1)
                        m.next = "BACK-PORCH"

                with m.State("BACK-PORCH"):
                    with m.If(self.r_hline_count == (self.syncv_vbp +
                                                     self.syncv_vbpe)):
                        m.d.sync += self.r_hline_count.eq(1)
                        m.next = "DISPLAY"

                with m.State("DISPLAY"):
                    with m.If(self.r_hline_count == self.syncv_vdp):
                        m.d.sync += self.r_hline.eq(1)
                        m.d.sync += self.r_hline_count.eq(1)
                        m.next = "FRONT-PORCH"

                with m.State("FRONT-PORCH"):
                    with m.If(self.r_hline_count == (self.syncv_vfp +
                                                     self.syncv_vfpe)):
                        m.d.sync += self.r_hline_count.eq(1)
                        m.d.sync += self.o_odd.eq(~self.o_odd)
                        m.next = "SYNC"

        return m
Example #2
0
File: crc.py Project: ret/daqnet
    def elaborate(self, platform):

        m = Module()
        crc = Signal(32)

        self.crctable = Memory(32, 256, make_crc32_table())
        table_port = self.crctable.read_port()
        m.submodules += table_port

        m.d.comb += [
            self.crc_out.eq(crc ^ 0xFFFFFFFF),
            self.crc_match.eq(crc == 0xDEBB20E3),
            table_port.addr.eq(crc ^ self.data),
        ]

        with m.FSM():
            with m.State("RESET"):
                m.d.sync += crc.eq(0xFFFFFFFF)
                m.next = "IDLE"

            with m.State("IDLE"):
                with m.If(self.reset):
                    m.next = "RESET"
                with m.Elif(self.data_valid):
                    m.next = "BUSY"

            with m.State("BUSY"):
                with m.If(self.reset):
                    m.next = "RESET"
                m.d.sync += crc.eq(table_port.data ^ (crc >> 8))
                m.next = "IDLE"

        return m
Example #3
0
    def elaborate(self, platform):
        m = Module()
        rx_port = self.user_rx_mem.read_port()
        tx_port = self.user_tx_mem.write_port()

        m.submodules += [self.mem_r_port, self.mem_w_port, rx_port, tx_port]

        led1 = platform.request("user_led", 0)
        led2 = platform.request("user_led", 1)

        m.d.comb += [
            tx_port.addr.eq(0),
            tx_port.en.eq(0),
            tx_port.data.eq(0),
            rx_port.addr.eq(0),
        ]

        m.d.sync += [
            led1.eq(rx_port.data & 1),
            led2.eq((rx_port.data & 2) >> 1),
        ]

        with m.FSM():
            with m.State("IDLE"):
                m.d.sync += self.transmit_packet.eq(0)
                with m.If(self.packet_received):
                    m.next = "RX"
            with m.State("RX"):
                with m.If(self.transmit_ready):
                    m.d.sync += self.transmit_packet.eq(1)
                    m.next = "IDLE"

        return m
Example #4
0
    def elaborate(self, platform):
        m = Module()
        mac = [Signal(8) for _ in range(6)]

        m.d.sync += self.mac_match.eq(
            reduce(operator.and_,
                   [(mac[idx] == self.mac_addr[idx]) | (mac[idx] == 0xFF)
                    for idx in range(6)]))

        with m.FSM():
            with m.State("RESET"):
                m.d.sync += [mac[idx].eq(0) for idx in range(6)]
                with m.If(~self.reset):
                    m.next = "BYTE0"

            for idx in range(6):
                next_state = f"BYTE{idx+1}" if idx < 5 else "DONE"

                with m.State(f"BYTE{idx}"):
                    m.d.sync += mac[idx].eq(self.data)
                    with m.If(self.reset):
                        m.next = "RESET"
                    with m.Elif(self.data_valid):
                        m.next = next_state

            with m.State("DONE"):
                with m.If(self.reset):
                    m.next = "RESET"

        return m
Example #5
0
    def elaborate(self, platform):
        m = Module()

        # This state machine recognizes sequences of 6 bits and drops the 7th
        # bit.  The fsm implements a counter in a series of several states.
        # This is intentional to help absolutely minimize the levels of logic
        # used.
        drop_bit = Signal(1)

        with m.FSM(domain="usb_io"):

            for i in range(6):
                with m.State(f"D{i}"):
                    with m.If(self.i_valid):
                        with m.If(self.i_data):
                            # Receiving '1' increments the bitstuff counter.
                            m.next = (f"D{i + 1}")
                        with m.Else():
                            # Receiving '0' resets the bitstuff counter.
                            m.next = "D0"

            with m.State("D6"):
                with m.If(self.i_valid):
                    m.d.comb += drop_bit.eq(1)
                    # Reset the bitstuff counter, drop the data.
                    m.next = "D0"

        m.d.usb_io += [
            self.o_data.eq(self.i_data),
            self.o_stall.eq(drop_bit | ~self.i_valid),
            self.o_error.eq(drop_bit & self.i_data & self.i_valid),
        ]

        return m
Example #6
0
    def elaborate(self, platform):
        m = Module()
        interface = self.interface

        # Create convenience aliases for our interface components.
        setup = interface.setup
        handshake = interface.handshake

        with m.FSM(domain="usb"):

            # IDLE -- not handling any active request
            with m.State('IDLE'):

                # If we've received a new setup packet, handle it.
                # TODO: limit this to standard requests
                with m.If(setup.received):

                    # Select which standard packet we're going to handler.
                    m.next = 'UNHANDLED'

            # UNHANDLED -- we've received a request we're not prepared to handle
            with m.State('UNHANDLED'):

                # When we next have an opportunity to stall, do so,
                # and then return to idle.
                with m.If(interface.data_requested
                          | interface.status_requested):
                    m.d.comb += handshake.stall.eq(1)
                    m.next = 'IDLE'

        return m
Example #7
0
    def elaborate(self, platform):
        m = Module()
        m.submodules.serdes = serdes = self.serdes

        # The symbol table reads the corresponding symbols for each
        # symbol in PACKET and outputs them on tx_data
        m.submodules.symboltable = symboltable = SymbolTable(
            table=pack_mem(TABLE, width=20),
            packet=Memory(width=16,
                          depth=len(PACKET),
                          init=[int(i) for i in np.array(PACKET) * 5000 / 20]),
            samples_per_symbol=int(5e9 / 1e6),
            tx_domain="tx")
        m.d.comb += [
            symboltable.packet_length.eq(len(PACKET)),
            serdes.tx_data.eq(symboltable.tx_data)
        ]

        # Quick state machine to transmit and then wait a bit before
        # transmitting again
        counter = Signal(32)
        with m.FSM():
            with m.State("START"):
                m.d.sync += symboltable.tx_reset.eq(1)
                m.next = "WAIT_DONE"
            with m.State("WAIT_DONE"):
                m.d.sync += symboltable.tx_reset.eq(0)
                with m.If(symboltable.tx_done):
                    m.d.sync += counter.eq(0)
                    m.next = "PAUSE"
            with m.State("PAUSE"):
                m.d.sync += counter.eq(counter + 1)
                with m.If(counter >= int(1e4)):
                    m.next = "START"
        return m
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        # Signal defaults
        m.d.comb += self.ft.oe.o.eq(0)
        m.d.comb += self.ft.write.o.eq(0)
        m.d.comb += self.ft.read.o.eq(0)

        with m.FSM():
            with m.State("READY"):
                # If there is data to read, we read it first before entering the write state
                with m.If(self.ft.rxf.i):
                    m.d.comb += self.ft.oe.o.eq(1)

                    m.d.comb += self.ft.data.oe.eq(0)
                    m.d.comb += self.ft.be.oe.eq(0)

                    m.next = "READ"
                with m.Elif(self.ft.txe.i & self.input_valid):
                    m.d.comb += self.ft.data.oe.eq(1)
                    m.d.comb += self.ft.be.oe.eq(1)

                    m.next = "WRITE"

            with m.State("READ"):
                m.d.comb += self.ft.oe.o.eq(1)

                # Set pins in correct direction (input)
                m.d.comb += self.ft.data.oe.eq(0)
                m.d.comb += self.ft.be.oe.eq(0)

                # Connect FIFO
                m.d.comb += self.output_payload.eq(self.ft.data.i)
                m.d.comb += self.output_valid.eq(self.ft.rxf.i)
                m.d.comb += self.ft.read.o.eq(self.output_ready)

                with m.If(~self.ft.rxf.i):
                    m.next = "READY"

            with m.State("WRITE"):
                # Set pins in correct direction (output)
                m.d.comb += self.ft.data.oe.eq(1)
                m.d.comb += self.ft.be.oe.eq(1)

                # All bytes are valid
                m.d.comb += self.ft.oe.o.eq(0)
                m.d.comb += self.ft.be.o.eq(0b11)

                # Connect FIFO
                m.d.comb += self.ft.data.o.eq(self.input_payload)
                m.d.comb += self.input_ready.eq(self.ft.txe.i)
                m.d.comb += self.ft.write.o.eq(self.input_valid)

                # TODO: Should we go to ready if there is data to read, or wait until write is done?
                with m.If(~self.ft.txe.i | ~self.input_valid):
                    m.next = "READY"

        return m
Example #9
0
File: rmii.py Project: ret/daqnet
    def elaborate(self, platform):
        m = Module()

        # Register input data on the data_valid signal
        data_reg = Signal(8)

        with m.FSM() as fsm:
            m.d.comb += [
                self.ready.eq(fsm.ongoing("IDLE") | fsm.ongoing("NIBBLE4")),
                self.txen.eq(~fsm.ongoing("IDLE")),
            ]

            with m.State("IDLE"):
                m.d.comb += [
                    self.txd0.eq(0),
                    self.txd1.eq(0),
                ]
                m.d.sync += data_reg.eq(self.data)
                with m.If(self.data_valid):
                    m.next = "NIBBLE1"

            with m.State("NIBBLE1"):
                m.d.comb += [
                    self.txd0.eq(data_reg[0]),
                    self.txd1.eq(data_reg[1]),
                ]
                m.next = "NIBBLE2"

            with m.State("NIBBLE2"):
                m.d.comb += [
                    self.txd0.eq(data_reg[2]),
                    self.txd1.eq(data_reg[3]),
                ]
                m.next = "NIBBLE3"

            with m.State("NIBBLE3"):
                m.d.comb += [
                    self.txd0.eq(data_reg[4]),
                    self.txd1.eq(data_reg[5]),
                ]
                m.next = "NIBBLE4"

            with m.State("NIBBLE4"):
                m.d.comb += [
                    self.txd0.eq(data_reg[6]),
                    self.txd1.eq(data_reg[7]),
                ]
                m.d.sync += data_reg.eq(self.data)
                with m.If(self.data_valid):
                    m.next = "NIBBLE1"
                with m.Else():
                    m.next = "IDLE"

        return m
Example #10
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        # TODO: Add async FIFOs internally
        # m.submodules.write_fifo = write_fifo = AsyncFIFOBuffered(...)
        # m.submodules.read_fifo = read_fifo = AsyncFIFOBuffered(...)

        m.d.comb += self.ft_data.eq(self.ft_override)

        # Signal defaults
        m.d.comb += self.ft_oe.eq(0)
        m.d.comb += self.ft_write.eq(0)
        m.d.comb += self.ft_read.eq(0)

        with m.FSM():
            with m.State("READY"):
                # If there is data to read, we read it first before entering the write state
                with m.If(self.ft_rxf):
                    m.d.comb += self.ft_oe.eq(1)

                    m.next = "READ"
                with m.Elif(self.ft_txe & self.input_valid):

                    m.next = "WRITE"

            with m.State("READ"):
                m.d.comb += self.ft_oe.eq(1)

                # Connect FIFO, TODO: Add support for IO on the data and be lines
                m.d.comb += self.output_payload.eq(self.ft_data)
                m.d.comb += self.output_valid.eq(self.ft_rxf)
                m.d.comb += self.ft_read.eq(self.output_ready)

                with m.If(~self.ft_rxf):
                    m.next = "READY"

            with m.State("WRITE"):
                m.d.comb += self.ft_be.eq(0b11)

                # Connect FIFO, TODO: Add support for IO on the data and be lines
                m.d.comb += self.ft_data.eq(self.input_payload)
                m.d.comb += self.input_ready.eq(self.ft_txe)
                m.d.comb += self.ft_write.eq(self.input_valid)

                # TODO: Should we go to ready if there is data to read, or wait until write is done?
                with m.If(~self.ft_txe | ~self.input_valid):
                    m.next = "READY"

        return m
Example #11
0
File: rmii.py Project: ret/daqnet
    def elaborate(self, platform):

        m = Module()

        m.submodules.crc = crc = CRC32()
        m.submodules.mac_match = mac_match = MACAddressMatch(self.mac_addr)
        m.submodules.rxbyte = rxbyte = RMIIRxByte(self.crs_dv, self.rxd0,
                                                  self.rxd1)

        adr = Signal(self.write_port.addr.nbits)

        with m.FSM() as fsm:
            m.d.comb += [
                self.write_port.addr.eq(adr),
                self.write_port.data.eq(rxbyte.data),
                self.write_port.en.eq(rxbyte.data_valid),
                crc.data.eq(rxbyte.data),
                crc.data_valid.eq(rxbyte.data_valid),
                crc.reset.eq(fsm.ongoing("IDLE")),
                mac_match.data.eq(rxbyte.data),
                mac_match.data_valid.eq(rxbyte.data_valid),
                mac_match.reset.eq(fsm.ongoing("IDLE")),
            ]

            # Idle until we see data valid
            with m.State("IDLE"):
                m.d.sync += self.rx_len.eq(0)
                m.d.sync += self.rx_valid.eq(0)
                with m.If(rxbyte.dv):
                    m.d.sync += self.rx_offset.eq(adr)
                    m.next = "DATA"

            # Save incoming data to memory
            with m.State("DATA"):
                with m.If(rxbyte.data_valid):
                    m.d.sync += adr.eq(adr + 1)
                    m.d.sync += self.rx_len.eq(self.rx_len + 1)
                with m.Elif(~rxbyte.dv):
                    m.next = "EOF"

            with m.State("EOF"):
                with m.If(crc.crc_match & mac_match.mac_match):
                    m.d.sync += self.rx_valid.eq(1)
                m.next = "IDLE"

        return m
Example #12
0
    def elaborate(self, platform):
        m = Module()
        stuff_bit = Signal()

        with m.FSM(domain="usb"):

            for i in range(5):

                with m.State(f"D{i}"):
                    # Receiving '1' increments the bitstuff counter.
                    with m.If(self.i_data):
                        m.next = f"D{i+1}"

                    # Receiving '0' resets the bitstuff counter.
                    with m.Else():
                        m.next = "D0"


            with m.State("D5"):
                with m.If(self.i_data):

                    # There's a '1', so indicate we might stall on the next loop.
                    m.d.comb += self.o_will_stall.eq(1),
                    m.next = "D6"

                with m.Else():
                    m.next = "D0"


            with m.State("D6"):
                m.d.comb += stuff_bit.eq(1)
                m.next = "D0"


        m.d.comb += [
            self.o_stall.eq(stuff_bit)
        ]

        # flop outputs
        with m.If(stuff_bit):
            m.d.usb += self.o_data.eq(0),
        with m.Else():
            m.d.usb += self.o_data.eq(self.i_data)

        return m
Example #13
0
    def elaborate(self, platform):
        m = Module()

        pkt_start = Signal()
        pkt_active = Signal()
        pkt_end = Signal()

        with m.FSM(domain="usb_io"):

            for i in range(5):

                with m.State(f"D{i}"):
                    with m.If(self.i_valid):
                        with m.If(self.i_data | self.i_se0):
                            # Receiving '1' or SE0 early resets the packet start counter.
                            m.next = "D0"

                        with m.Else():
                            # Receiving '0' increments the packet start counter.
                            m.next = f"D{i + 1}"

            with m.State("D5"):
                with m.If(self.i_valid):
                    with m.If(self.i_se0):
                        m.next = "D0"
                    # once we get a '1', the packet is active
                    with m.Elif(self.i_data):
                        m.d.comb += pkt_start.eq(1)
                        m.next = "PKT_ACTIVE"

            with m.State("PKT_ACTIVE"):
                m.d.comb += pkt_active.eq(1)
                with m.If(self.i_valid & self.i_se0):
                    m.d.comb += [pkt_active.eq(0), pkt_end.eq(1)]
                    m.next = "D0"

        # pass all of the outputs through a pipe stage
        m.d.comb += [
            self.o_pkt_start.eq(pkt_start),
            self.o_pkt_active.eq(pkt_active),
            self.o_pkt_end.eq(pkt_end),
        ]

        return m
Example #14
0
    def elaborate(self, platform):
        m = Module()

        for i in range(self.width):
            m.submodules["pipe{:02}".format(i)] = pipe = PixelPipeline()
            self._add_pipeline_settings(m, pipe, self.pipes[i])

        with m.FSM():
            with m.State("READ"):
                with m.Switch(self.i_address):
                    with m.Case(Register.ALPHA_1):
                        # TODO: Multiple rendering contexts
                    with m.Case(Register.DIMX):
                        for x in range(4):
                            for y in range(4):
                                index = 16*x + 4*y
                                m.d.sync += self.i_dimx_dm[x][y].eq(self.i_data[index:index+3])

        return m
Example #15
0
    def elaborate(self, platform):
        m = Module()

        counter = Signal(max=self.nclks)

        with m.FSM() as fsm:
            m.d.comb += self.pulse.eq(fsm.ongoing("STRETCH"))
            with m.State("WAIT"):
                m.d.sync += counter.eq(0)
                with m.If(self.trigger):
                    m.next = "STRETCH"

            with m.State("STRETCH"):
                with m.If(counter == self.nclks - 1):
                    m.next = "WAIT"
                with m.Else():
                    m.d.sync += counter.eq(counter + 1)

        return m
Example #16
0
    def elaborate(self, platform):
        m = Module()

        # Counter that stores how many cycles we've spent in reset.
        cycles_in_reset = Signal(range(0, self.reset_length_cycles))

        reset_state = 'RESETTING' if self.power_on_reset else 'IDLE'
        with m.FSM(reset=reset_state, domain='sync') as fsm:

            # Drive the PHY reset whenever we're in the RESETTING cycle.
            m.d.comb += [
                self.phy_reset.eq(fsm.ongoing('RESETTING')),
                self.phy_stop.eq(~fsm.ongoing('IDLE'))
            ]

            with m.State('IDLE'):
                m.d.sync += cycles_in_reset.eq(0)

                # Wait for a reset request.
                with m.If(self.trigger):
                    m.next = 'RESETTING'

            # RESETTING: hold the reset line active for the given amount of time
            with m.State('RESETTING'):
                m.d.sync += cycles_in_reset.eq(cycles_in_reset + 1)

                with m.If(cycles_in_reset + 1 == self.reset_length_cycles):
                    m.d.sync += cycles_in_reset.eq(0)
                    m.next = 'DEFERRING_STARTUP'

            # DEFERRING_STARTUP: Produce a signal that will defer startup for
            # the provided amount of time. This allows line state to stabilize
            # before the PHY will start interacting with us.
            with m.State('DEFERRING_STARTUP'):
                m.d.sync += cycles_in_reset.eq(cycles_in_reset + 1)

                with m.If(cycles_in_reset + 1 == self.stop_length_cycles):
                    m.d.sync += cycles_in_reset.eq(0)
                    m.next = 'IDLE'

        return m
Example #17
0
    def elaborate(self, platform: Platform) -> Module:
        m = Module()

        with m.FSM(reset="IDLE") as self.fsm:
            with m.State("IDLE"):
                self.Idle(m)

            with m.State("START"):
                self.Start(m)

            with m.State("DATA"):
                self.Data(m)

            with m.State("STOP"):
                self.Stop(m)

            with m.State("DONE"):
                self.Done(m)

            # with m.State("ERROR"):
            #     self.Error(m)

        return m
Example #18
0
File: rmii.py Project: ret/daqnet
    def elaborate(self, platform):
        m = Module()

        # Transmit byte counter
        tx_idx = Signal(self.read_port.addr.nbits)
        # Transmit length latch
        tx_len = Signal(11)
        # Transmit offset latch
        tx_offset = Signal(self.read_port.addr.nbits)

        m.submodules.crc = crc = CRC32()
        m.submodules.txbyte = txbyte = RMIITxByte(self.txen, self.txd0,
                                                  self.txd1)

        with m.FSM() as fsm:
            m.d.comb += [
                self.read_port.addr.eq(tx_idx + tx_offset),
                crc.data.eq(txbyte.data),
                crc.reset.eq(fsm.ongoing("IDLE")),
                crc.data_valid.eq((fsm.ongoing("DATA") | fsm.ongoing("PAD"))
                                  & txbyte.ready),
                self.tx_ready.eq(fsm.ongoing("IDLE")),
                txbyte.data_valid.eq(~(fsm.ongoing("IDLE")
                                       | fsm.ongoing("IPG"))),
            ]

            with m.State("IDLE"):
                m.d.comb += txbyte.data.eq(0)
                m.d.sync += [
                    tx_idx.eq(0),
                    tx_offset.eq(self.tx_offset),
                    tx_len.eq(self.tx_len),
                ]
                with m.If(self.tx_start):
                    m.next = "PREAMBLE"

            with m.State("PREAMBLE"):
                m.d.comb += txbyte.data.eq(0x55)
                with m.If(txbyte.ready):
                    with m.If(tx_idx == 6):
                        m.d.sync += tx_idx.eq(0)
                        m.next = "SFD"
                    with m.Else():
                        m.d.sync += tx_idx.eq(tx_idx + 1)

            with m.State("SFD"):
                m.d.comb += txbyte.data.eq(0xD5)
                with m.If(txbyte.ready):
                    m.next = "DATA"

            with m.State("DATA"):
                m.d.comb += txbyte.data.eq(self.read_port.data)
                with m.If(txbyte.ready):
                    m.d.sync += tx_idx.eq(tx_idx + 1)
                    with m.If(tx_idx == tx_len - 1):
                        with m.If(tx_len < 60):
                            m.next = "PAD"
                        with m.Else():
                            m.next = "FCS1"

            with m.State("PAD"):
                m.d.comb += txbyte.data.eq(0x00)
                with m.If(txbyte.ready):
                    m.d.sync += tx_idx.eq(tx_idx + 1)
                    with m.If(tx_idx == 59):
                        m.next = "FCS1"

            with m.State("FCS1"):
                m.d.comb += txbyte.data.eq(crc.crc_out[0:8])
                with m.If(txbyte.ready):
                    m.next = "FCS2"

            with m.State("FCS2"):
                m.d.comb += txbyte.data.eq(crc.crc_out[8:16])
                with m.If(txbyte.ready):
                    m.next = "FCS3"

            with m.State("FCS3"):
                m.d.comb += txbyte.data.eq(crc.crc_out[16:24])
                with m.If(txbyte.ready):
                    m.next = "FCS4"

            with m.State("FCS4"):
                m.d.comb += txbyte.data.eq(crc.crc_out[24:32])
                with m.If(txbyte.ready):
                    m.d.sync += tx_idx.eq(0)
                    m.next = "IPG"

            with m.State("IPG"):
                m.d.sync += tx_idx.eq(tx_idx + 1)
                with m.If(tx_idx == 48):
                    m.next = "IDLE"

        return m
Example #19
0
File: rmii.py Project: ret/daqnet
    def elaborate(self, platform):
        m = Module()

        # Sample RMII signals on rising edge of ref_clk
        crs_dv_reg = Signal()
        rxd_reg = Signal(2)
        m.d.sync += [
            crs_dv_reg.eq(self.crs_dv),
            rxd_reg.eq(Cat(self.rxd0, self.rxd1)),
        ]

        with m.FSM():
            with m.State("IDLE"):
                m.d.sync += [
                    self.crs.eq(0),
                    self.dv.eq(0),
                    self.data_valid.eq(0),
                ]
                with m.If(crs_dv_reg & (rxd_reg == 0b01)):
                    m.next = "PREAMBLE_SFD"

            with m.State("PREAMBLE_SFD"):
                m.d.sync += [
                    self.crs.eq(1),
                    self.dv.eq(1),
                    self.data_valid.eq(0),
                ]
                with m.If(rxd_reg == 0b11):
                    m.next = "NIBBLE1"
                with m.Elif(rxd_reg != 0b01):
                    m.next = "IDLE"

            with m.State("NIBBLE1"):
                m.d.sync += [
                    self.data[0:2].eq(rxd_reg),
                    self.data_valid.eq(0),
                ]
                with m.If(self.dv):
                    m.d.sync += self.crs.eq(crs_dv_reg)
                    m.next = "NIBBLE2"
                with m.Else():
                    m.next = "IDLE"

            with m.State("NIBBLE2"):
                m.d.sync += [
                    self.data[2:4].eq(rxd_reg),
                    self.data_valid.eq(0),
                ]
                with m.If(self.dv):
                    m.d.sync += self.dv.eq(crs_dv_reg)
                    m.next = "NIBBLE3"
                with m.Else():
                    m.next = "IDLE"

            with m.State("NIBBLE3"):
                m.d.sync += [
                    self.data[4:6].eq(rxd_reg),
                    self.data_valid.eq(0),
                ]
                with m.If(self.dv):
                    m.d.sync += self.crs.eq(crs_dv_reg)
                    m.next = "NIBBLE4"
                with m.Else():
                    m.next = "IDLE"

            with m.State("NIBBLE4"):
                m.d.sync += [
                    self.data[6:8].eq(rxd_reg),
                    self.data_valid.eq(0),
                ]
                with m.If(self.dv):
                    m.d.sync += [
                        self.dv.eq(crs_dv_reg),
                        self.data_valid.eq(1),
                    ]
                    m.next = "NIBBLE1"
                with m.Else():
                    m.d.sync += self.data_valid.eq(1),
                    m.next = "IDLE"

        return m
Example #20
0
    def elaborate(self, platform):
        m = Module()
        m.submodules.bridge = self._bridge

        # Shortcuts to our components.
        token          = self.interface.tokenizer
        tx             = self.interface.tx
        handshakes_out = self.interface.handshakes_out

        #
        # Core FIFO.
        #


        # Create our FIFO; and set it to be cleared whenever the user requests.
        m.submodules.fifo = fifo = \
             ResetInserter(self.reset.w_stb)(SyncFIFOBuffered(width=8, depth=self.max_packet_size))

        m.d.comb += [
            # Whenever the user DATA register is written to, add the relevant data to our FIFO.
            fifo.w_en         .eq(self.data.w_stb),
            fifo.w_data       .eq(self.data.w_data),
        ]

        # Keep track of the amount of data in our FIFO.
        bytes_in_fifo = Signal(range(0, self.max_packet_size + 1))

        # If we're clearing the whole FIFO, reset our data count.
        with m.If(self.reset.w_stb):
            m.d.usb += bytes_in_fifo.eq(0)

        # Keep track of our FIFO's data count as data is added or removed.
        increment = fifo.w_en & fifo.w_rdy
        decrement = fifo.r_en & fifo.r_rdy

        with m.Elif(increment & ~decrement):
            m.d.usb += bytes_in_fifo.eq(bytes_in_fifo + 1)
        with m.Elif(decrement & ~increment):
            m.d.usb += bytes_in_fifo.eq(bytes_in_fifo - 1)


        #
        # Register updates.
        #

        # Active endpoint number.
        with m.If(self.epno.w_stb):
            m.d.usb += self.epno.r_data.eq(self.epno.w_data)

        # Keep track of which endpoints are stalled.
        endpoint_stalled = Array(Signal() for _ in range(16))

        # Set the value of our endpoint `stall` based on our `stall` register...
        with m.If(self.stall.w_stb):
            m.d.usb += endpoint_stalled[self.epno.r_data].eq(self.stall.w_data)

        # ... but clear our endpoint `stall` when we get a SETUP packet.
        with m.If(token.is_setup & token.new_token):
            m.d.usb += endpoint_stalled[token.endpoint].eq(0)

        # Manual data toggle control.
        # TODO: Remove this in favor of automated tracking?
        m.d.comb += self.interface.tx_pid_toggle.eq(self.pid.r_data)
        with m.If(self.pid.w_stb):
            m.d.usb += self.pid.r_data.eq(self.pid.w_data)


        #
        # Status registers.
        #
        m.d.comb += [
            self.have.r_data  .eq(fifo.r_rdy)
        ]

        #
        # Control logic.
        #

        # Logic shorthand.
        new_in_token     = (token.is_in & token.ready_for_response)
        endpoint_matches = (token.endpoint == self.epno.r_data)
        stalled          = endpoint_stalled[token.endpoint]

        with m.FSM(domain='usb') as f:

            # Drive our IDLE line based on our FSM state.
            m.d.comb += self.idle.r_data.eq(f.ongoing('IDLE'))

            # IDLE -- our CPU hasn't yet requested that we send data.
            # We'll wait for it to do so, and NAK any packets that arrive.
            with m.State("IDLE"):

                # If we get an IN token...
                with m.If(new_in_token):

                    # STALL it, if the endpoint is STALL'd...
                    with m.If(stalled):
                        m.d.comb += handshakes_out.stall.eq(1)

                    # Otherwise, NAK.
                    with m.Else():
                        m.d.comb += handshakes_out.nak.eq(1)


                # If the user request that we send data, "prime" the endpoint.
                # This means we have data to send, but are just waiting for an IN token.
                with m.If(self.epno.w_stb & ~stalled):
                    m.next = "PRIMED"

            # PRIMED -- our CPU has provided data, but we haven't been sent an IN token, yet.
            # Await that IN token.
            with m.State("PRIMED"):

                with m.If(new_in_token):

                    # If the target endpoint is STALL'd, reply with STALL no matter what.
                    with m.If(stalled):
                        m.d.comb += handshakes_out.stall.eq(1)

                    # If we have a new IN token to our endpoint, move to responding to it.
                    with m.Elif(endpoint_matches):

                        # If there's no data in our endpoint, send a ZLP.
                        with m.If(~fifo.r_rdy):
                            m.next = "SEND_ZLP"

                        # Otherwise, send our data, starting with our first byte.
                        with m.Else():
                            m.d.usb += tx.first.eq(1)
                            m.next = "SEND_DATA"

                    # Otherwise, we don't have a response; NAK the packet.
                    with m.Else():
                        m.d.comb += handshakes_out.nak.eq(1)

            # SEND_ZLP -- we're now now ready to respond to an IN token with a ZLP.
            # Send our response.
            with m.State("SEND_ZLP"):
                m.d.comb += [
                    tx.valid  .eq(1),
                    tx.last   .eq(1)
                ]
                m.next = 'IDLE'

            # SEND_DATA -- we're now ready to respond to an IN token to our endpoint.
            # Send our response.
            with m.State("SEND_DATA"):
                last_packet = (bytes_in_fifo == 1)

                m.d.comb += [
                    tx.valid    .eq(1),
                    tx.last     .eq(last_packet),

                    # Drive our transmit data directly from our FIFO...
                    tx.payload  .eq(fifo.r_data),

                    # ... and advance our FIFO each time a data byte is transmitted.
                    fifo.r_en   .eq(tx.ready)
                ]

                # After we've sent a byte, drop our first flag.
                with m.If(tx.ready):
                    m.d.usb += tx.first.eq(0)

                # Once we transmit our last packet, we're done transmitting. Move back to IDLE.
                with m.If(last_packet & tx.ready):
                    m.next = 'IDLE'

        return DomainRenamer({"sync": "usb"})(m)
Example #21
0
    def elaborate(self, platform):
        m = Module()

        # Shortcuts.
        tx = self.interface.tx
        tokenizer = self.interface.tokenizer

        # Grab a copy of the relevant signal that's in our USB domain; synchronizing if we need to.
        if self._signal_domain == "usb":
            target_signal = self.signal
        else:
            target_signal = synchronize(m, self.signal, o_domain="usb")

        # Store a latched version of our signal, captured before we start a transmission.
        latched_signal = Signal.like(self.signal)

        # Grab an byte-indexable reference into our signal.
        bytes_in_signal = (self._width + 7) // 8
        signal_bytes = Array(latched_signal[n * 8:n * 8 + 8]
                             for n in range(bytes_in_signal))

        # Store how many bytes we've transmitted.
        bytes_transmitted = Signal(range(0, bytes_in_signal + 1))

        #
        # Data transmission logic.
        #

        # If this signal is big endian, send them in reading order; otherwise, index our multiplexer in reverse.
        # Note that our signal is captured little endian by default, due the way we use Array() above. If we want
        # big endian; then we'll flip it.
        if self._endianness == "little":
            index_to_transmit = bytes_transmitted
        else:
            index_to_transmit = bytes_in_signal - bytes_transmitted - 1

        # Always transmit the part of the latched signal byte that corresponds to our
        m.d.comb += tx.payload.eq(signal_bytes[index_to_transmit])

        #
        # Core control FSM.
        #

        endpoint_number_matches = (tokenizer.endpoint == self._endpoint_number)
        targeting_endpoint = endpoint_number_matches & tokenizer.is_in
        packet_requested = targeting_endpoint & tokenizer.ready_for_response

        with m.FSM(domain="usb"):

            # IDLE -- we've not yet gotten an token requesting data. Wait for one.
            with m.State('IDLE'):

                # Once we're ready to send a response...
                with m.If(packet_requested):

                    m.d.usb += [
                        # ... clear our transmit counter ...
                        bytes_transmitted.eq(0),

                        # ... latch in our response...
                        latched_signal.eq(self.signal),
                    ]

                    # ...  and start transmitting it.
                    m.next = "TRANSMIT_RESPONSE"

            # TRANSMIT_RESPONSE -- we're now ready to send our latched response to the host.
            with m.State("TRANSMIT_RESPONSE"):
                is_last_byte = bytes_transmitted + 1 == bytes_in_signal

                # While we're transmitting, our Tx data is valid.
                m.d.comb += [
                    tx.valid.eq(1),
                    tx.first.eq(bytes_transmitted == 0),
                    tx.last.eq(is_last_byte)
                ]

                # Each time we receive a byte, move on to the next one.
                with m.If(tx.ready):
                    m.d.usb += bytes_transmitted.eq(bytes_transmitted + 1)

                    # If this is the last byte to be transmitted, move to waiting for an ACK.
                    with m.If(is_last_byte):
                        m.next = "WAIT_FOR_ACK"

            # WAIT_FOR_ACK -- we've now transmitted our full packet; we need to wait for the host to ACK it
            with m.State("WAIT_FOR_ACK"):

                # If the host does ACK, we're done! Move back to our idle state.
                with m.If(self.interface.handshakes_in.ack):
                    m.d.comb += self.status_read_complete.eq(1)
                    m.d.usb += self.interface.tx_pid_toggle[0].eq(
                        ~self.interface.tx_pid_toggle[0])
                    m.next = "IDLE"

                # If the host starts a new packet without ACK'ing, we'll need to retransmit.
                # Wait for a new IN token.
                with m.If(self.interface.tokenizer.new_token):
                    m.next = "RETRANSMIT"

            # RETRANSMIT -- the host failed to ACK the data we've most recently sent.
            # Wait here for the host to request the data again.
            with m.State("RETRANSMIT"):

                # Once the host does request the data again...
                with m.If(packet_requested):

                    # ... retransmit it, starting from the beginning.
                    m.d.usb += bytes_transmitted.eq(0),
                    m.next = "TRANSMIT_RESPONSE"

        return m
Example #22
0
    def elaborate(self, platform):
        m = Module()

        m.submodules.rdiv = self.r_rdiv
        m.submodules.gdiv = self.r_gdiv
        m.submodules.bdiv = self.r_bdiv

        with m.FSM() as fsm:
            with m.State("START"):
                # Reset output signals
                m.d.sync += [
                    self.o_valid.eq(0),
                    self.o_last.eq(0)
                ]

                # Transpose the coordinates so we're always in the positive X and Y quadrant.
                dx = Signal((self.width + 1, True))
                dy = Signal((self.width + 1, True))
                m.d.comb += [
                    dx.eq(self.i_x0 - self.i_x1),
                    dy.eq(self.i_y0 - self.i_y1)
                ]

                m.d.sync += [
                    self.r_x0.eq(self.i_x0),
                    self.r_y0.eq(self.i_y0),
                    self.r_x1.eq(self.i_x1),
                    self.r_y1.eq(self.i_y1),

                    self.r_dx.eq(Mux(dx < 0, -dx, dx)),
                    self.r_dy.eq(Mux(dy < 0, -dy, dy))
                ]

                m.d.sync += [
                    self.r_red.eq(self.i_r0 << 4),
                    self.r_green.eq(self.i_g0 << 4),
                    self.r_blue.eq(self.i_b0 << 4),

                    self.r_rdiv.i_colour.eq((self.i_r1 - self.i_r0) << 4),
                    self.r_gdiv.i_colour.eq((self.i_g1 - self.i_g0) << 4),
                    self.r_bdiv.i_colour.eq((self.i_b1 - self.i_b0) << 4),
                ]

                with m.If(self.i_start):
                    m.next = "TRANSPOSE"

            with m.State("TRANSPOSE"):
                # Transpose if the angle is steep.
                steep = Signal()
                m.d.comb += steep.eq(self.r_dx < self.r_dy),
                m.d.sync += [
                    self.r_steep.eq(steep),

                    self.r_x0.eq(Mux(steep, self.r_y0, self.r_x0)),
                    self.r_y0.eq(Mux(steep, self.r_x0, self.r_y0)),
                    self.r_x1.eq(Mux(steep, self.r_y1, self.r_x1)),
                    self.r_y1.eq(Mux(steep, self.r_x1, self.r_y1)),

                    self.r_dx.eq(Mux(steep, self.r_dy, self.r_dx)),
                    self.r_dy.eq(Mux(steep, self.r_dx, self.r_dy))
                ]

                m.d.sync += [
                    self.r_rdiv.i_start.eq(1),
                    self.r_gdiv.i_start.eq(1),
                    self.r_bdiv.i_start.eq(1),

                    self.r_rdiv.i_dx.eq(self.r_dx),
                    self.r_gdiv.i_dx.eq(self.r_dx),
                    self.r_bdiv.i_dx.eq(self.r_dx)
                ]

                m.next = "FLIP"

            with m.State("FLIP"):
                # (x0, y0) should be the bottom left coordinate.
                flip = Signal()
                m.d.comb += flip.eq(self.r_x1 < self.r_x0)

                m.d.sync += [
                    self.r_error.eq(0),
                    self.r_y_inc.eq(Mux(flip ^ (self.r_y0 < self.r_y1), +self.one, -self.one))
                ]

                m.d.sync += [
                    self.r_x0.eq(Mux(flip, self.r_x1, self.r_x0)),
                    self.r_y0.eq(Mux(flip, self.r_y1, self.r_y0)),
                    self.r_x1.eq(Mux(flip, self.r_x0, self.r_x1)),
                    self.r_y1.eq(Mux(flip, self.r_y0, self.r_y1))
                ]

                m.next = "NEXT-PIXEL"

            with m.State("NEXT-PIXEL"):
                # Output current coordinates
                m.d.sync += [
                    self.o_x.eq(Mux(self.r_steep, self.r_y0, self.r_x0) >> 4),
                    self.o_y.eq(Mux(self.r_steep, self.r_x0, self.r_y0) >> 4),

                    self.o_r.eq(self.r_red >> 4),
                    self.o_g.eq(self.r_green >> 4),
                    self.o_b.eq(self.r_blue >> 4),

                    self.o_valid.eq(1),
                    self.o_last.eq(self.r_x0 > self.r_x1)
                ]

                # Calculate next coordinates
                m.d.sync += [
                    self.r_error.eq(self.r_error + (self.r_dy << 1)),
                    self.r_x0.eq(self.r_x0 + self.one),

                    self.r_red.eq(self.r_red + self.r_rdiv.o_result),
                    self.r_green.eq(self.r_green + self.r_gdiv.o_result),
                    self.r_blue.eq(self.r_blue + self.r_bdiv.o_result)
                ]

                with m.If(self.o_last):
                    m.next = "FINISH"
                with m.Else():
                    m.next = "WAIT"
                
            # Wait for pixel acknowledgement before continuing.
            # While waiting, pre-calculate the next coordinates.
            with m.State("WAIT"):
                # If error goes above threshold, update Y
                with m.If(self.r_error > self.r_dx):
                    m.d.sync += [
                        self.r_y0.eq(self.r_y0 + self.r_y_inc),
                        self.r_error.eq(self.r_error - (self.r_dx << 1))
                    ]

                with m.If(self.i_next):
                    m.next = "NEXT-PIXEL"

            # Wait for pixel acknowledgement before resetting.
            with m.State("FINISH"):
                m.d.sync += [
                    self.r_rdiv.i_reset.eq(1),
                    self.r_gdiv.i_reset.eq(1),
                    self.r_bdiv.i_reset.eq(1)
                ]

                with m.If(self.i_next):
                    m.next = "START"

        return m
Example #23
0
    def elaborate(self, platform):
        m = Module()

        with m.FSM() as fsm:
            with m.State("START"):
                m.d.sync += self.o_ready.eq(0)

                m.d.sync += self.r_colour.eq(self.i_colour << 4)

                # The following mess calculates the reciprocal of i_dx
                # as a Q12.4 fixed-point number.
                m.d.sync += self.r_recip.eq(0)
                with m.If((self.i_dx >= 0) & (self.i_dx < 1)): m.d.sync += self.r_recip.eq(0)
                with m.If((self.i_dx >= 1) & (self.i_dx < 2)): m.d.sync += self.r_recip.eq(4096)
                with m.If((self.i_dx >= 2) & (self.i_dx < 3)): m.d.sync += self.r_recip.eq(2048)
                with m.If((self.i_dx >= 3) & (self.i_dx < 4)): m.d.sync += self.r_recip.eq(1365)
                with m.If((self.i_dx >= 4) & (self.i_dx < 5)): m.d.sync += self.r_recip.eq(1024)
                with m.If((self.i_dx >= 5) & (self.i_dx < 6)): m.d.sync += self.r_recip.eq(819)
                with m.If((self.i_dx >= 6) & (self.i_dx < 7)): m.d.sync += self.r_recip.eq(682)
                with m.If((self.i_dx >= 7) & (self.i_dx < 8)): m.d.sync += self.r_recip.eq(585)
                with m.If((self.i_dx >= 8) & (self.i_dx < 9)): m.d.sync += self.r_recip.eq(512)
                with m.If((self.i_dx >= 9) & (self.i_dx < 10)): m.d.sync += self.r_recip.eq(455)
                with m.If((self.i_dx >= 10) & (self.i_dx < 11)): m.d.sync += self.r_recip.eq(409)
                with m.If((self.i_dx >= 11) & (self.i_dx < 12)): m.d.sync += self.r_recip.eq(372)
                with m.If((self.i_dx >= 12) & (self.i_dx < 13)): m.d.sync += self.r_recip.eq(341)
                with m.If((self.i_dx >= 13) & (self.i_dx < 14)): m.d.sync += self.r_recip.eq(315)
                with m.If((self.i_dx >= 14) & (self.i_dx < 15)): m.d.sync += self.r_recip.eq(292)
                with m.If((self.i_dx >= 15) & (self.i_dx < 16)): m.d.sync += self.r_recip.eq(273)
                with m.If((self.i_dx >= 16) & (self.i_dx < 17)): m.d.sync += self.r_recip.eq(256)
                with m.If((self.i_dx >= 17) & (self.i_dx < 18)): m.d.sync += self.r_recip.eq(240)
                with m.If((self.i_dx >= 18) & (self.i_dx < 19)): m.d.sync += self.r_recip.eq(227)
                with m.If((self.i_dx >= 19) & (self.i_dx < 20)): m.d.sync += self.r_recip.eq(215)
                with m.If((self.i_dx >= 20) & (self.i_dx < 21)): m.d.sync += self.r_recip.eq(204)
                with m.If((self.i_dx >= 21) & (self.i_dx < 22)): m.d.sync += self.r_recip.eq(195)
                with m.If((self.i_dx >= 22) & (self.i_dx < 23)): m.d.sync += self.r_recip.eq(186)
                with m.If((self.i_dx >= 23) & (self.i_dx < 24)): m.d.sync += self.r_recip.eq(178)
                with m.If((self.i_dx >= 24) & (self.i_dx < 25)): m.d.sync += self.r_recip.eq(170)
                with m.If((self.i_dx >= 25) & (self.i_dx < 26)): m.d.sync += self.r_recip.eq(163)
                with m.If((self.i_dx >= 26) & (self.i_dx < 27)): m.d.sync += self.r_recip.eq(157)
                with m.If((self.i_dx >= 27) & (self.i_dx < 28)): m.d.sync += self.r_recip.eq(151)
                with m.If((self.i_dx >= 28) & (self.i_dx < 29)): m.d.sync += self.r_recip.eq(146)
                with m.If((self.i_dx >= 29) & (self.i_dx < 30)): m.d.sync += self.r_recip.eq(141)
                with m.If((self.i_dx >= 30) & (self.i_dx < 31)): m.d.sync += self.r_recip.eq(136)
                with m.If((self.i_dx >= 31) & (self.i_dx < 32)): m.d.sync += self.r_recip.eq(132)
                with m.If((self.i_dx >= 32) & (self.i_dx < 33)): m.d.sync += self.r_recip.eq(128)
                with m.If((self.i_dx >= 33) & (self.i_dx < 34)): m.d.sync += self.r_recip.eq(124)
                with m.If((self.i_dx >= 34) & (self.i_dx < 35)): m.d.sync += self.r_recip.eq(120)
                with m.If((self.i_dx >= 35) & (self.i_dx < 36)): m.d.sync += self.r_recip.eq(117)
                with m.If((self.i_dx >= 36) & (self.i_dx < 37)): m.d.sync += self.r_recip.eq(113)
                with m.If((self.i_dx >= 37) & (self.i_dx < 38)): m.d.sync += self.r_recip.eq(110)
                with m.If((self.i_dx >= 38) & (self.i_dx < 39)): m.d.sync += self.r_recip.eq(107)
                with m.If((self.i_dx >= 39) & (self.i_dx < 40)): m.d.sync += self.r_recip.eq(105)
                with m.If((self.i_dx >= 40) & (self.i_dx < 41)): m.d.sync += self.r_recip.eq(102)
                with m.If((self.i_dx >= 41) & (self.i_dx < 42)): m.d.sync += self.r_recip.eq(99)
                with m.If((self.i_dx >= 42) & (self.i_dx < 43)): m.d.sync += self.r_recip.eq(97)
                with m.If((self.i_dx >= 43) & (self.i_dx < 44)): m.d.sync += self.r_recip.eq(95)
                with m.If((self.i_dx >= 44) & (self.i_dx < 45)): m.d.sync += self.r_recip.eq(93)
                with m.If((self.i_dx >= 45) & (self.i_dx < 46)): m.d.sync += self.r_recip.eq(91)
                with m.If((self.i_dx >= 46) & (self.i_dx < 47)): m.d.sync += self.r_recip.eq(89)
                with m.If((self.i_dx >= 47) & (self.i_dx < 48)): m.d.sync += self.r_recip.eq(87)
                with m.If((self.i_dx >= 48) & (self.i_dx < 49)): m.d.sync += self.r_recip.eq(85)
                with m.If((self.i_dx >= 49) & (self.i_dx < 50)): m.d.sync += self.r_recip.eq(83)
                with m.If((self.i_dx >= 50) & (self.i_dx < 51)): m.d.sync += self.r_recip.eq(81)
                with m.If((self.i_dx >= 51) & (self.i_dx < 52)): m.d.sync += self.r_recip.eq(80)
                with m.If((self.i_dx >= 52) & (self.i_dx < 53)): m.d.sync += self.r_recip.eq(78)
                with m.If((self.i_dx >= 53) & (self.i_dx < 54)): m.d.sync += self.r_recip.eq(77)
                with m.If((self.i_dx >= 54) & (self.i_dx < 55)): m.d.sync += self.r_recip.eq(75)
                with m.If((self.i_dx >= 55) & (self.i_dx < 56)): m.d.sync += self.r_recip.eq(74)
                with m.If((self.i_dx >= 56) & (self.i_dx < 57)): m.d.sync += self.r_recip.eq(73)
                with m.If((self.i_dx >= 57) & (self.i_dx < 58)): m.d.sync += self.r_recip.eq(71)
                with m.If((self.i_dx >= 58) & (self.i_dx < 59)): m.d.sync += self.r_recip.eq(70)
                with m.If((self.i_dx >= 59) & (self.i_dx < 60)): m.d.sync += self.r_recip.eq(69)
                with m.If((self.i_dx >= 60) & (self.i_dx < 61)): m.d.sync += self.r_recip.eq(68)
                with m.If((self.i_dx >= 61) & (self.i_dx < 62)): m.d.sync += self.r_recip.eq(67)
                with m.If((self.i_dx >= 62) & (self.i_dx < 63)): m.d.sync += self.r_recip.eq(66)
                with m.If((self.i_dx >= 63) & (self.i_dx < 64)): m.d.sync += self.r_recip.eq(65)
                with m.If((self.i_dx >= 64) & (self.i_dx < 65)): m.d.sync += self.r_recip.eq(64)
                with m.If((self.i_dx >= 65) & (self.i_dx < 66)): m.d.sync += self.r_recip.eq(63)
                with m.If((self.i_dx >= 66) & (self.i_dx < 67)): m.d.sync += self.r_recip.eq(62)
                with m.If((self.i_dx >= 67) & (self.i_dx < 68)): m.d.sync += self.r_recip.eq(61)
                with m.If((self.i_dx >= 68) & (self.i_dx < 69)): m.d.sync += self.r_recip.eq(60)
                with m.If((self.i_dx >= 69) & (self.i_dx < 70)): m.d.sync += self.r_recip.eq(59)
                with m.If((self.i_dx >= 70) & (self.i_dx < 71)): m.d.sync += self.r_recip.eq(58)
                with m.If((self.i_dx >= 71) & (self.i_dx < 72)): m.d.sync += self.r_recip.eq(57)
                with m.If((self.i_dx >= 72) & (self.i_dx < 74)): m.d.sync += self.r_recip.eq(56)
                with m.If((self.i_dx >= 74) & (self.i_dx < 75)): m.d.sync += self.r_recip.eq(55)
                with m.If((self.i_dx >= 75) & (self.i_dx < 76)): m.d.sync += self.r_recip.eq(54)
                with m.If((self.i_dx >= 76) & (self.i_dx < 78)): m.d.sync += self.r_recip.eq(53)
                with m.If((self.i_dx >= 78) & (self.i_dx < 79)): m.d.sync += self.r_recip.eq(52)
                with m.If((self.i_dx >= 79) & (self.i_dx < 81)): m.d.sync += self.r_recip.eq(51)
                with m.If((self.i_dx >= 81) & (self.i_dx < 82)): m.d.sync += self.r_recip.eq(50)
                with m.If((self.i_dx >= 82) & (self.i_dx < 84)): m.d.sync += self.r_recip.eq(49)
                with m.If((self.i_dx >= 84) & (self.i_dx < 86)): m.d.sync += self.r_recip.eq(48)
                with m.If((self.i_dx >= 86) & (self.i_dx < 88)): m.d.sync += self.r_recip.eq(47)
                with m.If((self.i_dx >= 88) & (self.i_dx < 90)): m.d.sync += self.r_recip.eq(46)
                with m.If((self.i_dx >= 90) & (self.i_dx < 92)): m.d.sync += self.r_recip.eq(45)
                with m.If((self.i_dx >= 92) & (self.i_dx < 94)): m.d.sync += self.r_recip.eq(44)
                with m.If((self.i_dx >= 94) & (self.i_dx < 96)): m.d.sync += self.r_recip.eq(43)
                with m.If((self.i_dx >= 96) & (self.i_dx < 98)): m.d.sync += self.r_recip.eq(42)
                with m.If((self.i_dx >= 98) & (self.i_dx < 100)): m.d.sync += self.r_recip.eq(41)
                with m.If((self.i_dx >= 100) & (self.i_dx < 103)): m.d.sync += self.r_recip.eq(40)
                with m.If((self.i_dx >= 103) & (self.i_dx < 106)): m.d.sync += self.r_recip.eq(39)
                with m.If((self.i_dx >= 106) & (self.i_dx < 108)): m.d.sync += self.r_recip.eq(38)
                with m.If((self.i_dx >= 108) & (self.i_dx < 111)): m.d.sync += self.r_recip.eq(37)
                with m.If((self.i_dx >= 111) & (self.i_dx < 114)): m.d.sync += self.r_recip.eq(36)
                with m.If((self.i_dx >= 114) & (self.i_dx < 118)): m.d.sync += self.r_recip.eq(35)
                with m.If((self.i_dx >= 118) & (self.i_dx < 121)): m.d.sync += self.r_recip.eq(34)
                with m.If((self.i_dx >= 121) & (self.i_dx < 125)): m.d.sync += self.r_recip.eq(33)
                with m.If((self.i_dx >= 125) & (self.i_dx < 129)): m.d.sync += self.r_recip.eq(32)
                with m.If((self.i_dx >= 129) & (self.i_dx < 133)): m.d.sync += self.r_recip.eq(31)
                with m.If((self.i_dx >= 133) & (self.i_dx < 137)): m.d.sync += self.r_recip.eq(30)
                with m.If((self.i_dx >= 137) & (self.i_dx < 142)): m.d.sync += self.r_recip.eq(29)
                with m.If((self.i_dx >= 142) & (self.i_dx < 147)): m.d.sync += self.r_recip.eq(28)
                with m.If((self.i_dx >= 147) & (self.i_dx < 152)): m.d.sync += self.r_recip.eq(27)
                with m.If((self.i_dx >= 152) & (self.i_dx < 158)): m.d.sync += self.r_recip.eq(26)
                with m.If((self.i_dx >= 158) & (self.i_dx < 164)): m.d.sync += self.r_recip.eq(25)
                with m.If((self.i_dx >= 164) & (self.i_dx < 171)): m.d.sync += self.r_recip.eq(24)
                with m.If((self.i_dx >= 171) & (self.i_dx < 179)): m.d.sync += self.r_recip.eq(23)
                with m.If((self.i_dx >= 179) & (self.i_dx < 187)): m.d.sync += self.r_recip.eq(22)
                with m.If((self.i_dx >= 187) & (self.i_dx < 196)): m.d.sync += self.r_recip.eq(21)
                with m.If((self.i_dx >= 196) & (self.i_dx < 205)): m.d.sync += self.r_recip.eq(20)
                with m.If((self.i_dx >= 205) & (self.i_dx < 216)): m.d.sync += self.r_recip.eq(19)
                with m.If((self.i_dx >= 216) & (self.i_dx < 228)): m.d.sync += self.r_recip.eq(18)
                with m.If((self.i_dx >= 228) & (self.i_dx < 241)): m.d.sync += self.r_recip.eq(17)
                with m.If((self.i_dx >= 241) & (self.i_dx < 257)): m.d.sync += self.r_recip.eq(16)
                with m.If((self.i_dx >= 257) & (self.i_dx < 274)): m.d.sync += self.r_recip.eq(15)
                with m.If((self.i_dx >= 274) & (self.i_dx < 293)): m.d.sync += self.r_recip.eq(14)
                with m.If((self.i_dx >= 293) & (self.i_dx < 316)): m.d.sync += self.r_recip.eq(13)
                with m.If((self.i_dx >= 316) & (self.i_dx < 342)): m.d.sync += self.r_recip.eq(12)
                with m.If((self.i_dx >= 342) & (self.i_dx < 373)): m.d.sync += self.r_recip.eq(11)
                with m.If((self.i_dx >= 373) & (self.i_dx < 410)): m.d.sync += self.r_recip.eq(10)
                with m.If((self.i_dx >= 410) & (self.i_dx < 456)): m.d.sync += self.r_recip.eq(9)
                with m.If((self.i_dx >= 456) & (self.i_dx < 513)): m.d.sync += self.r_recip.eq(8)
                with m.If((self.i_dx >= 513) & (self.i_dx < 586)): m.d.sync += self.r_recip.eq(7)
                with m.If((self.i_dx >= 586) & (self.i_dx < 683)): m.d.sync += self.r_recip.eq(6)
                with m.If((self.i_dx >= 683) & (self.i_dx < 820)): m.d.sync += self.r_recip.eq(5)
                with m.If((self.i_dx >= 820) & (self.i_dx < 1025)): m.d.sync += self.r_recip.eq(4)
                with m.If((self.i_dx >= 1025) & (self.i_dx < 1366)): m.d.sync += self.r_recip.eq(3)
                with m.If((self.i_dx >= 1366) & (self.i_dx < 2049)): m.d.sync += self.r_recip.eq(2)
                with m.If((self.i_dx >= 2049) & (self.i_dx < 4097)): m.d.sync += self.r_recip.eq(1)

                with m.If(self.i_start):
                    m.next = "RECIP"
                
            with m.State("RECIP"):
                m.d.sync += self.o_ready.eq(1)
                m.d.sync += self.o_result.eq(self.r_colour * self.r_recip)

            with m.State("DONE"):
                with m.If(self.i_reset):
                    m.next = "START"

        return m
Example #24
0
File: mac.py Project: ret/daqnet
    def elaborate(self, platform):
        m = Module()

        # Create MDIO submodule
        clk_div = int(self.clk_freq // 2.5e6)
        m.submodules.mdio = mdio = MDIO(clk_div, self.mdio, self.mdc)
        self.mdio_mod = mdio
        mdio.phy_addr = Const(self.phy_addr)

        # Latches for registers we read
        bsr = Signal(16)

        # Compute output signal from registers
        m.d.comb += self.link_up.eq(bsr[2] &  # Link must be up
                                    ~bsr[4] &  # No remote fault
                                    bsr[5] &  # Autonegotiation complete
                                    bsr[14]  # 100Mbps full duplex
                                    )

        registers_to_write = [
            # Enable 100Mbps, autonegotiation, and full-duplex
            # ("BCR", 0x00, (1 << 13) | (1 << 12) | (1 << 8)),
        ]

        registers_to_read = [
            # Basic status register contains everything we need to know
            ("BSR", 0x01, bsr),
        ]

        # Controller FSM
        one_ms = int(self.clk_freq // 1000)
        counter = Signal(max=one_ms)
        with m.FSM():

            # Assert PHY_RST and begin 1ms counter
            with m.State("RESET"):
                m.d.comb += self.phy_rst.eq(0)
                m.d.sync += counter.eq(one_ms)
                m.next = "RESET_WAIT"

            # Wait for reset timeout
            with m.State("RESET_WAIT"):
                m.d.comb += self.phy_rst.eq(0)
                m.d.sync += counter.eq(counter - 1)
                with m.If(self.phy_reset):
                    m.next = "RESET"
                with m.Elif(counter == 0):
                    m.d.sync += counter.eq(one_ms)
                    write = bool(registers_to_write)
                    m.next = "WRITE_WAIT" if write else "POLL_WAIT"

            # Wait 1ms before writing
            if registers_to_write:
                with m.State("WRITE_WAIT"):
                    m.d.comb += self.phy_rst.eq(1),
                    m.d.sync += counter.eq(counter - 1)
                    with m.If(self.phy_reset):
                        m.next = "RESET"
                    with m.Elif(counter == 0):
                        m.next = f"WRITE_{registers_to_write[0][0]}"
            else:
                m.d.comb += mdio.write_data.eq(0)

            for idx, (name, addr, val) in enumerate(registers_to_write):
                if idx == len(registers_to_write) - 1:
                    next_state = "POLL_WAIT"
                else:
                    next_state = f"WRITE_{registers_to_write[idx+1][0]}"

                with m.State(f"WRITE_{name}"):
                    m.d.comb += [
                        self.phy_rst.eq(0),
                        mdio.reg_addr.eq(Const(addr)),
                        mdio.rw.eq(1),
                        mdio.write_data.eq(Const(val)),
                        mdio.start.eq(1),
                    ]

                    with m.If(self.phy_reset):
                        m.next = "RESET"
                    with m.Elif(mdio.busy):
                        m.next = f"WRITE_{name}_WAIT"

                with m.State(f"WRITE_{name}_WAIT"):
                    m.d.comb += [
                        self.phy_rst.eq(1),
                        mdio.reg_addr.eq(0),
                        mdio.rw.eq(0),
                        mdio.write_data.eq(0),
                        mdio.start.eq(0),
                    ]
                    with m.If(self.phy_reset):
                        m.next = "RESET"
                    with m.Elif(~mdio.busy):
                        m.d.sync += counter.eq(one_ms)
                        m.next = next_state

            # Wait 1ms between polls
            with m.State("POLL_WAIT"):
                m.d.comb += self.phy_rst.eq(1)
                m.d.sync += counter.eq(counter - 1)
                with m.If(self.phy_reset):
                    m.next = "RESET"
                with m.Elif(counter == 0):
                    m.next = f"POLL_{registers_to_read[0][0]}"

            for idx, (name, addr, latch) in enumerate(registers_to_read):
                if idx == len(registers_to_read) - 1:
                    next_state = "POLL_WAIT"
                else:
                    next_state = f"POLL_{registers_to_read[idx+1][0]}"

                # Trigger a read of the register
                with m.State(f"POLL_{name}"):
                    m.d.comb += [
                        self.phy_rst.eq(1),
                        mdio.reg_addr.eq(Const(addr)),
                        mdio.rw.eq(0),
                        mdio.start.eq(1),
                    ]

                    with m.If(self.phy_reset):
                        m.next = "RESET"
                    with m.Elif(mdio.busy):
                        m.next = f"POLL_{name}_WAIT"

                # Wait for MDIO to stop being busy
                with m.State(f"POLL_{name}_WAIT"):
                    m.d.comb += [
                        self.phy_rst.eq(1),
                        mdio.reg_addr.eq(0),
                        mdio.rw.eq(0),
                        mdio.start.eq(0),
                    ]

                    with m.If(self.phy_reset):
                        m.next = "RESET"
                    with m.Elif(~mdio.busy):
                        m.d.sync += [
                            latch.eq(mdio.read_data),
                            counter.eq(one_ms),
                        ]
                        m.next = next_state

        return m
Example #25
0
    def elaborate(self, platform):
        m = Module()

        #
        # Transciever state.
        #

        # Handle our PID-sequence reset.
        # Note that we store the _inverse_ of our data PID, as we'll toggle our DATA PID
        # before sending.
        with m.If(self.reset_sequence):
            m.d.usb += self.data_pid.eq(~self.start_with_data1)

        #
        # Transmit buffer.
        #
        # Our USB connection imposed a few requirements on our stream:
        # 1) we must be able to transmit packets at a full rate; i.e.
        #    must be asserted from the start to the end of our transfer; and
        # 2) we must be able to re-transmit data if a given packet is not ACK'd.
        #
        # Accordingly, we'll buffer a full USB packet of data, and then transmit
        # it once either a) our buffer is full, or 2) the transfer ends (last=1).
        #
        # This implementation is double buffered; so a buffer fill can be pipelined
        # with a transmit.
        #

        # We'll create two buffers; so we can fill one as we empty the other.
        # Since each buffer will be used for every other transaction, and our PID toggle flips every other transcation,
        # we'll identify which buffer we're targeting by the current PID toggle.
        buffer = Array(
            Memory(width=8,
                   depth=self._max_packet_size,
                   name=f"transmit_buffer_{i}") for i in range(2))
        buffer_write_ports = Array(buffer[i].write_port(domain="usb")
                                   for i in range(2))
        buffer_read_ports = Array(buffer[i].read_port(domain="usb")
                                  for i in range(2))

        m.submodules.read_port_0, m.submodules.read_port_1 = buffer_read_ports
        m.submodules.write_port_0, m.submodules.write_port_1 = buffer_write_ports

        # Create values equivalent to the buffer numbers for our read and write buffer; which switch
        # whenever we swap our two buffers.
        write_buffer_number = self.data_pid[0]
        read_buffer_number = ~self.data_pid[0]

        # Create a shorthand that refers to the buffer to be filled; and the buffer to send from.
        # We'll call these the Read and Write buffers.
        buffer_write = buffer_write_ports[write_buffer_number]
        buffer_read = buffer_read_ports[read_buffer_number]

        # Buffer state tracking:
        # - Our ``fill_count`` keeps track of how much data is stored in a given buffer.
        # - Our ``stream_ended`` bit keeps track of whether the stream ended while filling up
        #   the given buffer. This indicates that the buffer cannot be filled further; and, when
        #   ``generate_zlps`` is enabled, is used to determine if the given buffer should end in
        #   a short packet; which determines whether ZLPs are emitted.
        buffer_fill_count = Array(
            Signal(range(0, self._max_packet_size + 1)) for _ in range(2))
        buffer_stream_ended = Array(
            Signal(name=f"stream_ended_in_buffer{i}") for i in range(2))

        # Create shortcuts to active fill_count / stream_ended signals for the buffer being written.
        write_fill_count = buffer_fill_count[write_buffer_number]
        write_stream_ended = buffer_stream_ended[write_buffer_number]

        # Create shortcuts to the fill_count / stream_ended signals for the packet being sent.
        read_fill_count = buffer_fill_count[read_buffer_number]
        read_stream_ended = buffer_stream_ended[read_buffer_number]

        # Keep track of our current send position; which determines where we are in the packet.
        send_position = Signal(range(0, self._max_packet_size + 1))

        # Shortcut names.
        in_stream = self.transfer_stream
        out_stream = self.packet_stream

        # Use our memory's two ports to capture data from our transfer stream; and two emit packets
        # into our packet stream. Since we'll never receive to anywhere else, or transmit to anywhere else,
        # we can just unconditionally connect these.
        m.d.comb += [

            # We'll only ever -write- data from our input stream...
            buffer_write_ports[0].data.eq(in_stream.payload),
            buffer_write_ports[0].addr.eq(write_fill_count),
            buffer_write_ports[1].data.eq(in_stream.payload),
            buffer_write_ports[1].addr.eq(write_fill_count),

            # ... and we'll only ever -send- data from the Read buffer.
            buffer_read.addr.eq(send_position),
            out_stream.payload.eq(buffer_read.data),

            # We're ready to receive data iff we have space in the buffer we're currently filling.
            in_stream.ready.eq((write_fill_count != self._max_packet_size)
                               & ~write_stream_ended),
            buffer_write.en.eq(in_stream.valid & in_stream.ready)
        ]

        # Increment our fill count whenever we accept new data.
        with m.If(buffer_write.en):
            m.d.usb += write_fill_count.eq(write_fill_count + 1)

        # If the stream ends while we're adding data to the buffer, mark this as an ended stream.
        with m.If(in_stream.last & buffer_write.en):
            m.d.usb += write_stream_ended.eq(1)

        # Shortcut for when we need to deal with an in token.
        # Pulses high an interpacket delay after receiving an IN token.
        in_token_received = self.active & self.tokenizer.is_in & self.tokenizer.ready_for_response

        with m.FSM(domain='usb'):

            # WAIT_FOR_DATA -- We don't yet have a full packet to transmit, so  we'll capture data
            # to fill the our buffer. At full throughput, this state will never be reached after
            # the initial post-reset fill.
            with m.State("WAIT_FOR_DATA"):

                # We can't yet send data; so NAK any packet requests.
                m.d.comb += self.handshakes_out.nak.eq(in_token_received)

                # If we have valid data that will end our packet, we're no longer waiting for data.
                # We'll now wait for the host to request data from us.
                packet_complete = (write_fill_count +
                                   1 == self._max_packet_size)
                will_end_packet = packet_complete | in_stream.last

                with m.If(in_stream.valid & will_end_packet):

                    # If we've just finished a packet, we now have data we can send!
                    with m.If(packet_complete | in_stream.last):
                        m.next = "WAIT_TO_SEND"
                        m.d.usb += [

                            # We're now ready to take the data we've captured and _transmit_ it.
                            # We'll swap our read and write buffers, and toggle our data PID.
                            self.data_pid[0].eq(~self.data_pid[0]),

                            # Mark our current stream as no longer having ended.
                            read_stream_ended.eq(0)
                        ]

            # WAIT_TO_SEND -- we now have at least a buffer full of data to send; we'll
            # need to wait for an IN token to send it.
            with m.State("WAIT_TO_SEND"):
                m.d.usb += send_position.eq(0),

                # Once we get an IN token, move to sending a packet.
                with m.If(in_token_received):

                    # If we have a packet to send, send it.
                    with m.If(read_fill_count):
                        m.next = "SEND_PACKET"
                        m.d.usb += out_stream.first.eq(1)

                    # Otherwise, we entered a transmit path without any data in the buffer.
                    with m.Else():
                        m.d.comb += [
                            # Send a ZLP...
                            out_stream.valid.eq(1),
                            out_stream.last.eq(1),
                        ]
                        # ... and clear the need to follow up with one, since we've just sent a short packet.
                        m.d.usb += read_stream_ended.eq(0)
                        m.next = "WAIT_FOR_ACK"

            with m.State("SEND_PACKET"):
                last_packet = (send_position + 1 == read_fill_count)

                m.d.comb += [
                    # We're always going to be sending valid data, since data is always
                    # available from our memory.
                    out_stream.valid.eq(1),

                    # Let our transmitter know when we've reached our last packet.
                    out_stream.last.eq(last_packet)
                ]

                # Once our transmitter accepts our data...
                with m.If(out_stream.ready):

                    m.d.usb += [
                        # ... move to the next byte in our packet ...
                        send_position.eq(send_position + 1),

                        # ... and mark our packet as no longer the first.
                        out_stream.first.eq(0)
                    ]

                    # Move our memory pointer to its next position.
                    m.d.comb += buffer_read.addr.eq(send_position + 1),

                    # If we've just sent our last packet, we're now ready to wait for a
                    # response from our host.
                    with m.If(last_packet):
                        m.next = 'WAIT_FOR_ACK'

            # WAIT_FOR_ACK -- We've just sent a packet; but don't know if the host has
            # received it correctly. We'll wait to see if the host ACKs.
            with m.State("WAIT_FOR_ACK"):

                # If the host does ACK...
                with m.If(self.handshakes_in.ack):
                    # ... clear the data we've sent from our buffer.
                    m.d.usb += read_fill_count.eq(0)

                    # Figure out if we'll need to follow up with a ZLP. If we have ZLP generation enabled,
                    # we'll make sure we end on a short packet. If this is max-packet-size packet _and_ our
                    # transfer ended with this packet; we'll need to inject a ZLP.
                    follow_up_with_zlp = \
                        self.generate_zlps & (read_fill_count == self._max_packet_size) & read_stream_ended

                    # If we're following up with a ZLP, move back to our "wait to send" state.
                    # Since we've now cleared our fill count; this next go-around will emit a ZLP.
                    with m.If(follow_up_with_zlp):
                        m.next = "WAIT_TO_SEND"

                    # Otherwise, there's a possibility we already have a packet-worth of data waiting
                    # for us in our "write buffer", which we've been filling in the background.
                    # If this is the case, we'll flip which buffer we're working with, toggle our data pid,
                    # and then ready ourselves for transmit.
                    packet_completing = in_stream.valid & (
                        write_fill_count + 1 == self._max_packet_size)
                    with m.Elif(~in_stream.ready | packet_completing):
                        m.next = "WAIT_TO_SEND"
                        m.d.usb += [
                            self.data_pid[0].eq(~self.data_pid[0]),
                            read_stream_ended.eq(0)
                        ]

                    # If neither of the above conditions are true; we now don't have enough data to send.
                    # We'll wait for enough data to transmit.
                    with m.Else():
                        m.next = "WAIT_FOR_DATA"

                # If the host starts a new packet without ACK'ing, we'll need to retransmit.
                # We'll move back to our "wait for token" state without clearing our buffer.
                with m.If(self.tokenizer.new_token):
                    m.next = 'WAIT_TO_SEND'

        return m
Example #26
0
    def elaborate(self, platform):
        m = Module()


        #
        # Core ROM.
        #

        data_length = len(self.data)

        rom = Memory(width=self.data_width, depth=data_length, init=self.data)
        m.submodules.rom_read_port = rom_read_port = rom.read_port()

        # Register that stores our current position in the stream.
        position_in_stream = Signal(range(0, data_length))

        # Track when we're on the first and last packet.
        on_first_packet = position_in_stream == 0
        on_last_packet  = \
            (position_in_stream == (data_length - 1))      | \
            (position_in_stream == (self.max_length - 1))

        m.d.comb += [
            # Always drive the stream from our current memory output...
            self.stream.payload  .eq(rom_read_port.data),

            ## ... and base First and Last based on our current position in the stream.
            self.stream.first    .eq(on_first_packet & self.stream.valid),
            self.stream.last     .eq(on_last_packet  & self.stream.valid)
        ]



        #
        # Controller.
        #
        with m.FSM(domain=self.domain) as fsm:
            m.d.comb += self.stream.valid.eq(fsm.ongoing('STREAMING'))

            # IDLE -- we're not actively transmitting.
            with m.State('IDLE'):

                # Keep ourselves at the beginning of the stream, but don't yet count.
                m.d.sync += position_in_stream.eq(0)

                # Once the user requests that we start, move to our stream being valid.
                with m.If(self.start & (self.max_length > 0)):
                    m.next = 'STREAMING'


            # STREAMING -- we're actively transmitting data
            with m.State('STREAMING'):
                m.d.comb += [
                    rom_read_port.addr  .eq(position_in_stream)
                ]

                # If the current data byte is accepted, move past it.
                with m.If(self.stream.ready):

                    should_continue = \
                        ((position_in_stream + 1) < self.max_length) & \
                        ((position_in_stream + 1) < data_length)

                    # If there's still data left to transmit, move forward.
                    with m.If(should_continue):
                        m.d.sync += position_in_stream.eq(position_in_stream + 1)
                        m.d.comb += rom_read_port.addr.eq(position_in_stream + 1)

                    # Otherwise, we've finished streaming. Return to IDLE.
                    with m.Else():
                        m.next = 'DONE'

            # DONE -- report our completion; and then return to idle
            with m.State('DONE'):
                m.d.comb += self.done.eq(1)
                m.next = 'IDLE'


        # 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
Example #27
0
File: standard.py Project: zyp/luna
    def elaborate(self, platform):
        m = Module()
        interface = self.interface

        # Create convenience aliases for our interface components.
        setup = interface.setup
        handshake_generator = interface.handshakes_out
        tx = interface.tx

        #
        # Submodules
        #

        # Handler for Get Descriptor requests; responds with our various fixed descriptors.
        m.submodules.get_descriptor = get_descriptor_handler = GetDescriptorHandler(
            self.descriptors)
        m.d.comb += [
            get_descriptor_handler.value.eq(setup.value),
            get_descriptor_handler.length.eq(setup.length),
        ]

        # Handler for various small-constant-response requests (GET_CONFIGURATION, GET_STATUS).
        m.submodules.transmitter = transmitter = \
            StreamSerializer(data_length=2, domain="usb", stream_type=USBInStreamInterface, max_length_width=2)

        #
        # Handlers.
        #
        with m.If(setup.type == USBRequestType.STANDARD):
            with m.FSM(domain="usb"):

                # IDLE -- not handling any active request
                with m.State('IDLE'):

                    # If we've received a new setup packet, handle it.
                    with m.If(setup.received):

                        # Select which standard packet we're going to handler.
                        with m.Switch(setup.request):

                            with m.Case(USBStandardRequests.GET_STATUS):
                                m.next = 'GET_STATUS'
                            with m.Case(USBStandardRequests.SET_ADDRESS):
                                m.next = 'SET_ADDRESS'
                            with m.Case(USBStandardRequests.SET_CONFIGURATION):
                                m.next = 'SET_CONFIGURATION'
                            with m.Case(USBStandardRequests.GET_DESCRIPTOR):
                                m.next = 'GET_DESCRIPTOR'
                            with m.Case(USBStandardRequests.GET_CONFIGURATION):
                                m.next = 'GET_CONFIGURATION'
                            with m.Case():
                                m.next = 'UNHANDLED'

                # GET_STATUS -- Fetch the device's status.
                # For now, we'll always return '0'.
                with m.State('GET_STATUS'):
                    # TODO: handle reporting endpoint stall status
                    # TODO: copy the remote wakeup and bus-powered attributes from bmAttributes of the relevant descriptor?
                    self.handle_simple_data_request(m,
                                                    transmitter,
                                                    0,
                                                    length=2)

                # SET_ADDRESS -- The host is trying to assign us an address.
                with m.State('SET_ADDRESS'):
                    self.handle_register_write_request(
                        m, interface.new_address, interface.address_changed)

                # SET_CONFIGURATION -- The host is trying to select an active configuration.
                with m.State('SET_CONFIGURATION'):
                    # TODO: stall if we don't have a relevant configuration
                    self.handle_register_write_request(
                        m, interface.new_config, interface.config_changed)

                # GET_DESCRIPTOR -- The host is asking for a USB descriptor -- for us to "self describe".
                with m.State('GET_DESCRIPTOR'):
                    m.d.comb += [
                        get_descriptor_handler.tx.attach(tx),
                        handshake_generator.stall.eq(
                            get_descriptor_handler.stall)
                    ]

                    # Respond to our data stage with a descriptor...
                    with m.If(interface.data_requested):
                        m.d.comb += get_descriptor_handler.start.eq(1),

                    # ... and ACK our status stage.
                    with m.If(interface.status_requested):
                        m.d.comb += handshake_generator.ack.eq(1)
                        m.next = 'IDLE'

                # GET_CONFIGURATION -- The host is asking for the active configuration number.
                with m.State('GET_CONFIGURATION'):
                    self.handle_simple_data_request(m, transmitter,
                                                    interface.active_config)

                # UNHANDLED -- we've received a request we're not prepared to handle
                with m.State('UNHANDLED'):

                    # When we next have an opportunity to stall, do so,
                    # and then return to idle.
                    with m.If(interface.data_requested
                              | interface.status_requested):
                        m.d.comb += handshake_generator.stall.eq(1)
                        m.next = 'IDLE'

        return m
Example #28
0
File: request.py Project: zyp/luna
    def elaborate(self, platform):
        m = Module()

        # If we're standalone, generate the things we need.
        if self.standalone:

            # Create our tokenizer...
            m.submodules.tokenizer = tokenizer = USBTokenDetector(
                utmi=self.utmi)
            m.d.comb += tokenizer.interface.connect(self.tokenizer)

            # ... and our timer.
            m.submodules.timer = timer = USBInterpacketTimer()
            timer.add_interface(self.timer)

            m.d.comb += timer.speed.eq(self.speed)

        # Create a data-packet-deserializer, which we'll use to capture the
        # contents of the setup data packets.
        m.submodules.data_handler = data_handler = \
            USBDataPacketDeserializer(utmi=self.utmi, max_packet_size=8, create_crc_generator=self.standalone)
        m.d.comb += self.data_crc.connect(data_handler.data_crc)

        # Instruct our interpacket timer to begin counting when we complete receiving
        # our setup packet. This will allow us to track interpacket delays.
        m.d.comb += self.timer.start.eq(data_handler.new_packet)

        # Keep our output signals de-asserted unless specified.
        m.d.usb += [
            self.packet.received.eq(0),
        ]

        with m.FSM(domain="usb"):

            # IDLE -- we haven't yet detected a SETUP transaction directed at us
            with m.State('IDLE'):
                pid_matches = (self.tokenizer.pid == self.SETUP_PID)

                # If we're just received a new SETUP token addressed to us,
                # the next data packet is going to be for us.
                with m.If(pid_matches & self.tokenizer.new_token):
                    m.next = 'READ_DATA'

            # READ_DATA -- we've just seen a SETUP token, and are waiting for the
            # data payload of the transaction, which contains the setup packet.
            with m.State('READ_DATA'):

                # If we receive a token packet before we receive a DATA packet,
                # this is a PID mismatch. Bail out and start over.
                with m.If(self.tokenizer.new_token):
                    m.next = 'IDLE'

                # If we have a new packet, parse it as setup data.
                with m.If(data_handler.new_packet):

                    # If we got exactly eight bytes, this is a valid setup packet.
                    with m.If(data_handler.length == 8):

                        # Collect the signals that make up our bmRequestType [USB2, 9.3].
                        request_type = Cat(self.packet.recipient,
                                           self.packet.type,
                                           self.packet.is_in_request)

                        m.d.usb += [

                            # Parse the setup data itself...
                            request_type.eq(data_handler.packet[0]),
                            self.packet.request.eq(data_handler.packet[1]),
                            self.packet.value.eq(
                                Cat(data_handler.packet[2],
                                    data_handler.packet[3])),
                            self.packet.index.eq(
                                Cat(data_handler.packet[4],
                                    data_handler.packet[5])),
                            self.packet.length.eq(
                                Cat(data_handler.packet[6],
                                    data_handler.packet[7])),

                            # ... and indicate that we have new data.
                            self.packet.received.eq(1),
                        ]

                        # We'll now need to wait a receive-transmit delay before initiating our ACK.
                        # Per the USB 2.0 and ULPI 1.1 specifications:
                        #   - A HS device needs to wait 8 HS bit periods before transmitting [USB2, 7.1.18.2].
                        #     Each ULPI cycle is 8 HS bit periods, so we'll only need to wait one cycle.
                        #   - We'll use our interpacket delay timer for everything else.
                        with m.If(self.timer.tx_allowed
                                  | (self.speed == USBSpeed.HIGH)):

                            # If we're a high speed device, we only need to wait for a single ULPI cycle.
                            # Processing delays mean we've already met our interpacket delay; and we can ACK
                            # immediately.
                            m.d.comb += self.ack.eq(1)
                            m.next = "IDLE"

                        # For other cases, handle the interpacket delay by waiting.
                        with m.Else():
                            m.next = "INTERPACKET_DELAY"

                    # Otherwise, this isn't; and we should ignore it. [USB2, 8.5.3]
                    with m.Else():
                        m.next = "IDLE"

            # INTERPACKET -- wait for an inter-packet delay before responding
            with m.State('INTERPACKET_DELAY'):

                # ... and once it equals zero, ACK and return to idle.
                with m.If(self.timer.tx_allowed):
                    m.d.comb += self.ack.eq(1)
                    m.next = "IDLE"

        return m
Example #29
0
    def elaborate(self, platform):

        m = Module()
        spi = self.spi

        sample_edge = falling_edge_detector(m, spi.sck)

        # Bit counter: counts the number of bits received.
        max_bit_count = max(self.word_size, self.command_size)
        bit_count = Signal(range(0, max_bit_count + 1))

        # Shift registers for our command and data.
        current_command = Signal.like(self.command)
        current_word    = Signal.like(self.word_received)

        # De-assert our control signals unless explicitly asserted.
        m.d.sync += [
            self.command_ready.eq(0),
            self.word_complete.eq(0)
        ]

        with m.FSM():

            # STALL: entered when we can't accept new bits -- either when
            # CS starts asserted, or when we've received more data than expected.
            with m.State("STALL"):

                # Wait for CS to clear.
                with m.If(~spi.cs):
                    m.next = 'IDLE'


            # We ignore all data until chip select is asserted, as that data Isn't For Us (TM).
            # We'll spin and do nothing until the bus-master addresses us.
            with m.State('IDLE'):
                m.d.sync += bit_count.eq(0)

                with m.If(spi.cs):
                    m.next = 'RECEIVE_COMMAND'


            # Once CS is low, we'll shift in our command.
            with m.State('RECEIVE_COMMAND'):

                # Continue shifting in data until we have a full command.
                with m.If(bit_count < self.command_size):
                    with m.If(sample_edge):
                        m.d.sync += [
                            bit_count       .eq(bit_count + 1),
                            current_command .eq(Cat(spi.sdi, current_command[:-1]))
                        ]

                # ... and then pass that command out to our controller.
                with m.Else():
                    m.d.sync += [
                        bit_count          .eq(0),
                        self.command_ready .eq(1),
                        self.command       .eq(current_command)
                    ]
                    m.next = 'PROCESSING'


            # Give our controller a wait state to prepare any response they might want to...
            with m.State('PROCESSING'):
                m.next = 'LATCH_OUTPUT'


            # ... and then latch in the response to transmit.
            with m.State('LATCH_OUTPUT'):
                m.d.sync += current_word.eq(self.word_to_send)
                m.next = 'SHIFT_DATA'


            # Finally, exchange data.
            with m.State('SHIFT_DATA'):
                m.d.sync += spi.sdo.eq(current_word[-1])

                # Continue shifting data until we have a full word.
                with m.If(bit_count < self.word_size):
                    with m.If(sample_edge):
                        m.d.sync += [
                            bit_count    .eq(bit_count + 1),
                            current_word .eq(Cat(spi.sdi, current_word[:-1]))
                        ]

                # ... and then output that word on our bus.
                with m.Else():
                    m.d.sync += [
                        bit_count          .eq(0),
                        self.word_complete .eq(1),
                        self.word_received .eq(current_word)
                    ]

                    # Stay in the stall state until CS is de-asserted.
                    m.next = 'STALL'

        return m
Example #30
0
File: stream.py Project: zyp/luna
    def elaborate(self, platform):
        m = Module()

        # Create our core, single-byte-wide endpoint, and attach it directly to our interface.
        m.submodules.stream_ep = stream_ep = USBStreamInEndpoint(
            endpoint_number=self._endpoint_number,
            max_packet_size=self._max_packet_size
        )
        stream_ep.interface = self.interface

        # Create semantic aliases for byte-wise and word-wise streams;
        # so the code below reads more clearly.
        byte_stream = stream_ep.stream
        word_stream = self.stream

        # We'll put each word to be sent through an shift register
        # that shifts out words a byte at a time.
        data_shift = Signal.like(word_stream.payload)

        # Latched versions of our first and last signals.
        first_latched = Signal()
        last_latched  = Signal()

        # Count how many bytes we have left to send.
        bytes_to_send = Signal(range(0, self._byte_width + 1))

        # Always provide our inner transmitter with the least byte of our shift register.
        m.d.comb += byte_stream.payload.eq(data_shift[0:8])


        with m.FSM(domain="usb"):

            # IDLE: transmitter is waiting for input
            with m.State("IDLE"):
                m.d.comb += word_stream.ready.eq(1)

                # Once we get a send request, fill in our shift register, and start shifting.
                with m.If(word_stream.valid):
                    m.d.usb += [
                        data_shift         .eq(word_stream.payload),
                        first_latched      .eq(word_stream.first),
                        last_latched       .eq(word_stream.last),

                        bytes_to_send      .eq(self._byte_width - 1),
                    ]
                    m.next = "TRANSMIT"


            # TRANSMIT: actively send each of the bytes of our word
            with m.State("TRANSMIT"):
                m.d.comb += byte_stream.valid.eq(1)

                # Once the byte-stream is accepting our input...
                with m.If(byte_stream.ready):
                    is_first_byte = (bytes_to_send == self._byte_width - 1)
                    is_last_byte  = (bytes_to_send == 0)

                    # Pass through our First and Last signals, but only on the first and
                    # last bytes of our word, respectively.
                    m.d.comb += [
                        byte_stream.first  .eq(first_latched & is_first_byte),
                        byte_stream.last   .eq(last_latched  & is_last_byte)
                    ]

                    # ... if we have bytes left to send, move to the next one.
                    with m.If(bytes_to_send > 0):
                        m.d.usb += [
                            bytes_to_send .eq(bytes_to_send - 1),
                            data_shift    .eq(data_shift[8:]),
                        ]

                    # Otherwise, complete the frame.
                    with m.Else():
                        m.d.comb += word_stream.ready.eq(1)

                        # If we still have data to send, move to the next byte...
                        with m.If(self.stream.valid):
                            m.d.usb += [
                                data_shift     .eq(word_stream.payload),
                                first_latched  .eq(word_stream.first),
                                last_latched   .eq(word_stream.last),

                                bytes_to_send  .eq(self._byte_width - 1),
                            ]

                        # ... otherwise, move to our idle state.
                        with m.Else():
                            m.next = "IDLE"


        return m