Archont
Archont

Reputation: 41

Verilog wait function explanation

I have problem with my Verilog code. I have 2 clocks - one 100kHz, second 10kHz. I'd like to toggle LED with 100kHz frequency only when 10kHz is HIGH. But my output is still low. This is my code:

module LED_toggle(
    input clock_100kHz,
    input clock_10kHz,

    output reg LED_PIN,
);
    initial begin           
        LED_PIN <= 1'b0;
    end

    always begin
        if(clock_10kHz) begin
            LED_PIN = 1'b1;
            @(posedge clock_100kHz);            
            LED_PIN = 1'b0;
            @(posedge clock_100kHz);
        end
        else begin
            LED_PIN = 1'b0;
        end
    end

endmodule

I know that I can do this in other way (like trigger on 100kHz edge and check state ot 10kHz), but I try to understand why @(posedge clock_100kHz); don't act like I would expect. I also try wait(clock_100kHz) insted, but this also don't work.

I'm sure that my clocks are configured properly, because this code works like I expect:

module LED_toggle (
    input clock_100kHz,
    input clock_10kHz,

    output reg LED_PIN,
);
    initial begin           
        LED_PIN <= 1'b0;
    end

    always begin
        if(clock_10kHz) begin
            LED_PIN = ~LED_PIN;
        end
        else begin
            LED_PIN = 1'b0;
        end
    end

endmodule

but I try to understand what is wrong with my wait conditions.

Upvotes: 0

Views: 990

Answers (1)

l Steveo l
l Steveo l

Reputation: 558

It would likely be best if you built this more like HW instead of SW. Your always begin blocks act more like a behavioral model than a HW representation.

It looks like, based on the first snippet that you actually want the LED to run at 50kHz (since you are toggling the LED output on each posedge of the 100kHz)? This would be what I would do, for 100kHz:

assign LED_PIN = clock_10kHz & clock_100Hz;

For 50kHz

always @(posedge clock_100kHz) begin
    if(clock_10kHz) LED_PIN <= ~LED_PIN
    else            LED_PIN <= 1'b0;
end

What the first snippet does is just use the 10kHz clock as a gate and basically the 100kHz clock directly drives the LED.

The second snippet still uses the 10kHz clock as a gate, but there is a register built that is clocked with the 100kHz clock that drives the LED_PIN output. This will make the effective toggling of the LED 50kHz instead of the 100kHz you described/desired, but this matches your behavioral in your first snippet. I'm making an assumption that these clocks are synchronous, but really that gate should be synchronized into the 100kHZ clock domain, but that's a different topic.

always begin is really a behavioral construct. It is essentially something that say "always do this, and do it as fast as I say". In your example, I'm not sure how the simulator didn't just run away when the clock_10kHz was low. Many simulators would see no time statement (such as a #delay or @()) and try to compute that as many times as possible, or just error if it was smart enough to see an infinite loop. Remember that verilog is an event based language. In your code, there are cases where you don't have any "Events", just actions that should happen. This can, and will cause you some grief. If you've done other programming languages, and start verilog, this is usually the hardest part to grasp, but when you do, it makes much more sense.

Hopefully this helps!

Upvotes: 2

Related Questions