コード例 #1
0
ファイル: macc.py プロジェクト: tcal-x/CFU-Playground
class Accumulator(SimpleElaboratable):
    """An accumulator for a Madd4Pipline

    Public Interface
    ----------------
    add_en: Signal() input
        When to add the input
    in_value: Signal(signed(32)) input
        The input data to add
    clear: Signal() input
        Zero accumulator.
    result: Signal(signed(32)) output
        Result of the multiply and add
    """
    def __init__(self):
        super().__init__()
        self.add_en = Signal()
        self.in_value = Signal(signed(32))
        self.clear = Signal()
        self.result = Signal(signed(32))

    def elab(self, m):
        accumulator = Signal(signed(32))
        m.d.comb += self.result.eq(accumulator)
        with m.If(self.add_en):
            m.d.sync += accumulator.eq(accumulator + self.in_value)
            m.d.comb += self.result.eq(accumulator + self.in_value)
        # clear always resets accumulator next cycle, even if add_en is high
        with m.If(self.clear):
            m.d.sync += accumulator.eq(0)
コード例 #2
0
ファイル: shifter.py プロジェクト: bieganski/mtkcpu
class ShifterUnit(Elaboratable):
    def __init__(self):
        self.src1 = Signal(32, name="shifter_src1")
        self.src1signed = Signal(signed(32))
        self.shift = Signal(5, name="shifter_shift")  # 5 lowest imm bits
        self.res = Signal(32, name="shifter_res")
        self.funct3 = Signal(Funct3)
        self.funct7 = Signal(Funct7)

    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
コード例 #3
0
ファイル: macc.py プロジェクト: tcal-x/CFU-Playground
class ByteToWordShifter(SimpleElaboratable):
    """Shifts bytes into a word.

    Bytes are shifted from high to low, so that result is little-endian,
    with the "first" byte occupying the LSBs

    Public Interface
    ----------------
    shift_en: Signal() input
        When to shift the input
    in_value: Signal(8) input
        The input data to shift
    result: Signal(32) output
        Result of the shift
    """
    def __init__(self):
        super().__init__()
        self.shift_en = Signal()
        self.in_value = Signal(8)
        self.clear = Signal()
        self.result = Signal(32)

    def elab(self, m):
        register = Signal(32)
        m.d.comb += self.result.eq(register)

        with m.If(self.shift_en):
            calc = Signal(32)
            m.d.comb += [
                calc.eq(Cat(register[8:], self.in_value)),
                self.result.eq(calc),
            ]
            m.d.sync += register.eq(calc)
コード例 #4
0
    def elab(self, m: Module):
        buffering = Signal()  # True if there is a value being buffered
        buffered_value = Signal.like(Value.cast(self.input.payload))

        # Pipe valid and ready back and forth
        m.d.comb += [
            self.input.ready.eq(~buffering | self.output.ready),
            self.output.valid.eq(buffering | self.input.valid),
            self.output.payload.eq(
                Mux(buffering, buffered_value, self.input.payload))
        ]

        # Buffer when have incoming value but cannot output just now
        with m.If(~buffering & ~self.output.ready & self.input.valid):
            m.d.sync += buffering.eq(True)
            m.d.sync += buffered_value.eq(self.input.payload)

        # Handle cases when transfering out from buffer
        with m.If(buffering & self.output.ready):
            with m.If(self.input.valid):
                m.d.sync += buffered_value.eq(self.input.payload)
            with m.Else():
                m.d.sync += buffering.eq(False)

        # Reset all state
        with m.If(self.reset):
            m.d.sync += buffering.eq(False)
            m.d.sync += buffered_value.eq(0)
コード例 #5
0
ファイル: post_process.py プロジェクト: tcal-x/CFU-Playground
    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),
            ]
コード例 #6
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)
コード例 #7
0
class AdderUnit(Elaboratable):
    def __init__(self):
        self.sub = Signal()  # add or sub
        self.src1 = Signal(32, name="adder_src1")
        self.src2 = Signal(32, name="adder_src2")
        self.res = Signal(32, name="adder_res")

        self.overflow = Signal(name="adder_overflow")
        self.carry = Signal(name="adder_carry")

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

        # neat way of setting carry flag
        res_and_carry = Cat(self.res, self.carry)

        m.d.comb += res_and_carry.eq(
            Mux(self.sub, self.src1 - self.src2, self.src1 + self.src2))

        with m.If(self.sub):
            with m.If((self.src1[-1] != self.src2[-1])
                      & (self.src1[-1] != self.res[-1])):
                m.d.comb += self.overflow.eq(1)
        with m.Else():
            # add
            with m.If((self.src1[-1] == self.src2[-1])
                      & (self.src1[-1] != self.res[-1])):
                m.d.comb += self.overflow.eq(1)

        return m
コード例 #8
0
    def elaborate(self, platform):
        m = Module()

        with m.If(self.pending.w_stb):
            m.d.sync += self.pending.r_data.eq(self.pending.r_data
                                               & ~self.pending.w_data)

        with m.If(self.enable.w_stb):
            m.d.sync += self.enable.r_data.eq(self.enable.w_data)

        for i, event in enumerate(self._events):
            m.d.sync += self.status.r_data[i].eq(event.stb)

            if event.mode in ("rise", "fall"):
                event_stb_r = Signal.like(event.stb, name_suffix="_r")
                m.d.sync += event_stb_r.eq(event.stb)

            event_trigger = Signal(name="{}_trigger".format(event.name))
            if event.mode == "level":
                m.d.comb += event_trigger.eq(event.stb)
            elif event.mode == "rise":
                m.d.comb += event_trigger.eq(~event_stb_r & event.stb)
            elif event.mode == "fall":
                m.d.comb += event_trigger.eq(event_stb_r & ~event.stb)
            else:
                assert False  # :nocov:

            with m.If(event_trigger):
                m.d.sync += self.pending.r_data[i].eq(1)

        m.d.comb += self.irq.eq(
            (self.pending.r_data & self.enable.r_data).any())

        return m
コード例 #9
0
ファイル: spi.py プロジェクト: greatscottgadgets/luna
    def spi_edge_detectors(self, m):
        """ Generates edge detectors for the sample and output clocks, based on the current SPI mode.

        Returns:
            sample_edge, output_edge -- signals that pulse high for a single cycle when we should
                                        sample and change our outputs, respectively
        """

        # Select whether we're working with an inverted or un-inverted serial clock.
        serial_clock = Signal()
        if self.clock_polarity:
            m.d.comb += serial_clock.eq(~self.spi.sck)
        else:
            m.d.comb += serial_clock.eq(self.spi.sck)

        # Generate the leading and trailing edge detectors.
        # Note that we use rising and falling edge detectors, but call these leading and
        # trailing edges, as our clock here may have been inverted.
        leading_edge = Rose(serial_clock, domain="sync")
        trailing_edge = Fell(serial_clock, domain="sync")

        # Determine the sample and output edges based on the SPI clock phase.
        sample_edge = trailing_edge if self.clock_phase else leading_edge
        output_edge = leading_edge if self.clock_phase else trailing_edge

        return sample_edge, output_edge
コード例 #10
0
class MaccInstruction(InstructionBase):
    """Multiply accumulate x4

    in0 contains 4 signed input values
    in1 contains 4 signed filter values
    """

    def __init__(self):
        super().__init__()
        self.input_offset = Signal(signed(32))
        self.accumulator = Signal(signed(32))
        self.reset_acc = Signal()

    def elab(self, m):
        in_vals = [Signal(signed(8), name=f"in_val_{i}") for i in range(4)]
        filter_vals = [
            Signal(
                signed(8),
                name=f"filter_val_{i}") for i in range(4)]
        mults = [Signal(signed(19), name=f"mult_{i}") for i in range(4)]
        for i in range(4):
            m.d.comb += [
                in_vals[i].eq(self.in0.word_select(i, 8).as_signed()),
                filter_vals[i].eq(self.in1.word_select(i, 8).as_signed()),
                mults[i].eq(
                    (in_vals[i] + self.input_offset) * filter_vals[i]),
            ]
        m.d.sync += self.done.eq(0)
        with m.If(self.start):
            m.d.sync += self.accumulator.eq(self.accumulator + sum(mults))
            # m.d.sync += self.accumulator.eq(self.accumulator + 72)
            m.d.sync += self.done.eq(1)
        with m.Elif(self.reset_acc):
            m.d.sync += self.accumulator.eq(0)
コード例 #11
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)
コード例 #12
0
class ValueBufferTest(TestBase):
    def create_dut(self):
        self.capture = Signal()
        self.in_signal = Signal(4)
        return ValueBuffer(self.in_signal, self.capture)

    def test(self):
        DATA = [
            ((0, 0), 0),
            ((1, 5), 5),
            ((0, 3), 5),
            ((0, 2), 5),
            ((0, 2), 5),
            ((1, 2), 2),
            ((0, 2), 2),
            ((0, 2), 2),
        ]

        def process():
            for n, ((capture, in_sig), expected_output) in enumerate(DATA):
                yield self.in_signal.eq(in_sig)
                yield self.capture.eq(capture)
                yield Settle()
                self.assertEqual((yield self.dut.output), expected_output,
                                 f"cycle={n}")
                yield

        self.run_sim(process, False)
コード例 #13
0
ファイル: util.py プロジェクト: tcal-x/CFU-Playground
    def elab(self, m):
        # Track previous restart, next
        was_restart = Signal()
        m.d.sync += was_restart.eq(self.restart)
        was_next = Signal()
        m.d.sync += was_next.eq(self.next)

        # Decide address to be output (determines data available next cycle)
        last_mem_addr = Signal.like(self.mem_addr)
        m.d.sync += last_mem_addr.eq(self.mem_addr)
        incremented_addr = Signal.like(self.limit)
        m.d.comb += incremented_addr.eq(
            Mux(last_mem_addr == self.limit - 1, 0, last_mem_addr + 1))
        with m.If(self.restart):
            m.d.comb += self.mem_addr.eq(0)
        with m.Elif(was_next | was_restart):
            m.d.comb += self.mem_addr.eq(incremented_addr)
        with m.Else():
            m.d.comb += self.mem_addr.eq(last_mem_addr)

        # Decide data to be output
        last_data = Signal.like(self.data)
        m.d.sync += last_data.eq(self.data)
        with m.If(was_restart | was_next):
            m.d.comb += self.data.eq(self.mem_data)
        with m.Else():
            m.d.comb += self.data.eq(last_data)
コード例 #14
0
ファイル: counter.py プロジェクト: adamgreig/nmigen-examples
class Counter(Elaboratable):
    def __init__(self, limit):
        self.limit = limit

        # Counter state.
        #
        # Using `range(limit)` means the signal will be wide enough to
        # represent any integer up to but excluding `limit`.
        #
        # For example, with limit=128, we'd get a 7-bit signal which can
        # represent the integers 0 to 127.
        self.counter = Signal(range(limit))

        # Rollover output will be pulsed high for one clock cycle
        # when the counter reaches `limit-1`.
        self.rollover = Signal()

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

        # Make the output `rollover` always equal to this comparison,
        # which will only be 1 for a single cycle every counter period.
        m.d.comb += self.rollover.eq(self.counter == self.limit - 1)

        # Conditionally reset the counter to 0 on rollover, otherwise
        # increment it. We could write the comparison out again here
        # to the same effect.
        with m.If(self.rollover):
            m.d.sync += self.counter.eq(0)
        with m.Else():
            m.d.sync += self.counter.eq(self.counter + 1)

        return m
コード例 #15
0
ファイル: ulpi.py プロジェクト: greatscottgadgets/luna
    def add_composite_register(self, m, address, value, *, reset_value=0):
        """ Adds a ULPI register that's composed of multiple control signals.

        Params:
            address      -- The register number in the ULPI register space.
            value       -- An 8-bit signal composing the bits that should be placed in
                           the given register.

            reset_value -- If provided, the given value will be assumed as the reset value
                        -- of the given register; allowing us to avoid an initial write.
        """

        current_register_value = Signal(8, reset=reset_value, name=f"current_register_value_{address:02x}")

        # Create internal signals that request register updates.
        write_requested = Signal(name=f"write_requested_{address:02x}")
        write_value     = Signal(8, name=f"write_value_{address:02x}")
        write_done      = Signal(name=f"write_done_{address:02x}")

        self._register_signals[address] = {
            'write_requested': write_requested,
            'write_value':     write_value,
            'write_done':      write_done
        }

        # If we've just finished a write, update our current register value.
        with m.If(write_done):
            m.d.usb += current_register_value.eq(write_value),

        # If we have a mismatch between the requested and actual register value,
        # request a write of the new value.
        m.d.comb += write_requested.eq(current_register_value != value)
        with m.If(current_register_value != value):
            m.d.usb += write_value.eq(value)
コード例 #16
0
ファイル: post_process.py プロジェクト: tcal-x/CFU-Playground
    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
コード例 #17
0
    def elab(self, m: Module):
        num_words = Signal(range(Constants.MAX_INPUT_WORDS + 1))
        index = Signal(range(Constants.MAX_INPUT_WORDS))
        reset = Signal()
        m.d.comb += reset.eq(self.num_words_input.valid)
        memory = WideReadMemory(depth=Constants.MAX_INPUT_WORDS)
        m.submodules['memory'] = memory

        with m.FSM(reset="RESET"):
            with m.State("RESET"):
                m.d.sync += num_words.eq(0)
                m.d.sync += index.eq(0)
                m.d.sync += self.data_output.valid.eq(0)
                m.next = "NUM_WORDS"
            with m.State("NUM_WORDS"):
                m.d.comb += self.num_words_input.ready.eq(1)
                with m.If(self.num_words_input.is_transferring()):
                    m.d.sync += num_words.eq(self.num_words_input.payload)
                    m.next = "WRITING"
            with m.State("WRITING"):
                self.handle_writing(m, memory, num_words, index)
                with m.If(reset):
                    m.next = "RESET"
            with m.State("READING"):
                self.handle_reading(m, memory, num_words, index, reset)
                with m.If(reset):
                    m.next = "RESET"
コード例 #18
0
class RegisterSetter(Xetter):
    """A Setter for a value.

    Sets new value from in0. Return previous value on set.

    Parameters
    ----------
    width: int
        Number of bits in the Xetter value (1-32)

    Public Interface
    ----------------
    value: Signal(width) output
        The value held by this register. It will be set from in0.
    set: Signal output
        This signal is pulsed high for a single cycle when register is set.
    """
    def __init__(self, width=32):
        super().__init__()
        self.value = Signal(width)
        self.set = Signal()

    def elab(self, m):
        m.d.sync += self.set.eq(0)
        with m.If(self.start):
            m.d.sync += self.value.eq(self.in0),
            m.d.sync += self.set.eq(1),
            m.d.comb += self.output.eq(self.value)
            m.d.comb += self.done.eq(1)
コード例 #19
0
    def _elab_write(self, m, dps, r_full):
        w_curr_buf = Signal()
        # Address within current buffer
        w_addr = Signal.like(self.input_depth)

        # Connect to memory write port
        for n, dp in enumerate(dps):
            m.d.comb += [
                dp.w_addr.eq(Cat(w_addr[2:], w_curr_buf)),
                dp.w_data.eq(self.w_data),
                dp.w_en.eq(self.w_en & self.w_ready & (n == w_addr[:2])),
            ]
        # Ready to write current buffer if reading is not allowed
        m.d.comb += self.w_ready.eq(~r_full[w_curr_buf])

        # Write address increment
        with m.If(self.w_en & self.w_ready):
            with m.If(w_addr == self.input_depth - 1):
                # at end of buffer - mark buffer ready for reading and go to
                # next
                m.d.sync += [
                    w_addr.eq(0),
                    r_full[w_curr_buf].eq(1),
                    w_curr_buf.eq(~w_curr_buf),
                ]
            with m.Else():
                m.d.sync += w_addr.eq(w_addr + 1)

        with m.If(self.restart):
            m.d.sync += [
                w_addr.eq(0),
                w_curr_buf.eq(0),
            ]
コード例 #20
0
    def elab(self, m):
        # Define parameters
        repeats = Signal(unsigned_upto(self._max_repeats))
        count = Signal(unsigned_upto(self._depth))

        # Accept new parameters
        m.d.comb += self.params_input.ready.eq(1)
        with m.If(self.params_input.valid):
            m.d.sync += [
                repeats.eq(self.params_input.payload.repeats),
                count.eq(self.params_input.payload.count),
            ]

        # Count repeats
        m.submodules.rc = repeat_counter = LoopingCounter(self._max_repeats)
        m.d.comb += [
            repeat_counter.count.eq(repeats),
            repeat_counter.reset.eq(self.params_input.valid),
            repeat_counter.next.eq(self.next),
        ]

        # Count addresses
        m.submodules.ac = addr_counter = LoopingCounter(self._depth)
        m.d.comb += [
            addr_counter.count.eq(count),
            addr_counter.reset.eq(self.params_input.valid),
            addr_counter.next.eq(self.next & repeat_counter.last),
            self.addr.eq(addr_counter.value),
        ]
コード例 #21
0
ファイル: nrzidecoder.py プロジェクト: hansfbaier/adat-core
    def decode_nrzi(self, m: Module, bit_time: Signal, got_edge: Signal, sync_counter: DividingCounter):
        """Do the actual decoding of the NRZI bitstream"""
        sync = m.d.sync
        bit_counter  = Signal(7)
        # this counter is used to detect a dead signal
        # to determine when to go back to SYNC state
        dead_counter = Signal(8)
        output       = Signal(reset=1)

        # recover ADAT clock
        with m.If(bit_counter <= (bit_time >> 1)):
            m.d.comb += self.recovered_clock_out.eq(1)
        with m.Else():
            m.d.comb += self.recovered_clock_out.eq(0)

        # when the frame decoder got garbage
        # then we need to go back to SYNC state
        with m.If(self.invalid_frame_in):
            sync += [
                sync_counter.reset_in.eq(1),
                bit_counter.eq(0),
                dead_counter.eq(0)
            ]
            m.next = "SYNC"

        sync += bit_counter.eq(bit_counter + 1)
        with m.If(got_edge):
            sync += [
                # latch 1 until we read it in the middle of the bit
                output.eq(1),
                # resynchronize at each bit edge, 1 to compensate
                # for sync delay
                bit_counter.eq(1),
                # when we get an edge, the signal is alive, reset counter
                dead_counter.eq(0)
            ]
        with m.Else():
            sync += dead_counter.eq(dead_counter + 1)

        # wrap the counter
        with m.If(bit_counter == bit_time):
            sync += bit_counter.eq(0)
        # output at the middle of the bit
        with m.Elif(bit_counter == (bit_time >> 1)):
            sync += [
                self.data_out.eq(output),
                self.data_out_en.eq(1), # pulse out_en
                output.eq(0) # edge has been output, wait for new edge
            ]
        with m.Else():
            sync += self.data_out_en.eq(0)

        # when we had no edge for 16 bits worth of time
        # then we go back to sync state
        with m.If(dead_counter >= bit_time << 4):
            sync += dead_counter.eq(0)
            m.next = "SYNC"
コード例 #22
0
ファイル: macc.py プロジェクト: tcal-x/CFU-Playground
 def elab(self, m):
     accumulator = Signal(signed(32))
     m.d.comb += self.result.eq(accumulator)
     with m.If(self.add_en):
         m.d.sync += accumulator.eq(accumulator + self.in_value)
         m.d.comb += self.result.eq(accumulator + self.in_value)
     # clear always resets accumulator next cycle, even if add_en is high
     with m.If(self.clear):
         m.d.sync += accumulator.eq(0)
コード例 #23
0
ファイル: post_process.py プロジェクト: tcal-x/CFU-Playground
class StreamLimiter(SimpleElaboratable):
    """Allows only a certain number of elements to apss through stream.

    Counts a given number of items, then signals that it is done.

    Parameters
    ----------

    payload_type:
        The type carried by the stream

    Attributes
    ----------

    stream_in: Endpoint(payload_type), in
        The incoming stream. Will always be ready after start and
        until done.
    stream_out: Endpoint(payload_type), out
        The outgoing stream. Does not respect back pressure.

    num_allowed: Signal(18), in
        The number of items allowed to pass.

    start: Signal(), in
        Pulse high to allow items beginning next cycle.

    running: Signal(), out
        Indicates that items are being allowed to pass

    finished: Signal(), out
        Indicates that last item has been handled.
    """

    def __init__(self, payload_type=signed(32)):
        self.stream_in = Endpoint(payload_type)
        self.stream_out = Endpoint(payload_type)
        self.num_allowed = Signal(18)
        self.start = Signal()
        self.running = Signal()
        self.finished = Signal()

    def elab(self, m):
        m.d.sync += self.finished.eq(0)
        m.d.comb += [
            self.stream_in.ready.eq(self.running),
            self.stream_out.valid.eq(self.stream_in.is_transferring()),
            self.stream_out.payload.eq(self.stream_in.payload),
        ]
        counter = Signal.like(self.num_allowed)
        with m.If(self.start):
            m.d.sync += counter.eq(self.num_allowed)
        with m.If(self.stream_in.is_transferring()):
            m.d.sync += counter.eq(counter - 1)
            with m.If(counter == 1):
                m.d.sync += self.finished.eq(1)
        m.d.comb += self.running.eq(counter != 0)
コード例 #24
0
    def elab(self, m):
        running = Signal()
        with m.If(self.start_run):
            m.d.sync += running.eq(1)
        with m.If(self.all_output_finished):
            m.d.sync += running.eq(0)

        m.d.comb += self.gate.eq((running | self.start_run)
                                 & self.in_store_ready
                                 & self.fifo_has_space)
コード例 #25
0
    def elab(self, m):
        x_count = Signal(7)
        next_row_addr = Signal(14)
        addr = Signal(14)

        with m.If(self.start):
            # Start overrides other behaviors
            m.d.comb += self.addr_out.eq(self.start_addr)
            m.d.sync += [
                addr.eq(self.start_addr),
                x_count.eq(1),
                next_row_addr.eq(self.start_addr + self.num_blocks_y),
            ]
        with m.Else():
            m.d.comb += self.addr_out.eq(addr)
            # x_size is the number of cycles to read 4 consecutive pixels
            x_size = Signal(7)
            m.d.comb += x_size.eq(self.depth << 4)
            with m.If(x_count != (x_size - 1)):
                m.d.sync += x_count.eq(x_count + 1)
                with m.If(x_count[:2] == 3):
                    m.d.sync += addr.eq(addr + 1)
            with m.Else():
                # x_count == x_size - 1 ==> End of row
                m.d.sync += [
                    addr.eq(next_row_addr),
                    next_row_addr.eq(next_row_addr + self.num_blocks_y),
                    x_count.eq(0),
                ]
コード例 #26
0
ファイル: macc.py プロジェクト: tcal-x/CFU-Playground
    def elab(self, m):
        register = Signal(32)
        m.d.comb += self.result.eq(register)

        with m.If(self.shift_en):
            calc = Signal(32)
            m.d.comb += [
                calc.eq(Cat(register[8:], self.in_value)),
                self.result.eq(calc),
            ]
            m.d.sync += register.eq(calc)
コード例 #27
0
 def elab(self, m):
     waiting = Signal()
     with m.If(self.ready & (waiting | self.start)):
         m.d.comb += [
             self.output.eq(self.data),
             self.next.eq(1),
             self.done.eq(1),
         ]
         m.d.sync += waiting.eq(0)
     with m.Elif(self.start & ~self.ready):
         m.d.sync += waiting.eq(1)
コード例 #28
0
ファイル: get.py プロジェクト: tcal-x/CFU-Playground
class StatusRegister(SimpleElaboratable):
    """A register set by gateware.

    Allows gateware to provide data to a CPU.

    Parameters
    ----------

    valid_at_reset: bool
      Whether payload is valid at reset or register ought to wait
      to transfer a value from its input stream.

    ready_when_valid: bool
      Whether the register should allow overwriting valid values
      with new values from its input stream.
      If true, the register is unconditionally ready to accept new values.
      If false, the register will only accept new values when it is not
      already holding a valid value.

    Attributes
    ----------

    input: Endpoint(unsigned(32)), in
      A stream of new values.

    invalidate: Signal(), in
      Causes valid to be deassserted.

    value: Signal(32), out
      The value held by the register. Received from sink.payload.

    valid: Signal(), out
      Deasserted when clear is asserted. Asserted when new value
      received at sink.

    """
    def __init__(self, valid_at_reset=True, ready_when_valid=True):
        super().__init__()
        self.ready_when_valid = ready_when_valid
        self.input = Endpoint(unsigned(32))
        self.invalidate = Signal()
        self.valid = Signal(reset=valid_at_reset)
        self.value = Signal(32)

    def elab(self, m):
        if self.ready_when_valid:
            m.d.comb += self.input.ready.eq(1)
        else:
            m.d.comb += self.input.ready.eq(~self.valid)
        with m.If(self.invalidate):
            m.d.sync += self.valid.eq(0)
        with m.If(self.input.is_transferring()):
            m.d.sync += self.value.eq(self.input.payload)
            m.d.sync += self.valid.eq(1)
コード例 #29
0
 def max_(word0, word1):
     result = [Signal(8, name=f"result{i}") for i in range(4)]
     bytes0 = [word0[i:i + 8] for i in range(0, 32, 8)]
     bytes1 = [word1[i:i + 8] for i in range(0, 32, 8)]
     for r, b0, b1 in zip(result, bytes0, bytes1):
         sb0 = Signal(signed(8))
         m.d.comb += sb0.eq(b0)
         sb1 = Signal(signed(8))
         m.d.comb += sb1.eq(b1)
         m.d.comb += r.eq(Mux(sb1 > sb0, b1, b0))
     return Cat(*result)
コード例 #30
0
ファイル: output.py プロジェクト: tcal-x/CFU-Playground
 def elab(self, m):
     waiting = Signal()
     with m.If(self.start | waiting):
         m.d.comb += self.r_en.eq(1)
         with m.If(self.r_rdy):
             m.d.comb += [
                 self.output.eq(self.r_data),
                 self.done.eq(1),
             ]
             m.d.sync += waiting.eq(0)
         with m.Else():
             m.d.sync += waiting.eq(1)