def elaborate(self, platform): """ Generate the Blinky tester. """ m = Module() # Grab our I/O connectors. leds = [ platform.request_optional("led", i, default=NullPin()).o for i in range(0, 8) ] user_io = [ platform.request_optional("user_io", i, default=NullPin()).o for i in range(0, 8) ] # Clock divider / counter. counter = Signal(28) m.d.sync += counter.eq(counter + 1) # Attach the LEDs and User I/O to the MSBs of our counter. m.d.comb += Cat(leds).eq(counter[-7:-1]) m.d.comb += Cat(user_io).eq(counter[7:21]) # Return our elaborated module. return m
def elaborate(self, platform): m = Module() # Create RMII clock domain from RMII clock input cd = ClockDomain("rmii", reset_less=True) m.d.comb += cd.clk.eq(self.rmii.ref_clk) m.domains.rmii = cd # Create RX write and TX read ports for RMII use rx_port_w = self.rx_mem.write_port(domain="rmii") tx_port_r = self.tx_mem.read_port(domain="rmii", transparent=False) m.submodules += [self.rx_port, rx_port_w, self.tx_port, tx_port_r] m.d.comb += [self.rx_port.en.eq(1), tx_port_r.en.eq(1)] # Create submodules for PHY and RMII m.submodules.phy_manager = phy_manager = PHYManager( self.clk_freq, self.phy_addr, self.phy_rst, self.mdio.mdio, self.mdio.mdc) m.submodules.stretch = stretch = PulseStretch(int(1e6)) rmii_rx = RMIIRx(self.mac_addr, rx_port_w, self.rmii.crs_dv, self.rmii.rxd0, self.rmii.rxd1) rmii_tx = RMIITx(tx_port_r, self.rmii.txen, self.rmii.txd0, self.rmii.txd1) # Create FIFOs to interface to RMII modules rx_fifo = AsyncFIFO(width=11 + self.rx_port.addr.nbits, depth=4) tx_fifo = AsyncFIFO(width=11 + self.tx_port.addr.nbits, depth=4) m.d.comb += [ # RX FIFO rx_fifo.din.eq(Cat(rmii_rx.rx_offset, rmii_rx.rx_len)), rx_fifo.we.eq(rmii_rx.rx_valid), Cat(self.rx_offset, self.rx_len).eq(rx_fifo.dout), rx_fifo.re.eq(self.rx_ack), self.rx_valid.eq(rx_fifo.readable), # TX FIFO tx_fifo.din.eq(Cat(self.tx_offset, self.tx_len)), tx_fifo.we.eq(self.tx_start), Cat(rmii_tx.tx_offset, rmii_tx.tx_len).eq(tx_fifo.dout), tx_fifo.re.eq(rmii_tx.tx_ready), rmii_tx.tx_start.eq(tx_fifo.readable), # Other submodules phy_manager.phy_reset.eq(self.phy_reset), self.link_up.eq(phy_manager.link_up), stretch.trigger.eq(self.rx_valid), self.eth_led.eq(stretch.pulse), ] rdr = DomainRenamer({"read": "sync", "write": "rmii"}) wdr = DomainRenamer({"write": "sync", "read": "rmii"}) rr = DomainRenamer("rmii") m.submodules.rx_fifo = rdr(rx_fifo) m.submodules.tx_fifo = wdr(tx_fifo) m.submodules.rmii_rx = rr(rmii_rx) m.submodules.rmii_tx = rr(rmii_tx) return m
def synth(core, m: Module): with m.If(core.cycle == 1): m.d.comb += core.alu.oper.eq(Operation.NOP) m.d.sync += [ core.reg.PC.eq(add16(core.reg.PC, 1)), core.enable.eq(1), core.addr.eq(add16(core.reg.PC, 1)), core.RWB.eq(1), core.cycle.eq(2), ] with m.If(core.cycle == 2): m.d.comb += core.alu.oper.eq(Operation.NOP) m.d.sync += [ core.tmp.eq(core.dout), core.reg.PC.eq(add16(core.reg.PC, 1)), core.enable.eq(1), core.addr.eq(add16(core.reg.PC, 1)), core.RWB.eq(1), core.cycle.eq(3), ] with m.If(core.cycle == 3): m.d.comb += core.alu.oper.eq(Operation.NOP) m.d.sync += [ core.reg.PC.eq(Cat(core.tmp, core.dout)), core.enable.eq(1), core.addr.eq(Cat(core.tmp, core.dout)), core.RWB.eq(1), core.cycle.eq(1), ]
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 verify_btype(self, m): sig = self.build_signal(m, "B", [(0, 6, "1001011"), (7, 7, "1"), (8, 11, "0000"), (12, 14, "001"), (15, 19, "00010"), (20, 24, "00011"), (25, 30, "011111"), (31, 31, "1")]) b = BType("btype") b.elaborate(m.d.comb, sig) m.d.comb += Assert(b.opcode == Const(0b1001011, 7)) m.d.comb += Assert(b.funct3 == Const(1, 3)) m.d.comb += Assert(b.rs1 == Const(2, 5)) m.d.comb += Assert(b.rs2 == Const(3, 5)) m.d.comb += Assert( b.imm == Cat(Const(0b1101111100000, 13), Repl(1, 19))) m.d.comb += Assert(b.match(opcode=0b1001011)) m.d.comb += Assert(b.match(rs1=2)) m.d.comb += Assert(b.match(rs2=3)) m.d.comb += Assert(b.match(funct3=1)) m.d.comb += Assert(b.match(imm=0b11111111111111111111101111100000)) m.d.comb += Assert( b.match(opcode=0b1001011, funct3=1, rs1=2, rs2=3, imm=0b11111111111111111111101111100000)) m.d.comb += Assert(~b.match(opcode=0b1001011, funct3=3, rs1=1, rs2=5, imm=0b11111111111111111111101111100000)) b_builder_check = Signal(32) b_builder_opcode = Signal(7) b_builder_f3 = Signal(3) b_builder_rs1 = Signal(5) b_builder_rs2 = Signal(5) b_builder_imm = Signal(13) m.d.comb += Assume(b_builder_imm[0] == 0) built_btype = BType.build_i32(opcode=b_builder_opcode, funct3=b_builder_f3, rs1=b_builder_rs1, rs2=b_builder_rs2, imm=b_builder_imm) m.d.comb += b_builder_check.eq(built_btype) b = BType("btype.build") b.elaborate(m.d.comb, built_btype) m.d.comb += Assert(b_builder_opcode == b.opcode) m.d.comb += Assert(b_builder_imm == Cat(Const(0, 1), b.imm[1:13])) m.d.comb += Assert(b.imm[13:32] == Repl(b_builder_imm[12], 32 - 13)) return [ b_builder_check, b_builder_opcode, b_builder_f3, b_builder_rs1, b_builder_rs2, b_builder_imm ]
def elaborate(self, platform): m = Module() x = Signal() tap = LFSR.TAPS[self.k] m.d.comb += x.eq(self.state[self.k - 1] ^ self.state[tap - 1]) with m.If(self.reset): m.d.sync += self.state.eq(1) with m.Else(): m.d.sync += Cat(self.state).eq(Cat(x, self.state)) return m
def elaborate(self, platform): m = Module() # create the byte selector with m.Switch(self.x_funct3): with m.Case(Funct3.B): m.d.comb += self.x_byte_sel.eq(0b0001 << self.x_offset) with m.Case(Funct3.H): m.d.comb += self.x_byte_sel.eq(0b0011 << self.x_offset) with m.Case(Funct3.W): m.d.comb += self.x_byte_sel.eq(0b1111) # format output data with m.Switch(self.x_funct3): with m.Case(Funct3.B): m.d.comb += self.x_data_w.eq(Repl(self.x_store_data[:8], 4)) with m.Case(Funct3.H): m.d.comb += self.x_data_w.eq(Repl(self.x_store_data[:16], 2)) with m.Case(Funct3.W): m.d.comb += self.x_data_w.eq(self.x_store_data) # format input data _byte = Signal((8, True)) _half = Signal((16, True)) m.d.comb += [ _byte.eq(self.m_data_r.word_select(self.m_offset, 8)), _half.eq(self.m_data_r.word_select(self.m_offset[1], 16)), ] with m.Switch(self.m_funct3): with m.Case(Funct3.B): m.d.comb += self.m_load_data.eq(_byte) with m.Case(Funct3.BU): m.d.comb += self.m_load_data.eq(Cat(_byte, 0)) # make sign bit = 0 with m.Case(Funct3.H): m.d.comb += self.m_load_data.eq(_half) with m.Case(Funct3.HU): m.d.comb += self.m_load_data.eq(Cat(_half, 0)) # make sign bit = 0 with m.Case(Funct3.W): m.d.comb += self.m_load_data.eq(self.m_data_r) # misalignment with m.Switch(self.x_funct3): with m.Case(Funct3.H, Funct3.HU): m.d.comb += self.x_misaligned.eq(self.x_offset[0]) with m.Case(Funct3.W): m.d.comb += self.x_misaligned.eq(self.x_offset != 0) return m
def populate_ulpi_registers(self, m): """ Creates translator objects that map our control signals to ULPI registers. """ # Function control. function_control = Cat(self.xcvr_select, self.term_select, self.op_mode, Const(0), ~self.suspend, Const(0)) self.add_composite_register(m, 0x04, function_control, reset_value=0b01000001) # OTG control. otg_control = Cat( self.id_pullup, self.dp_pulldown, self.dm_pulldown, self.dischrg_vbus, self.chrg_vbus, Const(0), Const(0), self.use_external_vbus_indicator ) self.add_composite_register(m, 0x0A, otg_control, reset_value=0b00000110)
def elaborate(self, platform: Platform) -> Module: m = Module() m.submodules.big = big = ALU_big(self.verification) m.d.comb += [ big.inputa.eq(Cat(self.inputa[:4], self.inputa[4:])), big.inputb.eq(Cat(self.inputb[:4], self.inputb[4:])), big.oper.eq(self.oper), self.result.eq(Cat(big.result[:4], big.result[4:])), self.PSW.eq(big.PSW), ] return m
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
def elaborate(self, platform): m = Module() board_spi = platform.request("debug_spi") # Create a set of registers, and expose them over SPI. spi_registers = SPIRegisterInterface( default_read_value=0x4C554E41) #default read = u'LUNA' m.submodules.spi_registers = spi_registers # Fill in some example registers. # (Register 0 is reserved for size autonegotiation). spi_registers.add_read_only_register(1, read=0xc001cafe) led_reg = spi_registers.add_register(2, size=6, name="leds") spi_registers.add_read_only_register(3, read=0xdeadbeef) # ... and tie our LED register to our LEDs. led_out = Cat( [platform.request("led", i, dir="o") for i in range(0, 6)]) m.d.comb += led_out.eq(led_reg) # Connect up our synchronized copies of the SPI registers. spi = synchronize(m, board_spi) m.d.comb += spi_registers.spi.connect(spi) return m
def check(m: Module, data: Snapshot, alu: Signal): m.d.comb += [ Assert(data.read_data[0].matches(MOV_A_read.opcode)), ] m.d.comb += [ Assert(Past(alu.oper, 4) == Operation.NOP), Assert(Past(alu.oper, 3) == Operation.NOP), Assert(Past(alu.oper, 2) == Operation.NOP), Assert(Past(alu.oper, 1) == Operation.OOR), Assert(Past(alu.inputa) == data.read_data[3]), Assert(Past(alu.inputb) == 0), Assert(Past(alu.result) == data.read_data[3]), ] m.d.comb += [ Assert(data.post.A == Past(alu.result)), Assert(data.post.X == data.pre.X), Assert(data.post.Y == data.pre.Y), Assert(data.post.SP == data.pre.SP), Assert(data.post.PC == add16(data.pre.PC, 3)), ] m.d.comb += [ Assert(data.addresses_read == 4), Assert(data.addresses_written == 0), Assert(data.read_addr[0] == add16(data.pre.PC, 0)), Assert(data.read_addr[1] == add16(data.pre.PC, 1)), Assert(data.read_addr[2] == add16(data.pre.PC, 2)), Assert(data.read_addr[3] == Cat(data.read_data[1], data.read_data[2])), ]
def check(m: Module, data: Snapshot, alu: Signal): m.d.comb += [ Assert(data.read_data[0].matches(MOV_A_write.opcode)), ] m.d.comb += [ Assert(Past(alu.oper, 5) == Operation.NOP), Assert(Past(alu.oper, 4) == Operation.NOP), Assert(Past(alu.oper, 3) == Operation.NOP), Assert(Past(alu.oper, 2) == Operation.NOP), Assert(Past(alu.oper, 1) == Operation.NOP), ] m.d.comb += [ Assert(data.post.A == data.pre.A), Assert(data.post.X == data.pre.X), Assert(data.post.Y == data.pre.Y), Assert(data.post.SP == data.pre.SP), Assert(data.post.PC == add16(data.pre.PC, 3)), Assert(data.post.PSW == data.pre.PSW), ] m.d.comb += [ Assert(data.addresses_read == 3), Assert(data.addresses_written == 1), Assert(data.read_addr[0] == add16(data.pre.PC, 0)), Assert(data.read_addr[1] == add16(data.pre.PC, 1)), Assert(data.read_addr[2] == add16(data.pre.PC, 2)), Assert(data.write_addr[0] == Cat(data.read_data[1], data.read_data[2])), Assert(data.write_data[0] == data.pre.A), ]
def elaborate(self, platform): m = Module() # Create our core USB device, and add a standard control endpoint. m.submodules.usb = usb = USBDevice(bus=self._bus) _control_ep = usb.add_standard_control_endpoint( self.create_descriptors()) # Cram all the registers into a single report statuses = Cat( [signal for (signal, _input_range, _usage) in self.inputs]) # Create an endpoint to emit our report every time we get polled status_ep = USBSignalInEndpoint(width=statuses.shape().width, endpoint_number=1, endianness="little") usb.add_endpoint(status_ep) # Connect our USB device m.d.comb += [ status_ep.signal.eq(statuses), usb.connect.eq(self.connect) ] return m
def __init__(self, *, signals, sample_depth, domain="sync", sample_rate=60e6, samples_pretrigger=1): self.domain = domain self.signals = signals self.inputs = Cat(*signals) self.sample_width = len(self.inputs) self.sample_depth = sample_depth self.samples_pretrigger = samples_pretrigger self.sample_rate = sample_rate self.sample_period = 1 / sample_rate # # Create a backing store for our samples. # self.mem = Memory(width=self.sample_width, depth=sample_depth, name="ila_buffer") # # I/O port # self.trigger = Signal() self.sampling = Signal() self.complete = Signal() self.captured_sample_number = Signal(range(0, self.sample_depth)) self.captured_sample = Signal(self.sample_width)
def process_load(self, input_value): lh_value = Signal(32) comb = self.core.current_module.d.comb bit_to_replicate=Mux(self.core.itype.funct3[2], Const(0,1), input_value[15]) comb += lh_value.eq(Cat(input_value[0:16], Repl(bit_to_replicate, 16))) return lh_value
def handle_simple_data_request(self, m, transmitter, data, length=1): """ Fills in a given current state with a request that returns a given piece of data. For e.g. GET_CONFIGURATION and GET_STATUS requests. Parameters: transmitter -- The transmitter module we're working with. data -- The data to be returned. """ # Connect our transmitter up to the output stream... m.d.comb += [ transmitter.stream.attach(self.interface.tx), Cat(transmitter.data[0:1]).eq(data), transmitter.max_length.eq(length) ] # ... trigger it to respond when data's requested... with m.If(self.interface.data_requested): m.d.comb += transmitter.start.eq(1) # ... and ACK our status stage. with m.If(self.interface.status_requested): m.d.comb += self.interface.handshakes_out.ack.eq(1) m.next = 'IDLE'
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), ]
def LCat(*args) -> Value: """Left or logical concatenation. Concatenates arguments such that the first argument is placed in the highest bit positions, and the last is placed in the lowest bit positions. """ return Cat(*args[::-1])
def elaborate_right(self, m: Module): comb = m.d.comb last_round = self.input for i in range(self.xlen.bit_length() - 1): next_round = Signal(self.xlen, name=f"{self.prefix}_r{i}") with m.If(self.shamt[i]): # 00 AAAA # 01 0AAA # 10 00AA # 11 000A shift_by = 2**i shift_end = self.xlen - shift_by comb += next_round[0:shift_end].eq(last_round >> shift_by) comb += next_round[shift_end:self.xlen].eq( Cat([self.msb for _ in range(shift_by)])) with m.Else(): comb += next_round.eq(last_round) last_round = next_round comb += self.output.eq(last_round) return
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), ]
def elaborate(self, platform): m = Module() m.submodules += self.ila # Generate our clock domains. clocking = LunaECP5DomainGenerator(clock_frequencies=CLOCK_FREQUENCIES) m.submodules.clocking = clocking # Clock divider / counter. m.d.fast += self.counter.eq(self.counter + 1) # 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 == 7) # Grab our I/O connectors. leds = [platform.request("led", i, dir="o") for i in range(0, 6)] spi_bus = synchronize(m, platform.request('debug_spi'), o_domain='fast') # Attach the LEDs and User I/O to the MSBs of our counter. m.d.comb += Cat(leds).eq(self.counter[-7:-1]) # Connect our ILA up to our board's aux SPI. m.d.comb += self.ila.spi.connect(spi_bus) # Return our elaborated module. return m
def elaborate(self, platform: Platform) -> Module: m = Module() sign_fill = Signal() operand = Signal(32) r_direction = Signal() r_result = Signal(32) shdata = Signal(64) # temp data # pre-invert the value, if needed # Direction: 1 = right. 0 = left. m.d.comb += [ operand.eq(Mux(self.direction, self.dat, self.dat[::-1])), sign_fill.eq(Mux(self.direction & self.sign_ext, self.dat[-1], 0)), shdata.eq(Cat(operand, Repl(sign_fill, 32))) ] with m.If(~self.stall): m.d.sync += [ r_direction.eq(self.direction), r_result.eq(shdata >> self.shamt) ] m.d.comb += self.result.eq(Mux(r_direction, r_result, r_result[::-1])) return m
def mode_ext(self, m: Module) -> Statement: """Generates logic to get the 16-bit operand for extended mode instructions. Returns a Statement containing the 16-bit operand. After cycle 2, tmp16 contains the operand. """ operand = Mux(self.cycle == 2, Cat(self.Din, self.tmp16[8:]), self.tmp16) with m.If(self.cycle == 1): m.d.ph1 += self.tmp16[8:].eq(self.Din) m.d.ph1 += self.pc.eq(self.pc + 1) m.d.ph1 += self.Addr.eq(self.pc + 1) m.d.ph1 += self.RW.eq(1) m.d.ph1 += self.cycle.eq(2) if self.verification is not None: self.formalData.read(m, self.Addr, self.Din) with m.If(self.cycle == 2): m.d.ph1 += self.tmp16[:8].eq(self.Din) m.d.ph1 += self.pc.eq(self.pc + 1) m.d.ph1 += self.cycle.eq(3) if self.verification is not None: self.formalData.read(m, self.Addr, self.Din) return operand
def check(self, m: Module, instr: Value, data: FormalData): b = instr[6] 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), ] m.d.comb += [ Assert(data.post_pc == data.plus16(data.pre_pc, 3)), Assert(data.addresses_read == 2), Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)), Assert(data.read_addr[1] == data.plus16(data.pre_pc, 2)), Assert(data.addresses_written == 1), Assert(data.write_addr[0] == Cat(data.read_data[1], data.read_data[0])), Assert(data.write_data[0] == input), ] self.assertFlags(m, data.post_ccs, data.pre_ccs, Z=(input == 0), N=input[7], V=0)
def check(self, m: Module, instr: Value, data: FormalData): mode = instr[4:6] 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), ] with m.If(mode == ModeBits.EXTENDED.value): m.d.comb += [ Assert(data.addresses_read == 2), Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)), Assert(data.read_addr[1] == data.plus16(data.pre_pc, 2)), Assert( data.post_pc == Cat(data.read_data[1], data.read_data[0])), ] with m.If(mode == ModeBits.INDEXED.value): m.d.comb += [ Assert(data.addresses_read == 1), Assert(data.read_addr[0] == data.plus16(data.pre_pc, 1)), Assert( data.post_pc == (data.pre_x + data.read_data[0])[:16]), ]
def check(self, m: Module, instr: Value, data: FormalData): b = instr[6] pre_input = Mux(b, data.pre_b, data.pre_a) output = Mux(b, data.post_b, data.post_a) with m.If(b): m.d.comb += Assert(data.post_a == data.pre_a) with m.Else(): m.d.comb += Assert(data.post_b == data.pre_b) m.d.comb += [ 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] z = output == 0 n = output[7] v = 0 m.d.comb += Assert(output == (input1 | input2)) self.assertFlags(m, data.post_ccs, data.pre_ccs, Z=z, N=n, V=v)
def elaborate(self, platform): m = Module() m.submodules += self.ila # Clock divider / counter. m.d.sync += self.counter.eq(self.counter + 1) # 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 == 7) # Grab our I/O connectors. leds = [ platform.request_optional("led", i, default=NullPin(), dir="o") for i in range(0, 6) ] spi_bus = synchronize(m, platform.request('debug_spi')) # Attach the LEDs and User I/O to the MSBs of our counter. m.d.comb += Cat(leds).eq(self.counter[-7:-1]) # Connect our ILA up to our board's aux SPI. m.d.comb += self.ila.spi.connect(spi_bus) # Return our elaborated module. return m
def elaborate(self, comb: List[Statement], input: Signal): comb += self.opcode.eq(input[0:7]) comb += self.funct3.eq(input[12:15]) comb += self.rs1.eq(input[15:20]) comb += self.rs2.eq(input[20:25]) comb += self.imm.eq( Cat(Const(0, 1), input[8:12], input[25:31], input[7], Repl(input[31], 20)))
def formal_ripple(cls) -> Tuple[Module, List[Signal]]: """Formal verification for a bunch of ALUs in ripple-carry mode.""" m = Module() alus = [None] * 8 m.submodules.alu0 = alus[0] = IC_74181() m.submodules.alu1 = alus[1] = IC_74181() m.submodules.alu2 = alus[2] = IC_74181() m.submodules.alu3 = alus[3] = IC_74181() m.submodules.alu4 = alus[4] = IC_74181() m.submodules.alu5 = alus[5] = IC_74181() m.submodules.alu6 = alus[6] = IC_74181() m.submodules.alu7 = alus[7] = IC_74181() a = Signal(32) b = Signal(32) f = Signal(32) cin = Signal() cout = Signal() s = Signal(4) mt = Signal() for x in range(8): m.d.comb += alus[x].a.eq(a[x * 4:x * 4 + 4]) m.d.comb += alus[x].b.eq(b[x * 4:x * 4 + 4]) m.d.comb += f[x * 4:x * 4 + 4].eq(alus[x].f) m.d.comb += alus[x].m.eq(mt) m.d.comb += alus[x].s.eq(s) for x in range(7): m.d.comb += alus[x + 1].n_carryin.eq(alus[x].n_carryout) m.d.comb += alus[0].n_carryin.eq(~cin) m.d.comb += cout.eq(~alus[7].n_carryout) add_mode = (s == 9) & (mt == 0) sub_mode = (s == 6) & (mt == 0) m.d.comb += Assume(add_mode | sub_mode) y = Signal(33) with m.If(add_mode): m.d.comb += y.eq(a + b + cin) m.d.comb += Assert(f == y[:32]) m.d.comb += Assert(cout == y[32]) with m.Elif(sub_mode): m.d.comb += y.eq(a - b - ~cin) m.d.comb += Assert(f == y[:32]) m.d.comb += Assert(cout == ~y[32]) # Check how equality, unsigned gt, and unsigned gte comparisons work. with m.If(cin == 0): all_eq = Cat(*[i.a_eq_b for i in alus]).all() m.d.comb += Assert(all_eq == (a == b)) m.d.comb += Assert(cout == (a > b)) with m.Else(): m.d.comb += Assert(cout == (a >= b)) return m, [a, b, f, cin, cout, s, mt, y]