1.5.3 Verilog HDL的程序结构
Verilog HDL的基本设计单元是模块,一个模块由两部分组成,一部分用于描述端口,另一部分用于描述逻辑功能,即定义输入是如何影响输出的。下面是一段完整的Verilog HDL程序代码。
module block (a,b,c,d) input a,b; output c,d; assign c= a | b; assign d= a & b; endmodule
在上面的例子中,模块block的第2行和第3行说明了端口的信号流向,第4行和第5行说明了模块的逻辑功能。以上就是设计一个简单的Verilog HDL程序所需的全部内容。从这个例子可以看出,Verilog HDL的程序结构完全嵌在module和endmodule之间,每个Verilog HDL程序包括四个主要部分:端口定义、I/O说明、内部信号声明和逻辑功能定义。
(1)端口定义。模块的端口声明了模块的输入/输出端口,其格式如下:
module 模块名(端口1,端口2…)
(2)模块内容。模块的内容包括I/O说明、内部信号声明和逻辑功能定义。I/O说明的格式为:
输入端口:input 端口名1,端口名2,…,端口名i; //共有i个端口 输出端口:output 端口名1,端口名2,…,端口名j; //共有j个端口
I/O说明也可以写在端口声明语句里,其格式如下:
module 模块名(input 端口1,input 端口2,…,output 端口1,input 端口2…);
内部信号说明是指在模块内用到的与端口有关的wire和reg变量的声明,例如:
reg [width-1: 0] R变量1,R变量2…; wire [width-1: 0] W变量1,W变量2…;
模块中最重要的部分是逻辑功能定义部分。有三种方法可以在模块中实现逻辑功能定义:采用assign声明语句、采用实例元件和采用always块。下面分别是采用三种方法实现逻辑功能定义的例子。
//采用assign声明语句 assign a = b & c; //采用实例元件 and and_inst(q, a, b); //采用always块 always @(posedge clk or posedge clr) begin if (clr) q <= 0; elseif (en) q <= d; end
需要注意的是,如果用Verilog HDL模块实现一定的功能,首先应该清楚哪些是同时发生的,哪些是顺序发生的。上面三个例子分别采用了assign声明语句、实例元件和always块,这三个例子描述的逻辑功能是同时执行的。也就是说,如果把这三个例子写到一个Verilog HDL模块文件中,它们的次序不会影响逻辑实现的功能。这三个例子是同时执行的,也就是并发的。
然而,在always块中,逻辑是按照指定的顺序执行的。always块中的语句称为顺序语句,因为它们是顺序执行的。请注意,两个或多个always块也是同时执行的,但是always块内部的语句是顺序执行的。看一下always块内的语句,就会明白它是如何实现功能的。if…else…if必须顺序执行,否则其功能就没有任何意义。如果else语句在if语句之前执行,功能就不符合要求。为了能实现上述描述的功能,always块中的语句将按照书写的顺序执行。