def elaborate(self, platform): m = Module() delay_tap = Signal(self._SREG_LEN) m.d.comb += delay_tap.eq(1 << self.log_downsample_ratio) # Dynamic delay shift register out_val = Signal(signed(self._dw)) delay_reg = Array( Signal(signed(self._dw), reset=0) for _ in range(self._SREG_LEN)) src = self.i for x in range(self._SREG_LEN): m.d.sync += delay_reg[x].eq(src) src = delay_reg[x] m.d.comb += out_val.eq(delay_reg[delay_tap - 1]) counter = Signal(signed(self._dw)) with m.If(counter == delay_tap - 1): m.d.sync += counter.eq(0) m.d.comb += self.data_valid.eq(1) with m.Else(): m.d.sync += counter.eq(counter + 1) moving_average_full = Signal(signed(self._dw + self.MAX_DELAY_BITS)) m.d.sync += moving_average_full.eq(moving_average_full + self.i - out_val) m.d.comb += [ self.o.eq(moving_average_full >> self.log_downsample_ratio) ] return m
def init(self, p, zi: iterable = None) -> None: """ Initialize filter with parameter dict `p` by initialising all registers and quantizers. This needs to be done every time quantizers or coefficients are updated. Parameters ---------- p : dict dictionary with coefficients and quantizer settings (see docstring of `__init__()` for details) zi : array-like Initialize `L = len(b)` filter registers. Strictly speaking, `zi[0]` is not a register but the current input value. When `len(zi) != len(b)`, truncate or fill up with zeros. When `zi == None`, all registers are filled with zeros. Returns ------- None. """ self.p = p # fb.fil[0]['fxqc'] # parameter dictionary with coefficients etc. # ------------- Define I/Os -------------------------------------- self.i = Signal(signed(self.p['QI']['W'])) # input signal self.o = Signal(signed(self.p['QO']['W'])) # output signal
def __init__(self, platform=None, divider=50, top=False): ''' platform -- pass test platform divider -- original clock of 100 MHz via PLL reduced to 50 MHz if this is divided by 50 motor state updated with 1 Mhz top -- trigger synthesis of module ''' self.top = top self.divider = divider self.platform = platform self.order = DEGREE # change code for other orders assert self.order == 3 self.motors = platform.motors self.max_steps = int(MOVE_TICKS / 2) # Nyquist # inputs self.coeff = Array() for _ in range(self.motors): self.coeff.extend( [Signal(signed(64)), Signal(signed(64)), Signal(signed(64))]) self.start = Signal() self.ticklimit = Signal(MOVE_TICKS.bit_length()) # output self.busy = Signal() self.totalsteps = Array( Signal(signed(self.max_steps.bit_length() + 1)) for _ in range(self.motors)) self.dir = Array(Signal() for _ in range(self.motors)) self.step = Array(Signal() for _ in range(self.motors))
def run_general(self): last = self.time[1] m = self.module core: Core = self.uut comb = m.d.comb lhs = Signal(signed(core.xlen)) rhs = Signal(signed(core.xlen)) blt_res = Signal(name="blt_res") comb += lhs.eq(last.r[last.btype.rs1]) comb += rhs.eq(last.r[last.btype.rs2]) comb += blt_res.eq(lhs < rhs) with m.If(blt_res): self.assert_jump_was_taken() with m.Else(): self.assert_no_jump_taken() lhs_bz = Signal() # bz = below-zero rhs_bz = Signal() comb += lhs_bz.eq(lhs[core.xlen - 1]) comb += rhs_bz.eq(rhs[core.xlen - 1]) with m.If(lhs_bz & (~rhs_bz)): self.assert_jump_was_taken() with m.Elif((~lhs_bz) & (rhs_bz)): self.assert_no_jump_taken()
def elaborate(self, platform: Platform) -> Module: m = Module() a = Signal(signed(33)) b = Signal(signed(33)) result_ll = Signal(32) result_lh = Signal(33) result_hl = Signal(33) result_hh = Signal(33) result_3 = Signal(64) result_4 = Signal(64) active = Signal(5) is_signed = Signal() a_is_signed = Signal() b_is_signed = Signal() low = Signal() m.d.sync += [ is_signed.eq(a_is_signed ^ b_is_signed), active.eq(Cat(self.valid & (active == 0), active)), low.eq(self.op == Funct3.MUL) ] # ---------------------------------------------------------------------- # fist state m.d.comb += [ a_is_signed.eq(( (self.op == Funct3.MULH) | (self.op == Funct3.MULHSU)) & self.dat1[-1]), b_is_signed.eq((self.op == Funct3.MULH) & self.dat2[-1]) ] m.d.sync += [ a.eq(Mux(a_is_signed, -Cat(self.dat1, 1), self.dat1)), b.eq(Mux(b_is_signed, -Cat(self.dat2, 1), self.dat2)), ] # ---------------------------------------------------------------------- # second state m.d.sync += [ result_ll.eq(a[0:16] * b[0:16]), result_lh.eq(a[0:16] * b[16:33]), result_hl.eq(a[16:33] * b[0:16]), result_hh.eq(a[16:33] * b[16:33]) ] # ---------------------------------------------------------------------- # third state m.d.sync += [ result_3.eq( Cat(result_ll, result_hh) + Cat(Repl(0, 16), (result_lh + result_hl))) ] # ---------------------------------------------------------------------- # fourth state m.d.sync += [ result_4.eq(Mux(is_signed, -result_3, result_3)), self.result.eq(Mux(low, result_4[:32], result_4[32:64])) ] m.d.comb += self.ready.eq(active[-1]) return m
def __init__(self): self.in0 = Signal(32) self.in1 = Signal(32) self.funct7 = Signal(7) self.output = Signal(32) self.start = Signal() self.done = Signal() self.in0s = Signal(signed(32)) self.in1s = Signal(signed(32))
def decode_imm(self, m: Module): """Decodes the immediate value out of the instruction.""" with m.Switch(self._imm_format): # Format I instructions. Surprisingly, SLTIU (Set if Less Than # Immediate Unsigned) actually does sign-extend the immediate # value, and then compare as if the sign-extended immediate value # were unsigned! with m.Case(OpcodeFormat.I): tmp = Signal(signed(12)) m.d.comb += tmp.eq(self.state._instr[20:]) m.d.comb += self._imm.eq(tmp) # Format S instructions: with m.Case(OpcodeFormat.S): tmp = Signal(signed(12)) m.d.comb += tmp[0:5].eq(self.state._instr[7:12]) m.d.comb += tmp[5:].eq(self.state._instr[25:]) m.d.comb += self._imm.eq(tmp) # Format R instructions: with m.Case(OpcodeFormat.R): m.d.comb += self._imm.eq(0) # Format U instructions: with m.Case(OpcodeFormat.U): m.d.comb += self._imm.eq(0) m.d.comb += self._imm[12:].eq(self.state._instr[12:]) # Format B instructions: with m.Case(OpcodeFormat.B): tmp = Signal(signed(13)) m.d.comb += [ tmp[12].eq(self.state._instr[31]), tmp[11].eq(self.state._instr[7]), tmp[5:11].eq(self.state._instr[25:31]), tmp[1:5].eq(self.state._instr[8:12]), tmp[0].eq(0), self._imm.eq(tmp), ] # Format J instructions: with m.Case(OpcodeFormat.J): tmp = Signal(signed(21)) m.d.comb += [ tmp[20].eq(self.state._instr[31]), tmp[12:20].eq(self.state._instr[12:20]), tmp[11].eq(self.state._instr[20]), tmp[1:11].eq(self.state._instr[21:31]), tmp[0].eq(0), self._imm.eq(tmp), ] with m.Case(OpcodeFormat.SYS): m.d.comb += [ self._imm[0:5].eq(self.state._instr[15:]), self._imm[5:].eq(0), ]
def comparison_impl(self, rv1, rv2): core : Core = self.core m = core.current_module comb = m.d.comb rv1_signed = Signal(signed(core.xlen)) rv2_signed = Signal(signed(core.xlen)) comb += rv1_signed.eq(rv1) comb += rv2_signed.eq(rv2) return rv1_signed < rv2_signed
def __init__(self, MAX_DELAY_BITS=5, dw=16): self._dw = dw self.MAX_DELAY_BITS = MAX_DELAY_BITS self._SREG_LEN = 2**MAX_DELAY_BITS self.i, self.o = (Signal(signed(self._dw), name='i'), Signal(signed(self._dw), name='o')) self.data_valid = Signal(name='data_valid') # log_downsample_ratio must be a power of 2. self.log_downsample_ratio = Signal(MAX_DELAY_BITS, name='log_downsample_ratio')
def elab(self, m): # Product is 17 bits: 8 bits * 9 bits = 17 bits products = [Signal(signed(17), name=f"product_{n}") for n in range(4)] for i_val, f_val, product in zip(all_words(self.i_data, 8), all_words(self.f_data, 8), products): f_tmp = Signal(signed(9)) m.d.sync += f_tmp.eq(f_val.as_signed()) i_tmp = Signal(signed(9)) m.d.sync += i_tmp.eq(i_val.as_signed() + self.offset) m.d.comb += product.eq(i_tmp * f_tmp) m.d.sync += self.result.eq(tree_sum(products))
def __init__(self): super().__init__() self.input_offset = Signal(signed(32)) self.reset_acc = Signal() self.output_offset = Signal(signed(32)) self.out_depth_set = Signal() self.out_depth = Signal(32) self.out_mult_set = Signal() self.out_mult = Signal(signed(32)) self.out_bias_shift_set = Signal() self.out_bias_shift = Signal(32)
def __init__(self, clk_freq): self.clk_freq = clk_freq self.i2s = Record([ ('mclk', 1), ('lrck', 1), ('sck', 1), ('sd', 1), ]) self.samples = Array((Signal(signed(16)), Signal(signed(16)))) self.stb = Signal() self.ack = Signal() self.ports = [self.i2s.mclk, self.i2s.lrck, self.i2s.sck, self.i2s.sd] self.ports += [self.samples[0], self.samples[1], self.stb, self.ack]
def elab(self, m): with_bias = Signal(signed(32)) m.d.comb += with_bias.eq(self.accumulator + self.bias) # acc = cpp_math_mul_by_quantized_mul_software( # acc, param_store_read(&output_multiplier), # param_store_read(&output_shift)); left_shift = Signal(5) right_sr = [Signal(5, name=f'right_sr_{n}') for n in range(4)] with m.If(self.shift > 0): m.d.comb += left_shift.eq(self.shift) with m.Else(): m.d.comb += right_sr[0].eq(-self.shift) left_shifted = Signal(32) m.d.comb += left_shifted.eq(with_bias << left_shift), # Pass right shift value down through several cycles to where # it is needed for a, b in zip(right_sr, right_sr[1:]): m.d.sync += b.eq(a) # All logic is combinational up to the inputs to the SRDHM m.submodules['srdhm'] = srdhm = SRDHM() m.d.comb += [ srdhm.a.eq(left_shifted), srdhm.b.eq(self.multiplier), ] # Output from SRDHM appears several cycles later right_shifted = Signal(signed(32)) m.d.sync += right_shifted.eq( rounding_divide_by_pot(srdhm.result, right_sr[-1])) # This logic is combinational to output # acc += reg_output_offset # if (acc < reg_activation_min) { # acc = reg_activation_min # } else if (acc > reg_activation_max) { # acc = reg_activation_max # } # return acc with_offset = Signal(signed(32)) m.d.comb += [ with_offset.eq(right_shifted + self.offset), self.result.eq( clamped(with_offset, self.activation_min, self.activation_max)), ]
def check(self, m: Module): ret_addr = (self.data.pre_pc + 2)[:16] offset = Signal(signed(8)) self.assert_cycles(m, 8) data = self.assert_cycle_signals(m, 1, address=self.data.pre_pc + 1, vma=1, rw=1, ba=0) self.assert_cycle_signals(m, 2, vma=0, ba=0) ret_addr_lo = self.assert_cycle_signals(m, 3, address=self.data.pre_sp, vma=1, rw=0, ba=0) ret_addr_hi = self.assert_cycle_signals(m, 4, address=self.data.pre_sp - 1, vma=1, rw=0, ba=0) self.assert_cycle_signals(m, 5, vma=0, ba=0) self.assert_cycle_signals(m, 6, vma=0, ba=0) self.assert_cycle_signals(m, 7, vma=0, ba=0) m.d.comb += offset.eq(data) m.d.comb += Assert(LCat(ret_addr_hi, ret_addr_lo) == ret_addr) self.assert_registers(m, PC=ret_addr + offset, SP=self.data.pre_sp - 2) self.assert_flags(m)
def __init__(self): self.accumulator = Signal(signed(32)) self.bias = Signal(signed(32)) self.multiplier = Signal(signed(32)) self.shift = Signal(signed(32)) self.offset = Signal(signed(32)) self.activation_min = Signal(signed(32)) self.activation_max = Signal(signed(32)) 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)
def as_signed(m: Module, signal: Signal): """ Create a new copy of signal, but marked as signed """ if signal.signed: # signed already print(f"Warning: trying to cast already signed sigan {signal.name}") return signal new_signal = Signal(signed(signal.width), name=signal.name + "_signed") m.d.comb += new_signal.eq(signal) return new_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)
def check(self, m: Module, instr: Value, data: FormalData): b = instr[6] pre_input = Mux(b, data.pre_b, data.pre_a) m.d.comb += [ Assert(data.post_a == data.pre_a), Assert(data.post_b == data.pre_b), Assert(data.post_x == data.pre_x), Assert(data.post_sp == data.pre_sp), Assert(data.addresses_written == 0), ] m.d.comb += [ Assert(data.post_pc == data.plus16(data.pre_pc, 3)), Assert(data.addresses_read == 3), Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)), Assert(data.read_addr[1] == data.plus16(data.pre_pc, 2)), Assert( data.read_addr[2] == Cat(data.read_data[1], data.read_data[0])), ] input1 = pre_input input2 = data.read_data[2] sinput1 = Signal(signed(8)) sinput2 = Signal(signed(8)) m.d.comb += sinput1.eq(input1) m.d.comb += sinput2.eq(input2) z = (input1 == input2) n = (input1 - input2)[7] # The following is wrong. This would calculate LT (less than), not N. # In other words, N is not a comparison, it's just the high bit # of the (unsigned) result. # n = ((sinput1 - sinput2) < 0) # GE is true if and only if N^V==0 (i.e. N == V). ge = sinput1 >= sinput2 v = Mux(ge, n, ~n) c = (input1 < input2) self.assertFlags(m, data.post_ccs, data.pre_ccs, Z=z, N=n, V=v, C=c)
def elaborate(self, platform) -> Module: """ `platform` normally specifies FPGA platform, not needed here. """ m = Module() # instantiate a module ### muls = [0] * len(self.p['b']) DW = int(np.ceil(np.log2(len(self.p['b'])))) # word growth # word format for sum of partial products b_i * x_i QP = { 'WI': self.p['QI']['WI'] + self.p['QCB']['WI'] + DW, 'WF': self.p['QI']['WF'] + self.p['QCB']['WF'] } QP.update({'W': QP['WI'] + QP['WF'] + 1}) src = self.i # first register is connected to input signal i = 0 for b in self.p['b']: sreg = Signal(signed( self.p['QI']['W'])) # create chain of registers m.d.sync += sreg.eq(src) # with input word length src = sreg # TODO: keep old data sreg to allow frame based processing (requiring reset) muls[i] = int(b) * sreg i += 1 # logger.debug(f"b = {pprint_log(self.p['b'])}\nW(b) = {self.p['QCB']['W']}") sum_full = Signal(signed( QP['W'])) # sum of all multiplication products with m.d.sync += sum_full.eq(reduce(add, muls)) # full product wordlength # rescale from full product wordlength to accumulator format sum_accu = Signal(signed(self.p['QA']['W'])) m.d.comb += sum_accu.eq(requant(m, sum_full, QP, self.p['QA'])) # rescale from accumulator format to output width m.d.comb += self.o.eq(requant(m, sum_accu, self.p['QA'], self.p['QO'])) return m # return result as list of integers
def __init__(self, config): self.divisor = config.osc_divisor self._calc_params(config) self.sync_in = Signal() # self.note_in = Signal(range(MIDI_NOTES)) self.mod_in = Signal(signed(16)) self.pw_in = Signal(7, reset=~0) self.note_in = voice_note_spec.outlet() self.pulse_out = mono_sample_spec(config.osc_depth).inlet() self.saw_out = mono_sample_spec(config.osc_depth).inlet()
def check(self, m: Module): input1, input2, actual_output, size, use_a = self.common_check(m) sinput1 = Signal(signed(8)) sinput2 = Signal(signed(8)) m.d.comb += sinput1.eq(input1) m.d.comb += sinput2.eq(input2) z = input1 == input2 n = (input1 - input2)[7] # The following is wrong. This would calculate LT (less than), not N. # In other words, N is not a comparison, it's just the high bit # of the (unsigned) result. # n = ((sinput1 - sinput2) < 0) # GE is true if and only if N^V==0 (i.e. N == V). ge = sinput1 >= sinput2 v = Mux(ge, n, ~n) c = input1 < input2 self.assert_registers(m, PC=self.data.pre_pc + size) self.assert_flags(m, Z=z, N=n, V=v, C=c)
def BR(self, m: Module): operand = self.mode_immediate8(m) relative = Signal(signed(8)) m.d.comb += relative.eq(operand) # At this point, pc is the instruction start + 2, so we just # add the signed relative offset to get the target. with m.If(self.cycle == 2): m.d.ph1 += self.tmp16.eq(self.pc + relative) with m.If(self.cycle == 3): take_branch = self.branch_check(m) self.end_instr(m, Mux(take_branch, self.tmp16, self.pc))
def check(self, m: Module, instr: Value, data: FormalData): input1, input2, actual_output = self.common_check(m, instr, data) sinput1 = Signal(signed(8)) sinput2 = Signal(signed(8)) m.d.comb += sinput1.eq(input1) m.d.comb += sinput2.eq(input2) output = input1 z = (input1 == input2) n = (input1 - input2)[7] # The following is wrong. This would calculate LT (less than), not N. # In other words, N is not a comparison, it's just the high bit # of the (unsigned) result. # n = ((sinput1 - sinput2) < 0) # GE is true if and only if N^V==0 (i.e. N == V). ge = sinput1 >= sinput2 v = Mux(ge, n, ~n) c = (input1 < input2) m.d.comb += Assert(actual_output == output) self.assertFlags(m, data.post_ccs, data.pre_ccs, Z=z, N=n, V=v, C=c)
def __init__(self): super().__init__() self.bias = Signal(signed(32)) self.bias_next = Signal() self.multiplier = Signal(signed(32)) self.multiplier_next = Signal() self.shift = Signal(signed(32)) self.shift_next = Signal() self.offset = Signal(signed(32)) self.activation_min = Signal(signed(32)) self.activation_max = Signal(signed(32))
def check(self, m: Module, instr: Value, data: FormalData): m.d.comb += [ Assert(data.post_ccs == data.pre_ccs), Assert(data.post_a == data.pre_a), Assert(data.post_b == data.pre_b), Assert(data.post_x == data.pre_x), Assert(data.post_sp == data.pre_sp), Assert(data.addresses_written == 0), ] m.d.comb += [ Assert(data.addresses_read == 1), Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)), ] n = data.pre_ccs[Flags.N] z = data.pre_ccs[Flags.Z] v = data.pre_ccs[Flags.V] c = data.pre_ccs[Flags.C] offset = Signal(signed(8)) br = instr[:4] take_branch = Array([ Const(1), Const(0), (c | z) == 0, (c | z) == 1, c == 0, c == 1, z == 0, z == 1, v == 0, v == 1, n == 0, n == 1, (n ^ v) == 0, (n ^ v) == 1, (z | (n ^ v)) == 0, (z | (n ^ v)) == 1, ]) m.d.comb += offset.eq(data.read_data[0]) m.d.comb += Assert( data.post_pc == Mux(take_branch[br], (data.pre_pc + 2 + offset)[:16], (data.pre_pc + 2)[:16]))
def __init__(self, platform, top=False): """ platform -- pass test platform top -- trigger synthesis of module """ self.platform = platform self.top = top self.spi = SPIBus() self.position = Array(Signal(signed(64)) for _ in range(platform.motors)) self.pinstate = Signal(8) self.read_commit = Signal() self.read_en = Signal() self.read_discard = Signal() self.dispatcherror = Signal() self.execute = Signal() self.read_data = Signal(MEMWIDTH) self.empty = Signal()
def check(self, m: Module): self.assert_cycles(m, 4) data = self.assert_cycle_signals(m, 1, address=self.data.pre_pc + 1, vma=1, rw=1, ba=0) self.assert_cycle_signals(m, 2, vma=0, ba=0) self.assert_cycle_signals(m, 3, vma=0, ba=0) n = self.data.pre_ccs[Flags.N] z = self.data.pre_ccs[Flags.Z] v = self.data.pre_ccs[Flags.V] c = self.data.pre_ccs[Flags.C] offset = Signal(signed(8)) br = self.instr[:4] take_branch = Array([ Const(1), Const(0), (c | z) == 0, (c | z) == 1, c == 0, c == 1, z == 0, z == 1, v == 0, v == 1, n == 0, n == 1, (n ^ v) == 0, (n ^ v) == 1, (z | (n ^ v)) == 0, (z | (n ^ v)) == 1, ]) m.d.comb += offset.eq(data) target = Mux(take_branch[br], self.data.pre_pc + 2 + offset, self.data.pre_pc + 2) self.assert_registers(m, PC=target) self.assert_flags(m)
def __verify_right(m): m.submodules.shr = shr = Shifter(32, Shifter.RIGHT, "shr") comb = m.d.comb input_with_msb = Signal(signed(33)) expected = Signal(32) comb += input_with_msb[0:32].eq(shr.input) comb += input_with_msb[32].eq(shr.msb) comb += expected.eq(input_with_msb >> shr.shamt) comb += Assert(shr.output == expected) with m.If(shr.shamt == 0): comb += Assert(shr.output == shr.input) with m.If((shr.input == 0) & (shr.output != 0)): comb += Assert(shr.msb) with m.If(shr.shamt == 31): comb += Assert(shr.output[0] == shr.input[31]) comb += Assert(shr.output[0] == shr.input.bit_select(shr.shamt, 1)) with m.If(shr.msb == shr.input[31]): comb += Assert(shr.output == as_signed(m, shr.input) >> shr.shamt) return shr.ports()
def elab(self, m): m.d.sync += self.done.eq(0) ab = Signal(signed(64)) nudge = 1 << 30 # for some reason negative nudge is not used with m.FSM(): with m.State("stage0"): with m.If(self.start): with m.If((self.a == INT32_MIN) & (self.b == INT32_MIN)): m.d.sync += [ self.result.eq(INT32_MAX), self.done.eq(1) ] with m.Else(): m.d.sync += ab.eq(self.a * self.b) m.next = "stage1" with m.State("stage1"): m.d.sync += [ self.result.eq((ab + nudge)[31:]), self.done.eq(1) ] m.next = "stage0"