cjspook
cjspook

Reputation: 89

Verilog Always block at time = 0

I am currently writing Verilog code to construct a game of "Tug of War." The module below represents the central LED of the 15 LED's that represent the playing field. The central light must be on until the game begins, e.g. when the it receives some sort of input (the input is given by L and R, where L is one movement to the left, and R is one movement to the right).

However, I have run into a strange bug. Although I give enabled a value of 1 at construction, and L and R are 0 (or should be) at construction, when I run the code enabled immediately turns to 0.

My question is, why does this occur? And how would I go about making a variable maintain a value of 1 until input is seen?

module centerLight(Clock, reset, L, R, NL, NR, lightOn);
    input Clock, reset, L, R, NL, NR;
    output reg lightOn;

    reg gameStart = 0;
    reg enabled = 1;

    always@(L or R)
    if (L | R) begin
        gameStart = 1;
        enabled = 0;
    end
    else if (enabled)
        gameStart = 0;
    wire PS;
    reg NS;

    always@(PS or L or R or NL or NR)
    if((NL && R) || (NR && L)) NS = ~PS;
    else               NS = PS;

    always@(PS or gameStart)
    case(PS || !gameStart)
        0: lightOn = 0;
        1: lightOn = 1;
    endcase

    D_FF cl (PS, NS, reset, Clock);

endmodule

module D_FF (q, d, reset, clk);
    input d, reset, clk;
    output reg q;

    always@(posedge clk or posedge reset)
    if (reset)
        q = 0;
    else
        q = d;

endmodule

Upvotes: 1

Views: 2383

Answers (3)

user1471518
user1471518

Reputation: 11

It could be due to a compiler switch.

Your default setting of enabled is effectively an initial block, as initial blocks are not synthesisable (well Altera's Quartus can be directed to read them to set powerup conditions, but officially according to Doulos they are not supported for synthesis) then it should not effect the result of the FPGA logic.

This should be simulated ok as RTL though. But I know for Altera devices for example all logic powers up as zero on startup unless the "Powerup don't care" switch is set to on, in this case it will look at the logic and set registers to values that would minimise the logic.

In this case it would set enabled as logic 0 since that produces the smallest logic thus removing the need for (because your code never sets enabled to 1 anywhere except in the initial construct which technically should be ignored, even if it was reading the initial construct then with that switch it could be ).

I did try adding a reset to enabled by adding an always and putting all the assignments to enabled there (keeping it as a latch)

always@(reset) if (reset) enabled <= 1'b1; else if (L | R) enabled <= 1'b0;

By doing this I could see the functionality for enabled was preserved on the logic.

On a different note I would recommend going for a synchronous registered approach rather then latches.

Also its recommended for Verilog to be consistent with case throughout your code as eventually you will get into trouble (the classic error is connecting modules up and the compiler inferring a wire if the statement `default_nettype none is not used (I'd look at code like Clifford Cummin's from Sunburst technology, or Doulos for inspiration).

I hope this helps!

Upvotes: 1

Katy Montgomerie
Katy Montgomerie

Reputation: 436

In you design enable is a latch, if either L or R are high (or possibly floating) for the shortest amount of time, enable will switch on.

It might be better to make the whole design sequential and then use the reset to make sure gameStart is low.

this is how I'd do it:

module centerLight(Clock, reset, L, R, NL, NR, lightOn);
    input Clock, reset, L, R, NL, NR;
    output reg lightOn;

    reg lightOn_d;
    reg gameStart, gameStart_d;
    reg PN, NS;

    always @ (posedge Clock or posedge reset)
        if(reset)
            begin
                gameStart <= 1'b0;
                PS        <= 1'b0;
                lightOn   <= 1'b0;
            end
        else
            begin
                gameStart <= gameStart_d;
                PS        <= NS;
                lightOn   <= lightOn_d;
            end

    always @ *
        begin
            if(L || R)
                gameStart_d = 1'b1;
            else
                gameStart_d = gameStart;

            if((NL && R) || (NR && L))
                NS = ~PS;
            else
                NS = PS;

            if(PS || !gameStart)
                lightOn_d = 1'b1;
            else
                lightOn_d = 1'b0;
        end

endmodule

I hope that helps.

Upvotes: 1

Ari
Ari

Reputation: 7556

The enable value in your code is assigned to 0 when L|R=1. If the initial values of L and R in your testbench or the values of these pins on your FPGS are 1 initially, enable will switch to 0. Dangling L and R pins may be evaluated as 1 too.

Simulators such as Modelsim allow you to set a breakpoint on the line when "enabled = 0;".

Upvotes: 0

Related Questions