0
\$\begingroup\$

I want to create an 8 bit counter with reset button on a FPGA board. I have two signals: btn_up which is debounced and btn_center which isn't. R is an output signal which represents 8 bit counter. I want to use btn_up rising edge to increment the counter and btn_center to reset it to "00000000".
I thought there are 3 ways to do it, but only one of them works. Here is the code:

Using concurrent statement "when-else" :

R <= R + 1      when (rising_edge(clk))          else
     "00000000" when (rising_edge(btn_center))   else
     R;

if I press btn_center R incements by 1 and doesn't get set to "00000000"

Using sequential "if-elsif" statement:

process(clk, btn_center)
begin
    if rising_edge(clk) then
        R <= R + 1;
    elsif btn_center = '1' then
        R <= "00000000";
    end if;
end process;

during synthesis I get error code 9 again

Using 2 sequential "if-if" statements:

process(clk, btn_center)
begin
    if rising_edge(clk) then
        R <= R + 1;
    end if;
    if btn_center = '1' then
        R <= "00000000";
    end if;
end process;

It works.

Why aren't these 3 ways of doing this the same in this case?

\$\endgroup\$
2
\$\begingroup\$

Why aren't these 3 ways of doing this the same in this case?

The behaviour of the three codes is NOT identical.

Number one:

R <= R + 1      when (rising_edge(clk))          else
 "00000000" when (rising_edge(btn_center))   else
 R;

R has to change on a rising clock edge, but if there is no rising clock edge it has to reset on a rising btn_center edge.
There exists no hardware with this behavior. You have register with asynchronous reset and/or set but the asynchronous input is level sensitive, not (rising) edge sensitive. Also the rising_edge of the clk has to override the reset.

Number two:

process(clk, btn_center)
begin
    if rising_edge(clk) then
        R <= R + 1;
    elsif btn_center = '1' then
        R <= "00000000";
    end if;
end process;

R has to change on a rising clock edge, but if there is no rising clock edge it has to reset on a btn_center being one.
There exists no hardware with this behavior. It is some sort of register with asynchronous reset and/or set but the asynchronous behaviour is overridden by a clock edge.

Number three:

process(clk, btn_center)
begin
    if rising_edge(clk) then
        R <= R + 1;
    end if;
    if btn_center = '1' then
        R <= "00000000";
    end if;
end process;

This one we have to deal with differently. You have two independent 'if' statements so the second one overrides the first one. Hence we have to start with the second one:
If btn_center is one R is set to zero, else if there is a rising edge R is incremented.
This is a typical register with an asynchronous reset

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you for the answer, but what do you mean by "There exists no harware with this behaviour"? \$\endgroup\$ – ToTheSpace 2 Jan 4 at 13:20
  • \$\begingroup\$ Synthesis means the code is converted to hardware which behaves just like the code. e.g. There exists no hardware, inside our outside an FPGA, which has two clock (edge sensitive) inputs and controls one output with it. There are many more ways of writing HDL code which work in simulation but which can not be mapped onto hardware. \$\endgroup\$ – Oldfart Jan 4 at 13:27
  • \$\begingroup\$ Thank you very much! \$\endgroup\$ – ToTheSpace 2 Jan 4 at 13:35
0
\$\begingroup\$

One additional point that the accepted (correct) answer doesn't cover:

Notice the differences come from the implementation details, not the different styles of statement.

For example you could implement solution(3) in the style of (1) as:

R <= "00000000" when btn_center = '1' else
      R + 1  when rising_edge(clk);

This gives the asynchronous reset priority over the clocked increment, just as the later assignment in process (3) does. You'll get the same behavior in simulation, and MOST modern synthesis tools should accept it and generate the correct hardware.

A similar transformation (reset branch first) is possible in process (2) which is the "standard" solution accepted by all tools.

So - get the implementation right, and there is NO difference between the statement types in this example.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This helped so much! But I still don't understand why changing the order of these statements makes a difference. I'll try and learn more about this but thank you very much! \$\endgroup\$ – ToTheSpace 2 Jan 4 at 16:02
  • \$\begingroup\$ A concurrent conditional assignment statement is elaborated into a process statement equivalent with an if statement. IEEE Std 1076-2008 11. Concurrent statements, 11.6 Concurrent signal assignment statements "A concurrent signal assignment statement represents an equivalent process statement that assigns values to signals.", 10. Sequential statements, 10.5.3 Conditional signal assignments. "The conditional signal assignment represents an equivalent if statement that assigns values to signals or that forces or releases signals." \$\endgroup\$ – user8352 Jan 4 at 19:01
  • \$\begingroup\$ An if statement is inherently a priority encoder. 10.8 If statement "For the execution of an if statement, the condition specified after if, and any conditions specified after elsif, are evaluated in succession (treating a final else as elsif TRUE then) until one evaluates to TRUE or all conditions are evaluated and yield FALSE. If one condition evaluates to TRUE, then the corresponding sequence of statements is executed; otherwise, none of the sequences of statements is executed." \$\endgroup\$ – user8352 Jan 4 at 19:03
  • \$\begingroup\$ The (correct) order of evaluating the is dictated by the equivalent if statement and accepted RTL synthesis syntax (e.g. IEEE Std 1076.5-2004, withdrawn, 6.1.3.5 Edge-sensitive storage using concurrent signal assignment statements ). Here evaluating an asynchronous reset prior to a clock edge. \$\endgroup\$ – user8352 Jan 4 at 19:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.