[[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()
```