[[amaranth - python hardware description language|amaranth]] View `.vcd` files in GTKWave or the VSCode plugin WaveTrace useful tutorial: https://cfu-playground.readthedocs.io/en/latest/crash-course/gateware.html#edge-detection ## Simulation example with scan generator test code The scan generator object: ```python class ScanGenerator(Elaboratable): def __init__(self): self.cycle_length = 10 self.cycle_count = Signal(4) self.ovf = Signal() ## Control self.x_enable = Signal() self.y_enable = Signal() self.a_enable = Signal() def elaborate(self,platform): m = Module() ## evaluate whether counter is at its limit m.d.comb += self.ovf.eq(self.cycle_count == self.cycle_length) m.d.comb += [ self.x_data.eq(200), self.x_enable.eq(1), self.y_enable.eq(1), self.a_enable.eq(1) ] ## incrementing the counter with m.If(1): with m.If(self.ovf): ## if the counter is at overflow, set it to 0 m.d.sync += self.cycle_count.eq(0) with m.Else(): ## else, increment the counter by 1 m.d.sync += self.cycle_count.eq(self.cycle_count + 1) with m.If(self.cycle_count == 1): m.d.comb += self.x_enable.eq(0) with m.If(self.cycle_count == 4): m.d.comb += self.y_enable.eq(0) with m.If(self.cycle_count == 7): m.d.comb += self.a_enable.eq(0) return m ``` Ports: This is where you put the signals you want to see in the simulation. Think "virtual logic analyzer" ```python def ports(self): return[self.module.ovf, self.module.cycle_count, self.module.x_enable, self.module.y_enable,self.module.a_enable] ``` Initializing a test: Create an object ```python dut = ScanGenerator() ``` Define a test function: ```python def bench(): for _ in range(20): yield yield ``` Create a simulator: Add a clock to the simulator Add your test process to the simulator Define a `.vcd` file to write to and run the simulation ```python sim = Simulator(dut) sim.add_clock(1e-6) # 1 MHz sim.add_testbench(bench) with sim.write_vcd("scan_sim.vcd"): sim.run() ```