I/O声明
输入声明
input[msb:lsb]端口1,端口2,端口3,……
输出声明
output[msb:lsb]端口1,端口2,端口3,……
输入输出声明
inout[msb:lsb]端口1,端口2,端口3,……
信号类型声明
常用的信号类型有连线性(wire)、寄存器型(reg)、整形(integer)、实型(real)、时间型(time)等
功能描述
1.用assign语句实现 eg.assgin a=b&c;
2.用实例元件实现 eg. and u1(q,a,b) 其中a,b为输入,q为输出
3.用always块实现带有异步清除端的D触发器
always @(posedge clk or posedge clr)
begin
if(clk)q<=0;
else q<=d;
end
用initial块实现,与always块语句类似,不过在程序中initial块语句只能被执行一次,一般用于电路的初始化
常量
整形常量
x:未知,z:高阻
6'B10X1Z0 //6位二进制数
92 //十进制数
'H67 //位宽为32位的十六进制数
5'O37 //5位八进制数
实行常量
7.56 ,34.56e2 6E-2
字符串常量
"hello!"
n换行符
t制表符Tab键
\符号
*符号*
ddd 三位八进制数表示的ASCII码
%%符号%
参数常量
parameter PI=3.14,A=8'B10110101,WORD_LENGTH=16;
变量
wire型
输入、输出信号在默认情况下自动定义为wire型
wire[msb:lsb]变量1,变量2,…,变量n
eg.wire[7:0]m,n;
reg型
reg[msb:lsb]变量1,变量2,…,变量n
eg.reg[7:0]m,n;
reg型变量和wire型变量的区别是:wire型变量需要持续地驱动,而reg型变量保持最后一次的赋值
memory型
memory型是存储器型,是通过建立reg型数组来描述的
eg.
reg[8:1]RAM[3:0];
RAM[0]=8'H1A;
RAM[1]=8'H00;
RAM[2]=8'H55;
RAM[3]=8'H31;
integer型
integer是32位带符号整形变量,用于对循环控制变量的说明,典型应用是高层次的行为建模,它与后面的time和real类型一样是不可综合的,也就是说这些类型是数学的抽象描述,不与任何物理电路相对应。
eg.integer d[1:8];//定义了一个含有8个数据的整形数组
time型
time类型用于储存和处理时间,是64位无符号数
time 变量1,变量2,…,变量n;
real型
real型是64位带符号实型变量,用于储存和处理实型数据
real 变量1,变量2,…,变量n;
运算符
算术运算符
+,-,*,/,%
逻辑运算符
&&,||,!
关系运算符
<,<=,>,>=
等值运算符
==逻辑相等,!=逻辑不等(可能为1,0,x),===全等(按位比较),!==非全等
位运算符
~,&,~&,|,~|,^(异或),~^(同或)
缩减运算符
~,&,~&,|,~|,^(异或),~^(同或)
缩减运算符与逻辑运算符的法则是一样的,但缩减运算符是对单一操作数按位进行逻辑递推运算的,运算结果为1位二进制数。
移位运算符
>>,<<
eg.
i=8;
m=3;
i<<m;//结果为64
i>>m;//结果为1
条件运算符
条件? 表达式1:表达式2
eg.
a=10,b=20;
y=a>b?a:b;
拼接运算符
X={a[7:4],b[3],c[2:0]};
运算符的优先级
赋值语句
连续赋值语句
连续赋值语句用来驱动wire型变量,这个变量必须事先定义过。
eg.
wire a,b,c;
assign c=a&b;
过程赋值语句
过程赋值语句是在initial或者always语句块内赋值的,它对reg型、memory型、integer型、time型、real型变量进行赋值,这些变量在下一次过程赋值之前保持原来的值。
阻塞型赋值
在该语句结束时就完成赋值操作
变量=赋值语句;
非阻塞型赋值
在块结束时才完成赋值操作
变量<=赋值语句;
条件语句
if else语句case语句
case(控制表达式)
分支表达式1:语句1;
分支表达式2:语句2;
分支表达式3:语句3;
…
分支表达式m:语句m;
default:语句n
endcase
循环语句
forever循环语句
forever循环语句常用语产生周期性的波形,与always不同的地方在于它不能独立写在程序中,必须写在initial块中,常用于产生仿真测试信号。
eg.
initial
begin
clock = 0;
# 5 forever
# 10 clock = ~ clock;
end
repeat循环语句
repeat循环语句是用于执行指定循环次数的过程语句,格式如下:
repeat(表达式)语句
eg.
initial
begin
s=0;
i=1;
repeat(100)
begin
s=s+i;
i=i+1
end
end
while循环语句
while循环执行过程中赋值语句直到指定的条件为假
for循环语句
结构声明语句
initial说明语句
initial语句常用于对各变量的初始化,一个程序模块中可以有多个initial语句,所有的initial语句在程序一开始同时执行,并且只执行一次。
always说明语句
always语句和initial语句一样可以有多个always语句,always语句也是在程序一开始的时候就被执行,不同的是always语句不断重复运行。但是always语句后跟的语句是否执行,要看其敏感事件列表是否满足,若有条件满足,则运行一次语句。电平触发的always块常用于说明组合逻辑的行为,而在边沿触发的always块常用于描述时序行为。
eg.
reg[7:0] count
always @(posedge clk)
begin
count=count+1b'1;
end
task说明语句
任务类似于高级语言中的子程序,用来单独完成某项任务,并被其他模块或者其他任务调用。
任务定义
task 任务名;
端口声明语句;
类型声明语句;
语句;
endtask
任务调用
任务名(端口名列表);
任务的定义和调用必须在同一个模块内
任务定义时,task语句后没有端口名列表,输入输出端口名是通过端口声明语句进行顺序声明的;一个任务也可以没有输入输出端口
当任务被调用时,任务被激活,如果一个任务有输入输出端口,调用时需列出端口名列表,其顺序和类型应该与任务定义中的完全一致
进行任务调用时参数的传递是按值传递的,不能按地址传递
一个任务可以调用别的任务或函数,可调用的任务和函数的个数不受限制
function说明语句
function语句用来定义函数,单独完成某项具体的 操作。
函数的定义
function <返回值得类型或范围> 函数名;
端口声明语句;
类型声明语句;
语句;
endfunction
函数的调用
函数名(端口名列表)
函数只能有一个返回值,而任务可以有多个或者没有返回值。
函数至少有一个输入变量
函数只能与主模块共用一个仿真时间,而任务可以定义自己的仿真时间单位
函数不能调用任务,而任务能调用其他函数或任务
编译预处理语句
宏定义('define和'undef)
eg.
'define BYTE 8
…
wire ['BYTE-1:0]bus;
…
'undef BYTE
文件包含('include)
eg.
'include "d:edas1.v"
时间尺度('timescale)
eg.
'timescal 10ns/100ps
…
always #1.55 clock=~clock;
条件编译('ifdef,'else,'endif)
eg.
'ifdef COMPUTER_SIZE-PC
parameter WORD_SIZE=16
'else
parameter WORD_SIZE=32
'endif
模块化设计
module count_dec(clk,clr,en,cout,q);
input clk,clr,en;
output [15:0]q;
output cout;
reg[15:0]q;
reg cout;
wire[3:0]q1,q2;
wire x;
count4 u1(clk,clr,en,x,q1);
count4 u2(clk,clr,x,cout,q2);
dec_seg7 u3(q1,q[7:0]);
dec_seg7 u4(q2,q[15:8]);
endmoudle