我只是想知道这两个陈述之间的区别
always @(posedge CLK)
begin
state <= next_state;
end
和
always @(CLK)
begin
case(CLK)
1'b1:
state <= next_state;
1'b0:
state <= state;
end
两者之间有区别吗?
由于
答案 0 :(得分:9)
不完全。 posedge
检测到这些转换(来自LRM):
Table 43—Detecting posedge and negedge
To 0 1 x z
From
0 No edge posedge posedge posedge
1 negedge No edge negedge negedge
x negedge posedge No edge No edge
z negedge posedge No edge No edge
因此,例如,0-> x是posedge
。您的第二个示例仅检测CLK
最终为1的情况,因此错过了0-&gt; x和0-&gt; z。
答案 1 :(得分:2)
从功能上讲,这两个电路在verilog中描述了相同的行为,所以我认为应该没有区别。
但是,您通常应该使用第一种样式,因为这是编写可合成代码的标准样式,并且大多数人都可以阅读您的代码。后一种风格虽然描述了正确的行为,但可能会混淆一些不期望看到对正边缘和负边缘都敏感的时钟的合成器。
答案 2 :(得分:2)
IEEE标准。 1364.1(E):2002(IEC 624142(E):2005),Verilog寄存器传输级综合标准,在Sec。 5.1在灵敏度列表中没有任何posedge
/ negedge
事件的始终阻塞是组合逻辑。即忽略事件列表中的信号,并合成块,就像使用了隐式表达式列表(@(*)
,@*
)一样。标准中给出了以下示例(第14页的“示例4”):
always @ (in)
if (ena)
out = in;
else
out = 1’b1;
// Supported, but simulation mismatch might occur.
// To assure the simulation will match the synthesized logic, add ena
// to the event list so the event list reads: always @ (in or ena)
(评论也从标准文件中复制)
即。对于综合工具,您的第二个块是有效的:
always @*
begin
case(CLK)
1'b1:
state <= next_state;
1'b0:
state <= state;
end
它只是一个多路复用器,CLK
作为选择输入,next_state
作为active-1输入,输出(state
)作为active-0输入反馈。智能综合工具可能会检测到这与使用CLK
作为启用输入的d型锁存器相同,并创建一个d型锁存器而不是组合环路。请注意,合成工具不需要检测此锁存器,因为代码在所有分支中明确指定state
(比较标准的5.3节)。
无论哪种方式,这都与您的第一个代码示例合成的d型触发器不同。这是Verilog代码在仿真和综合中具有不同含义的许多情况之一。因此,重要的是(1)以避免这种情况的方式编写可合成的Verilog代码,以及(2)始终对您的设计进行合成后仿真(即使您也使用形式验证!)以确保您已成功避免这个陷阱。
答案 3 :(得分:1)
两个街区非常不同。
顶部的一个给你一个触发器,而底部的一个给你一个带多路复用器的锁存器,CLK作为选择信号。
两个块之间的关键区别在于,最上面的一个是同步块,即 posedge clk 部分,而底部的一个是与CLK级别异步,而不是边缘。
答案 4 :(得分:1)
verilog模拟器可以对CLK
进行左手采样,有效地使case(CLK)
版本与negedge CLK
翻牌相同。否则,模拟器会将其视为posedge CLK
翻牌。这实际上取决于它在特定模拟器的调度程序中的处理方式(或特定合成器将如何处理它)。
最常见的编码风格都使用第一个条件。合成器和任何读取代码的人都明确清楚state
是一个带有正边沿时钟触发器的触发器。
还存在模拟性能差异。 posedge CLK
每个时钟周期执行2次CPU操作,而case(CLK)
每个时钟周期执行6次CPU操作。在这个例子中,差异是微不足道的,但在大型设计中,到处使用的不良编码将浪费数小时的模拟时间。