module aoi(a,b,c,d,f);/*模块名为aoi,端口列表a、b、c、d、f*/
input a,b,c,d;/*模块的输入端口为a,b,c,d*/
output f;;/*模块的输出端口为f*/
wire a,b,c,d,f;/*定义信号的数据类型*/
assign f=~((a&b)|(~(c&d)));/*逻辑功能描述*/
endmodule
- veirlog hdl 程序是由模块构成的。每个模块的内容都嵌在module和endmodule两个关键字之内,每个模块实现特定的功能。
- 每个模块首先要进行端口定义,并说明输入口和输出口(input 、output或inout),然后对模块
- Verilog HDL程序书写格式自由,一行可以写几个语句,一个语句也可以分多行写
- 除了endmodule等少数语句外,每个语句的最后必须有分号。
- 每个Verilog HDL程序包括4个主要部分:模块声明、端口定义、信号类型声明和逻辑功能定义。
module <模块名称> (<输入输出两边>);
input 输入端口列表;
output 输出端口列表;
/*定义数据、信号的类型、函数声明,用关键字wire、reg、task和function等*/
wire 信号名;
reg 信号名;
//逻辑功能定义
assign <结果信号名>=<表达式>;
//用always块模式逻辑功能
always @(<敏感信号表达式>)begin//过程赋值//if-else、case语句;for循环语句//task、function调用end
//调用其他模块
<调用模块名><例化模块名>(<端口列表>)
//门元件例化
门元件关键字 <例化元件名>(<端口列表>)
endmodule
1.模块声明
模块声明包括模块名称、模块输入、输出端口列表。模块定义格式如下:
module 模块名称(端口1,端口2,端口3,...);
模块结束的标志为关键字endmodule。
2.端口定义
对模块的输入、输出端口要明确说明,其格式为:
input 端口名1,端口名2,...,端口名n;//输入端口
output 端口名1,端口名2,...,端口名n;//输除端口
inout 端口名1,端口名2,...,端口名n;//输入/输出端口
定义端口时应注意:
- 每个端口出来要声明是输入、输出还是双向端口外,还要声明其数据类型,是wire型、reg型,还是其他类型。
- 输入和双向端口不能声明为reg型。
- 在测试模块中不需要定义端口。
3.信号类型声明
对模块中所有用到的信号都必须进行信号类型的定义。如果信号的数据类型没有定义,则默认为wire型。
reg cout;
可将端口定义和信号类型声明仿真一条语句中完成。
output reg cout;
还可以将端口定义和信号类型声明仿真模块列表中,而不是放在模块内部。
module aoi(input a,b,c,d,output f);
assign f=~((a&b)|(~(c&d)));
endmodule
4.逻辑功能定义
模块中最核心的部分就是逻辑功能定义。有多种方法可以在模块中描述和定义逻辑功能,还可以调用函数(function)和任务(task)来描述逻辑功能,几种基本方法为:
1.用assign 持续赋值语句定义,进行描述数据流
用数据流描述方式对一个设计建模的最基本的机制就是使用连续赋值语句。在连续赋值语句中,某个值被指派给线网变量。 连续赋值语句的语法为 :
assign [delay] LHS_net = RHS_ expression;
2.用always过程定义,进行描述行为
always过程语句既可以用来描述组合电路,也可以用来描述时序电路。
此语句总是循环执行 , 或者说此语句重复执行
只有寄存器类型数据能够在这两种语句中被赋值。寄存器类型数据在被赋新值前保持原
有值不变。所有的初始化语句和 always语句在0时刻并发执行。
3.用initial过程定义,进行描述行为
此语句只执行一次。
4.调用元件(元件例化),进行描述结构
- 可以调用Verilog HDL内置门元件(门级结构描述)
- 可以调用开关级元件(开关级结构描述)
- 在多层次结构电路设计中,高层次可以调用低层次模块
5.混合描述
在模块中,结构的和行为的结构可以自由混合。也就是说,模块描述中可以包含实例化的门、模块实例化语句、连续赋值语句以及 a l w a y s语句和 i n i t i a l语句的混合。它们之间可以相互包含。来自 a l w a y s语句和 i n i t i a l语句(切记只有寄存器类型数据可以在这两种语句中赋值)的值能够驱动门或开关,而来自于门或连续赋值语句(只能驱动线网)的值能够反过来用于触发always语句和initial语句。