Always Blocks
顾名思义,always语句块会always执行,不像initial 语句块只在仿真开始时执行一次。
always语句块还有一个敏感列表,其告诉always语句块何时执行代码块。
always @ (a or b or sel)
begin
y = 0;
if (sel == 0) begin
y = a;
end else begin
y = b;
end
end
**@符号后面是always语句块触发的条件。**always语句块内只能驱动reg类型的变量。
以上示例为2:1 mux,输入a和b; sel是选择输入,y是mux输出。
在任何组合逻辑中,只要输入改变,输出就会改变。 这意味着每当敏感列表中包含的变量发生变化时,即a,b和sel,就会执行always语句块中的代码。
敏感列表有两种类型:电平敏感(用于组合电路)和边沿敏感(用于触发器)。下面的代码是相同的2:1 Mux,但输出y现在是触发器输出。
always @ (posedge clk )
if (reset == 0) begin
y <= 0;
end else if (sel == 0) begin
y <= a;
end else begin
y <= b;
end
我们通常在时钟边沿(posedge)检查复位是否被置位(同步复位),然后我们继续执行功能逻辑。我们可以发现在之前的组合逻辑中,我们使用“=”进行赋值,而对于时序语句块,我们使用“<=”进行赋值。
“=”是阻塞赋值,“<=”是非阻塞赋值。****“=”在begin / end内顺序执行,而非阻塞“<=”是并行执行的。
Assign Statement
assign语句仅用于建模组合逻辑,并且它是连续执行的。因此,assign语句称为“连续赋值语句”,其没有敏感列表。
assign out = (enable) ? data : 1'bz;
上面的例子是一个三态门。当enable为1时,数据被驱动为out,否则out被拉至高阻态。
Task and Function
Verilog像任何其他编程语言一样,提供了解决代码重复使用的方法,这些代码称为Task和Function。
下面的代码用于计算偶校验。
function parity;
input [31:0] data;
integer i;
begin
parity = 0;
for (i= 0; i < 32; i = i + 1) begin
parity = parity ^ data[i];
end
end
endfunction
Task和Function具有相同的语法:
第一个区别是Task可能有延迟,而Function不能有任何延迟。这意味着Function可用于对组合逻辑进行建模。
第二个区别是Function可以返回值,而Task则不能。
本文转载自公众号:芯片数字实验室
原文链接:https://mp.weixin.qq.com/s/Z\_GUolRabhpxD2LO\_WLSgw
未经作者同意,请勿转载!
推荐阅读
想了解更多内容,欢迎关注芯片数字实验室专栏