电子说
Verilog语法的基本概念
一、Verilog HDL
Verilog HDL是一种用于数字系统设计的语言。用Verilog HDL描述的电路设计就是该电路的Verilog HDL模型也称为模块。Verilog HDL既是一种行为描述的语言也是一种结构描述的语言。这也就是说,无论描述电路功能行为的模块或描述元器件或较大部件互连的模块都可以用Verilog语言来建立电路模型。如果按照一定的规矩编写,功能行为模块可以通过工具自动地转换为门级互连模块。Verilog模型可以是实际电路的不同级别的抽象。这些抽象的级别和它们对应的模型类型共有以下五种:
1.1 系统级(system): 用语言提供的高级结构实现设计模块外部性能的模型。
1.2 算法级(algorithm): 用语言提供的高级结构实现算法运行的模型。
1.3 RTL级(Register Transfer Level):描述数据在寄存器之间流动和如何处理和控制这些数据流动的模型。
1.4 门级(gate-level):描述逻辑门以及逻辑门之间的连接的模型。
1.5 开关级(switch-level):描述器件中三极管和储存节点以及它们之间连接的模型。
二、Verilog HDL模块
一个复杂电路系统的完整Verilog HDL模型是由若干个Verilog HDL模块构成的,每一个模块又可以由若干个子模块构成。其中有些模块需要综合成具体电路,而有些模块只是与用户所设计的模块有交互联系的现存电路或激励信号源。利用Verilog HDL语言结构所提供的这种功能就可以构造一个模块间的清晰层次结构来描述极其复杂的大型设计,并对所作设计的逻辑电路进行严格的验证。
Verilog HDL行为描述语言作为一种结构化和过程性的语言,其语法结构非常适合于算法级和RTL级的模型设计。这种行为描述语言具有以下功能:
(1) 可描述顺序执行或并行执行的程序结构。
(2) 用延迟表达式或事件表达式来明确地控制过程的启动时间。
(3) 通过命名的事件来触发其它过程里的激活行为或停止行为。
(4) 提供了条件、if-else、case、循环程序结构。
(5) 提供了可带参数且非零延续时间的任务(task)程序结构。
(6) 提供了可定义新的操作符的函数结构(function)。
(7) 提供了用于建立表达式的算术运算符、逻辑运算符、位运算符。
Verilog HDL作为一种高级的硬件描述编程语言,与C语言的风格有许多类似之处。其中有许多语句如:if语句、case语句等和C语言中的对应语句十分相似。如果读者已经掌握C语言编程的基础,那么学习Verilog HDL并不困难。我们只要对Verilog HDL某些语句的特殊方面着重理解,并加强上机练习就能很好地掌握它,就能利用它的强大功能来设计复杂的数字逻辑电路系统。
2.1 简单的Verilog HDL模块
2.1.1 Verilog 语法简介
下面先介绍一个个简单的Verilog HDL程序,从中了解Verilog模块的特性。
module test_project_top( //模块名
input clk, // 时钟输入
input resetn, // 复位
input[7:0] a, //信号输入,信号a 位宽为8 bit
input[7:0] b, //信号输入,信号b 位宽为8 bit
input en, // 信号是能输入 信号en 位宽为1 bit
output reg [8:0] c, // 寄存器类型定义,信号输出 c为9bit
output reg [15:0] d // 寄存器类型定义,信号输出 d 为16bit
);
/ ........ / //.........表示注释部分,注释只是为了方便程序员理解程序,对编译是不起作用的。
/*一个 .v文件中主要由 一个或多个 module ... endmodule块组成
每个module块内包括:模块名,输入端口,输出端口,以及多个时序电路,组合电路等组成
*/
// 简单的时序电路组成
always@(posedge clk or negedge resetn)
begin
if(~resetn) // 或者 if(!resetn) 取 resetn 反
begin
d<=16'h0;
end
else
begin
if(en) // if en ==1 那么 d等于a*b+a/b;否则d<=0
d<=ab+a/b; // + , - , ,/ 加减乘除
else
d<=0;
end
end
// 简单的组合电路
always@(a or b) // 只要其中a或b一个变化就执行always块内语句
begin
if(en) // verilog 语法 if ... else ...,在组合电路中一个if对应一个else,不能缺else,防止产生锁存器
c<=a*b+a/b;
else
c<=0;
end
wire[8:0] sum; // 常见变量定义类型:wire-线网型,reg-寄存器
assign sum =a+b; // 组合电路赋值,关键字 assign
wire[15:0] multy;
assign multy = (en ) ? ab :0;// 如果 en ==1,那么 multy =ab,否则multy =0;
wire e;
assign e =&a; // & 按位与
wire f;
assign f =|b;// | 按位或
wire [8:0] c_sum;
// 实例化模块
my_add u_add_top( // my_add 模块名 ,u_add_top 实例化名
.clk(clk), //端口连接输入
.resetn(resetn),//端口连接输入
.a(a),//端口连接输入
.b(b),//端口连接输入
.c(c_sum)//端口连接输出
);
endmodule
这个小程序表述了一个.v文件包含了常用的verilog语法,变量的定义类型包括:wire,reg等,常见的运算符号跟C语言中相同,理解较容易。在这个例子中存在着两个模块。模块test_project_top引用由模块my_add定义的实例部件u_add_top。模块test_project_top是顶层模块。模块my_add则被称为子模块。在实例部件u_add_top中,带 “.”的表示被引用模块的端口,名称必须与被引用模块my_add的端口定义一致,小括号中表示在本模块中与之连接的线路。
2.1.2 Verilog用于模块的测试
Verilog 还可以用来描述变化的测试信号。描述测试信号的变化和测试过程的模块也叫做测试平台(Testbench 或Testfixture),它可以对上面介绍的电路模块(无论是行为的或结构的)进行动态的全面测试。通过观测被测试模块的输出信号是否符合要求,可以调试和验证逻辑系统的设计和结构正确与否,发现问题及时修改。
下面我们来看一个Verilog的测试模块,
// 测试激励产生
`timescale 1ns / 1ps
module test_project_top_tb; // 测试文件模块名
// 信号测试激励,输入变量声明
reg clk ;
reg reset;
reg [7:0] a;
reg [7:0] b;
reg en;
// 输出变量声明
wire[8:0] c;
wire [15:0] d;
// 信号变量初始化 ,关键字 initial
initial
begin
clk =0;
reset =0;
a =0;
b =0;
en =0;
#1000; // 在1000 ns后 reset拉高
reset =1;
end
// 时钟生成
always #5 clk =~clk; //时钟周期 10ns ,每隔5ns 取反一次
always @(posedge clk)
begin // {$random} 为系统任务,它会产生一个随机数
#1 a= {$random}%256; // 产生随机的位信号流a和b ,%256为做模256运算
#3 b = {$random}%256; // 分别延迟1和3个时间单位后产生随机的位信号流a 和b
end
always #10000 en = !en; //产生周期为10000个单位时间的选通信号变化
// 实例化 被测试模块
test_project_top u_top(
.clk(clk), // 时钟输入
.resetn(reset), // 复位
.a(a), //信号输入,信号a 位宽为8 bit
.b(b), //信号输入,信号b 位宽为8 bit
.en(en), // 信号是能输入 信号en 位宽为1 bit
.c(c), // 寄存器类型定义,信号输出 c为9bit
.d(d) // 寄存器类型定义,信号输出 d 为16bit
);
endmodule
本测试例程是对2.1.1中的小程序的测试,属于RTL级功能仿真,主要调试语法及时序信号是否跟设计时一致。对于初学者来说,这是最基本的技能,必须熟练掌握。
图1 仿真时序图
2.1.3 总结:
通过上面这些的例子可以看到以下几点:
(1) Verilog HDL程序是由模块构成的。每个模块的内容都是位于module和endmodule两个语句之间,每个模块实现特定的功能。
(2) 模块是可以进行层次嵌套的。正因为如此,才可以将大型的数字电路设计分割成不同的小模块来实现特定的功能。
(3) 每个模块都是可以综合的,通过综合工具可以把它们的功能描述全都转换为最基本的逻辑单元描述,最后可以用一个上层模块通过实例引用把这些模块连接起来,把它们整合成一个很大的逻辑系统。
(4) Verilog 模块可以分为两种类型:一种是为了让模块最终能生成电路结构,另一种只是为了测试所设计的电路其逻辑功能是否正确。
(5) 每个模块要进行端口定义,并说明输入输出口,然后对模块的功能进行 描述。
(6) Verilog HDL程序的书写格式自由,一行可以写几个语句,一个语句也可以分写多行。
(7) 除了endmodule语句外,每个语句和数据定义的最后必须有分号。
(8) 可以用/ ..... /和//.......对Verilog HDL程序的任何部分作注释。一个好的,有使用价值的源程序都应当加上必要的注释,以增强程序的可读性和可维护性。
全部0条评论
快来发表一下你的评论吧 !