Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17254 Discussions

Clocking question: modelsim

Altera_Forum
Honored Contributor II
1,446 Views

Hello, I came across a matter which I do not understand: 

 

always@(posedge clk or negedge reset) begin if(!reset) ....  

 

When clk does not clock I change reset from high to low and ... always does not work. I would expect that when I change reset high to low (like Reset input of D-trigger) I have !reset condition effective in always construction. My assumption seem to be wrong. 

 

So my question is - what happens is a bug or a feature? If it is feature, please point me to the explanation of how this "always" with reset is implemented @ FPGA gate level. 

 

Thank you.
0 Kudos
3 Replies
Altera_Forum
Honored Contributor II
607 Views

Hi, 

 

at FPGA gate level the reset is actually level-triggered, i.e. as long as reset is low, the register is held in reset. Depending on the FPGA you use, it might actually be an asynchronous active-high clear (as shown in the Cyclone IV handbook), or an asynchronous active-low clear (as shown in the Cyclone II handbook), but the synthesis tool will fix the logic for you. The only edge-sensitive element of a logic cell is the clock, which is always sensitive on the rising edge. 

 

However, simulation works different. There is no syntax (as far as I know) that describes level-sensitivity. Therefore you define the sensitivity as "@(posedge clk or negedge reset)", which means the always-block will be "executed" whenever the clock goes high, or when the reset becomes asserted (becomes low). It does not matter what happens while the reset is asserted, it only matters what happens when the reset becomes asserted. Example: 

  • clock rising edge -> process becomes executed, the "else" path of your statement becomes executed since the reset is not asserted (i.e. not low) 

  • reset becomes low -> this is basically a reset falling edge -> process becomes executed, the "if" path of your statement becomes executed -> reset 

  • clock rising edge -> process becomes executed, the "if" path of your statement becomes executed, since the reset is still asserted (i.e. still low) 

  • reset becomes high -> nothing happens 

  • clock rising edge -> process becomes executed, the "else" path of your statement becomes executed since the reset is not asserted any more (i.e. not low again) 

 

 

Keep in mind that the always@ is virtually irrelevant for synthesis; the synthesis tool only deduces from the overall structure (the "always" and the if-else) that it has to implement this piece of Verilog as a rising-edge clocked D-register, with an asynchronous active-low reset. 

 

What I assume is that you did the if-else wrong. It has to look like this: 

always @(posedge clk or negedge rst) if(!rst) q<=0; else q<=d; 

 

If you do this instead, it won't work, as the second if will also execute: 

always @(posedge clk or negedge rst) if(!rst) q<=0; if(clk) // WRONG! q<=d; 

 

Best regards, 

GooGooCluster
0 Kudos
Altera_Forum
Honored Contributor II
607 Views

Thank you so much! Very informative and thorough answer. I use Cyclone-3, and use the "right" code. Tried moidelsim several times and it seems it was an intermittent problem of modelsim, or I did something wrong during simulation. 

 

You raised one thing which was bothering me some time ago with your second, "wrong" example. When posedge of clk happens, what will happen if this "if (clk)" is used in the body of always? I thought to use it before, but decided that it may cause metastability of the circuit. Please advise.
0 Kudos
Altera_Forum
Honored Contributor II
607 Views

If you use the "bad" example above: 

always @(posedge clk or negedge rst) if(!rst) q<=0; if(clk) // WRONG! q<=d; 

...this will happen during simulation: 

  • clock rising edge -> process becomes executed, the "if(clk)" path of your statement becomes (so far so good) 

  • reset becomes low -> this is basically a reset falling edge -> process becomes executed, the "if(!rst)" path of your statement becomes executed -> reset (still good), but since the clock is still high, the "if(clk)" path is then also executed, virtually overriding the thing the "if(!rst)" path did! 

  • clock falling edge -> nothing happens (as expected) 

  • clock rising edge -> process becomes executed, again both paths become executed, as before - again, the reset has no effect! 

  • reset becomes high -> nothing happens (as expected) 

  • clock rising edge -> everything goes as usual 

 

This is a consequence of how these non-blocking assignments ("<=") work in Verliog (it would be the same in VHDL, by the way). The reset still would have some effect if it happens to arrive when the clock is low, but that might be even worse (it might appear to be non-deterministic). 

 

I assume when both the rising clock edge and the falling reset edge happen at the very same time, then ModelSim might simply execute the block once, again ignoring the reset, as the effects of "q<=0" become overriden by the "q<=d" two lines below. 

 

Now I didn't try what the synthesis tool would do, but I assume it would throw an error, as I don't see how such a construct can be implemented with a logic cell. You definitely won't get the expected result. 

 

 

Best regards, 

GooGooCluster
0 Kudos
Reply