Weird register behavior during simulation

I was writing a test bench for a ps2 host transmitter and signals are sent from the device to the board. I registered the inputs, but I got some weird behavior in the simulation. If the signals come in at the same time as the host tries to register them, then it fails. Instead of registering the value before the edge it takes the value after.

I know that if I were to put this design on a board it would have metastability issues because of the asynchronous input, but I assumed that wouldn’t happen in a simulation. Is there any simple solution to this or detail I’ve overlooked? All I can think of is making the the two’s periods have a large least common multiple, so I won’t run into this issue while simulating.

My work around is to make the input din only change on the falling edges of clk. I do this by making the period of the incoming signal an even multiple of clk_period. This works, but I would still like to know if there’s a more elegant and general way to fix this.

Here’s the minimal code for my hack.

from myhdl import block,  always, Signal, delay, traceSignals, instance


@block
def foo_sim():
    clk = Signal(bool(0))
    din = Signal(bool(0))

    clk_period = 5*2

    @always(delay(clk_period // 2))
    def clk_gen():
        clk.next = not clk

    din_period = clk_period*2*6

    @instance
    def din_gen():
        # uncomment this to shift din by half a clk period
        # delay(clk_period//2)
        while True:
            din.next = 0
            yield delay(din_period//2)
            din.next = 1
            yield delay(din_period//2)

    last_din = Signal(bool(0))

    @always(clk.posedge)
    def reg():
        last_din.next = din

    return clk_gen, din_gen, reg

if __name__ == '__main__':
    inst = traceSignals(foo_sim())
    inst.run_sim(1000)

Please don’t call what you did a hack or weird
If you have two signals rising at the same time and one is clocked by the other, that clock sees the other as a zero at the time of rising. So you were getting what you asked for.
It is common practice in simulation (all languages) to provide proper setup/hold times, some use a quarter delay, others use the negative edge of the clock.
If you had generated the din signal from on the clock you wouldn’t have seen the weird behaviour, but I understand the the din is the PS/2 strobe/clock.

1 Like