概述
FPGA开发语言-Verilog HDL
1、简介
Verilog Baidu Baike
既是一种行为描述语言也是一种结构描述语言,可以用来进行数字电路的仿真验证、时序分析、逻辑综合。
Verilog HDL模型可以是实际电路的不同级别抽象,抽象级别可分为五级:
- 系统级(system level) :用高级语言结构实现的设计模块外部性能的模型
- 算法级(algorithmic) :用高级语言结构实现的设计算法模型
- RTL级(register transfer level):描述数据在寄存器之间流动和如何处理这些数据的模型
- 门级(gate level) :描述逻辑门以及逻辑门之间连接的模型
- 开关级(switch):描述器件中三极管和储存节点及其之间连接的模型
Verilog的基本设计单元是“模块(block)”,每个模块嵌套在module和endmodule声明语句中。模块是可以进行层次嵌套的。
module block1(a,b,c,d);
input a,b,c;
output d;
wire x;
assign d = a|x;
assign x = ( b & ~c );
endmodule
主要包括了四部分:
- 端口定义
- I/O说明
- 信号类型声明
- 功能描述
除了endmodule语句、begin_end语句、fork_join语句外,每个语句和数据定义的最后必须有分号。
对程序做注释与C语言方法相同,注释可以增强程序的可读性和维护性。
*在Verilog模块中有三种方法可以描述电路的逻辑功能:
(1)使用assign语句
assign x = ( b & ~c )
assign语句:无论右边表达式操作数何时发生变化,右边表达式都会重新计算,并且在指定的延迟后给左边的表达式赋值。
(2)使用元件例化(instantiate)
and myand3(f,a,b,c)
(3)使用“always”块语句
always @(posedge clk)
begin
if(load)
out = data;
else
out = data + 1 + cin;
end
//"always"常用于描述时序逻辑,也可描述组合逻辑
//"always"块语句与assign语句是并发执行的,assign语句一定要放在“always”块语句之外
在Verilog模块中所有过程块、连续赋值语句、实例引用都是并行的,模块内部的语句是顺序执行的。
- Verlog HDL程序是由模块构成的,每个模块实现特定的功能。
- 模块是可以进行层次嵌套的。
- 模块可以分为两种类型:一种是为了让模块最终能生成电路的结构,另一种只是为了测试所涉及的电路的逻辑结构是否正确。
- 每个模块要进行端口定义,并说明输入、输出口,然后对模块的功能进行描述。
- 除了endmodule语句外,每个语句和数据定义的最后都必须有分号。
2、Verilog数据类型
数据类型有19种,常用的3种:寄存器数据类型、线网数据类型、参数数据类型
(1)nets型变量
输出始终随输入的变化而变化的变量,表示结构实体(如门)之间的物理连接。(nets型变量不能储存值)
常用nets型变量:
- wire,tri 连线类型
- wor,trior 具有线或特性的连线
- wand,triand
- tri1,tri0 上拉电阻和下拉电阻
- supply1,supply0 电源和地
wire型变量是最常用的,常用来表示assign语句赋值的组合逻辑信号,模块中的输入/输出信号类型缺省为wire型。
(2)register型变量
对应具有状态保持作用的电路元件(如触发器、寄存器等),常用来表示过程块语句(如initial,always,task,function)内的指定信号。
常用的register型变量:
- reg 常表示触发器
- integer 32位带符号整数型变量
- real 64位带符号实数型变量
- time 无符号时间变量
register型变量与nets型变量的根本区别是: register型变量需要被明确地赋值,并且在被重新赋值前一直保持 原值。
register型变量必须通过过程赋值语句赋值!不能通过assign语句赋值!
在过程块内被赋值的每个信号必须定义成register型!(reg型变量可以储存)
3、简单的Verilog HDL例子
8位全加器:
//8位全加器
module adder8)cout,sum,a,b,cin);
output cout;//输出端口声明
output [7:0] sum;
input [7:0] a,b;//输入端口声明
input cin;
assign {cout,sum}=a+b+cin;//功能描述
endmodule
//整个程序嵌套在module和endmodule声明语句中
8位计数器:
module counter8(out,cout,data,load,cin,clk);
output [7:0] out;
output cout;
input [7:0] data;
input load,cin,clk;
reg [7:0] out;
always @(posedge clk)
begin
if(load)
out<=data;//同步预置数据
else
out<=out+1+cin;
end
assign cout = &out & cin;//若out为8'hFF,cin为1,则cout为1
endmodule
2位比较器:
module compare2(equal,a,b);
output equal;
input [1:0] a,b;
assign equal = (a==b) ? 1 : 0;
endmodule
- "<="非阻塞过程性赋值:将想要赋给左式的值安排在未来时刻。不等上一个赋值完成执行下个赋值语句。
- “=”阻塞赋值:按照顺序进行,前一个赋值结束才执行下边的赋值语句。
三态驱动器:
module trist2(out,in,enable);
output out;
input in,enable;
bufifl mybuf(out,in,enable);//门元件关键字-例化元件名
endmodule
//门元件例化---程序通过调用一个在Verilog语言库中现存的实例门元件来实现某逻辑门功能
- 任何用Verilog HDL语言描述的都通过其名字来识别,这个名字被称为标识符:可由字母、数字、下划线和$符号构成;
- 但第一个字符必须是字母或下划线,不能是数字或$符号。
循环语句
- for语句
- repeat语句
- while语句
- forever语句
//用for语句描述的7人投票表决器
//超过四人-赞成-》表决通过
module vote7(pass,vote);
output pass;
input[6:0] vote;
reg[2:0] sum;
integer i;
reg pass;
always @(vote)
begin
sum=0;
for(i=0;i<=6;i=i+1)
if(vote[i])
sum=sum+1;
if(sum[2])
pass=1;
else
pass=0;
end
endmodule
结构说明语句
- initial-只执行一次
- always-不断重复执行,直到仿真结束
- task-可在程序模块中的一处或多处调用
- function-同task
//如果always块中包含一个以上的语句,则这些语句必须放在begin_end或fork_join块中
//always语句必须与一定的时序控制结合在一起才有用,如果没有时序控制,易形成仿真死锁
//时间控制可以为沿触发,也可以为电平触发
//关键字posedge表示上升沿,negedge表示下降沿
always@(posedge clk or negedge clear)
begin
if(!clear) qout=0;
else
qout=1;
end
task和function语句分别用来由用户定义任务和函数,任务和函数往往是大的程序模块中在不同地点多次用到的相同的程序段,利用任务和函数可将一个很大的程序模块分解为许多较小的任务和函数,便于理解和调试,输入、输出和总线信号的值可以传入、传出任务和函数。
函数的使用规范:
- 函数的定义不能包含任何时间控制语句------用延迟#、事件控制@或等待wait标识的语句
- 函数不能启动任务
- 定义函数时至少要有一个输入参量且不能有任何输出或输入/输出双向变量
- 在函数的定义中必须有一条赋值语句,给函数中的一个内部寄存器赋以函数的结果值,该内部寄存器与函数同名
最后
以上就是顺利凉面为你收集整理的SECE_01_FPGA设计开发基础_Verilog HDL基础FPGA开发语言-Verilog HDL的全部内容,希望文章能够帮你解决SECE_01_FPGA设计开发基础_Verilog HDL基础FPGA开发语言-Verilog HDL所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复