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

        interface = self.interface
        setup = self.interface.setup

        #
        # Class request handlers.
        #

        with m.If(setup.type == USBRequestType.CLASS):
            with m.Switch(setup.request):

                # SET_LINE_CODING: The host attempts to tell us how it wants serial data
                # encoding. Since we output a stream, we'll ignore the actual line coding.
                with m.Case(self.SET_LINE_CODING):

                    # Always ACK the data out...
                    with m.If(interface.rx_ready_for_response):
                        m.d.comb += interface.handshakes_out.ack.eq(1)

                    # ... and accept whatever the request was.
                    with m.If(interface.status_requested):
                        m.d.comb += self.send_zlp()

                with m.Case():

                    #
                    # Stall unhandled requests.
                    #
                    with m.If(interface.status_requested
                              | interface.data_requested):
                        m.d.comb += interface.handshakes_out.stall.eq(1)

                return m
Ejemplo n.º 2
0
 def elaborate(self, platform):
     m = Module()
     with m.Switch(self.funct3):
         with m.Case(Funct3.OR):
             m.d.comb += self.res.eq(self.src1 | self.src2)
         with m.Case(Funct3.AND):
             m.d.comb += self.res.eq(self.src1 & self.src2)
         with m.Case(Funct3.XOR):
             m.d.comb += self.res.eq(self.src1 ^ self.src2)
     return m
Ejemplo n.º 3
0
    def elaborate(self, platform):
        m = Module()

        interface         = self.interface
        setup             = self.interface.setup

        # Grab a reference to the board's LEDs.
        leds  = Cat(platform.request_optional("led", i, default=NullPin()).o for i in range(8))

        #
        # Vendor request handlers.

        with m.If(setup.type == USBRequestType.VENDOR):
            with m.Switch(setup.request):

                # SET_LEDS request handler: handler that sets the board's LEDS
                # to a user provided value
                with m.Case(self.REQUEST_SET_LEDS):

                    # If we have an active data byte, splat it onto the LEDs.
                    #
                    # For simplicity of this example, we'll accept any byte in
                    # the packet; and not just the first one; each byte will
                    # cause an update. This is fun; we can PWM the LEDs with
                    # USB packets. :)
                    with m.If(interface.rx.valid & interface.rx.next):
                        m.d.usb += leds.eq(interface.rx.payload)

                    # Once the receive is complete, respond with an ACK.
                    with m.If(interface.rx_ready_for_response):
                        m.d.comb += interface.handshakes_out.ack.eq(1)

                    # If we reach the status stage, send a ZLP.
                    with m.If(interface.status_requested):
                        m.d.comb += self.send_zlp()


                with m.Case():

                    #
                    # Stall unhandled requests.
                    #
                    with m.If(interface.status_requested | interface.data_requested):
                        m.d.comb += interface.handshakes_out.stall.eq(1)

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

        with m.Switch(self.funct3):
            with m.Case(Funct3.W):
                comb += self.mask.eq(0b1111)
            with m.Case(Funct3.H):
                comb += self.mask.eq(0b0011)
            with m.Case(Funct3.B):
                comb += self.mask.eq(0b0001)
            with m.Case(Funct3.HU):
                comb += self.mask.eq(0b0011)
            with m.Case(Funct3.BU):
                comb += self.mask.eq(0b0001)

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

        #
        # Our module has three core parts:
        #   - an encoder, which converts from our one-hot signal to a mux select line
        #   - a multiplexer, which handles multiplexing e.g. payload signals
        #   - a set of OR'ing logic, which joints together our simple or'd signals

        # Create our encoder...
        m.submodules.encoder = encoder = Encoder(len(self._inputs))
        for index, interface in enumerate(self._inputs):

            # ... and tie its inputs to each of our 'valid' signals.
            valid_signal = getattr(interface, self._valid_field)
            m.d.comb += encoder.i[index].eq(valid_signal)


        # Create our multiplexer, and drive each of our output signals from it.
        with m.Switch(encoder.o):
            for index, interface in enumerate(self._inputs):

                # If an interface is selected...
                with m.Case(index):
                    for identifier in self._mux_signals:

                        # ... connect all of its muxed signals through to the output.
                        output_signal = self._get_signal(self.output, identifier)
                        input_signal  = self._get_signal(interface,   identifier)
                        m.d.comb += output_signal.eq(input_signal)


        # Create the OR'ing logic for each of or or_signals.
        for identifier in self._or_signals:

            # Figure out the signals we want to work with...
            output_signal = self._get_signal(self.output, identifier)
            input_signals = (self._get_signal(i, identifier) for i in self._inputs)

            # ... and OR them together.
            or_reduced = functools.reduce(operator.__or__, input_signals, 0)
            m.d.comb += output_signal.eq(or_reduced)


        # Finally, pass each of our pass-back signals from the output interface
        # back to each of our input interfaces.
        for identifier in self._pass_signals:
            output_signal = self._get_signal(self.output, identifier)

            for interface in self._inputs:
                input_signal = self._get_signal(interface, identifier)
                m.d.comb += input_signal.eq(output_signal)


        return m
Ejemplo n.º 6
0
    def elaborate(self, platform):
        assert Funct3.SLLI == Funct3.SLL
        assert Funct3.SRL == Funct3.SRLI
        assert Funct3.SRA == Funct3.SRAI
        m = Module()
        with m.Switch(self.funct3):
            with m.Case(Funct3.SLL):
                m.d.comb += self.res.eq(self.src1 << self.shift)
            with m.Case(Funct3.SRL):
                assert Funct3.SRL == Funct3.SRA
                assert Funct7.SRL != Funct7.SRA

                with m.If(self.funct7 == Funct7.SRL):
                    m.d.comb += self.res.eq(self.src1 >> self.shift)
                with m.Elif(self.funct7 == Funct7.SRA):
                    m.d.comb += [
                        self.src1signed.eq(self.src1),
                        self.res.eq(self.src1signed >> self.shift),
                    ]
        return m
Ejemplo n.º 7
0
    def elaborate(self, platform):
        m = Module()
        with m.Switch(self.funct3):
            with m.Case(Funct3.SLT):
                m.d.comb += self.condition_met.eq(self.negative
                                                  | self.overflow)
            with m.Case(Funct3.SLTU):
                m.d.comb += self.condition_met.eq(self.carry)

            with m.Case(Funct3.BEQ):
                m.d.comb += self.condition_met.eq(self.zero)
            with m.Case(Funct3.BNE):
                m.d.comb += self.condition_met.eq(~self.zero)
            with m.Case(Funct3.BLT):
                m.d.comb += self.condition_met.eq(self.negative
                                                  ^ self.overflow)
            with m.Case(Funct3.BGE):
                m.d.comb += self.condition_met.eq(~(self.negative
                                                    ^ self.overflow))
            with m.Case(Funct3.BLTU):
                m.d.comb += self.condition_met.eq(self.carry)
            with m.Case(Funct3.BGEU):
                m.d.comb += self.condition_met.eq(~self.carry)
        return m
Ejemplo n.º 8
0
    def elaborate(self, platform):
        m = Module()

        # Synchronize the USB signals at our I/O boundary.
        # Despite the assumptions made in ValentyUSB, this line rate recovery FSM
        # isn't enough to properly synchronize these inputs. We'll explicitly synchronize.
        sync_dp = synchronize(m, self._usbp, o_domain="usb_io")
        sync_dn = synchronize(m, self._usbn, o_domain="usb_io")

        #######################################################################
        # Line State Recovery State Machine
        #
        # The receive path doesn't use a differential receiver.  Because of
        # this there is a chance that one of the differential pairs will appear
        # to have changed to the new state while the other is still in the old
        # state.  The following state machine detects transitions and waits an
        # extra sampling clock before decoding the state on the differential
        # pair.  This transition period  will only ever last for one clock as
        # long as there is no noise on the line.  If there is enough noise on
        # the line then the data may be corrupted and the packet will fail the
        # data integrity checks.
        #
        dpair = Cat(sync_dp, sync_dn)

        # output signals for use by the clock recovery stage
        line_state_in_transition = Signal()

        with m.FSM(domain="usb_io") as fsm:
            m.d.usb_io += [
                self.line_state_se0.eq(fsm.ongoing("SE0")),
                self.line_state_se1.eq(fsm.ongoing("SE1")),
                self.line_state_dj.eq(fsm.ongoing("DJ")),
                self.line_state_dk.eq(fsm.ongoing("DK")),
            ]

            # If we are in a transition state, then we can sample the pair and
            # move to the next corresponding line state.
            with m.State("DT"):
                m.d.comb += line_state_in_transition.eq(1)

                with m.Switch(dpair):
                    with m.Case(0b10):
                        m.next = "DJ"
                    with m.Case(0b01):
                        m.next = "DK"
                    with m.Case(0b00):
                        m.next = "SE0"
                    with m.Case(0b11):
                        m.next = "SE1"

            # If we are in a valid line state and the value of the pair changes,
            # then we need to move to the transition state.
            with m.State("DJ"):
                with m.If(dpair != 0b10):
                    m.next = "DT"

            with m.State("DK"):
                with m.If(dpair != 0b01):
                    m.next = "DT"

            with m.State("SE0"):
                with m.If(dpair != 0b00):
                    m.next = "DT"

            with m.State("SE1"):
                with m.If(dpair != 0b11):
                    m.next = "DT"

        #######################################################################
        # Clock and Data Recovery
        #
        # The DT state from the line state recovery state machine is used to align to
        # transmit clock.  The line state is sampled in the middle of the bit time.
        #
        # Example of signal relationships
        # -------------------------------
        # line_state        DT  DJ  DJ  DJ  DT  DK  DK  DK  DK  DK  DK  DT  DJ  DJ  DJ
        # line_state_valid  ________----____________----____________----________----____
        # bit_phase         0   0   1   2   3   0   1   2   3   0   1   2   0   1   2
        #

        # We 4x oversample, so make the line_state_phase have
        # 4 possible values.
        line_state_phase = Signal(2)
        m.d.usb_io += self.line_state_valid.eq(line_state_phase == 1)

        with m.If(line_state_in_transition):
            m.d.usb_io += [
                # re-align the phase with the incoming transition
                line_state_phase.eq(0),

                # make sure we never assert valid on a transition
                self.line_state_valid.eq(0),
            ]
        with m.Else():
            # keep tracking the clock by incrementing the phase
            m.d.usb_io += line_state_phase.eq(line_state_phase + 1)

        return m
Ejemplo n.º 9
0
    def elaborate(self, platform):
        m = Module()
        comb = m.d.comb
        sync = m.d.sync
        loadstore = self.loadstore

        store = self.store
        addr = Signal(32)

        comb += [
            addr.eq(self.offset + self.src1),
        ]

        sel = m.submodules.sel = Selector()

        # sel.mask will be calculated.
        comb += [
            sel.funct3.eq(self.funct3),
            sel.store.eq(store),
        ]

        word = Signal(signed(32))
        half_word = Signal(signed(16))
        byte = Signal(8)

        write_data = Signal(32)
        signed_write_data = Signal(signed(32))

        load_res = Signal(signed(32))

        addr_lsb = Signal(2)
        m.d.comb += addr_lsb.eq(addr[:2])  # XXX

        # allow naturally aligned addresses
        # TODO trap on wrong address
        with m.If(store):
            data = self.src2
            comb += [
                word.eq(data),
                half_word.eq(data.word_select(addr_lsb[1], 16)),
                byte.eq(data.word_select(addr_lsb, 8)),
            ]
        with m.Else():
            data = loadstore.read_data
            comb += [
                word.eq(data),
                half_word.eq(data.word_select(addr_lsb[1], 16)),
                byte.eq(data.word_select(addr_lsb, 8))
            ]

        with m.If(~store):
            with m.Switch(self.funct3):
                with m.Case(Funct3.W):
                    comb += load_res.eq(word)
                with m.Case(Funct3.H):
                    comb += load_res.eq(half_word)
                with m.Case(Funct3.B):
                    comb += load_res.eq(byte)
                with m.Case(Funct3.HU):
                    comb += load_res.eq(Cat(half_word, 0))
                with m.Case(Funct3.BU):
                    comb += load_res.eq(Cat(byte, 0))

        with m.If(store):
            with m.Switch(self.funct3):
                with m.Case(Funct3.W):
                    comb += (write_data.eq(word), )
                with m.Case(Funct3.H):
                    comb += [
                        signed_write_data.eq(half_word),
                        write_data.eq(signed_write_data),
                    ]
                with m.Case(Funct3.B):
                    comb += [
                        signed_write_data.eq(byte),
                        write_data.eq(signed_write_data),
                    ]
                with m.Case(Funct3.HU):
                    comb += (write_data.eq(half_word), )
                with m.Case(Funct3.BU):
                    comb += (write_data.eq(byte), )

        with m.If(self.en):
            comb += [
                loadstore.en.eq(1),
                loadstore.store.eq(store),
                loadstore.addr.eq(addr),
                loadstore.mask.eq(sel.mask),
                loadstore.write_data.eq(write_data),
            ]
        with m.If(loadstore.ack):
            comb += [
                self.ack.eq(1),
                self.res.eq(load_res),
            ]
        return m