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 run_general(self): last = self.time[1] now = self.time[0] m = self.module comb = m.d.comb core: Core = self.uut with m.If( last.itype.match(opcode=Opcode.Jalr) & (last.itype.funct3 == 0)): with m.If(last.itype.rd == 0): now.assert_same_gpr(m, last.r) with m.Else(): now.assert_same_gpr_but_one(m, last.r, last.itype.rd) comb += Assert(now.r[last.itype.rd] == (last.r.pc + 4)[0:32]) sum = Signal(core.xlen) expected_jalr_pc = Signal(core.xlen) comb += sum.eq(last.r[last.itype.rs1] + last.itype.imm) comb += expected_jalr_pc.eq(Cat(Const(0, 1), sum[1:core.xlen])) comb += Assert(now.r.pc == expected_jalr_pc)
def elaborate(self, platform): m = Module() width = self._width # Instead of using a counter, we will use a sentinel bit in the shift # register to indicate when it is full. shift_reg = Signal(width + 1, reset=0b1) m.d.comb += self.o_data.eq(shift_reg[0:width]) m.d.usb_io += self.o_put.eq(shift_reg[width - 1] & ~shift_reg[width] & self.i_valid), with m.If(self.reset): m.d.usb_io += shift_reg.eq(1) with m.If(self.i_valid): with m.If(shift_reg[width]): m.d.usb_io += shift_reg.eq(Cat(self.i_data, Const(1))) with m.Else(): m.d.usb_io += shift_reg.eq(Cat(self.i_data, shift_reg[0:width])), return m
def elab(self, m): areg = Signal.like(self.a) breg = Signal.like(self.b) ab = Signal(signed(64)) overflow = Signal() # for some reason negative nudge is not used nudge = 1 << 30 # cycle 0, register a and b m.d.sync += [ areg.eq(self.a), breg.eq(self.b), ] # cycle 1, decide if this is an overflow and multiply m.d.sync += [ overflow.eq((areg == INT32_MIN) & (breg == INT32_MIN)), ab.eq(areg * breg), ] # cycle 2, apply nudge determine result m.d.sync += [ self.result.eq(Mux(overflow, INT32_MAX, (ab + nudge)[31:])), ]
class LogicUnit(Elaboratable): def __init__(self): # inputs self.op = Signal(3) self.dat1 = Signal(32) self.dat2 = Signal(32) # outputs self.result = Signal(32) def elaborate(self, platform): m = Module() with m.Switch(self.op): with m.Case(Funct3.XOR): m.d.comb += self.result.eq(self.dat1 ^ self.dat2) with m.Case(Funct3.OR): m.d.comb += self.result.eq(self.dat1 | self.dat2) with m.Case(Funct3.AND): m.d.comb += self.result.eq(self.dat1 & self.dat2) with m.Default(): m.d.comb += self.result.eq(0) return m
class Producer(Elaboratable): def __init__(self, data_shape): # inputs self.w_rdy_i = Signal() # outputs self.w_en_o = Signal() self.w_data_o = Signal(data_shape) def elaborate(self, platform): m = Module() data = Signal(4) with m.If(self.w_rdy_i): m.d.comb += self.w_en_o.eq(1) m.d.comb += self.w_data_o.eq(data) m.d.sync += data.eq(data + 1) with m.Else(): m.d.comb += self.w_en_o.eq(0) return m
def elaborate(self, platform): m = Module() m.submodules.stuff = stuff = FSM() stuff_bit = Signal(1) for i in range(5): stuff.act("D%d" % i, If(self.i_data, # Receiving '1' increments the bitstuff counter. NextState("D%d" % (i + 1)) ).Else( # Receiving '0' resets the bitstuff counter. NextState("D0") ) ) stuff.act("D5", If(self.i_data, # There's a '1', so indicate we might stall on the next loop. self.o_will_stall.eq(1), # Receiving '1' increments the bitstuff counter. NextState("D6") ).Else( # Receiving '0' resets the bitstuff counter. NextState("D0") ) ) stuff.act("D6", # stuff a bit stuff_bit.eq(1), # Reset the bitstuff counter NextState("D0") ) m.d.comb += [ self.o_stall.eq(stuff_bit) ] # flop outputs with m.If(stuff_bit): m.d.sync += self.o_data.eq(0), with m.Else(): m.d.sync += self.o_data.eq(self.i_data) return m
def elaborate(self, platform): m = Module() bits_per_sub = self.n // self.m ci = 0 for idx in range(self.m): sub_adder = Signal(bits_per_sub + 1, name=f"sub{idx}") i0 = idx * bits_per_sub i1 = (idx + 1) * bits_per_sub m.d.sync += sub_adder.eq(self.a[i0:i1] + self.b[i0:i1] + ci) m.d.comb += self.c[i0:i1].eq(sub_adder[:bits_per_sub]) ci = sub_adder[-1] return m
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)
class ILAExample(Elaboratable): """ Gateware module that demonstrates use of the internal ILA. """ def __init__(self): self.counter = Signal(16) self.hello = Signal(8) self.ila = USBIntegratedLogicAnalyer( signals=[self.counter, self.hello], sample_depth=32) def interactive_display(self): frontend = USBIntegratedLogicAnalyzerFrontend(ila=self.ila) frontend.interactive_display() 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
def verify_utype(self, m): sig = self.build_signal(m, "U", [(0, 6, "1001011"), (7, 11, "10000"), (12, 31, "00100010000110111111")]) u = UType("utype") u.elaborate(m.d.comb, sig) m.d.comb += Assert(u.opcode == Const(0b1001011, 7)) m.d.comb += Assert(u.rd == Const(0b10000, 5)) m.d.comb += Assert( u.imm == Const(0b00100010000110111111000000000000, 32)) m.d.comb += Assert(u.match(opcode=0b1001011)) m.d.comb += Assert(u.match(rd=0b10000)) m.d.comb += Assert(u.match(imm=0b00100010000110111111000000000000)) m.d.comb += Assert(u.match(opcode=0b1011011) == 0) m.d.comb += Assert(u.match(rd=0b11000) == 0) m.d.comb += Assert( u.match(imm=0b10100010000110111111000000000000) == 0) m.d.comb += Assert( u.match(opcode=0b1001011, rd=0b10000, imm=0b00100010000110111111000000000000)) u = UType("utype.sign") u.elaborate(m.d.comb, Const(0x8000_0000, 32)) m.d.comb += Assert(u.imm[31] == 1) u = UType("utype.trailzero") u.elaborate(m.d.comb, Const(0xFFFF_FFFF, 32)) m.d.comb += Assert(u.imm.bit_select(0, 12) == 0) u_builder_check = Signal(32) u_builder_opcode = Signal(7) u_builder_rd = Signal(5) u_builder_imm = Signal(20) m.d.comb += Assume(u_builder_imm[0:12] == 0) built_utype = UType.build_i32(opcode=u_builder_opcode, rd=u_builder_rd, imm=u_builder_imm) m.d.comb += u_builder_check.eq(built_utype) u = UType("utype.build") u.elaborate(m.d.comb, built_utype) m.d.comb += Assert(u_builder_opcode == u.opcode) m.d.comb += Assert(u_builder_rd == u.rd) m.d.comb += Assert(Cat(Repl(0, 12), u_builder_imm[12:32]) == u.imm) return [u_builder_check, u_builder_opcode, u_builder_rd, u_builder_imm]
def elaborate(self, platform): m = Module() # Generate our domain clocks/resets. m.submodules.car = platform.clock_domain_generator() # Create our USB device interface... ulpi = platform.request(platform.default_usb_connection) m.submodules.usb = usb = USBDevice(bus=ulpi) # Add our standard control endpoint to the device. descriptors = self.create_descriptors() control_ep = usb.add_standard_control_endpoint(descriptors) # Create an interrupt endpoint which will carry the value of our counter to the host # each time our interrupt EP is polled. # Create the 32-bit counter we'll be using as our status signal. counter = Signal(32) m.d.usb += counter.eq(counter + 1) status_ep = USBSignalInEndpoint( width=32, endpoint_number=INTERRUPT_ENDPOINT_NUMBER, endianness="big") usb.add_endpoint(status_ep) m.d.comb += status_ep.signal.eq(counter) # Add a stream endpoint to our device. iso_ep = USBIsochronousInEndpoint(endpoint_number=ISO_ENDPOINT_NUMBER, max_packet_size=MAX_ISO_PACKET_SIZE) usb.add_endpoint(iso_ep) # We'll tie our address directly to our value, ensuring that we always # count as each offset is increased. m.d.comb += [ iso_ep.bytes_in_frame.eq(MAX_ISO_PACKET_SIZE), iso_ep.value.eq(iso_ep.address) ] # Connect our device as a high speed device by default. m.d.comb += [ usb.connect.eq(1), usb.full_speed_only.eq(1 if os.getenv('LUNA_FULL_ONLY') else 0), ] return m
class SimDdr(Elaboratable): def __init__(self, pins: TristateDdrIo, domain): self.pins = pins self.domain = domain self.o = Signal(pins.o0.shape()) def elaborate(self, platform): m = Module() toggle = Signal() m.d.sync += toggle.eq(~toggle) m.d.comb += self.o.eq(Mux(toggle, self.pins.o0, self.pins.o1)) return DomainRenamer(self.domain)(m)
def check(self, m: Module, instr: Value, data: FormalData): input1, input2, actual_output = self.common_check(m, instr, data) carry_in = Signal() sum9 = Signal(9) sum8 = Signal(8) with_carry = (instr[1] == 1) n = sum9[7] c = ~sum9[8] z = (sum9[:8] == 0) v = (sum8[7] ^ sum9[8]) with m.If(with_carry): m.d.comb += carry_in.eq(data.pre_ccs[Flags.C]) with m.Else(): m.d.comb += carry_in.eq(0) m.d.comb += [ sum9.eq(input1 + ~input2 + ~carry_in), sum8.eq(input1[:7] + ~input2[:7] + ~carry_in), Assert(actual_output == sum9[:8]), ] self.assertFlags(m, data.post_ccs, data.pre_ccs, Z=z, N=n, V=v, C=c)
class Consumer(Elaboratable): def __init__(self, data_shape): # inputs self.r_rdy_i = Signal() self.r_data_i = Signal(data_shape) # outputs self.r_en_o = Signal() self.data = Signal(data_shape) def elaborate(self, platform): m = Module() data = self.data with m.If(self.r_rdy_i): m.d.comb += self.r_en_o.eq(1) m.d.comb += data.eq(self.r_data_i) with m.Else(): m.d.comb += self.r_en_o.eq(0) m.d.comb += data.eq(0) return m
class Reset: def __init__(self, core): self.reset_state = Signal(2) self.core = core def setup(self, m: Module): with m.Switch(self.reset_state): with m.Case(0): m.d.ph1 += self.core.Addr.eq(0xFFFE) m.d.ph1 += self.core.RW.eq(1) m.d.ph1 += self.reset_state.eq(1) with m.Case(1): m.d.ph1 += self.core.Addr.eq(0xFFFF) m.d.ph1 += self.core.RW.eq(1) m.d.ph1 += self.core.registers.tmp8.eq(self.core.Din) m.d.ph1 += self.reset_state.eq(2) with m.Case(2): m.d.ph1 += self.reset_state.eq(3) reset_vec = Cat(self.core.Din, self.core.registers.tmp8) m.d.ph1 += self.core.registers.ccr.eq((1 << Ccr.RUN) | (1 << Ccr.RUN_2)) self.core.next(m, reset_vec) def is_running(self, m: Module): return self.reset_state == 3
def elaborate(self, platform): m = Module() # Move the pipeline along m.d.sync += [ self.o_x_coord.eq(self.i_x_coord), self.o_y_coord.eq(self.i_y_coord), self.o_z_coord.eq(self.i_z_coord), self.o_red.eq(self.i_red), self.o_green.eq(self.i_green), self.o_blue.eq(self.i_blue), self.o_alpha.eq(self.i_alpha), ] # Z Test, relative to ZREF. test = Signal() with m.If(self.i_enable): with m.Switch(self.i_test): with m.Case(ZTestMode.NEVER): m.d.comb += test.eq(0) with m.Case(ZTestMode.ALWAYS): m.d.comb += test.eq(1) with m.Case(ZTestMode.GEQUAL): m.d.comb += test.eq(self.i_z_coord >= self.i_zref) with m.Case(ZTestMode.GREATER): m.d.comb += test.eq(self.i_z_coord > self.i_zref) with m.Else(): m.d.comb += test.eq(1) m.d.sync += [ self.o_rgbrndr.eq(self.i_rgbrndr & test), self.o_arndr.eq(self.i_arndr & test), self.o_zrndr.eq(self.i_zrndr & test) ] return m
def elaborate(self, platform): bits = self.bits bytes = self.bytes m = Module() frame_count = Signal(7) frame_count_next = Signal(7) with m.If(bits.multiframe): m.d.comb += frame_count_next.eq(0) with m.Else(): m.d.comb += frame_count_next.eq(frame_count + 1) m.d.sync += [ bytes.data_strobe.eq(0), bytes.frame_strobe.eq(bits.frame_strobe), bytes.multiframe_strobe.eq(bits.multiframe_strobe), ] bit_count = Signal(3) with m.Elif(bits.frame_strobe): # First byte in frame is the frame counter and F bit. m.d.sync += [ bytes.data.eq(Cat(bits.data, frame_count_next)), bytes.data_strobe.eq(1), bit_count.eq(0), frame_count.eq(frame_count_next), ] with m.Elif(bits.data_strobe): m.d.sync += [ bytes.data.eq(Cat(bits.data, bytes.data[1:])), bytes.data_strobe.eq(bit_count == 7), bit_count.eq(bit_count + 1), ] return m
class AdderUnit(Elaboratable): def __init__(self) -> None: self.sub = Signal() # input self.dat1 = Signal(32) # input self.dat2 = Signal(32) # input self.result = Signal(32) # output self.carry = Signal() # output self.overflow = Signal() # output def elaborate(self, platform: Platform) -> Module: m = Module() # From: http://teaching.idallen.com/cst8214/08w/notes/overflow.txt with m.If(self.sub): m.d.comb += [ Cat(self.result, self.carry).eq(self.dat1 - self.dat2), self.overflow.eq((self.dat1[-1] != self.dat2[-1]) & (self.dat2[-1] == self.result[-1])) ] with m.Else(): m.d.comb += [ Cat(self.result, self.carry).eq(self.dat1 + self.dat2), self.overflow.eq((self.dat1[-1] == self.dat2[-1]) & (self.dat2[-1] != self.result[-1])) ] return m
class LTC2292(Elaboratable): """ """ def __init__(self, posedge_domain, negedge_domain): """ """ self._width = 12 self._posedge_domain = posedge_domain self._negedge_domain = negedge_domain self.di = Signal(self._width) self.dao = Signal(self._width) self.dbo = Signal(self._width) def elaborate(self, platform): """ """ m = Module() dbuf = Signal(self._width) m.d[self._posedge_domain] += [self.dao.eq(dbuf), self.dbo.eq(self.di)] m.d[self._negedge_domain] += dbuf.eq(self.di) return m
class Counter(Elaboratable): """Logic for the Counter module.""" def __init__(self): self.count = Signal(40, reset=1) def elaborate(self, _: Platform) -> Module: """Implements the logic for the Counter module.""" m = Module() with m.If(self.count == 999_999_999_999): m.d.sync += self.count.eq(1) with m.Else(): m.d.sync += self.count.eq(self.count + 1) return m
class SigmaDeltaDAC(Elaboratable): def __init__(self, width: int): self.width = width self.out = Signal() self.waveform = Signal(width) def elaborate(self, platform): m = Module() acc = Signal(self.width + 1) m.d.sync += acc.eq(acc[:self.width] + self.waveform) m.d.comb += self.out.eq(acc[-1]) return m
class UnsignedComparator(Elaboratable): """Logic for the UnsignedComparator module.""" def __init__(self): self.a = Signal(16) self.b = Signal(16) self.lt = Signal() def elaborate(self, _: Platform) -> Module: """Implements the logic for the UnsignedComparator module.""" m = Module() m.d.comb += self.lt.eq(self.a < self.b) return m
class SyncSerialReadoutILATest(SPIGatewareTestCase): def instantiate_dut(self): self.input_signal = Signal(12) return SyncSerialILA(signals=[self.input_signal], sample_depth=16, clock_polarity=1, clock_phase=0) def initialize_signals(self): yield self.input_signal.eq(0xF00) @sync_test_case def test_spi_readout(self): input_signal = self.input_signal # Trigger the test while offering our first sample. yield yield from self.pulse(self.dut.trigger, step_after=False) # Provide the remainder of our samples. for i in range(1, 16): yield input_signal.eq(0xF00 | i) yield # Wait a few cycles to account for delays in # the sampling pipeline. yield from self.advance_cycles(5) # We've now captured a full set of samples. # We'll test reading them out. self.assertEqual((yield self.dut.complete), 1) # Start the transaction, and exchange 16 bytes of data. yield self.dut.spi.cs.eq(1) yield # Read our our result over SPI... data = yield from self.spi_exchange_data(b"\0" * 32) # ... and ensure it matches what was sampled. i = 0 while data: datum = data[0:4] del data[0:4] expected = b"\x00\x00\x0f" + bytes([i]) self.assertEqual(datum, expected) i += 1
def elaborate(self, platform): m = Module() m.submodules.sincos_lookup = sincos_lookup = SinCosLookup(out_width=self.width, samples=self.samples) phase_acc = Signal(32) m.d.comb += [ sincos_lookup.addr.eq(phase_acc[-sincos_lookup.addr.width:]), # last `sincos_lookup.addr.width` bits of the phase accumulator self.sin.eq(sincos_lookup.sin), self.cos.eq(sincos_lookup.cos), ] # with m.If(self.enable): m.d.sync += phase_acc.eq(phase_acc + self.phase_step) return m
def dump_inputs(from_module: Module, to_module: Module, prefix="", suffix="") -> List[Signal]: input_copies = [] for signal in from_module.inputs(): if signal.__class__ == Signal: new_signal = Signal(shape=signal.shape(), name=prefix + signal.name + suffix, attrs=signal.attrs, decoder=signal.decoder) to_module.d.comb += new_signal.eq(signal) input_copies.append(new_signal) else: raise Exception("Unsupported signal %s type %s" % (signal, signal.__class__)) return input_copies
def elaborate(self, platform): m = Module() m.submodules.crc = crc = CRC32() m.submodules.mac_match = mac_match = MACAddressMatch(self.mac_addr) m.submodules.rxbyte = rxbyte = RMIIRxByte(self.crs_dv, self.rxd0, self.rxd1) adr = Signal(self.write_port.addr.nbits) with m.FSM() as fsm: m.d.comb += [ self.write_port.addr.eq(adr), self.write_port.data.eq(rxbyte.data), self.write_port.en.eq(rxbyte.data_valid), crc.data.eq(rxbyte.data), crc.data_valid.eq(rxbyte.data_valid), crc.reset.eq(fsm.ongoing("IDLE")), mac_match.data.eq(rxbyte.data), mac_match.data_valid.eq(rxbyte.data_valid), mac_match.reset.eq(fsm.ongoing("IDLE")), ] # Idle until we see data valid with m.State("IDLE"): m.d.sync += self.rx_len.eq(0) m.d.sync += self.rx_valid.eq(0) with m.If(rxbyte.dv): m.d.sync += self.rx_offset.eq(adr) m.next = "DATA" # Save incoming data to memory with m.State("DATA"): with m.If(rxbyte.data_valid): m.d.sync += adr.eq(adr + 1) m.d.sync += self.rx_len.eq(self.rx_len + 1) with m.Elif(~rxbyte.dv): m.next = "EOF" with m.State("EOF"): with m.If(crc.crc_match & mac_match.mac_match): m.d.sync += self.rx_valid.eq(1) m.next = "IDLE" return m
def elaborate(self, platform: Platform) -> Module: m = Module() inputs = [self.a[i] for i in range(self.input_width)] h = 0 while len(inputs) > 1: h += 1 outputs = [] i = 0 while i < len(inputs): s = Signal(name=f"p{h}_{i}") m.d.comb += s.eq(inputs[i] ^ inputs[i + 1]) i += 2 outputs.append(s) inputs = outputs m.d.comb += self.parity.eq(~inputs[0]) return m
def elaborate(self, platform): m = Module() led0 = platform.request("led", 0) led1 = platform.request("led", 1) m.submodules.rdport = rdport = self.mem.read_port() with m.If(rdport.data == 255): m.d.comb += led0.eq(0) with m.Else(): m.d.comb += led0.eq(1) timer = Signal(range(round(100E6))) with m.If(timer > 100): m.d.comb += rdport.addr.eq(100) with m.Else(): m.d.comb += rdport.addr.eq(0) m.d.sync += timer.eq(timer + 1) m.d.comb += led1.o.eq(timer[-1]) return m
class RoundingDividebyPOT(SimpleElaboratable): """Implements gemmlowp::RoundingDivideByPOT This divides by a power of two, rounding to the nearest whole number. """ def __init__(self): self.x = Signal(signed(32)) self.exponent = Signal(5) self.result = Signal(signed(32)) def elab(self, m): # TODO: reimplement as a function that returns an expression mask = (1 << self.exponent) - 1 remainder = self.x & mask threshold = (mask >> 1) + self.x[31] rounding = Mux(remainder > threshold, 1, 0) m.d.comb += self.result.eq((self.x >> self.exponent) + rounding)