Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
11 years ago

Question on posedge in always block

I had something similar to the following code.

always @ (posedge a, posedge b)

begin

if(a)

begin

address <= address + 1;

end

else

begin

address <= 0;

end

end

'a' and 'b' are not clocks they are triggers. There is a separate clock that is used in separate state machines always blocks that run fine.

I was testing the code with signaltap and saw something that confused me.

Problem I was seeing is that address was incrementing on every clock cycle while ‘a’ was one ('b' was at zero) and not just when ‘a’ was transitioning from 0 to 1.

So with no posedges on either signal how could address be incrementing?

Thank you.....

9 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I had something similar to the following code.

    always @ (posedge a, posedge b)

    begin

    if(a)

    begin

    address <= address + 1;

    end

    else

    begin

    address <= 0;

    end

    end

    'a' and 'b' are not clocks they are triggers. There is a separate clock that is used in separate state machines always blocks that run fine.

    I was testing the code with signaltap and saw something that confused me.

    Problem I was seeing is that address was incrementing on every clock cycle while ‘a’ was one ('b' was at zero) and not just when ‘a’ was transitioning from 0 to 1.

    So with no posedges on either signal how could address be incrementing?

    Thank you.....

    --- Quote End ---

    based on my rusty verilog I think you should put the adder below rather than at top as (a) is meant to be reset while clock is (b)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Does quartus complain about your code? If so, that is probably a hint as to why it is doing what it is doing.

    But as kaz suggested, if you restructure your code with the reset condition at the highest priority, and the adder at the lowest priority, it will probably work as you expect.

    See example 13-39 of the Recommended HDL Coding Styles:

    http://www.altera.com/literature/hb/qts/qts_qii51007.pdf
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    'a' and 'b' are not clocks they are triggers. There is a separate clock that is used in separate state machines always blocks that run fine.

    I was testing the code with signaltap and saw something that confused me.

    Problem I was seeing is that address was incrementing on every clock cycle while ‘a’ was one ('b' was at zero) and not just when ‘a’ was transitioning from 0 to 1.

    So with no posedges on either signal how could address be incrementing?

    --- Quote End ---

    Time to learn a bit about required Verilog syntax for hardware synthesis. The always block structure in post# 1 has a well defined meaning for a Verilog compiler, which has been already mentioned by kaz. I agree that the usage of "event posedge a" for an asynchronous control input in this construct is somehow counter-intuitive, and may cause confusion if read literally. But the syntax is used by all synthesis tools and specified in ieee 1364.1 standard for verilog register transfer level synthesis.

    Besides understanding the required Verilog syntax, there are issues involved with the semantic of your code.

    - a FF can't be controlled by more than one edge sensitive input

    - using edge sensitive "triggers" other than the clock (s) in a design is against synchronous design rules and is likely to cause timing problems. In terms of timing analysis, any edge sensitive event will be recognized as clock

    In a strictly synchronous design, signal edges are detected by comparing previous and present state.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks for your replies.

    I have been winging it with verilog for a while now. Normally I stick to just using clock and reset in the sensitivity list (or just clock), however I was trying to copy a bit of Altera's code from their altsmi_parallel application note.

    always @ (posedge asmi_write_n, posedge reset_logic)

    begin

    if (reset_logic)

    flash_addr <= flash_start_add;

    else

    begin

    if (asmi_write_n)

    flash_addr <= flash_addr + 24'h000001;

    else

    flash_addr = flash_addr;

    end

    end

    I stuck the reset up front on my code and everything now works.

    I am still a bit confused about posedge though. i.e. Why does always block get triggered when there are no posedges?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    In what situation? In simulation it should not as it will go with whats in the sensitivity list. In synthesised code the sensitvity list is ignored and the logic is generated from the code.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    In what situation? In simulation it should not as it will go with whats in the sensitivity list. In synthesised code the sensitvity list is ignored and the logic is generated from the code.

    --- Quote End ---

    I am a reletive noob even though I have been doing this for awhile. As I said I have been winging it and winging it rather impressively at that (I have been keeping things strictly synchronous).

    So.... if I am understanding you right simulated code may operate differently from synthesized logic?

    I suspect looking at the RTL may help in future if I run into this sort of thing again so I will take a look at that.....
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Why does always block get triggered when there are no posedges?

    --- Quote End ---

    Most likely because your 'a' signal is being connected to the reset (aclr) signal of the register, and that signal is not edge sensitive, it is level sensitive.

    Why would Quartus do such a thing? Because of what FvM wrote above.

    Quartus knew you didn't really want that, and gave you some messages to that effect (combinatorial loop and latches for your adder?).

    If you care to learn more first hand, reduce your code to it's most simplest case and study the Post-fit netlist for each case (broken vs. working) and you'll see how such a simple thing as the signal's relative priority can have drastic impact on what you get.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    always @ (posedge asmi_write_n, posedge reset_logic)
    begin
    if (reset_logic)
    flash_addr <= flash_start_add;
    else 
    begin
    if (asmi_write_n)
    flash_addr <= flash_addr + 24'h000001;
    else
    flash_addr = flash_addr;
    end
    end

    According to what has been previously said about Verilog syntax for RTL synthesis, the code doesn't describe synchronous registers. Particularly flash_addr <= flash_addr + 24'h000001 is an asynchronous adder and won't work in synthesis. The question is if asmi_write_n should work as write enable in combination with a system clock or as a clock itself. flash_addr = flash_addr is superfluous in both cases.

    asmi_write_n is clock enable

    always @ (posedge clk, posedge reset_logic)
    begin
    if (reset_logic)
      flash_addr <= flash_start_add;
    else 
    begin
    if (asmi_write_n)
      flash_addr <= flash_addr + 24'h000001;
    end
    end

    asmi_write_n is a clock

    always @ (posedge asmi_write_n, posedge reset_logic)
    begin
    if (reset_logic)
      flash_addr <= flash_start_add;
    else 
    begin
      flash_addr <= flash_addr + 24'h000001;
    end
    end

    Final comment, if flash_start_add isn't a constant but a variable, the asynchronous preset function will be emulated by latches and additional logic because recent FPGA don't have an asynchronous register preset with their core registers. So it would be preferred to use a synchronous preset, if flash_start_add is a variable.