What logic will be created if variables in the sensitivity list are missing

荒凉一梦 提交于 2021-01-07 03:32:30

问题


This was an interview question asked by a top 10 company of US.

Code 1:

always @(a or b or sel) begin 
  if (sel == 1)
  c = a; 
  else if (sel == 0) 
  c =b; 
end 

This will create a mux.

Code 2: Now "SEL" is removed from sensitivity. Will it still create mux? For the code below? If not, what logic will be created?

always @(a or b) begin 
  if (sel == 1)
  c = a; 
  else if (sel == 0) 
  c =b; 
end 

回答1:


Yes, this will still synthesize to a multiplexer1. A synthesis tool will interpret this RTL as if the sensitivity list were complete.

However, a large issue here arises because you will see different behaviour in your RTL simulations compared to the gate-level simulations/the actual silicon. In your RTL simulation, c will only change if a or b change. If only the select-signal sel of the multiplexer changes, your output c will not change in RTL simulations.

When intending to create combinatorial logic, it is generally advisable to use

always @(*)

or

always_comb

if you can use SystemVerilog. This has the advantage that you never run into sensitivity-list related simulation/synthesis mismatches. The latter keyword furthermore has the advantage that you explicitly tell tools that you want to create combinatorial logic (rather than unintended latches, for example).

Finally: Mills & Cummings wrote a great paper on RTL Coding Styles That Yield Simulation and Synthesis Mismatches. This issue, among many others, is described here very well. I can greatly recommend to take a look at this paper!


Bonus: X-Propagation and simulation mismatches with actual silicon

As you indicated in your comment, you were wondering what would happen is sel === 1'bx. To better understand this matter, I highly recommend reading I'm Still In Love With My X! by Stuart Sutherland. I will give a very brief summary on your particular example here.

Conditional blocks in SystemVerilog are prone to X-optimism, which is defined in the aforementioned paper as:

X-optimism has been defined [...] as any time simulation converts an X value on the input to an operation or logic gate into a 0 or 1 on the output. [...] SystemVerilog can be overly optimistic, meaning an X propagates as a 0 or 1 in simulation when actual silicon is still ambiguous.

When looking at your code, we will see that an sel === 1'bx will not propagate to c. Rather, the simulator will hold the previous value of c and mimic a latch. This is overly X-optimistic and is a simulation mismatch with actual silicon, since the select line will not be X here: a signal is either 1 or 0. In other words, this will not be a latch in silicon!

One solution could be to make the multiplexer X-pessimistic in simulation, so that we would detect this undetermined state. To do so, we assign X to c when sel is neither 0, nor 1:

always_comb
    if (sel)
        c = a; 
    else if (!sel) 
        c = b; 
`ifndef SYNTHESIS // see footnote 2
    else
        c = 'x;
`endif

This has the problem, however, that it is overly pessimistic. When both a and b have the same value, we would unambiguously know what value c would have in actual silicon (regardless of the value of sel).

The aformentioned paper gives the conditional operator (? :) as a possible solution:

condition ? expression1 : expression2;

If the condition evaluates to unknown, the operator does a bit-by-bit comparison of the values of expression1 and expression2. For each bit position, if that bit is 0 in both expressions, then a 0 is returned for that bit. If both bits are 1, a 1 is returned. If the corresponding bits in each expression are different, or Z, or X, then an X is returned for that bit

So, by using the code below, we would have a compromise between the two aforementioned solutions:

always_comb
    c = sel ? a : b;

The downside here is that the conditional operator is not suited for more complex expressions.

The three approaches summarized:

╭───────────╥─────────────────────────────────────────────────╮      
│   input   ║                     sel(t)                      │
├───╥───╥───╫────────────┬─────────────┬────────────┬─────────┤
│sel║ a ║ b ║ optimistic │ pessimistic │ compromise │ silicon │
╞═══╬═══╬═══╬════════════╪═════════════╡════════════╪═════════╡
│ X ║ 0 ║ 0 ║  sel(t-1)  │      X      │     0      │    0    │
│ X ║ 0 ║ 1 ║  sel(t-1)  │      X      │     X      │   0/1   │
│ X ║ 1 ║ 0 ║  sel(t-1)  │      X      │     X      │   0/1   │
│ X ║ 1 ║ 1 ║  sel(t-1)  │      X      │     1      │    1    │
└───╨───╨───╨────────────┴─────────────┘────────────┴─────────┘

In his paper, Sutherland gives another solution with which I agree: It is best to use assertions to detect design issues which cause X, instead of letting X propagate through the design and spending a lot of time finding the root cause. For your particular code, this could look like this:

always_comb
begin
    assert (!$isknown(sel))
    else $error("sel = X!");

    if (sel)
        c = a; 
    else if (!sel) 
        c = b; 
 end

1: I assume here that sel is a 1-bit signal. Otherwise, you would end up with a latch

2: See my answer here for some more information on the SYNTHESIS macro identifier.



来源:https://stackoverflow.com/questions/62681508/what-logic-will-be-created-if-variables-in-the-sensitivity-list-are-missing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!