Verilog always block with pushbutton activation, FSM

1.2k views Asked by At

I'm writing some Verilog code to be programmed on an Altera Cyclone II FPGA board, and I have an always block which should be activated on the press of a key switch:

reg START;

...
...

always @ (negedge key[3]) begin
    if (START != 1) START = 1;
end

I'm writing a program for a finite state machine and this key press is supposed to indicate that the user would like to begin using the program and it should move from its initial state to the next state. Since the initialization of registers is not synthesizable, I can't assume that START begins at 0.

The problem is that once I program the board and turn it on, this always block has already run once before I press the key assigned to key[3]. I've done checks for the value of START at program execution and it is already at 1. I can't figure out why this would be happening, as the key is at its negative edge only upon key press. I've used always blocks with the same condition in previous situations and it worked fine, so I assume this has something to do with the initialization of START?

2

There are 2 answers

0
lvd On BEST ANSWER

It should be noted that synthesizability of initial depends on a target you are coding for.
For example, if you code for simulator, initial works just nice. If your target is FPGA, the tool (quartus in your case) has full control over the schematics and over the initial state of every trigger inside it: actually, uploading the firmware to FPGA sets every trigger to a known state, and quartus is able to parse initials to derive each trigger's state. In contrary, if your target is a bare silicon, every trigger is just a bunch of transistors and its state is totally indefinite upon power-on, so the only way to control it's power-on state is to apply some type of reset, like this:

always @(posedge clk, negedge rst_n)
if( !rst_n )
    START <= 1'b0; // no start condition upon reset
else if( some_condition )
    START <= 1'b1;

Another point on your code is that when parsing inputs from switches you should do first resynchronization to your design's clock, like this:

reg start_r, start_rr;
always @(posedge clk)
begin
    start_r  <= START;
    start_rr <= start_r;
end
// now use start_rr instead of START

Resynchronization is a key element to avoid metastable states in your synchronous design.

The second point is that you should consider debouncing of any input from mechanic switches, unless your design is tolerant to multiple tripping of switches.

Returning to the original problem Ryan McClure asks for. It could be seen, that in the original code without initial START is undefined at startup, and can trip only to '1' state. Therefore, synthesizer just assumes START is constant, always having it '1'.

3
grorel On

You should use an "initial" block to set the startup value of your signals. The value of START and key[3] has to be set.

initial begin
  START = 1'b0;
  key[3] = 1'b1;
end

You said

Since the initialization of registers is not synthesizable, I can't assume that START begins at 0.

But this is not true! You can set a default value to any signal in your design with the method above. This value is included in the bitstream of your firmware and the signal startup with this very value.

cheers