Verilog HDL是一种用于数字逻辑电路规划的言语。用Verilog HDL描绘的电路规划便是该电路的Verilog HDL模型。Verilog HDL既是一种行为描绘的言语,也是一种结构描绘的言语。也便是说,既能够用电路的功用描绘,也能够用元器材和它们之间的衔接来树立所规划电路的Verilog HDL模型。Verilog模型可所以实践电路的不同等级的笼统。这些笼统的等级和它们对应的模型类型共有以下5种。
- 体系级(system):用高档言语结构完成规划模块的外部功用的模型。
- 算法级(algorithm):用高档言语结构完成规划算法的模型。
- RTL级(Register Transfer Level):描绘数据在寄存器之间活动和怎么处理这些数据的模型。
- 门级(gate-level):描绘逻辑门以及逻辑门之间的衔接的模型。
- 开关级(switch-level):描绘器材中三极管和贮存节点以及它们之间衔接的模型。
一个杂乱电路体系的完好Verilog HDL模型是由若干个Verilog HDL模块构成的,每一个模块又能够由若干个子模块构成。其间有些模块需求综组成详细电路,而有些模块仅仅与用户所规划的模块交互的现存电路或鼓励信号源。运用Verilog HDL言语结构所供给的这种功用就能够结构一个模块间的明晰层次结构来描绘极端杂乱的大型规划,并对所作规划的逻辑电路进行严厉的验证。
Verilog HDL行为描绘言语作为一种结构化和进程性的言语,其语法结构十分适合于算法级和RTL级的模型规划。这种行为描绘言语具有以下功用。
- 可描绘次第履行或并行履行的程序结构。
- 用推迟表达式或事情表达式来明确地操控进程的发动时刻。
- 经过命名的事情来触发其他进程里的激活行为或中止行为。
- 供给了条件、if-else、case、循环程序结构。
- 供给了可带参数且非零接连时刻的使命(task)程序结构。
- 供给了可界说新的操作符的函数结构(function)。
- 供给了用于树立表达式的算术运算符、逻辑运算符、位运算符。
- Verilog HDL言语作为一种结构化的言语也十分适合于门级和开关级的模型规划。因其结构化的特色又使它具有以下功用。
- 供给了完好的一套组合型原语(primitive);
- 供给了双向通路和电阻器材的原语;
- 可树立MOS器材的电荷共享和电荷衰减动态模型。
Verilog HDL的结构性句子能够准确地树立信号的模型。这是由于在Verilog HDL中,供给了推迟和输出强度的原语来树立准确程度很高的信号模型。信号值能够有不同的强度,能够经过设定宽规模的含糊值来下降不确定条件的影响。
Verilog HDL作为一种高档的硬件描绘编程言语,有着相似C言语的风格。其间if句子、case句子等和C言语中的对应句子十分相似。假如读者现已把握C言语编程的根底,那么学习Verilog HDL并不困难,只要对Verilog HDL某些句子的特别方面侧重了解,并加强上机操练就能很好地把握它,运用它的强壮功用来规划杂乱的数字逻辑电路。下面将介绍Verilog HDL中的根本结构和语法。
Verilog HDL程序入门
首要来看几个Verilog HDL程序,然后从中剖析Verilog HDL程序的特性。
例1:加法器。
module adder ( count,sum,a,b,cin ); //加法器模块端口声明
input [2:0] a,b; //端口阐明
input cin;
output count;
output [2:0] sum;
assign {count,sum} = a + b + cin; //加法器算法完成
endmodule
这个比如经过接连赋值句子描绘了一个名为adder的三位加法器能够依据两个三比特数a、b和进位(cin)计算出和(sum)和进位(count)。从比如中能够看出整个Verilog HDL程序是嵌套在module和endmodule声明句子里的。
例2:比较器。
module compare ( equal,a,b ); //比较器模块端口声明
output equal; //输出信号equal
input [1:0] a,b; //输入信号a、b
assign equal=(a==b)?1:0; //假如a、b 两个输入信号持平,输出为1,不然为0
endmodule
这个程序经过接连赋值句子描绘了一个名为compare的比较器。对两比特数a、b进行比较,如a与b持平,则输出equal为高电平,不然为低电平。在这个程序中,“/*……..*/”和“//………”表明注释部分,注释仅仅为了便利程序员了解程序,对编译是不起作用的。
例3:运用原语的三态驱动器。
module trist2(out,in,enable); //三态发动器模块端口声明
output out; //端口阐明
input in, enable;
bufif1 mybuf(out,in,enable); //实例化宏模块bufif1
endmodule
这个比如描绘了一个名为trist2的三态驱动器。程序经过调用一个在Verilog言语库中现存的三态驱动器实例元件bufif1来完成其功用。
例4:自行规划的三态驱动器。
module trist1(out,in,enable); //三态发动器模块端口声明
output out; //端口阐明
input in, enable;
mytri tri_inst(out,in,enable);//实例化由mytri模块界说的实例元件tri_inst
endmodule
module mytri(out,in,enable); //三态发动器模块端口声明
output out; //端口阐明
input in, enable;
assign out = enable? in : bz; //三态发动器算法描绘
endmodule
这个比如经过另一种办法描绘了一个三态门。在这个比如中存在着两个模块。模块trist1调用由模块mytri界说的实例元件tri_inst。模块trist1是顶层模块。模块mytri则被称为子模块。
经过上面的比如能够看到。
- Verilog HDL程序是由模块构成的。每个模块的内容都是嵌在module和endmodule两个句子之间。每个模块完成特定的功用。模块是能够进行层次嵌套的。正由于如此,才能够将大型的数字电路规划分割成不同的小模块来完成特定的功用,最终经过顶层模块调用子模块来完成全体功用。
- 每个模块要进行端口界说,并阐明输入输出口,然后对模块的功用进行行为逻辑描绘。
- Verilog HDL程序的书写格局自在,一行能够写几个句子,一个句子也能够分写多行。
- 除了endmodule句子外,每个句子和数据界说的最终有必要有分号。
- 能够用“/*…..*/”和“//…….”对Verilog HDL程序的任何部分作注释。一个好的、有运用价值的源程序都应当加上必要的注释,以增强程序的可读性和可维护性。
模块的结构
模块的内容包含I/O声明、I/O阐明、内部信号声明和功用界说。
1.I/O声明
模块的端口声明晰模块的输入输出端口,其格局如下:
Module 模块名(端口1,端口2,端口3,端口4, …);
2.I/O阐明
I/O阐明的格局如下:
输进口:input 端口名1,端口名2,…,端口名i; //(共有i个输进口)
输出口:output 端口名1,端口名2,…,端口名j; //(共有j个输出口)
I/O阐明也能够写在端口声明句子里,其格局如下:
module module_name(input port1,input port2,…,output port1,output port2… )
3.内部信号声明
在模块内用到的和与端口有关的wire和reg变量的声明,如下所示:
reg [width-1 : 0] R变量1,R变量2 …;
wire [width-1 : 0] W变量1,W变量2 …;
4.功用界说
模块中最重要的部分是逻辑功用界说部分,有3种办法可在模块中产生逻辑。
(1)用“assign”声明句子。
assign a = b c;
这种办法的句法很简单,只需写一个“assign”,后边再加一个方程式即可。比如中的方程式描绘了一个有两个输入的与门。
(2)用实例元件。
and and_inst( q, a, b );
选用实例元件的办法在电路图输入办法下,调入库元件。键入元件的姓名和相连的引脚即可,表明在规划中用到一个跟与门(and)相同的名为and_inst的与门,其输入端为a、b,输出为q。要求每个实例元件的姓名有必要是专一的,以避免与其他调用与门(and)的实例混杂。
(3)用“always”块。
always @(posedge clk or posedge clr) begin //时钟上升沿触发,异步清零
if(clr) q = 0; //清零
else if(en) q = d; //使能赋值
end
选用“assign”句子是描绘组合逻辑最常用的办法之一,而“always”块既可用于描绘组合逻辑,也可描绘时序逻辑。上面的比如用“always”块生成了一个带有异步铲除端的D触发器。
“always”块可用很多种描绘手法来表达逻辑,例如上例中就用了“if…else”句子来表达逻辑关系。如按必定的风格来编写“always”块,能够经过归纳东西把源代码主动综组成用门级结构表明的组合或时序逻辑电路。需求留意的是,假如用Verilog模块完成必定的功用,首要应该清楚哪些是一起产生的,哪些是次第产生的。
上面3个比如别离选用了“assign”句子、实例元件和“always”块。这3个比如描绘的逻辑功用是一起履行的。也便是说,假如把这3项写到一个Verilog模块文件中去,它们的次第不会影响逻辑完成的功用。这3项是一起履行的,也便是并发的。
可是,在“always”模块内,逻辑是依照指定的次第履行的。“always”块中的句子称为“次第句子”,由于它们是次第履行的。请留意,两个或更多的“always”模块也是一起履行的,可是模块内部的句子是次第履行的。
看一下“always”内的句子,就会理解它是怎么完成功用的。“if…else… if”有必要次第履行,不然其功用就没有任何含义。假如else句子在if句子之前履行,功用就会不符合要求。为了能完成上述描绘的功用,“always”模块内部的句子将依照书写的次第履行。