verilog学习——Verilog的行为建模/Behavioral modeling(1)
(一)Verilog的块语句
可以将一组语句组合起来,这些语句在语法上等效于单个语句,称为块语句。块语句有看两种类型:顺序和并行。
1.顺序块语句
语句包含在关键字begin和end之间,并按给定顺序一次执行;延迟值相对于上一个语句的执行时间进行处理。
initial begin
// After 10 time units, data becomes 0xfe
#10 data = 8'hfe;
$display ("[Time=%0t] data=0x%0h", $time, data);
// After 20 time units, data becomes 0x11
#20 data = 8'h11;
$display ("[Time=%0t] data=0x%0h", $time, data);
end
[Time=10] data=0xfe
[Time=30] data=0x11
2.平行块语句
并行块可以并发执行语句,延迟控制可以用来控制赋值的时间顺序。通过将语句放在关键字fork和join之间来并行启动语句。
initial begin
#10 data = 8'hfe;
fork
#20 data = 8'h11;
#10 data = 8'h00;
join
end
3.块的命名
顺序块和并行块都可以在关键字begin和关键字fork之后加“:name“来命名。这样做可以在disable语句块中引用该块。
initial begin
#10 data = 8'hfe;
fork
#20 data = 8'h11;
#10 data = 8'h00;
join
end
(二)Verilog赋值类型
将值放置在nets和variables中称为赋值,有三种基本形式:
Procedural程序;continuous连续的;procedural continuous 程序连续;
1.合法的LHS值
赋值由两部分组成:左侧(LHS)和右侧(RHS),中间是等号(=)或不相等符号(<=);
RHS可以包含计算结果为最终值的任何表达式,将RHS中的值赋给LHS所指示的net或variable。
2.程序性赋值
程序性赋值发生在always、initial、task和functions等过程中,这可以通过使用控制流语句(如 if-else-if、case 语句和循环机制)来控制和修改。
不允许对数组进行变量声明赋值;
reg [3:0] array [3:0] = 0; // illegal
变量声明赋值:
reg [3:0] a = 4'b4;
// is equivalent to
reg [3:0] a;
initial a = 4'b4;
如果变量在声明期间和initial块中的时间 0 初始化,如下所示,则不能保证计算顺序,因此可以有 8’h05 或 8’hee。
module my_block;
reg [7:0] addr = 8'h05;
initial
addr = 8'hee;
endmodule
3.连续赋值
这用于将值赋值给标量和向量网络,并在 RHS 发生变化时发生。它提供了一种在不指定门互连的情况下对组合逻辑进行建模的方法,可以更轻松地使用逻辑表达式驱动网络
// Example model of an AND gate
wire a, b, c;
assign a = b & c;
网络(net)声明赋值:
在声明网络的同一语句上放置连续赋值。一个网络只能声明一次,所以一个网络只能进行一次声明赋值。
wire penable = 1;
4.程序性连续分配
过程性语句,允许将表达式连续分配给net或variable,有两种类型:
Assign…deassign;
Force…release;
① Assign…deassign
reg q;
initial begin
assign q = 0;
#10 deassign q;
end
assign 语句的 LHS 不能是位选择、部分选择或数组引用,但可以是变量或变量的串联。
② Force…release
reg o, a, b;
initial begin
force o = a & b;
...
release o;
end
LHS 可以是网络的位选择,网络的部分选择,或者网络,或者变量,但不能是对数组的引用和变量的位/部分选择。
(三)Verilog的阻塞和非阻塞
1.Blocking阻塞
阻塞赋值语句实在过程块中使用相等符号(=)赋值的,语句依次执行。不会阻止并行块中语句的执行。
module tb;
reg [7:0] a, b, c, d, e;
initial begin
a = 8'hDA;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
b = 8'hF1;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
c = 8'h30;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
end
initial begin
d = 8'hAA;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
e = 8'h55;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
end
endmodule
[0] a=0xda b=0xx c=0xx
[0] a=0xda b=0xf1 c=0xx
[0] a=0xda b=0xf1 c=0x30
[0] d=0xaa e=0xx
[0] d=0xaa e=0x55
2.non-blocking非阻塞
非阻塞赋值允许在不阻塞后续语句执行的情况下赋值,使用符号<= .
module tb;
reg [7:0] a, b, c, d, e;
initial begin
a <= 8'hDA;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
b <= 8'hF1;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
c <= 8'h30;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
end
initial begin
d <= 8'hAA;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
e <= 8'h55;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
end
endmodule
[0] a=0xx b=0xx c=0xx
[0] a=0xx b=0xx c=0xx
[0] a=0xx b=0xx c=0xx
[0] d=0xx e=0xx
[0] d=0xx e=0xx
捕获特定时间步长的每个非阻塞语句的 RHS,并移动到下一个语句上。捕获的 RHS 值仅在时间步长结束时分配给 LHS 变量。
(四)verilog控制流程
1.if-else-if
语法
// if statement without else part
if (expression)
[statement]
// if statment with an else part
if (expression)
[statement]
else
[statement]
// if else for multiple statements should be
// enclosed within "begin" and "end"
if (expression) begin
[multiple statements]
end else begin
[multiple statements]
end
// if-else-if statement
if (expression)
[statement]
else if (expression)
[statement]
else
[statement]
2.forever loop
持续执行块内的语句
forever
[statement]
forever begin
[multiple statements]
end
3.repeat loop
将语句执行固定次数。如果表达式的计算结果为 X 或 Z,则它将被视为零,并且根本不会执行。
repeat ([num_of_times]) begin
[statements]
end
repeat ([num_of_times]) @ ([some_event]) begin
[statements]
end
4.while循环
只要表达式为真,就执行语句。
while (expression) begin
[statements]
end
5.for循环
for (<initial_condition>; <condition>; <step_assignment>) begin
// Statements
end
for 循环具有由步长变量控制的确定的开始和结束条件。
(五)verilog 条件语句
条件语句用于根据某些条件控制执行流程。
1.条件运算符
<variable> = <condition> ? <expression_1> : <expression_2>;
如果条件为 true,则将 expression_1 分配给变量。否则,将分配expression_2。
条件运算符可以嵌套到任何级别。
条件运算符的优点:
① 语法简洁,
② 可读性好。
条件运算符的缺点:
① 功能有限,
② 缺乏灵活性,只允许基于条件的二元选择。
③ 可读性降低的可能性,
2.if-else语句
If-else语句允许根据条件执行不同的操作。
if (<condition>) begin
// statement 1
end else begin
// statement 2
end
3.case语句
当需要根据变量的值执行不同的操作时,使用case语句。
// Here 'expression' should match one of the items (item 1,2,3 or 4)
case (<expression>)
case_item1 : <single statement>
case_item2,
case_item3 : <single statement>
case_item4 : begin
<multiple statements>
end
default : <statement>
endcase
对表达式进行计算,并根据其值执行相应的语句。如果所有值都与表达式不匹配,则执行 default 下的语句。default 语句是可选的,并且 case 语句中只能有一个 default 语句。case 语句可以嵌套。
Case语句多用于实现多路复用器。
Case语句和if-else语句的区别:
① if-else 块中给出的表达式更通用,而在 case 块中,单个表达式与多个项目匹配,
② 当case 表达式中存在 X 和 Z 值时,将提供确定的结果。