def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the ToPennies module.""" m = Module() m.submodules.to_pennies = to_pennies = cls() m.d.comb += Cover((to_pennies.pennies == 37) & (to_pennies.nickels == 3) & (to_pennies.dimes == 10) & (to_pennies.quarters == 5) & (to_pennies.dollars == 2)) m.d.comb += Cover(to_pennies.pennies_out == 548) m.d.comb += Cover((to_pennies.pennies_out == 64) & (to_pennies.nickels == 2 * to_pennies.dimes) & (to_pennies.dimes > 0)) m.d.comb += Assert((to_pennies.pennies_out % 5) == (to_pennies.pennies % 5)) with m.If(to_pennies.pennies == 0): m.d.comb += Assert((to_pennies.pennies % 5) == 0) return m, [to_pennies.pennies, to_pennies.nickels, to_pennies.dimes, to_pennies.quarters, to_pennies.dollars]
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the shifter.""" m = Module() m.submodules.shifter = shifter = ShiftCard() shamt = Signal(5) m.d.comb += shamt.eq(shifter.data_y[:5]) with m.If(shamt > 0): m.d.comb += Cover(shifter.data_z == 0xFFFFAAA0) with m.Switch(shifter.alu_op): with m.Case(AluOp.SLL): m.d.comb += Assert( shifter.data_z == (shifter.data_x << shamt)[:32]) with m.Case(AluOp.SRL): m.d.comb += Assert(shifter.data_z == (shifter.data_x >> shamt)) with m.Case(AluOp.SRA): m.d.comb += Assert( shifter.data_z == (shifter.data_x.as_signed() >> shamt)) with m.Default(): m.d.comb += Assert(shifter.data_z == 0) return m, [ shifter.alu_op, shifter.data_x, shifter.data_y, shifter.data_z ]
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the NextDay module.""" m = Module() m.submodules.nd = nd = cls() # We don't have to create a signal here. Using is_zero is like just copying the logic. is_zero = ((nd.next_year == 0) & (nd.next_month == 0) & (nd.next_day == 0)) m.d.comb += Assert(nd.invalid == is_zero) all_nonzero = ((nd.next_year != 0) & (nd.next_month != 0) & (nd.next_day != 0)) m.d.comb += Assert(all_nonzero | is_zero) with m.If(~nd.invalid): with m.If(nd.day == 31): m.d.comb += Assert(nd.next_day == 1) with m.If((nd.month == 12) & (nd.day == 31)): m.d.comb += Assert(nd.next_month == 1) with m.If(((nd.year % 2) == 1) & (nd.month == 2) & (nd.day == 29)): m.d.comb += Assert(nd.invalid) m.d.comb += Cover((nd.next_month == 2) & (nd.next_day == 29)) return m, [nd.year, nd.month, nd.day]
def cover_pending_counter(bld: Builder): m = Module() m.submodules.pc = pc = PendingCounter(3, 5) was_full = Signal() was_emptied = Signal() m.d.comb += pc.i_remove.eq(AnySeq(1)) m.d.comb += Assume(~(pc.i_remove & ~pc.o_any)) m.d.comb += Assume(~(~pc.i_remove & pc.o_full)) with m.If(pc.o_full): m.d.sync += was_full.eq(1) with m.If(~pc.o_any & was_full): m.d.sync += was_emptied.eq(1) m.d.comb += Cover(was_emptied) with bld.temp_open("formal.il") as f: il_text = rtlil.convert(m, ports=[pc.pending, pc.timer]) f.write(il_text) sby.verify( bld, "formal.sby", "formal.il", sby.Task("sby", "cover", depth=40, engines=["smtbmc", "yices"]), )
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the Counter module.""" m = Module() m.submodules.c = c = cls() m.d.comb += Assert((c.count >= 1) & (c.count <= 9)) m.d.comb += Cover(c.count == 3) return m, []
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for my module.""" m = Module() m.submodules.my_class = my_class = cls() # Make sure that the output is always the same as the input m.d.comb += Assert(my_class.my_input == my_class.my_output) # Cover the case where the output is 1. m.d.comb += Cover(my_class.my_output == 1) return m, [my_class.my_input]
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the Cell4x4 module.""" m = Module() m.submodules.c = c = cls() m.d.comb += Cover((c.output[0] == c.input[5]) & (c.output[1] == c.input[6]) & (c.output[2] == c.input[9]) & (c.output[3] == c.input[10]) & (c.output != 0)) with m.If((c.output == 0b1111) & (c.input[5:7] == 0b11) & (c.input[9:11] == 0b11)): m.d.comb += Assert(c.input == 0b0000011001100000) return m, [c.input]
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for my module.""" m = Module() m.submodules.my_class = my_class = cls() sync_clk = ClockSignal("sync") sync_rst = ResetSignal("sync") # Make sure that the output is always the same as the input m.d.comb += Assert(my_class.my_input == my_class.my_output) # Cover the case where the output is 1. m.d.comb += Cover(my_class.my_output == 1) # Make sure the clock is clocking m.d.comb += Assume(sync_clk == ~Past(sync_clk)) # Include this only if you don't want to test resets m.d.comb += Assume(~sync_rst) # Ensure sync's clock and reset signals are manipulable. return m, [sync_clk, sync_rst, my_class.my_input]
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the transparent latch. Note that you MUST have multiclock on in the sby file, because there is more than one clock in the system -- the default formal clock and the local clock inside the transparent latch. """ m = Module() m.submodules.latch = latch = TransparentLatch(32) m.d.sync += Cover((latch.data_out == 0xAAAAAAAA) & (latch.le == 0) & (Past(latch.data_out, 2) == 0xBBBBBBBB) & (Past(latch.le, 2) == 0)) with m.If(latch.n_oe == 1): m.d.comb += Assert(latch.data_out == 0) with m.If((latch.n_oe == 0) & (latch.le == 1)): m.d.comb += Assert(latch.data_out == latch.data_in) with m.If((latch.n_oe == 0) & Fell(latch.le)): m.d.sync += Assert(latch.data_out == Past(latch.data_in)) return m, [latch.data_in, latch.le, latch.n_oe]
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the async memory. Note that you MUST have multiclock on in the sby file, because there is more than one clock in the system -- the default formal clock and the local clock inside the memory. """ m = Module() m.submodules.mem = mem = AsyncMemory(width=32, addr_lines=5) # Assume "good practices": # * n_oe and n_wr are never simultaneously 0, and any changes # are separated by at least a cycle to allow buffers to turn off. # * memory address remains stable throughout a write cycle, and # is also stable just before a write cycle. m.d.comb += Assume(mem.n_oe | mem.n_wr) # Paren placement is very important! While Python logical operators # and, or have lower precedence than ==, the bitwise operators # &, |, ^ have *higher* precedence. It can be confusing when it looks # like you're writing a boolean expression, but you're actually writing # a bitwise expression. with m.If(Fell(mem.n_oe)): m.d.comb += Assume((mem.n_wr == 1) & (Past(mem.n_wr) == 1)) with m.If(Fell(mem.n_wr)): m.d.comb += Assume((mem.n_oe == 1) & (Past(mem.n_oe) == 1)) with m.If(Rose(mem.n_wr) | (mem.n_wr == 0)): m.d.comb += Assume(Stable(mem.addr)) m.d.comb += Cover((mem.data_out == 0xAAAAAAAA) & (Past(mem.data_out) == 0xBBBBBBBB)) # Make sure that when the output is disabled, the output is zero, and # when enabled, it's whatever we're pointing at in memory. with m.If(mem.n_oe == 1): m.d.comb += Assert(mem.data_out == 0) with m.Else(): m.d.comb += Assert(mem.data_out == mem._mem[mem.addr]) # If we just wrote data, make sure that cell that we pointed at # for writing now contains the data we wrote. with m.If(Rose(mem.n_wr)): m.d.comb += Assert(mem._mem[Past(mem.addr)] == Past(mem.data_in)) # Pick an address, any address. check_addr = AnyConst(5) # We assert that unless that address is written, its data will not # change. To know when we've written the data, we have to create # a clock domain to let us save the data when written. saved_data_clk = ClockDomain("saved_data_clk") m.domains.saved_data_clk = saved_data_clk saved_data_clk.clk = mem.n_wr saved_data = Signal(32) with m.If(mem.addr == check_addr): m.d.saved_data_clk += saved_data.eq(mem.data_in) with m.If(Initial()): m.d.comb += Assume(saved_data == mem._mem[check_addr]) m.d.comb += Assume(mem.n_wr == 1) with m.Else(): m.d.comb += Assert(saved_data == mem._mem[check_addr]) return m, [mem.addr, mem.data_in, mem.n_wr, mem.n_oe]
def elaborate(self, platform: Platform) -> Module: m = Module() m.d.sync += self.PSW.eq(self._psw) m.d.comb += self._psw.eq(self.PSW) with m.Switch(self.oper): with m.Case(Operation.NOP): if self.verification is Operation.NOP: with m.If(~Initial()): m.d.comb += [ Assert(self._psw.N == self.PSW.N), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == self.PSW.Z), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.ADC): low = Cat(self.result[:4], self._psw.H) high = Cat(self.result[4:], self._psw.C) m.d.comb += [ low.eq(self.inputa[:4] + self.inputb[:4] + self.PSW.C), high.eq(self.inputa[4:] + self.inputb[4:] + self._psw.H), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), self._psw.V.eq(self.result[7] != self._psw.C), ] if self.verification is Operation.ADC: r = Signal(8) f = Signal(9) h = Signal(5) m.d.comb += [ r.eq(self.inputa.as_signed() + self.inputb.as_signed() + self.PSW.C), f.eq(self.inputa + self.inputb + self.PSW.C), h.eq(self.inputa[:4] + self.inputb[:4] + self.PSW.C), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self.result == f[:8]), Assert(self._psw.N == f[7]), Assert(self._psw.V == (f[7] ^ f[8])), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == h[4]), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(f[:8].bool())), Assert(self._psw.C == f[8]), ] with m.Case(Operation.SBC): low = Cat(self.result[:4], self._psw.H) high = Cat(self.result[4:], self._psw.C) m.d.comb += [ low.eq(self.inputa[:4] - self.inputb[:4] - self.PSW.C), high.eq(self.inputa[4:] - self.inputb[4:] - self._psw.H), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), self._psw.V.eq(self.result[7] != self._psw.C), ] if self.verification is Operation.SBC: r = Signal(8) f = Signal(9) h = Signal(5) m.d.comb += [ r.eq(self.inputa.as_signed() - self.inputb.as_signed() - self.PSW.C), f.eq(self.inputa - self.inputb - self.PSW.C), h.eq(self.inputa[:4] - self.inputb[:4] - self.PSW.C), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self.result == f[:8]), Assert(self._psw.N == f[7]), Assert(self._psw.V == (f[7] ^ f[8])), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == h[4]), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(f[:8].bool())), Assert(self._psw.C == f[8]), ] with m.Case(Operation.CMP): full = Cat(self.result, self._psw.C) m.d.comb += [ full.eq(self.inputa.as_signed() - self.inputb.as_signed()), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), self._psw.V.eq(self.result[7] != self._psw.C), ] if self.verification is Operation.CMP: r = Signal(9) m.d.comb += r.eq(self.inputa.as_signed() - self.inputb.as_signed()) with m.If(~Initial()): m.d.comb += [ Assert(self.result == r[:8]), Assert(self._psw.N == r[7]), Assert(self._psw.V == (r[7] ^ r[8])), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r[:8].bool())), Assert(self._psw.C == r[8]), ] with m.Case(Operation.AND): m.d.comb += [ self.result.eq(self.inputa & self.inputb), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.AND: r = Signal(8) m.d.comb += r.eq(self.inputa & self.inputb) with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == r[7]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.OOR): m.d.comb += [ self.result.eq(self.inputa | self.inputb), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.OOR: r = Signal(8) m.d.comb += [ r.eq(self.inputa | self.inputb), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == r[7]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.EOR): m.d.comb += [ self.result.eq(self.inputa ^ self.inputb), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.EOR: r = Signal(8) m.d.comb += [ r.eq(self.inputa ^ self.inputb), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == r[7]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.INC): m.d.comb += [ self.result.eq(self.inputa + 1), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.INC: r = Signal(8) m.d.comb += [ r.eq(self.inputa + 1), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == r[7]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.DEC): m.d.comb += [ self.result.eq(self.inputa - 1), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.DEC: r = Signal(8) m.d.comb += [ r.eq(self.inputa - 1), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == r[7]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.ASL): m.d.comb += [ Cat(self.result, self._psw.C).eq(Cat(Const(0), self.inputa)), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.ASL: r = Signal(8) m.d.comb += [ r.eq(self.inputa * 2), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == self.inputa[6]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.inputa[7]), ] with m.Case(Operation.LSR): m.d.comb += [ Cat(self._psw.C, self.result).eq(Cat(self.inputa, Const(0))), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.LSR: r = Signal(8) m.d.comb += [ r.eq(self.inputa // 2), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == 0), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.inputa[0]), ] with m.Case(Operation.ROL): m.d.comb += [ Cat(self.result, self._psw.C).eq(Cat(self.PSW.C, self.inputa)), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.ROL: r = Signal(8) m.d.comb += [ r.eq(self.inputa * 2 + self.PSW.C), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == self.inputa[6]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.inputa[7]), ] with m.Case(Operation.ROR): m.d.comb += [ Cat(self._psw.C, self.result).eq(Cat(self.inputa, self.PSW.C)), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.ROR: r = Signal(8) m.d.comb += [ r.eq(self.inputa // 2 + Cat(Signal(7), self.PSW.C)), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == self.PSW.C), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r.bool())), Assert(self._psw.C == self.inputa[0]), ] with m.Case(Operation.XCN): m.d.comb += [ self.result.eq(Cat(self.inputa[4:], self.inputa[:4])), self._psw.N.eq(self.result.as_signed() < 0), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.XCN: r = Signal(8) m.d.comb += [ r.eq(self.inputa * 16 + self.inputa // 16), ] with m.If(~Initial()): m.d.comb += [ Assert(self.result == r), Assert(self._psw.N == self.inputa[3]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(self.inputa.bool())), Assert(self._psw.C == self.PSW.C), ] with m.Case(Operation.DAA): temp = Signal().like(self.inputa) with m.If(self.PSW.C | (self.inputa > 0x99)): m.d.comb += self._psw.C.eq(1) m.d.comb += temp.eq(self.inputa + 0x60) with m.Else(): m.d.comb += temp.eq(self.inputa) with m.If(self.PSW.H | (temp[:4] > 0x09)): m.d.comb += self.result.eq(temp + 0x06) m.d.comb += [ self._psw.N.eq(self.result & 0x80), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.DAA: with m.If(~Initial()): m.d.comb += [Assert(False)] with m.Case(Operation.DAS): temp = Signal().like(self.inputa) with m.If(~self.PSW.C | (self.inputa > 0x99)): m.d.comb += self._psw.C.eq(0) m.d.comb += temp.eq(self.inputa - 0x60) with m.Else(): m.d.comb += temp.eq(self.inputa) with m.If(~self.PSW.H | (temp[:4] > 0x09)): m.d.comb += self.result.eq(temp - 0x06) m.d.comb += [ self._psw.N.eq(self.result & 0x80), self._psw.Z.eq(self.result == 0), ] if self.verification is Operation.DAS: with m.If(~Initial()): m.d.comb += [Assert(False)] # could be optimized with shift to right with m.Case(Operation.MUL): with m.Switch(self.count): for i in range(0, 8): with m.Case(i): prod = self.inputa * self.inputb[i] if i == 0: prod = Cat(prod[0:7], ~prod[7], Const(1)) elif i == 7: prod = Cat(~prod[0:7], prod[7], Const(1)) else: prod = Cat(prod[0:7], ~prod[7]) m.d.sync += self.partial.eq(self.partial + (prod << i)) m.d.sync += self.count.eq(i + 1) with m.Case(8): m.d.sync += self.partial_hi.eq(self.partial_lo) m.d.sync += self.count.eq(9) m.d.comb += [ self.result.eq(self.partial_hi), self._psw.N.eq(self.partial_hi.as_signed() < 0), self._psw.Z.eq(self.partial_hi == 0), ] with m.Case(9): m.d.sync += self.partial.eq(0) m.d.sync += self.count.eq(0) m.d.comb += [ self.result.eq(self.partial_hi), ] if self.verification is Operation.MUL: r = Signal(16) m.d.comb += [ r.eq(self.inputa.as_signed() * self.inputb.as_signed()), Cover(self.count == 9), ] with m.If(self.count == 9): m.d.comb += [ Assert(Past(self.result) == r[8:16]), Assert(self.result == r[0:8]), Assert(self._psw.N == r[15]), Assert(self._psw.V == self.PSW.V), Assert(self._psw.P == self.PSW.P), Assert(self._psw.B == self.PSW.B), Assert(self._psw.H == self.PSW.H), Assert(self._psw.I == self.PSW.I), Assert(self._psw.Z == ~(r[8:16].bool())), Assert(self._psw.C == self.PSW.C), ] with m.If(~Initial() & (self.count == 0)): m.d.comb += [ Assert(self.partial == 0), Assert((Past(self.count) == 0) | (Past(self.count) == 9)), ] with m.If(~Initial() & (self.count != 0)): m.d.comb += [ Assert(self.count == Past(self.count) + 1), Assume(self.inputa == Past(self.inputa)), Assume(self.inputb == Past(self.inputb)), ] with m.Case(Operation.DIV): over = Signal(reset=0) with m.Switch(self.count): with m.Case(0): m.d.sync += self.partial_hi.eq(self.inputa) # Y m.d.sync += self.count.eq(1) with m.Case(1): m.d.sync += self.partial_lo.eq(self.inputa) # A m.d.sync += self.count.eq(2) m.d.comb += self._psw.H.eq( Mux(self.partial_hi[0:4] >= self.inputb[0:4], 1, 0)) for i in range(2, 11): with m.Case(i): tmp1_w = Cat(self.partial << 1, over) tmp1_x = Signal(17) tmp1_y = Signal(17) tmp1_z = Signal(17) tmp2 = self.inputb << 9 m.d.comb += tmp1_x.eq(tmp1_w) with m.If(tmp1_w & 0x20000): m.d.comb += tmp1_x.eq((tmp1_w & 0x1FFFF) | 1) m.d.comb += tmp1_y.eq(tmp1_x) with m.If(tmp1_x >= tmp2): m.d.comb += tmp1_y.eq(tmp1_x ^ 1) m.d.comb += tmp1_z.eq(tmp1_y) with m.If(tmp1_y & 1): m.d.comb += tmp1_z.eq((tmp1_y - tmp2) & 0x1FFFF) m.d.sync += Cat(self.partial, over).eq(tmp1_z) m.d.sync += self.count.eq(i + 1) with m.Case(11): m.d.sync += self.count.eq(12) m.d.comb += [ self.result.eq( (Cat(self.partial, over) >> 9)), # Y % ] with m.Case(12): m.d.sync += self.partial.eq(0) m.d.sync += over.eq(0) m.d.sync += self.count.eq(0) m.d.comb += [ self.result.eq(self.partial_lo), # A / self._psw.N.eq(self.partial_lo.as_signed() < 0), self._psw.V.eq(over), self._psw.Z.eq(self.partial_lo == 0), ] if self.verification is Operation.DIV: m.d.comb += [ Cover(self.count == 12), ] with m.If(self.count == 12): m.d.comb += [Assert(False)] return m
m.submodules.core = core = Core(instr) if instr is not None: time = Signal(6, reset_less=True) m.d.sync += time.eq(time + 1) with m.If(Initial()): m.d.sync += Assume(ResetSignal()) with m.Else(): m.d.sync += Assume(~ResetSignal()) # A time slot delayed because PC and addr need to sync with m.If(time == 2): m.d.sync += Assume(~core.snapshot.taken) with m.If(time == 3): m.d.sync += Cover(core.snapshot.taken) m.d.sync += Assume(core.snapshot.taken) m.d.sync += Cover(Fell(core.snapshot.taken)) main_runner( parser, args, m, ports=core.ports() + [ClockSignal(), ResetSignal()] ) else: # Fake memory mem = { 0x0000: 0x5F, 0x1000: 0x12, 0x2000: 0x34, 0x1234: 0x5F, 0x1334: 0x00,
def verification_statements(m): #Create Local Reference to the LDPC_Encoder LDPC_Encoder = m.submodules.LDPC_Encoder #Ensure all codewords can be obtained m.d.sync += Cover((LDPC_Encoder.data_output == 0b000000)) m.d.sync += Cover((LDPC_Encoder.data_output == 0b011001)) m.d.sync += Cover((LDPC_Encoder.data_output == 0b110010)) m.d.sync += Cover((LDPC_Encoder.data_output == 0b101011)) m.d.sync += Cover((LDPC_Encoder.data_output == 0b111100)) m.d.sync += Cover((LDPC_Encoder.data_output == 0b100101)) m.d.sync += Cover((LDPC_Encoder.data_output == 0b001110)) m.d.sync += Cover((LDPC_Encoder.data_output == 0b010111)) #Ensure invalid codewords cannot be obtained m.d.sync += Cover((LDPC_Encoder.data_output != 0b111111)) #Ensure the correct codeword output is obtained for each input word. m.d.sync += Cover((LDPC_Encoder.data_input == 0b000) & (LDPC_Encoder.data_output == 0b000000)) m.d.sync += Cover((LDPC_Encoder.data_input == 0b011) & (LDPC_Encoder.data_output == 0b011001)) m.d.sync += Cover((LDPC_Encoder.data_input == 0b110) & (LDPC_Encoder.data_output == 0b110010)) m.d.sync += Cover((LDPC_Encoder.data_input == 0b101) & (LDPC_Encoder.data_output == 0b101011)) m.d.sync += Cover((LDPC_Encoder.data_input == 0b111) & (LDPC_Encoder.data_output == 0b111100)) m.d.sync += Cover((LDPC_Encoder.data_input == 0b100) & (LDPC_Encoder.data_output == 0b100101)) m.d.sync += Cover((LDPC_Encoder.data_input == 0b001) & (LDPC_Encoder.data_output == 0b001110)) m.d.sync += Cover((LDPC_Encoder.data_input == 0b010) & (LDPC_Encoder.data_output == 0b010111)) m.d.sync += Cover((LDPC_Encoder.data_input == 0b011) & (LDPC_Encoder.data_output != 0b010111)) #Ensure that done and output signals are reset when start is toggled. with m.If((LDPC_Encoder.start == 0) & Past(LDPC_Encoder.start)): m.d.sync += Assert((LDPC_Encoder.done == 0)) m.d.sync += Assert((LDPC_Encoder.data_output == 0)) return
from nmigen.asserts import Assert, Cover, Fell, Past, Rose, Stable from nmigen.cli import main_parser, main_runner from bin2dec import * if __name__ == '__main__': parser = main_parser() args = parser.parse_args() b2d = Bin2Dec(8) m = Module() m.submodules.b2d = b2d m.d.comb += Cover(b2d.o_digit_rd == 1) m.d.comb += Cover(b2d.o_conv_rd == 1) # o_digit_rd is a 1-cycle strobe with m.If((Past(b2d.o_digit_rd, 2) == 0) & (Past(b2d.o_digit_rd, 1) == 1)): m.d.comb += Assert(b2d.o_digit_rd == 0) # i_bin_stb resets all outputs with m.If(Past(b2d.i_bin_stb) == 1): m.d.comb += Assert(b2d.o_digit == 0) m.d.comb += Assert(b2d.o_digit_rd == 0) m.d.comb += Assert(b2d.o_conv_rd == 0) # o_digit is stable if o_digit_rd is low with m.If((Past(ResetSignal()) == 0) & (Past(b2d.i_bin_stb) == 0) & (b2d.o_digit_rd == 0)): m.d.comb += Assert(Stable(b2d.o_digit))
out_carry = alu._ccs[Flags.C] in1_dec = 10 * in1_hi + in1_lo in2_dec = 10 * in2_hi + in2_lo out_dec = 100 * out_carry + 10 * out_hi + out_lo m.d.ph1 += [ Assume(Past(alu.func) == ALU8Func.ADC), Assume(alu.func == ALU8Func.DAA), Assume(alu.input1 == Past(alu.output)), Assume(in1_lo < 10), Assume(in1_hi < 10), Assume(in2_lo < 10), Assume(in2_hi < 10), ] m.d.ph1 += [ Assert((in1_dec + in2_dec + in_carry) == out_dec), Assert(alu._ccs[Flags.N] == alu.output[7]), Assert(alu._ccs[Flags.Z] == (alu.output == 0)), ] m.d.ph1 += Cover(out_dec == 142) main_runner( parser, args, m, ports=alu.input_ports() + alu2.input_ports() + [ph1clk, rst, test_daa], )
def build_formal(bld: Builder): m = Module() in_data = AnySeq(8) en_data = AnySeq(1) hsync = AnySeq(1) vsync = AnySeq(1) enc_char = Signal(10) real_chr_bias = Signal(signed(5)) real_dc_bias = Signal(signed(5)) m.submodules.enc = enc = TMDSEncoder() m.submodules.dec = dec = TMDSDecoder() m.d.comb += [ enc.i_data.eq(in_data), enc.i_en_data.eq(en_data), enc.i_hsync.eq(hsync), enc.i_vsync.eq(vsync), dec.i_char.eq(enc.o_char), enc_char.eq(enc.o_char), ] m.d.comb += [ real_chr_bias.eq(popcount(enc.o_char) - 5), Assert(real_dc_bias >= -5), Assert(real_dc_bias <= +5), Assert(real_dc_bias[:4] == enc.dc_bias), ] m.d.sync += [ real_dc_bias.eq(real_dc_bias + real_chr_bias), ] with m.If(~enc.i_en_data): m.d.sync += real_dc_bias.eq(real_dc_bias) m.d.comb += Cover( (Past(dec.o_en_data, 4) & (Past(enc.o_char, 4)[8:10] == 0b00)) & (Past(dec.o_en_data, 3) & (Past(enc.o_char, 3)[8:10] == 0b01)) & (Past(dec.o_en_data, 2) & (Past(enc.o_char, 2)[8:10] == 0b10)) & (Past(dec.o_en_data, 1) & (Past(enc.o_char, 1)[8:10] == 0b11)) & (dec.o_vsync)) m.d.comb += Assert(dec.o_en_data == enc.i_en_data) with m.If(dec.o_en_data): m.d.comb += Assert(dec.o_data == enc.i_data) # Check that XNOR choice matches reference algorithm in_pop = Signal(4) use_xnor = Signal() m.d.comb += [ in_pop.eq(popcount(in_data)), use_xnor.eq((in_pop > 4) | ((in_pop == 4) & (in_data[0] == 0))), Assert(enc.o_char[8] == ~use_xnor), ] with m.Else(): m.d.comb += [ Assert(dec.o_hsync == enc.i_hsync), Assert(dec.o_vsync == enc.i_vsync), ] with bld.temp_open("formal.il") as f: il_text = rtlil.convert(m, ports=[enc_char, real_chr_bias, real_dc_bias]) f.write(il_text)
m.domains.ph1 = ph1 = ClockDomain("ph1") rst = Signal() ph1clk = ClockSignal("ph1") ph1.rst = rst if verification is not None: # Cycle counter cycle2 = Signal(6, reset_less=True) m.d.ph1 += cycle2.eq(cycle2 + 1) # Force a reset # m.d.comb += Assume(rst == (cycle2 < 8)) with m.If(cycle2 == 20): m.d.ph1 += Cover(core.formalData.snapshot_taken & core.end_instr_flag) m.d.ph1 += Assume(core.formalData.snapshot_taken & core.end_instr_flag) # Verify reset does what it's supposed to with m.If(Past(rst, 4) & ~Past(rst, 3) & ~Past(rst, 2) & ~Past(rst)): m.d.ph1 += Assert(Past(core.Addr, 2) == 0xFFFE) m.d.ph1 += Assert(Past(core.Addr) == 0xFFFF) m.d.ph1 += Assert(core.Addr[8:] == Past(core.Din, 2)) m.d.ph1 += Assert(core.Addr[:8] == Past(core.Din)) m.d.ph1 += Assert(core.Addr == core.pc) main_runner(parser, args, m, ports=core.ports() + [ph1clk, rst]) else: # Fake memory
def formal(cls) -> Tuple[Module, List[Signal]]: """Formal verification for the register card.""" m = Module() ph1 = ClockDomain("ph1") ph2 = ClockDomain("ph2") regs = RegCard() m.domains += [ph1, ph2] m.submodules += regs # Generate the ph1 and ph2 clocks. cycle_count = Signal(8, reset=0, reset_less=True) phase_count = Signal(3, reset=0, reset_less=True) m.d.sync += phase_count.eq(phase_count + 1) with m.Switch(phase_count): with m.Case(0, 1, 2): m.d.comb += ph1.clk.eq(1) with m.Default(): m.d.comb += ph1.clk.eq(0) with m.Switch(phase_count): with m.Case(1, 4): m.d.comb += ph2.clk.eq(0) with m.Default(): m.d.comb += ph2.clk.eq(1) with m.If(phase_count == 5): m.d.sync += phase_count.eq(0) m.d.sync += cycle_count.eq(cycle_count + 1) # This is how we expect to use the card. with m.If(phase_count > 0): m.d.comb += [ Assume(Stable(regs.reg_x)), Assume(Stable(regs.reg_y)), Assume(Stable(regs.reg_z)), Assume(Stable(regs.reg_page)), Assume(Stable(regs.reg_to_x)), Assume(Stable(regs.reg_to_y)), Assume(Stable(regs.data_z)), ] # Figure out how to get to the point where X and Y are nonzero and different. m.d.comb += Cover((regs.data_x != 0) & (regs.data_y != 0) & (regs.data_x != regs.data_y)) # X and Y buses should not change during a cycle, except for the first phase with m.Switch(phase_count): with m.Case(2, 3, 4, 5): with m.If(regs.data_x != 0): m.d.comb += Assert(Stable(regs.data_x)) with m.If(regs.data_y != 0): m.d.comb += Assert(Stable(regs.data_y)) # X and Y buses should be zero if there is no data transfer. with m.If(regs.reg_to_x == 0): m.d.comb += Assert(regs.data_x == 0) with m.If(regs.reg_to_y == 0): m.d.comb += Assert(regs.data_y == 0) with m.If(phase_count > 0): # X and Y buses should be zero if we read from register 0. with m.If(regs.reg_to_x & (regs.reg_x == 0)): m.d.comb += Assert(regs.data_x == 0) with m.If(regs.reg_to_y & (regs.reg_y == 0)): m.d.comb += Assert(regs.data_y == 0) write_pulse = Signal() m.d.comb += write_pulse.eq(phase_count != 4) # On write, the data should have been written to both banks. past_mem_addr = Signal(6) m.d.comb += past_mem_addr[:5].eq(Past(regs.reg_z)) m.d.comb += past_mem_addr[5].eq(Past(regs.reg_page)) past_z = Past(regs.data_z) with m.If(Rose(write_pulse)): m.d.comb += Assert(regs._x_bank._mem[past_mem_addr] == past_z) m.d.comb += Assert(regs._y_bank._mem[past_mem_addr] == past_z) # Pick an register, any register, except 0. We assert that unless # it is written, its data will not change. check_addr = AnyConst(5) check_page = AnyConst(1) saved_data = Signal(32) stored_x_data = Signal(32) stored_y_data = Signal(32) write_pulse_domain = ClockDomain("write_pulse_domain", local=True) m.domains.write_pulse_domain = write_pulse_domain write_pulse_domain.clk = write_pulse mem_addr = Signal(6) m.d.comb += Assume(check_addr != 0) m.d.comb += [ mem_addr[:5].eq(check_addr), mem_addr[5].eq(check_page), stored_x_data.eq(regs._x_bank._mem[mem_addr]), stored_y_data.eq(regs._y_bank._mem[mem_addr]), ] with m.If((regs.reg_z == check_addr) & (regs.reg_page == check_page)): m.d.write_pulse_domain += saved_data.eq(regs.data_z) with m.If(Initial()): m.d.comb += Assume(saved_data == stored_x_data) m.d.comb += Assume(stored_x_data == stored_y_data) with m.Else(): m.d.comb += Assert(saved_data == stored_x_data) m.d.comb += Assert(saved_data == stored_y_data) return m, [regs.data_z, regs.reg_to_x, regs.reg_to_y, regs.reg_x, regs.reg_y, regs.reg_z, regs.reg_page, ph1.clk, ph2.clk, saved_data, stored_x_data, stored_y_data]