Verilog 如果灵敏度列表中的变量缺失,将创建什么逻辑

Verilog 如果灵敏度列表中的变量缺失,将创建什么逻辑,verilog,system-verilog,register-transfer-level,Verilog,System Verilog,Register Transfer Level,这是我们十大公司提出的面试问题 代码1: always @(a or b or sel) begin if (sel == 1) c = a; else if (sel == 0) c =b; end 这将创建一个多路复用器 代码2:现在从灵敏度中删除“SEL”。它还会产生多路复用器吗? 下面的代码是什么?如果没有,将创建什么逻辑 always @(a or b) begin if (sel == 1) c = a; else if (sel == 0

这是我们十大公司提出的面试问题

代码1:

always @(a or b or sel) begin 
  if (sel == 1)
  c = a; 
  else if (sel == 0) 
  c =b; 
end 
这将创建一个多路复用器

代码2:现在从灵敏度中删除“SEL”。它还会产生多路复用器吗? 下面的代码是什么?如果没有,将创建什么逻辑

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

是的,这仍然会合成一个多工器。综合工具将解释此RTL,就像灵敏度列表已完成一样

然而,这里出现了一个大问题,因为您将在RTL模拟中看到与栅极级模拟/实际硅不同的行为。在RTL模拟中,
c
仅在
a
b
更改时才会更改。如果只有多路复用器的选择信号
sel
发生变化,您的输出
c
在RTL模拟中不会发生变化

当打算创建组合逻辑时,通常建议使用

always @(*)

如果您可以使用SystemVerilog。这样做的优点是,您永远不会遇到与灵敏度列表相关的模拟/合成不匹配。后一个关键字还有一个优点,即您可以明确地告诉工具您想要创建组合逻辑(例如,而不是意外的锁存)

最后:米尔斯和卡明斯写了一篇伟大的论文。在许多其他问题中,这个问题在这里描述得非常好。我极力推荐大家看看这篇文章


好处:X射线传播和模拟与实际硅不匹配 正如您在评论中指出的,您想知道会发生什么是
sel===1'bx
。为了更好地理解这件事,我强烈推荐斯图尔特·萨瑟兰的作品。在这里,我将对您的具体示例作一个非常简短的总结

SystemVerilog中的条件块倾向于X乐观,在前面的文章中定义为:

X乐观被定义为[…]任何时候模拟都会将输入上的X值转换为操作或逻辑门上的0或1。[…]SystemVerilog可能过于乐观,这意味着当实际硅仍然模糊不清时,X在模拟中传播为0或1

当查看您的代码时,我们将看到
sel===1'bx
不会传播到
c
。相反,模拟器将保持先前的
c
值并模拟锁存。这是过度的X乐观,并且是与实际硅的模拟不匹配,因为这里的选择线不是X:信号是1或0。换句话说,这将不是硅锁存器

一种解决方案是在模拟中使多路复用器X悲观,这样我们就可以检测到这种不确定的状态。为此,当
sel
既不是0也不是1时,我们将X指定给
c

always_comb
    if (sel)
        c = a; 
    else if (!sel) 
        c = b; 
`ifndef SYNTHESIS // see footnote 2
    else
        c = 'x;
`endif
然而,这有一个问题,那就是它过于悲观。当
a
b
具有相同的值时,我们将清楚地知道
c
在实际硅中具有什么值(无论
sel
的值如何)

上述论文给出了条件运算符(
?:
)作为可能的解决方案:

条件?表达式1:表达式2

如果条件的计算结果为未知,则运算符将对表达式1和表达式2的值进行逐位比较。对于每个位位置,如果该位在两个表达式中均为0,则该位返回0。如果两位都是1,则返回1。如果每个表达式中的对应位不同,或Z或X不同,则会为该位返回一个X

因此,通过使用以下代码,我们将在上述两种解决方案之间达成妥协:

always_comb
    c = sel ? a : b;
这里的缺点是,条件运算符不适合更复杂的表达式

总结了三种方法:

╭───────────╥─────────────────────────────────────────────────╮      
│   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    │
└───╨───╨───╨────────────┴─────────────┘────────────┴─────────┘
在他的论文中,Sutherland给出了另一个我同意的解决方案:最好使用断言来检测导致X的设计问题,而不是让X在设计中传播并花费大量时间寻找根本原因。对于您的特定代码,这可能如下所示:

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

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

1:这里我假设
sel
是一个1位信号。否则,您将以闩锁结束


2:有关合成宏标识符的更多信息。

是,这仍将合成为多路复用器1。综合工具将解释此RTL,就像灵敏度列表已完成一样

然而,这里出现了一个大问题,因为您将在RTL模拟中看到与栅极级模拟/实际硅不同的行为。在RTL模拟中,
c
仅在
a
b
更改时才会更改。如果只有多路复用器的选择信号
sel
发生变化,您的输出
c
在RTL模拟中不会发生变化

当打算创建组合逻辑时,通常建议使用

always @(*)

如果您可以使用SystemVerilog。这样做的优点是,您永远不会遇到与灵敏度列表相关的模拟/合成不匹配。后一个关键字还有一个优点,即您可以明确地告诉工具您想要创建组合逻辑(例如,而不是意外的锁存)

最后:米尔斯和卡明斯写了一篇伟大的论文。在许多其他问题中,这个问题在这里描述得非常好。我极力推荐大家看看这篇文章


好处:X射线传播和模拟与实际硅不匹配 正如您在评论中指出的,您想知道会发生什么是
sel===1'bx
。为了更好地理解这件事,我强烈推荐斯图尔特·萨瑟兰的作品。在这里,我将对您的具体示例作一个非常简短的总结

SystemVerilog中的条件块倾向于X乐观,在前面的文章中定义为:

X乐观主义被定义为[……]