硬件描述语言:Hardware Description Language HDL
综合:用代码的形式描述硬件。最终在硬件电路上实现功能。verilog描述出硬件功能后需要使用综合器对verilog代码进行解释并将代码转化成实际的电路来表示,最终产生实际的电路(网表)。
实质:代码->电路
**仿真:**通过仿真软件进行仿真测试,检测出BUG并解决
仿真需要测试程序(产生激励信号),verilog绝大多数须发都是为了仿真测试使用,少部分用于电路设计
可综合设计:以仿真测试为目的的程序,不能与实际电路对应起来的是不可综合的。
综合就是把编写的 rtl 代码转换成对应的实际电路。比如编写代码 assign a=b&c;EDA 综合工具就会去元件库里调用一个二输入与门,将输入端分别接上 b 和 c,输出端接上 a。
同样地,如果设计师编写了一些如下所示的语句
assign a=b&c;
assign c=e|f;
assign e=x^y;
综合工具就会像搭积木一样把这些“逻辑”电路用一些“门”电路来搭起来。当然,工具会对必要的地方做一些优化,比如编写一个电路 assing a=b&~b,工具就会将 a 恒接为 0,而不会去调用一个与门来搭这个电路。
不可综合,是指找不到对应的“门”器件来实现相应的代码。比如“#100”之类的延时功能,
简单的门器件是无法实现延时 100 个单元的,还有打印语句等,也是门器件无法实现的。这些是用来进行测试使用的。
初学者要明确哪些代码是可综合,哪些是不可综合。
模块介绍
模块(module)是verilog的基本描述单位。是用于描述某个设计的功能或结构及其他模块通信的外部端口。
Verilog 的基本设计单元是“模块”。采用模块化的设计使系统看起来更有条理也便于仿真和测试,因此整个项目的设计思想就是模块套模块,自顶向下依次展开。在一个工程的设计里,每个模块实现特定的功能,模块间可进行层次的嵌套。
模块有五个主要部分:端口定义、参数定义(可选)、 I/O 说明、内部信号声明、功能定义。
模块总是以关键词 module 开始,以关键词 endmodule 结尾。
模块名和端口定义:
第 1 至 5 行声明了模块的名字和输入输出口。其格式如下:
module 模块名(端口 1,端口 2,端口 3,……);
其中模块是以 module 开始,以 endmodule 结束。模块名是模块唯一的标识符,一般建议模块名尽量用能够描述其功能的名字来命名,并且模块名和文件名相同。
模块的端口表示的是模块的输入和输出口名,也是其与其他模块联系端口的标识。
参数定义
第 8 行参数定义是将常量用符号代替以增加代码可读性和可修改性。这是一个可选择的语句,用不到的情况下可以省略,类似C语言宏定义用法
接口定义
第 9 至 12 行是 I/O(输入/输出)说明,模块的端口可以是输入端口、输出端口或双向端口。其 说明格式如下。
输入端口: input [信号位宽-1 : 0] 端口名 1;
input [信号位宽-1 : 0] 端口名 2;
……;
输出端口: output [信号位宽-1 : 0] 端口名 1;
output [信号位宽-1 : 0] 端口名 2;
……;
双向端口:inout [信号位宽-1 : 0] 端口名 1;
inout [信号位宽-1 : 0] 端口名 2;
……;
信号类型
第 14 至 17 行定义了信号的类型。这些信号是在模块内使用到的信号,并且与端口有关的 wire和 reg 类型变量。其声明方式如下:
reg [width-1 : 0] R 变量 1, R 变量 2 ……;寄存器类型
wire [width-1 : 0] W 变量 1,W 变量 2……;线类型
如果没有定义信号类型,默认是 wire 型,并且信号位宽为 1。
功能描述
第 21 至 31 行是功能描述部分。模块中最重要的部分是逻辑功能定义部分,有三种方法可在模块中产生逻辑。
- 用“assign”声明语句,如描述一个两输入与门:assign a = b & c。详细功能见“功能描述-组合逻辑”一节。
- 用“always”块。即前面介绍的时序逻辑和组合逻辑。
- 模块例化。详细功能见“模块例化”一节
模块例化
对数字系统的设计一般采用的是自顶向下的设计方式,可将系统划分成几个功能模块,每个功能模块再划分成下一层的子模块。每个模块的设计对应一个 module ,每个 module 设计成一个 Verilog HDL 程序文件。因此,对一个系统的顶层模块采用结构化设计,即顶层模块分别调用了各个功能模块。
一个模块能够在另外一个模块中被引用,这样就建立了描述的层次。模块实例化语句形式如下:
module_nameinstance_name(port_associations) ;
信号端口可以通过位置或名称关联,但是关联方式不能够混合使用。端口关联形式如下:
port_expr / /通过位置。
.PortName (port_expr) / /通过名称
module and (C,A,B);
input A,B;
output C;
//省略
endmodule
//在下面的“and_2”块中对上一模块“and”进行例化,可以有两种方式:
module and_2(xxxxx)
...
//方式一:实例化时采用位置关联,T3 对应输出端口 C,A 对应 A,B 对应 B。
and A1