Beispiel #1
0
    def _elab_read(self, m, dps, r_full):
        r_curr_buf = Signal()
        # Address within current buffer
        r_addr = Signal.like(self.input_depth)

        # Create and connect sequential memory readers
        smrs = [
            SequentialMemoryReader(max_depth=self.max_depth // 2, width=32)
            for _ in range(4)
        ]
        for (n, dp, smr) in zip(range(4), dps, smrs):
            m.submodules[f"smr_{n}"] = smr
            m.d.comb += [
                dp.r_addr.eq(Cat(smr.mem_addr, r_curr_buf)),
                smr.mem_data.eq(dp.r_data),
                smr.limit.eq((self.input_depth + 3 - n) >> 2),
            ]

        smr_nexts = Array(smr.next for smr in smrs)

        # Ready if current buffer is full
        full = Signal()
        m.d.comb += full.eq(r_full[r_curr_buf])
        last_full = Signal()
        m.d.sync += last_full.eq(full)
        with m.If(full & ~last_full):
            m.d.sync += self.r_ready.eq(1)
            m.d.comb += [smr.restart.eq(1) for smr in smrs]

        # Increment address
        with m.If(self.r_next & self.r_ready):
            with m.If(r_addr == self.input_depth - 1):
                m.d.sync += r_addr.eq(0)
            with m.Else():
                m.d.sync += r_addr.eq(r_addr + 1)
            m.d.comb += smr_nexts[r_addr[:2]].eq(1)

        # Get data
        smr_datas = Array(smr.data for smr in smrs)
        m.d.comb += self.r_data.eq(smr_datas[r_addr[:2]])

        # On finished (overrides r_next)
        with m.If(self.r_finished):
            m.d.sync += [
                r_addr.eq(0),
                r_full[r_curr_buf].eq(0),
                last_full.eq(0),
                self.r_ready.eq(0),
                r_curr_buf.eq(~r_curr_buf),
            ]

        # On restart, reset addresses and Sequential Memory readers, go to not
        # ready
        with m.If(self.restart):
            m.d.sync += [
                r_addr.eq(0),
                last_full.eq(0),
                self.r_ready.eq(0),
                r_curr_buf.eq(0),
            ]
Beispiel #2
0
    def elab(self, m):
        was_updated = Signal()
        m.d.sync += was_updated.eq(self.updated)
        # Connect sequential memory readers
        smr_datas = Array([Signal(32, name=f"smr_data_{n}") for n in range(4)])
        smr_nexts = Array([Signal(name=f"smr_next_{n}") for n in range(4)])
        for n, (smr, mem_addr, mem_data, smr_data, smr_next) in enumerate(
                zip(self.smrs, self.mem_addrs, self.mem_datas, smr_datas,
                    smr_nexts)):
            m.submodules[f"smr_{n}"] = smr
            m.d.comb += [
                smr.limit.eq(self.limit >> 2),
                mem_addr.eq(smr.mem_addr),
                smr.mem_data.eq(mem_data),
                smr_data.eq(smr.data),
                smr.next.eq(smr_next),
                smr.restart.eq(was_updated),
            ]

        curr_bank = Signal(2)
        m.d.comb += self.data.eq(smr_datas[curr_bank])

        with m.If(self.restart):
            m.d.sync += curr_bank.eq(0)
        with m.Elif(self.next):
            m.d.comb += smr_nexts[curr_bank].eq(1)
            m.d.sync += curr_bank.eq(curr_bank + 1)
Beispiel #3
0
    def elab(self, m):
        # Unset valid on transfer (may be overrridden below)
        with m.If(self.output.ready):
            m.d.sync += self.output.valid.eq(0)

        # Set flag to remember that value is available
        flags = Array(Signal(name=f"flag_{i}") for i in range(8))
        for i in range(8):
            with m.If(self.accumulator_new[i]):
                m.d.sync += flags[i].eq(1)

        # Calculate index of value to output
        index = Signal(range(8))
        next_index = Signal(range(8))
        with m.If(self.half_mode):
            # counts: 0, 1, 4, 5, 0 ...
            m.d.comb += next_index[1].eq(0)
            m.d.comb += Cat(next_index[0], next_index[2]
                            ).eq(Cat(index[0], index[2]) + 1)
        with m.Else():
            m.d.comb += next_index.eq(index + 1)

        # If value available this cycle, or previously
        # - output new value
        # - unset flag
        # - increment index
        with m.If(Array(self.accumulator_new)[index] | flags[index]):
            m.d.sync += [
                self.output.payload.eq(Array(self.accumulator)[index]),
                self.output.valid.eq(1),
                flags[index].eq(0),
                index.eq(next_index),
            ]
Beispiel #4
0
 def __init__(self, order=3, totalbits=16, fractionalbits=5):
     # Fixed point arithmic
     # https://vha3.github.io/FixedPoint/FixedPoint.html
     self.totalbits = totalbits
     self.fractionalbits = fractionalbits
     self.signed = 1
     # Bernstein coefficients
     self.coeff = Array()
     for _ in order:
         self.coeff.extend([Signal(signed(totalbits))])
     # time
     self.t = Signal(signed(totalbits))
     # In / out signals
     self.done = Signal()
     self.beta = Array().like(self.coeff)
Beispiel #5
0
    def elab(self, m):
        group = Signal(range(4))
        repeat_count = Signal.like(self.repeats)
        mem = Array([Signal(14, name=f"mem{i}") for i in range(4)])

        with m.If(repeat_count == 0):
            # On first repeat - pass through next and addr and record addresses
            m.d.comb += self.gen_next.eq(self.next)
            m.d.comb += self.addr.eq(self.gen_addr)
            with m.If(self.next):
                m.d.sync += mem[group].eq(self.gen_addr)
        with m.Else():
            # Subsequently use recorded data
            m.d.comb += self.addr.eq(mem[group])

        # Update group and repeat_count on next
        with m.If(self.next):
            m.d.sync += group.eq(group + 1)
            with m.If(group == 3):
                m.d.sync += repeat_count.eq(repeat_count + 1)
                with m.If(repeat_count + 1 == self.repeats):
                    m.d.sync += repeat_count.eq(0)

        with m.If(self.start):
            m.d.sync += repeat_count.eq(0)
            m.d.sync += group.eq(0)
Beispiel #6
0
    def elab(self, m):
        # number of bytes received already
        byte_count = Signal(range(4))
        # output channel for next byte received
        pixel_index = Signal(range(self._num_pixels))
        # shift registers to buffer 3 incoming values
        shift_registers = Array(
            [Signal(24, name=f"sr_{i}") for i in range(self._num_pixels)])

        last_pixel_index = Signal.like(pixel_index)
        m.d.sync += last_pixel_index.eq(Mux(self.half_mode,
                                            self._num_pixels // 2 - 1,
                                            self._num_pixels - 1))
        next_pixel_index = Signal.like(pixel_index)
        m.d.comb += next_pixel_index.eq(Mux(pixel_index == last_pixel_index,
                                            0, pixel_index + 1))

        m.d.comb += self.input.ready.eq(1)
        with m.If(self.input.is_transferring()):
            sr = shift_registers[pixel_index]
            with m.If(byte_count == 3):
                # Output current value and shift register
                m.d.comb += self.output.valid.eq(1)
                payload = Cat(sr, self.input.payload)
                m.d.comb += self.output.payload.eq(payload)
            with m.Else():
                # Save input to shift register
                m.d.sync += sr[-8:].eq(self.input.payload)
                m.d.sync += sr[:-8].eq(sr[8:])

            # Increment pixel index
            m.d.sync += pixel_index.eq(next_pixel_index)
            with m.If(pixel_index == last_pixel_index):
                m.d.sync += pixel_index.eq(0)
                m.d.sync += byte_count.eq(byte_count + 1)  # allow rollover
Beispiel #7
0
 def __init__(self, bits_width, num_memories, depth):
     super().__init__()
     assert 0 == ((num_memories - 1) & num_memories
                  ), "Num memories (f{num_memories}) not a power of two"
     self.num_memories_bits = (num_memories - 1).bit_length()
     self.w_en = Array(Signal() for _ in range(num_memories))
     self.w_addr = Signal(range(depth))
     self.w_data = Signal(bits_width)
     self.restart = Signal()
     self.count = Signal(range(depth * num_memories + 1))
     self.updated = Signal()
Beispiel #8
0
    def elaborate(self, platform):
        m = Module()
        uart = platform.request("uart")

        clock_freq = int(60e6)
        char_freq = int(6e6)

        # Create our UART transmitter.
        transmitter = UARTTransmitter(divisor=int(clock_freq // 115200))
        m.submodules.transmitter = transmitter
        stream = transmitter.stream

        # Create a counter that will let us transmit ten times per second.
        counter = Signal(range(0, char_freq))
        with m.If(counter == (char_freq - 1)):
            m.d.sync += counter.eq(0)
        with m.Else():
            m.d.sync += counter.eq(counter + 1)

        # Create a simple ROM with a message for ourselves...
        letters = Array(ord(i) for i in "Hello, world! \r\n")

        # ... and count through it whenever we send a letter.
        current_letter = Signal(range(0, len(letters)))
        with m.If(stream.ready):
            m.d.sync += current_letter.eq(current_letter + 1)

        # Hook everything up.
        m.d.comb += [
            stream.payload.eq(letters[current_letter]),
            stream.valid.eq(counter == 0),
            uart.tx.o.eq(transmitter.tx),
        ]

        # If this platform has an output-enable control on its UART, drive it iff
        # we're actively driving a transmission.
        if hasattr(uart.tx, 'oe'):
            m.d.comb += uart.tx.oe.eq(transmitter.driving),

        # Turn on a single LED, just to show something's running.
        led = Cat(platform.request('led', i) for i in range(6))
        m.d.comb += led.eq(~transmitter.tx)

        return m
Beispiel #9
0
    def elab(self, m):
        # Create the four memories
        dps = [
            DualPortMemory(depth=self.max_depth,
                           width=32,
                           is_sim=is_pysim_run()) for _ in range(4)
        ]
        for n, dp in enumerate(dps):
            m.submodules[f"dp_{n}"] = dp

        # Tracks which buffers are "full" and ready for reading
        r_full = Array([Signal(name="r_full_0"), Signal(name="r_full_1")])
        with m.If(self.restart):
            m.d.sync += [
                r_full[0].eq(0),
                r_full[1].eq(0),
            ]

        # Track reading and writing
        self._elab_write(m, dps, r_full)
        self._elab_read(m, dps, r_full)
Beispiel #10
0
    def elaborate(self, platform):
        m = Module()
        m.submodules += self.ila

        # Generate our domain clocks/resets.
        m.submodules.car = platform.clock_domain_generator()

        # Clock divider / counter.
        m.d.usb += self.counter.eq(self.counter + 1)

        # Say "hello world" constantly over our ILA...
        letters = Array(ord(i) for i in "Hello, world! \r\n")

        current_letter = Signal(range(0, len(letters)))

        m.d.usb += current_letter.eq(current_letter + 1)
        m.d.comb += self.hello.eq(letters[current_letter])

        # Set our ILA to trigger each time the counter is at a random value.
        # This shows off our example a bit better than counting at zero.
        m.d.comb += self.ila.trigger.eq(self.counter == 227)

        # Return our elaborated module.
        return m
Beispiel #11
0
    def elab(self, m):
        # break out the functionid
        funct3 = Signal(3)
        funct7 = Signal(7)
        m.d.comb += [
            funct3.eq(self.cmd_function_id[:3]),
            funct7.eq(self.cmd_function_id[-7:]),
        ]
        stored_function_id = Signal(3)
        current_function_id = Signal(3)
        current_function_done = Signal()
        stored_output = Signal(32)

        instructions = self.__build_instructions(m)
        instruction_outputs = Array(Signal(32) for _ in range(8))
        instruction_dones = Array(Signal() for _ in range(8))
        instruction_starts = Array(Signal() for _ in range(8))
        for (i, instruction) in enumerate(instructions):
            m.d.comb += instruction_outputs[i].eq(instruction.output)
            m.d.comb += instruction_dones[i].eq(instruction.done)
            m.d.comb += instruction.start.eq(instruction_starts[i])

        def check_instruction_done():
            with m.If(current_function_done):
                m.d.comb += self.rsp_valid.eq(1)
                m.d.comb += self.rsp_out.eq(
                    instruction_outputs[current_function_id])
                with m.If(self.rsp_ready):
                    m.next = "WAIT_CMD"
                with m.Else():
                    m.d.sync += stored_output.eq(
                        instruction_outputs[current_function_id])
                    m.next = "WAIT_TRANSFER"
            with m.Else():
                m.next = "WAIT_INSTRUCTION"

        with m.FSM():
            with m.State("WAIT_CMD"):
                # We're waiting for a command from the CPU.
                m.d.comb += current_function_id.eq(funct3)
                m.d.comb += current_function_done.eq(
                    instruction_dones[current_function_id])
                m.d.comb += self.cmd_ready.eq(1)
                with m.If(self.cmd_valid):
                    m.d.sync += stored_function_id.eq(self.cmd_function_id[:3])
                    m.d.comb += instruction_starts[current_function_id].eq(1)
                    check_instruction_done()
            with m.State("WAIT_INSTRUCTION"):
                # An instruction is executing on the CFU. We're waiting until it
                # completes.
                m.d.comb += current_function_id.eq(stored_function_id)
                m.d.comb += current_function_done.eq(
                    instruction_dones[current_function_id])
                check_instruction_done()
            with m.State("WAIT_TRANSFER"):
                # Instruction has completed, but the CPU isn't ready to receive
                # the result.
                m.d.comb += self.rsp_valid.eq(1)
                m.d.comb += self.rsp_out.eq(stored_output)
                with m.If(self.rsp_ready):
                    m.next = "WAIT_CMD"

        for instruction in instructions:
            m.d.comb += [
                instruction.in0.eq(self.cmd_in0),
                instruction.in1.eq(self.cmd_in1),
                instruction.funct7.eq(funct7),
            ]

        # tie "reset" and "rst" together (issue #110)
        rst = ResetSignal('sync')
        m.d.comb += rst.eq(self.reset)
Beispiel #12
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.
        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.buffer_toggle
        read_buffer_number  = ~self.buffer_toggle

        # 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.buffer_toggle  .eq(~self.buffer_toggle),
                            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.d.usb += self.data_pid[0].eq(~self.data_pid[0]),
                        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) | in_stream.last)
                    with m.Elif(~in_stream.ready | packet_completing):
                        m.next = "WAIT_TO_SEND"
                        m.d.usb += [
                            self.buffer_toggle .eq(~self.buffer_toggle),
                            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
Beispiel #13
0
class Casteljau(Elaboratable):
    ''' Implements Bezier curves using Casteljau's algorithm

        Once calculation is done a signal is raised.
        User can obtain result by looking at beta zero.
    '''
    def __init__(self, order=3, totalbits=16, fractionalbits=5):
        # Fixed point arithmic
        # https://vha3.github.io/FixedPoint/FixedPoint.html
        self.totalbits = totalbits
        self.fractionalbits = fractionalbits
        self.signed = 1
        # Bernstein coefficients
        self.coeff = Array()
        for _ in order:
            self.coeff.extend([Signal(signed(totalbits))])
        # time
        self.t = Signal(signed(totalbits))
        # In / out signals
        self.done = Signal()
        self.beta = Array().like(self.coeff)

    def elaborate(self, platform):
        m = Module()

        beta = self.beta
        temp = Signal(signed(self.totalbits * 2))

        n = len(self.coeff)
        j = Signal(range(1, n))
        k = Signal.like(j)
        with m.FSM(reset='INIT') as algo:
            with m.State('INIT'):
                m.d.sync += self.done.eq(0)
                for i in range(n):
                    m.d.sync += beta[i].eq(self.coeff[i])
                m.d.sync += [k.eq(0), j.eq(1)]
                m.next = 'UPDATE'
            with m.FSM('UPDATE'):
                m.d.sync += temp.eq(beta[k] * (1 - self.t) +
                                    beta[k + 1] * self.t)
                m.next = 'MULTIPLICATIONFIX'
            # Fixed point arithmetic need fix
            # see multiplication as https://vha3.github.io/FixedPoint/FixedPoint.html
            with m.FSM('MULTIPLICATIONFIX'):
                m.d.sync += beta[k].eq(
                    temp[self.fractionalbits:self.fractionalbits +
                         self.totalbits])
                with m.If(k != n - j):
                    m.d.sync += k.eq(k + 1)
                    m.next = 'UPDATE'
                with m.Else():
                    with m.If(j != n):
                        m.d.sync += j.eq(j + 1)
                        m.d.sync += k.eq(0)
                        m.next = 'UPDATE'
                    with m.Else():
                        m.next = 'FINISH'
            with m.FSM('FINISH'):
                m.d.sync += self.done.eq(1)
                m.next = 'FINISH'
        return m
Beispiel #14
0
    def __init__(self, *, max_line_length=128):

        self.line_in     = Array(Signal(8) for _ in range(max_line_length))
        self.line_length = Signal(range(0, max_line_length + 1))
Beispiel #15
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