[libre-riscv-dev] Very Subtle Synchronous nMigen Behavior

Yehowshua yimmanuel3 at gatech.edu
Thu Jun 18 02:01:25 BST 2020

Take a look through the following code and the comments.
I’ve tried to capture some subtle BUT important
synchronous behavior in the nMigen simulator.
It will be very helpful when writing memory test benches.

from nmigen import *

class Simple(Elaboratable):
    def __init__(self):
        self.simple_in = Signal(range(4))
        self.simple_out = Signal(range(4))
    def elaborate(self,platform):
        m = Module()
        m.d.sync += self.simple_out.eq(self.simple_in)
        return m

m = Module()
simple = Simple()
m.submodules.simple = simple

from nmigen.back.pysim import Simulator, Delay, Settle
sim = Simulator(m)

def process():
    val = 2
    yield simple.simple_in.eq(val)
    # this will print simple_out = 0 which is the
    # reset value even though 
    # during this cycle, simple_out = 2
    # This is because as far as the simulator is concerned
    # we can't see changes until the edge right
    # before the next clock cycle
    print(f"simple_out = {(yield simple.simple_out)}")

    val = 3
    yield simple.simple_in.eq(val)
    yield Settle()
    # this will print out 3 as expected becuase
    # we use Settle() to advance right to the edge
    # before the next clock cycle
    print(f"simple_out = {(yield simple.simple_out)}")

sim_writer = sim.write_vcd(f"{__file__[:-3]}.vcd")

with sim_writer:

More information about the libre-riscv-dev mailing list