[转载]Verilog一到小题

Question: 
The example below models a flip-flop with asynchronous set/reset logic (active low).   
The model synthesizes correctly, but there is a corner case where simulation results are incorrect.   
What is the corner case? 

always_ff @(   posedge clk 
            or negedge rst_n     // active-low reset 
            or negedge set_n     // active-low set 
           ) 
  if (!rst_n)           // reset has priority over set 
    q_out <= ’0;        // reset all bits to zero 
  else if (!set_n) 
    q_out <= ’1;        // set all bits to one 
  else 
    q_out <= data_in;   // d input assignment 

The example below models a flip-flop with asynchronous set/reset logic (active low).  The model synthesizes correctly, but there is a corner case where simulation results are incorrect.  What is the corner case?

always_ff @(   posedge clk
            or negedge rst_n     // active-low reset
            or negedge set_n     // active-low set
           )
  if (!rst_n)           // reset has priority over set
    q_out <= ’0;        // reset all bits to zero
  else if (!set_n)
    q_out <= ’1;        // set all bits to one
  else
    q_out <= data_in;   // d input assignment
Answer

This model synthesizes as intended.  However, the model does not work correctly for all simulation conditions. 

Consider rst_n going low, which correctly asynchronously resets the flip-flop.  While rst_n is low, set_n goes low. 

With both rst_n and set_n low at the same time, the flip-flop will correctly remain in reset, because of the priority

coding of reset over set in the model.  Everything is OK so far.  Next, rst_n goes high and set_n stays low. 

Since the sensitivity list is only sensitive to leading edges (the negedge of rst_n and set_n), the release of rst_n

will not trigger the sensitivity list.  This means that the flip-flop will be in a reset state when only the set signal is active. 

 Gotcha!

This gotcha only exists with synthesizable asynchronous set/reset flip-flops, and will only be evident until the next clock. 

The next clock will cause the if...else decisions to be re-evaluated and transition the flip-flop to its set state. 

The problem is that actual asynchronous set/reset inputs are level sensitive, so when the reset is removed,

the active set takes over and drives the flip-flop to its set level.  In the model, however, synthesis rules require

the sensitivity list trigger on the leading edges of the set/reset inputs, causing the simulation to differ from actual

hardware behavior.

This gotcha is a result of the synthesis-imposed coding style for a set/reset flip-flop.  This style requires that all

signals in a sequential-logic sensitivity list be specified with an edge (posedge or negedge).  In order to model

accurate simulation behavior, the asynchronous set/reset signals need to be sensitive to all changes on those signals,

not just one edge (the leading edge) of those signals.

To avoid this gotcha, a recommended coding style (created by Don Mills of LCDM Engineering) is to:

1) Add a level-sensitive condition to the sensitivity list that triggers on the trailing edge of reset when set is active.

2) Use conditional compilation (`ifdef/`endif) or synthesis pragmas (translate_off/translate_on) to hide the additional sensitivity list condition from synthesis compilers.

Here's the recommended way to code the previous example:

always_ff @(   posedge clk
            or negedge rst_n     // active-low reset
            or negedge set_n     // active-low set
  `ifndef SYNTHESIS  // non-synthesizable simulation code
            or posedge (rst_n & ~set_n) // trailing edge of reset when set is low
  `endif
           )
  if (!rst_n)           // reset has priority over set
    q_out <= ’0;        // reset all bits to zero
  else if (!set_n)
    q_out <= ’1;        // set all bits to one
  else
    q_out <= data_in;   // d input assignment

An alternative coding style (invented by Cliff Cummings many years ago) to avoid this gotcha is to

use the verification force/release commands to override the simulation behavior of the synthesizable

model. This method requires adding an additional always block to the model, that is hidden from

synthesis using conditional compilation. Note that this alternate solution must use Verilog's general_purpose

"always" procedural block. It cannot take advantage of SystemVerilog's always_comb procedural block,

because always_comb does not allow multiple procedural blocks to write to the same variables.

`ifndef SYNTHESIS  // start non-synthesizable simulation code
always @*
   if (rst_n && !set_n)  force   q_out = 1'b1;
   else                  release q_out;
`endif             // start synthesizable and simulatable code
always_ff @(posedge clk, negedge rst_n, negedge set_n)
  if (!rst_n)           // reset has priority over set
    q_out <= ’0;        // reset all bits to zero
  else if (!set_n)
    q_out <= ’1;        // set all bits to one
  else
    q_out <= data_in;   // d input assignment

posted on 2011-05-21 21:18  o my god  阅读(694)  评论(0编辑  收藏  举报

导航