# Verilog 简而言之
Verilog 所有的行为代码都写在 module 和 endmodule 之间。因此,无论您打算创建什么数字设计,都需要 module 块中设计。它可能有也可能没有定义端口。端口允许信号作为 input 进入模块或作为 output 离开模块。
# 模块
下例中的空模块称为 testbench。我们可以随意命名它,但它应该是字母数字,并且可以包含下划线 _。
module testbench;
endmodule
1
2
3
2
3
让我们看看另一个模块。它有几个信号( d 、 clk 、 rstb )被声明为输入, q 被声明为输出。
module dff (input d,
clk,
rstb,
output q);
endmodule
1
2
3
4
5
6
2
3
4
5
6
# 数据类型
现在我们已经了解了模块的外观,让我们再次查看 testbench 模块,看看可以在模块中放入什么。 verilog 中主要有两种数据类型:
regwire
reg 数据类型用于保存变量等的值,而 wire 类似于导线,必须连续驱动。因此,通常使用 wire 连接多个模块和其他信号。
module testbench;
reg d;
reg rst_b;
reg clk;
wire q;
endmodule
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 赋值
Verilog 具有三个基本块:
| 块 | 语意 |
|---|---|
always @ (condition) | 每当 condition 满足时执行 |
initial | 当模拟开始时执行,只执行一次 |
assign [LHS] = [RHS] | 每当 RHS 更改时,LHS 的值都会实时更新 |
编写 Verilog 时需要牢记一些规则:
reg只能在initial块和assign块中赋值;wire只能通过assign语句赋值;- 如果在
initial/always块中有多个语句,它们应该被包裹在begin ... end之间。
module testbench;
reg d;
reg rst_b;
reg clk;
wire q;
initial begin
d = 0;
rst_b = 0;
clk = 0;
#100 $finish;
end
always begin
#10 clk = ~clk;
end
endmodule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
请注意上面示例中的以下内容:
- 由于初始块有多行,因此使用了
begin和end; - 信号
d、rst_b和clk在initial内赋值,因为它们的类型为reg; initial块内的代码将在0ns即仿真开始时执行;- 由于
always块没有条件,因此它将像 C 中的死循环一样运行; #用于表示时间延迟。#10告诉模拟器让模拟时间向前流动10个单位。clk = 〜clk;将切换时钟的值,由于#10放在该语句之前,时钟将每10个单位时间切换(从0变成1或者从1变成0)一次。$finish是手动结束模拟的方式,有点像 C 中表示终止进程的exit(0)函数。在这种情况下,它将运行100个单位时间并退出。