def test_pipelined_adder(): from nmigen.back import pysim import random n = 64 m = 4 adder = PipelinedAdder(n, m) def testbench(): for _ in range(100): a = random.randrange(2**n) b = random.randrange(2**n) yield yield adder.a.eq(a) yield adder.b.eq(b) for _ in range(m + 1): yield assert (yield adder.c) == (a + b) % (2**n) yield adder.a.eq(2**n - 1) yield adder.b.eq(1) for _ in range(m + 1): yield assert (yield adder.c) == 0 vcdf = open("adder.vcd", "w") with pysim.Simulator(adder, vcd_file=vcdf) as sim: sim.add_clock(1e-6) sim.add_sync_process(testbench()) sim.run()
def simulate(): uut = CPU() frag = uut.get_fragment(None) with pysim.Simulator(frag, vcd_file=open('cpu.vcd', 'w')) as sim: sim.add_clock(1 / 16e6, domain='sync') sim.run_until(1 / 16e6 * 10000, run_passive=True)
def _simulate(self): if isinstance(self.design, Module): design_file = self._caller_filename() elif isinstance(self.design, Elaboratable): design_file = inspect.getsourcefile(self.design.__class__) else: assert TypeError, 'can only simulate Elaboratable or Module' args = self.args prefix = os.path.splitext(design_file)[0] vcd_file = args.vcd_file or prefix + '.vcd' gtkw_file = args.gtkw_file = prefix + '.gtkw' traces = self._get_ports() with pysim.Simulator(self.design, vcd_file=open(vcd_file, 'w'), gtkw_file=open(gtkw_file, 'w'), traces=traces) as sim: self._sim.build(sim) if not self._sim.has_clocks(): sim.add_clock(args.sync_period) if args.sync_clocks: sim.run_until(args.sync_period * args.sync_clocks, run_passive=True) else: assert self._sim.has_procs(), ( "must provide either a sim process or --clocks") sim.run()
def test_crc32_match(): from nmigen.back import pysim crc = CRC32() frame = [ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xDE, 0xF1, 0x38, 0x89, 0x40, 0x08, 0x00, 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01, 0xB6, 0xD0, 0xC0, 0xA8, 0x01, 0x88, 0xC0, 0xA8, 0x01, 0x00, 0x08, 0x00, 0x0D, 0xD9, 0x12, 0x1E, 0x00, 0x07, 0x3B, 0x3E, 0x0C, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x13, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x48, 0x52, 0x32, 0x1F, 0x9E ] def testbench(): yield yield for byte in frame: yield (crc.data.eq(byte)) yield (crc.data_valid.eq(1)) yield yield (crc.data_valid.eq(0)) yield (crc.data.eq(0)) yield yield match = yield (crc.crc_match) assert match == 1 vcdf = open("crc32_match.vcd", "w") with pysim.Simulator(crc, vcd_file=vcdf) as sim: sim.add_clock(1e-6) sim.add_sync_process(testbench()) sim.run()
def test_phy_manager(): from nmigen.back import pysim from nmigen.lib.io import Pin mdc = Signal() mdio = Pin(1, 'io') phy_rst = Signal() # Specify a fake 10MHz clock frequency to reduce number of simulation steps phy_manager = PHYManager(10e6, 0, phy_rst, mdio, mdc) def testbench(): # 1ms is 10000 ticks, so check we're still asserting phy_rst for _ in range(10000): assert (yield phy_rst) == 0 yield assert (yield phy_manager.link_up) == 0 # Allow enough clocks to step the state machine through for _ in range(100): yield # Now we wait another 1ms for bring-up, without asserting reset for _ in range(9900): assert (yield phy_rst) == 1 yield assert (yield phy_manager.link_up) == 0 # Wait for the register read to synchronise to MDIO while True: if (yield phy_manager.mdio_mod.mdio.o) == 1: break yield # Clock through BSR register read, setting bits 14, 5, 2 for clk in range(260): if clk in (194, 230, 242): yield (phy_manager.mdio_mod.mdio.i.eq(1)) else: yield (phy_manager.mdio_mod.mdio.i.eq(0)) yield # Finish register reads for _ in range(100): yield # Check link_up becomes 1 assert (yield phy_manager.link_up) == 1 vcdf = open("phy_manager.vcd", "w") with pysim.Simulator(phy_manager, vcd_file=vcdf) as sim: sim.add_clock(1e-6) sim.add_sync_process(testbench()) sim.run()
def test_rmii_tx_byte(): import random from nmigen.back import pysim txen = Signal() txd0 = Signal() txd1 = Signal() rmii_tx_byte = RMIITxByte(txen, txd0, txd1) data = rmii_tx_byte.data data_valid = rmii_tx_byte.data_valid def testbench(): for _ in range(10): yield txbytes = [random.randint(0, 255) for _ in range(8)] txnibbles = [] rxnibbles = [] yield (data_valid.eq(1)) for txbyte in txbytes: txnibbles += [ (txbyte & 0b11), ((txbyte >> 2) & 0b11), ((txbyte >> 4) & 0b11), ((txbyte >> 6) & 0b11), ] yield (data.eq(txbyte)) yield rxnibbles.append((yield txd0) | ((yield txd1) << 1)) yield rxnibbles.append((yield txd0) | ((yield txd1) << 1)) yield rxnibbles.append((yield txd0) | ((yield txd1) << 1)) yield rxnibbles.append((yield txd0) | ((yield txd1) << 1)) yield (data_valid.eq(0)) yield rxnibbles.append((yield txd0) | ((yield txd1) << 1)) rxnibbles = rxnibbles[1:] assert txnibbles == rxnibbles for _ in range(10): yield vcdf = open("rmii_tx_byte.vcd", "w") with pysim.Simulator(rmii_tx_byte, vcd_file=vcdf) as sim: sim.add_clock(1 / 50e6) sim.add_sync_process(testbench()) sim.run()
def s(tx_cycle_accurate=False): top = Top(sim=True, sim_tx_cycle_accurate=tx_cycle_accurate, xwidth=xwidth, nwidth=nwidth) # in simulation we set the platform to None platform = None # ICEBreakerPlatform() fragment = Fragment.get(top, platform=platform) with open("top.vcd", "w") as vcd_file: with pysim.Simulator(fragment, vcd_file=vcd_file) as sim: sim.add_clock(83e-9) def driver_proc(): # --------- yield top.uartfifo.uart.rx_data.eq(65) yield top.uartfifo.uart.rx_rdy.eq(1) yield yield top.uartfifo.uart.rx_rdy.eq(0) sim.add_sync_process(driver_proc()) sim.run_until(100*1e-6, run_passive=True)
def main_runner(parser, args, maker, fw=None, ports=(), build_args={}): if args.action == "simulate": design, platform = maker(simulating=True) fragment = Fragment.get(design, platform) with pysim.Simulator(fragment, vcd_file=args.vcd_file, gtkw_file=args.gtkw_file, traces=ports) as sim: sim.add_clock(args.sync_period) sim.run_until(args.sync_period * args.sync_clocks, run_passive=True) if args.action == "build": design, platform = maker(simulating=False) platform.build(design, do_program=args.program, **build_args) if args.action == "boneload": import boneload boneload.boneload(fw(), args.port, args.ram)
def test_send(): baud = 1200 clk_freq = baud * 8 baud_period = 1 / baud tx = Tx(clk_freq, baud, data_bits=7, stop_bits=2) with pysim.Simulator(tx) as sim: sim.add_clock(1 / clk_freq) def fn(): yield Delay(2.5e-5) yield tx.i_data.eq(0b1001101) yield tx.i_start.eq(True) yield Delay(1 / clk_freq) yield tx.i_start.eq(False) yield Delay(baud_period / 2) bits = [ 0, # Start bit 1, 0, 1, 1, 0, 0, 1, # Data bits 1, 1, # Stop bits ] for bit in bits: assert (yield tx.o_serial_tx) == bit assert (yield tx.o_busy) yield Delay(baud_period) assert (yield tx.o_serial_tx) == 1 assert not (yield tx.o_busy) sim.add_process(fn()) sim.run()
def simulate(): uut = LCD() def testbench(): def read(addr): # Set up address and read transaction yield uut.addr.eq(addr) yield uut.r_en.eq(1) # Wait one clock cycle for data yield yield uut.r_en.eq(0) return (yield uut.r_data) def write(addr, data): # Set up address and write transaction yield uut.addr.eq(addr) yield uut.w_data.eq(data) yield uut.w_en.eq(1) # Wait one clock cycle for write to complete yield yield uut.w_en.eq(0) def write_and_wait(rs, db): data = rs << 8 | db yield from write(0, data) while (yield from read(0)): pass data = [(0, 0b00111000), (0, 0b00001110), (0, 0b00000110), (0, 0b00000001), *[(1, ord(c)) for c in 'Hello, world!']] yield for rs, db in data: yield from write_and_wait(rs, db) yield frag = uut.get_fragment(None) with pysim.Simulator(frag, vcd_file=open('lcd.vcd', 'w')) as sim: sim.add_clock(1 / 16e6, domain='sync') sim.add_sync_process(testbench(), domain='sync') sim.run()
def _simulate(self): args = self.args design_file = inspect.getsourcefile(self.design.__class__) prefix = os.path.splitext(design_file)[0] vcd_file = args.vcd_file or prefix + '.vcd' gtkw_file = args.gtkw_file = prefix + '.gtkw' traces = self._get_ports() with pysim.Simulator(self.design, vcd_file=open(vcd_file, 'w'), gtkw_file=open(gtkw_file, 'w'), traces=traces) as sim: self._sim.build(sim) if not self._sim.has_clocks(): sim.add_clock(args.sync_period) if args.sync_clocks: sim.run_until(args.sync_period * args.sync_clocks, run_passive=True) else: assert self._sim.has_procs(), ( "must provide either a sim process or --clocks") sim.run()
def test_receive(): baud = 1200 clk_freq = baud * 8 baud_period = 1 / baud rx = Rx(clk_freq, baud, data_bits=7, stop_bits=2) with pysim.Simulator(rx) as sim: sim.add_clock(1 / clk_freq) def fn(): yield Delay(2.5e-5) bits = [ 0, # Start bit 1, 0, 1, 1, 0, 0, 1, # Data bits 1, 1, # Stop bits ] for bit in bits: yield rx.i_serial_rx.eq(bit) yield Delay(baud_period) assert (yield rx.o_ready) assert (yield rx.o_data) == 0b1001101 yield rx.i_ack.eq(True) yield Delay(1 / clk_freq) yield rx.i_ack.eq(False) assert not (yield rx.o_ready) sim.add_process(fn()) sim.run()
def test_crc32(): from nmigen.back import pysim crc = CRC32() def testbench(): yield yield for byte in [ord(x) for x in "123456789"]: yield (crc.data.eq(byte)) yield (crc.data_valid.eq(1)) yield yield (crc.data_valid.eq(0)) yield (crc.data.eq(0)) yield yield out = yield (crc.crc_out) assert out == 0xCBF43926 vcdf = open("crc32.vcd", "w") with pysim.Simulator(crc, vcd_file=vcdf) as sim: sim.add_clock(1e-6) sim.add_sync_process(testbench()) sim.run()
m.d.comb += dataBus.eq(registers.output8) with m.Else(): with m.If(mcycler.rd): with m.Switch(addrBus): with m.Case(0): m.d.comb += dataBus.eq(0x0E) with m.Case(1): m.d.comb += dataBus.eq(0xAB) with m.Default(): m.d.comb += dataBus.eq(0x00) with m.Else(): m.d.comb += dataBus.eq(0xFF) ports = sequencer.ports() with pysim.Simulator(m, vcd_file=open("sequencer.vcd", "w"), traces=ports) as sim: sim.add_clock(1e-9, domain="pos") def process(): # initial reset yield yield yield yield yield yield yield yield yield yield yield
if __name__ == "__main__": variants = { '12F': ULX3S_12F_Platform, '25F': ULX3S_25F_Platform, '45F': ULX3S_45F_Platform, '85F': ULX3S_85F_Platform } # Figure out which FPGA variant we want to target... parser = argparse.ArgumentParser() parser.add_argument('variant', choices=variants.keys()) parser.add_argument("-s", action="store_true", help="Simulate Rotary Encoder (for debugging).") args = parser.parse_args() if args.s: pads = _TestPads() dut = UART(pads, clk_freq=4800, baud_rate=1200) sim = pysim.Simulator(dut) sim.add_clock(1.0 / 12e6) sim.add_sync_process(_test(pads.tx, pads.rx, dut)) with sim.write_vcd("uart.vcd", "uart.gtkw", traces=[pads.tx, pads.rx]): sim.run() else: plat = variants[args.variant]() plat.build(_LoopbackTest(), do_program=True)
def s(): # Note: direct_mode true/false -> exact same vcd! top = Top(sim=True) platform = None fragment = Fragment.get(top, platform=platform) with open("top.vcd", "w") as vcd_file: with pysim.Simulator(fragment, vcd_file=vcd_file) as sim: sim.add_clock(83e-9) def driver_proc(): # --------- # PROTOCOL: cmd are the high order bits # # DECIMAL (cmd=5) # p = Cat(Signal(maxn, reset=0x5F41112), Const(0x5)) # 99881234 = 0x5F41112 print(p.shape()) yield top.printer.din.eq(p) yield yield top.printer.we.eq(1) yield yield top.printer.we.eq(0) yield # p = Cat(Signal(maxn, reset=0x21FCCE715), Const(0x5)) # 9123456789 = 0x21FCCE715 print(p.shape()) yield top.printer.din.eq(p) yield yield top.printer.we.eq(1) yield yield top.printer.we.eq(0) yield # p = Cat(Signal(maxn, reset=0x2540BE3FF), Const(0x5)) # 9999999999 = 0x2540BE3FF print(p.shape()) yield top.printer.din.eq(p) yield yield top.printer.we.eq(1) yield yield top.printer.we.eq(0) yield # # # VERBATIM (cmd=4) # # padding needed to get to 34 bits data # CR, LF, BELL, 0<ignored>, pad(2bit), cmd(3bit) p = Cat(Signal(8, reset=13), Signal(8, reset=10), Signal(8, reset=7), Signal(8), Signal(2), Const(4)) #p = Cat(Signal(8,reset=13), Signal(8,reset=10), Signal(8,reset=7), Signal(8), Signal(2), Const(4)) print(p.shape()) yield top.printer.din.eq(p) yield yield top.printer.we.eq(1) yield yield top.printer.we.eq(0) yield # # padding needed to get to 34 bits data # R,E,T,O, pad(2bit), cmd(3bit) p = Cat(Signal(8, reset=ord('R')), Signal(8, reset=ord('E')), Signal(8, reset=ord('T')), Signal(8, reset=ord('O')), Signal(2), Const(4)) #p = Cat(Signal(8,reset=13), Signal(8,reset=10), Signal(8,reset=7), Signal(8), Signal(2), Const(4)) print(p.shape()) yield top.printer.din.eq(p) yield yield top.printer.we.eq(1) yield yield top.printer.we.eq(0) yield # # #yield top.printer.din.eq(Cat(Const(9876543210), Const(0x5))) #yield top.printer.we.eq(1) #yield #yield top.printer.we.eq(0) # HEX TESTS # padding needed to get to 34 bits data # "AB" pad(2bit), cmd(3bit) = 6 Hex 8bit print print('HEX TESTS') p = Cat(Signal(8, reset=0), Signal(8, reset=0), Signal(8, reset=2), Signal(8, reset=1), Signal(2), Const(6)) print(p.shape()) yield top.printer.din.eq(p) yield yield top.printer.we.eq(1) yield yield top.printer.we.eq(0) yield print('done.') def rcv_proc(): while (True): while not (yield top.b_fifo.readable): yield v = yield from top.b_fifo.read() print(v) sim.add_sync_process(driver_proc()) sim.add_sync_process(rcv_proc()) sim.run_until(10e-6, run_passive=True)
def test_mac_address_match(): import random from nmigen.back import pysim mac_address = [random.randint(0, 255) for _ in range(6)] mac_address = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB] mac_matcher = MACAddressMatch(mac_address) data = mac_matcher.data data_valid = mac_matcher.data_valid reset = mac_matcher.reset def testbench(): yield (reset.eq(1)) for _ in range(10): yield yield (reset.eq(0)) yield # Check it matches its own MAC address for byte in mac_address: yield (data.eq(byte)) yield (data_valid.eq(1)) yield yield (data_valid.eq(0)) yield for idx in range(100): yield (data.eq(idx)) yield (data_valid.eq(1)) yield yield (data_valid.eq(0)) yield assert (yield mac_matcher.mac_match) == 1 yield (reset.eq(1)) yield yield (reset.eq(0)) yield # Check it matches broadcast for byte in [0xFF] * 6: yield (data.eq(byte)) yield (data_valid.eq(1)) yield yield (data_valid.eq(0)) yield for idx in range(100): yield (data.eq(idx)) yield (data_valid.eq(1)) yield yield (data_valid.eq(0)) yield assert (yield mac_matcher.mac_match) == 1 yield (reset.eq(1)) yield yield (reset.eq(0)) yield # Check it doesn't match some other MAC address for byte in mac_address[::-1]: yield (data.eq(byte)) yield (data_valid.eq(1)) yield yield (data_valid.eq(0)) yield for idx in range(100): yield (data.eq(idx)) yield (data_valid.eq(1)) yield yield (data_valid.eq(0)) yield assert (yield mac_matcher.mac_match) == 0 yield (reset.eq(1)) yield yield (reset.eq(0)) yield vcdf = open("mac_matcher.vcd", "w") with pysim.Simulator(mac_matcher, vcd_file=vcdf) as sim: sim.add_clock(1e-6) sim.add_sync_process(testbench()) sim.run()
from nmigen.back import rtlil, verilog top = Top(sys_clk=0.5) print(verilog.convert(top, ports=top.ports(), name="top")) if sys.argv[1] == "generate-top-sim": from nmigen.back import rtlil, verilog top = CartSim(sys_clk=0.5) print(verilog.convert(top, ports=top.ports(), name="top")) elif sys.argv[1] == "sim": cart = CartSim(sys_clk=50) n64 = cart.n64 from nmigen.back import pysim sim = pysim.Simulator(cart) ports = [ n64.ale_h.i, cart.n64.ale_l.i, n64.read.i, n64.write.i, n64.ad.i, n64.ad.o ] with sim.write_vcd(vcd_file=open("/tmp/cart.vcd", "w"), gtkw_file=open("/tmp/cart.gtkw", "w"), traces=ports): sim.add_clock(1 / 50e6) def do_nothing(): for i in range(0, 10000): yield sim.add_sync_process(do_nothing)
def test_rmii_tx(): from nmigen.back import pysim from nmigen import Memory txen = Signal() txd0 = Signal() txd1 = Signal() txbytes = [ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x44, 0x4e, 0x30, 0x76, 0x9e, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x02, 0x44, 0x4e, 0x30, 0x76, 0x9e, 0xc0, 0xa8, 0x02, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xc8 ] preamblebytes = [0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xD5] padbytes = [0x00] * (60 - len(txbytes)) crcbytes = [0x44, 0x5E, 0xB4, 0xD2] txnibbles = [] rxnibbles = [] for txbyte in preamblebytes + txbytes + padbytes + crcbytes: txnibbles += [ (txbyte & 0b11), ((txbyte >> 2) & 0b11), ((txbyte >> 4) & 0b11), ((txbyte >> 6) & 0b11), ] # Put the transmit bytes into memory at some offset, and fill the rest of # memory with all-1s (to ensure we're not relying on memory being zeroed). txbytes_zp = txbytes + [0xFF] * (128 - len(txbytes)) txoffset = 120 txbytes_mem = txbytes_zp[-txoffset:] + txbytes_zp[:-txoffset] mem = Memory(8, 128, txbytes_mem) mem_port = mem.read_port() rmii_tx = RMIITx(mem_port, txen, txd0, txd1) def testbench(): for _ in range(10): yield yield (rmii_tx.tx_start.eq(1)) yield (rmii_tx.tx_offset.eq(txoffset)) yield (rmii_tx.tx_len.eq(len(txbytes))) yield yield (rmii_tx.tx_start.eq(0)) yield (rmii_tx.tx_offset.eq(0)) yield (rmii_tx.tx_len.eq(0)) for _ in range((len(txbytes) + 12) * 4 + 120): if (yield txen): rxnibbles.append((yield txd0) | ((yield txd1) << 1)) yield print(len(txnibbles), len(rxnibbles)) print(txnibbles) print(rxnibbles) assert txnibbles == rxnibbles mod = Module() mod.submodules += rmii_tx, mem_port vcdf = open("rmii_tx.vcd", "w") with pysim.Simulator(mod, vcd_file=vcdf) as sim: sim.add_clock(1 / 50e6) sim.add_sync_process(testbench()) sim.run()
ztst.o_zrndr, ztst.o_x_coord, ztst.o_y_coord, ztst.o_z_coord, ztst.o_red, ztst.o_green, ztst.o_blue, ztst.o_alpha, ] # print(verilog.convert(ztst, ports=ports)) import random with pysim.Simulator(ztst, gtkw_file=open("ztst.gtkw", "w"), vcd_file=open("ztst.vcd", "w")) as sim: # ZTE = 0 # Not hardware verified! def zte_off(): for rgbrndr in range(2): for arndr in range(2): for zrndr in range(2): for test in range(4): red, green, blue, alpha = random.randint( 0, 255), random.randint(0, 255), random.randint( 0, 255), random.randint(0, 255) x, y, z = random.randint( 0, 2**16 - 1), random.randint( 0,
points=[ (0, 10), (1, 9), (2, 8), (3, 7), (4, 6), (5, 5), (6, 4), (7, 3), (8, 2), (9, 1), (10, 0) ] ) with pysim.Simulator(dda, gtkw_file=gtkw, vcd_file=vcd) as sim: sim.add_sync_process(line45) sim.add_clock(1e-6) sim.run() with pysim.Simulator(dda) as sim: sim.add_sync_process(line135) sim.add_clock(1e-6) sim.run() with pysim.Simulator(dda) as sim: sim.add_sync_process(line225) sim.add_clock(1e-6) sim.run() with pysim.Simulator(dda) as sim:
] import argparse parser = argparse.ArgumentParser() p_action = parser.add_subparsers(dest="action") p_action.add_parser("simulate") p_action.add_parser("generate") args = parser.parse_args() if args.action == "simulate": from nmigen.hdl.ast import Passive from nmigen.back import pysim with pysim.Simulator(uart, vcd_file=open("uart.vcd", "w"), gtkw_file=open("uart.gtkw", "w"), traces=ports) as sim: sim.add_clock(1e-6) def loopback_proc(): yield Passive() while True: yield uart.rx_i.eq((yield uart.tx_o)) yield sim.add_sync_process(loopback_proc()) def transmit_proc(): assert (yield uart.tx_ack) assert not (yield uart.rx_rdy)
def test_mdio_read(): import random from nmigen.lib.io import Pin from nmigen.back import pysim mdc = Signal() mdio_pin = Pin(1, 'io') mdio = MDIO(20, mdio_pin, mdc) def testbench(): rng = random.Random(0) # Run ten random reads in sequence for testrun in range(10): phy_addr = rng.randint(0, 31) reg_addr = rng.randint(0, 31) reg_value = rng.randint(0, 65535) # Idle clocks at start for _ in range(10): yield # Set up a register read yield (mdio.phy_addr.eq(phy_addr)) yield (mdio.reg_addr.eq(reg_addr)) yield (mdio.rw.eq(0)) yield (mdio.start.eq(1)) yield yield (mdio.phy_addr.eq(0)) yield (mdio.reg_addr.eq(0)) yield (mdio.start.eq(0)) # Clock through the read ibits = [int(x) for x in f"{reg_value:016b}"] obits = [] oebits = [] mdio_clk = 0 last_mdc = (yield mdc) while True: yield new_mdc = (yield mdc) # Detect rising edge if new_mdc and last_mdc == 0: mdio_clk += 1 obits.append((yield mdio.mdio.o)) oebits.append((yield mdio.mdio.oe)) if mdio_clk >= 48: yield (mdio.mdio.i.eq(ibits[mdio_clk - 48])) if mdio_clk == 63: break last_mdc = new_mdc for _ in range(100): yield read_data = (yield mdio.read_data) was_busy = (yield mdio.busy) # Check transmitted bits were correct pre_32 = [1] * 32 st = [0, 1] op = [1, 0] pa5 = [int(x) for x in f"{phy_addr:05b}"] ra5 = [int(x) for x in f"{reg_addr:05b}"] expected = pre_32 + st + op + pa5 + ra5 assert obits[:46] == expected # Check OE transitioned correctly expected = [1] * 46 + [0] * 17 assert oebits == expected # Check we read the correct value in the end expected = int("".join(str(x) for x in ibits), 2) assert read_data == expected assert not was_busy vcdf = open("mdio_read.vcd", "w") with pysim.Simulator(mdio, vcd_file=vcdf) as sim: sim.add_clock(1e-6) sim.add_sync_process(testbench()) sim.run()
self.v = Signal(width, reset=2**width - 1) self.o = Signal() self.en = Signal() def elaborate(self, platform): m = Module() m.d.sync += self.v.eq(self.v + 1) m.d.comb += self.o.eq(self.v[-1]) return EnableInserter(self.en)(m) ctr = Counter(width=16) print(verilog.convert(ctr, ports=[ctr.o, ctr.en])) sim = pysim.Simulator(ctr) sim.add_clock(1e-6) def ce_proc(): yield yield yield yield ctr.en.eq(1) yield yield yield yield ctr.en.eq(0) yield yield yield
def test_mdio_write(): import random from nmigen.lib.io import Pin from nmigen.back import pysim mdc = Signal() mdio_pin = Pin(1, 'io') mdio = MDIO(20, mdio_pin, mdc) def testbench(): rng = random.Random(0) # Run ten random writes in sequence for testrun in range(10): phy_addr = rng.randint(0, 31) reg_addr = rng.randint(0, 31) reg_value = rng.randint(0, 65535) # Idle clocks at start for _ in range(10): yield # Set up a register write yield (mdio.phy_addr.eq(phy_addr)) yield (mdio.reg_addr.eq(reg_addr)) yield (mdio.write_data.eq(reg_value)) yield (mdio.rw.eq(1)) yield (mdio.start.eq(1)) yield yield (mdio.phy_addr.eq(0)) yield (mdio.write_data.eq(0)) yield (mdio.rw.eq(0)) yield (mdio.reg_addr.eq(0)) yield (mdio.start.eq(0)) # Clock through the write obits = [] oebits = [] mdio_clk = 0 last_mdc = (yield mdc) while True: yield new_mdc = (yield mdc) # Detect rising edge if new_mdc and last_mdc == 0: mdio_clk += 1 obits.append((yield mdio.mdio.o)) oebits.append((yield mdio.mdio.oe)) if mdio_clk == 64: break last_mdc = new_mdc # Idle at end for _ in range(100): yield was_busy = (yield mdio.busy) # Check transmitted bits were correct pre_32 = [1] * 32 st = [0, 1] op = [0, 1] pa5 = [int(x) for x in f"{phy_addr:05b}"] ra5 = [int(x) for x in f"{reg_addr:05b}"] ta = [1, 0] d16 = [int(x) for x in f"{reg_value:016b}"] expected = pre_32 + st + op + pa5 + ra5 + ta + d16 assert obits == expected # Check OE transitioned correctly expected = [1] * 64 assert oebits == expected assert not was_busy vcdf = open("mdio_write.vcd", "w") with pysim.Simulator(mdio, vcd_file=vcdf) as sim: sim.add_clock(1e-6) sim.add_sync_process(testbench()) sim.run()
def test_rmii_rx(): import random from nmigen.back import pysim from nmigen import Memory crs_dv = Signal() rxd0 = Signal() rxd1 = Signal() mem = Memory(8, 128) mem_port = mem.write_port() mac_addr = [random.randint(0, 255) for _ in range(6)] rmii_rx = RMIIRx(mac_addr, mem_port, crs_dv, rxd0, rxd1) def testbench(): def tx_packet(): yield (crs_dv.eq(1)) # Preamble for _ in range(random.randint(10, 40)): yield (rxd0.eq(1)) yield (rxd1.eq(0)) yield # SFD yield (rxd0.eq(1)) yield (rxd1.eq(1)) yield # Data for txbyte in txbytes: for dibit in range(0, 8, 2): yield (rxd0.eq((txbyte >> (dibit + 0)) & 1)) yield (rxd1.eq((txbyte >> (dibit + 1)) & 1)) yield yield (crs_dv.eq(0)) # Finish clocking for _ in range(6): yield for _ in range(10): yield txbytes = [ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xDE, 0xF1, 0x38, 0x89, 0x40, 0x08, 0x00, 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01, 0xB6, 0xD0, 0xC0, 0xA8, 0x01, 0x88, 0xC0, 0xA8, 0x01, 0x00, 0x08, 0x00, 0x0D, 0xD9, 0x12, 0x1E, 0x00, 0x07, 0x3B, 0x3E, 0x0C, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x13, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x48, 0x52, 0x32, 0x1F, 0x9E ] # Transmit first packet yield from tx_packet() # Check packet was received assert (yield rmii_rx.rx_valid) assert (yield rmii_rx.rx_len) == 102 assert (yield rmii_rx.rx_offset) == 0 mem_contents = [] for idx in range(102): mem_contents.append((yield mem[idx])) assert mem_contents == txbytes # Pause (inter-frame gap) for _ in range(20): yield assert (yield rmii_rx.rx_valid) == 0 # Transmit a second packet yield from tx_packet() # Check packet was received assert (yield rmii_rx.rx_valid) assert (yield rmii_rx.rx_len) == 102 assert (yield rmii_rx.rx_offset) == 102 mem_contents = [] for idx in range(102): mem_contents.append((yield mem[(102 + idx) % 128])) assert mem_contents == txbytes yield mod = Module() mod.submodules += rmii_rx, mem_port vcdf = open("rmii_rx.vcd", "w") with pysim.Simulator(mod, vcd_file=vcdf) as sim: sim.add_clock(1 / 50e6) sim.add_sync_process(testbench()) sim.run()
def test_rmii_rx_byte(): import random from nmigen.back import pysim crs_dv = Signal() rxd0 = Signal() rxd1 = Signal() rmii_rx_byte = RMIIRxByte(crs_dv, rxd0, rxd1) def testbench(): for _ in range(10): yield txbytes = [random.randint(0, 255) for _ in range(8)] rxbytes = [] yield (crs_dv.eq(1)) # Preamble for _ in range(random.randint(10, 40)): yield (rxd0.eq(1)) yield (rxd1.eq(0)) yield # SFD yield (rxd0.eq(1)) yield (rxd1.eq(1)) yield # Data (except last two bytes), with CRS=1 DV=1 for txbyte in txbytes[:-2]: for dibit in range(0, 8, 2): yield (rxd0.eq((txbyte >> (dibit + 0)) & 1)) yield (rxd1.eq((txbyte >> (dibit + 1)) & 1)) yield if (yield rmii_rx_byte.data_valid): rxbytes.append((yield rmii_rx_byte.data)) # Data (last two bytes), with CRS=0 DV=1 for txbyte in txbytes[-2:]: for dibit in range(0, 8, 2): yield (rxd0.eq((txbyte >> (dibit + 0)) & 1)) yield (rxd1.eq((txbyte >> (dibit + 1)) & 1)) if dibit in (0, 4): # CRS=0 yield (crs_dv.eq(0)) else: # DV=1 yield (crs_dv.eq(1)) yield if (yield rmii_rx_byte.data_valid): rxbytes.append((yield rmii_rx_byte.data)) yield (crs_dv.eq(0)) for _ in range(10): yield if (yield rmii_rx_byte.data_valid): rxbytes.append((yield rmii_rx_byte.data)) assert rxbytes == txbytes vcdf = open("rmii_rx_byte.vcd", "w") with pysim.Simulator(rmii_rx_byte, vcd_file=vcdf) as sim: sim.add_clock(1 / 50e6) sim.add_sync_process(testbench()) sim.run()
m.d.sync += [ # store the current and former state self.iq_history[1].eq(self.iq_history[0]), self.iq_history[0].eq(self.iq), ] return m if __name__ == "__main__": parser = ArgumentParser() parser.add_argument("-s", action="store_true", help="Simulate Rotary Encoder (for debugging).") args = parser.parse_args() if args.s: iq_to_step_dir = IQToStepDir() sim = pysim.Simulator(iq_to_step_dir) sim.add_clock(1.0 / 12e6) def out_proc(): seq = (0b00, 0b01, 0b11, 0b10) yield iq_to_step_dir.iq.eq(0b00) for _ in range(16): for _ in range(4): for iq in seq: yield iq_to_step_dir.iq.eq(iq) yield yield yield yield for _ in range(4): for iq in seq[::-1]:
self.pdm_level1.eq(pdm_level_gamma_n), self.pdm_level2.eq(pdm_level_gamma_p) ] return m if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("-s", action="store_true", help="Simulate PDMDriver (for debugging).") parser.add_argument("-g", type=float, default=2.2, help="Gamma exponent (default 2.2)") args = parser.parse_args() if args.s: p = PDMDriver(8) sim = pysim.Simulator(p) sim.add_clock(1.0 / 12e6) def out_proc(): for i in range(256): yield p.pdm_in.eq(i) yield yield yield yield sim.add_sync_process(out_proc) with sim.write_vcd("drv.vcd", "drv.gtkw", traces=[p.pdm_in, p.pdm_out]): sim.run() else: plat = ICEBreakerPlatform()
self.o = Signal() self.ce = Signal() def get_fragment(self, platform): m = Module() m.d.sync += self.v.eq(self.v + 1) m.d.comb += self.o.eq(self.v[-1]) return CEInserter(self.ce)(m.lower(platform)) ctr = Counter(width=16) frag = ctr.get_fragment(platform=None) # print(rtlil.convert(frag, ports=[ctr.o, ctr.ce])) print(verilog.convert(frag, ports=[ctr.o, ctr.ce])) with pysim.Simulator(frag, vcd_file=open("ctrl.vcd", "w"), gtkw_file=open("ctrl.gtkw", "w"), traces=[ctr.ce, ctr.v, ctr.o]) as sim: sim.add_clock(1e-6) def ce_proc(): yield; yield; yield yield ctr.ce.eq(1) yield; yield; yield yield ctr.ce.eq(0) yield; yield; yield yield ctr.ce.eq(1) sim.add_sync_process(ce_proc()) sim.run_until(100e-6, run_passive=True)