我在这里给出2个Verilog模块,在模拟过程中表现相同。但是我不明白为什么在这些模块中使用assign
/ deassign
,这两个代码之间有什么区别?
// Code 1 - Without assign-deassign
module dff (q,qbar,clk,reset,d)
input clk, reset, d;
output reg q, qbar;
always @ (posedge reset, negedge clk)
begin
if(reset)
begin
q=1;
qbar=0;
end
else
begin
q=d;
qbar=~d;
end
end
endmodule
// Code 2 - With assign-deassign
module dff (q,qbar,clk,reset,d)
input clk, reset, d;
output reg q, qbar;
always @ (negedge clk)
begin
q=d;
qbar=~d;
end
always @ (reset)
begin
if(reset)
begin
assign q=1;
assign qbar=0;
end
else
begin
deassign q;
deassign qbar;
end
end
endmodule
答案 0 :(得分:2)
示例中的过程赋值/取消分配语句的最初目的是在两个不同的进程中将同步逻辑与异步逻辑分开。它对模拟也更有效,因为同步模块不必在每个时钟周期检查复位信号。建模锁存器对于仿真也更有效,因为每次数据更改时都不必检查启用信号,只有当锁存器打开时才会检查。
这个结构可以通过早期的综合工具合成,但不幸的是,大综合供应商决定不支持它,所以没有人再使用这些程序结构了。
答案 1 :(得分:1)
没有assign
的语句位于@ edge块内,并且在该边缘仅计算 。 assign
描述了组合连续逻辑,并且根据定义对其输入敏感。
在Code 1
中,q
只会在clk
或reset
更改时更改,而不会在d
更改时更改。
Code 2
具有以下效果:当reset
被置位时,此块将持续驱动q=1
(与任何其他驱动程序冲突)但是当重置被否定时,它将停止驾驶q
。
在@edge块中,这实际上可能更常用于赋值。
更常规的用法就像
assign out = (enable) ? data : 1'bz;
只要启用或数据发生变化,它就会改变。