逻辑功能定义
方法
有以下3种方法可在模块中产生逻辑。
(1)assign(连续赋值)声明语句。描述组合逻辑最常用的方法之一
(2)实例元件
(3)“always”块。既可用于描述组合逻辑,也可描述时序逻辑
要点
(1)在Verilog模块中所有过程块(如initial块、always块)、连续赋值语句、实例引用语句都是并行的;
(2)在同一模块中这三者出现的先后秩序没有关系;
(3)只有连续赋值语句assign和实例引用语句可以独立于过程块而存在于模块的功能定义部分。
运算符
基本算术运算符
+、-、x、/、
%(模运算符,或称为求余运算符,要求%两侧均为整型数据。如7%3的值为1。结果值的符号位采用模运算式里第一个操作数的符号位。-10%3=-1,11%-3=2)
位运算符
~、&、|(或)、^(异或)
逻辑运算符
- &&逻辑与;
- ||逻辑或;
- !逻辑非
移位运算符
1.“ <<”(左移运算符)
2.“ >>”(右移运算符)
位拼接运算符
{信号1的某几位,信号2的某几位,……,……}
数据类型及其常量和变量
常量
- 负数:-8‘d5
- 下划线:可以用来分隔开数的表达以提高程序可读性。16’b1010_1011_1111_1010
- 当常量不说明位数时,默认值是32位,每个字母用8位的ASCII值表示。例如:
10=32’d10=32’b1010
1=32’d1=32’b1
-1=-32’d1=32’hFFFFFFFF
`BX=32’BX=32’BXXXXX……X
“AB”=16’B01000001_01000010 //字符串AB,为十六进制数16’h4142
参数
parameter average_delay=(r+f)/2; //用常数表达式赋值
参数型常数经常用于定义延迟时间和变量宽度。在模块或实例引用时,可通过参数传递改变在被引用模块或实例中已经定义的参数。
【例】模块Decode定义时用了两个参数类型变量:Width和Polarity,且都为1。在Top模块中引用Decode实例时,可改变参数值。实例D1实际引用的参数Width和Polarity分别为4和0时的Decode模块。
module Decode(A,F);
parameter Width=1,Polarity=1;
·
·
·
endmodule
module Top;
wire[3:0]A4;
wire[4:0]A5;
wire[15:0]F16;
wire[31:0]F32;
Decode #(4,0) D1(A4,F16);
Decode #(5) D2(A5,F32);
endmodule
【例】多层次模块构成的电路。在一个模块中改变另一个模块的参数时,需要使用defparam命令。在做布线后仿真时,就是利用这种方法把布线延迟通过布线工具生成的延迟参数文件反标注(back-annotate)到门级Verilog网表上。
`include "Top.v"
`include "Block.v"
`include "Annotate.v"
module Test;
wire W;
Top T();
endmodule
module Top;
wire W;
Block B1();
Block B2();
endmodule
module Block;
Parameter P=0;
endmodule
module Annotate;
defparam
Test.T.B1.P=2,
Test.T.B2.P=3;
endmodule // 原来在模块Block中定义的P=0,在实例B1和B2中分别被P=2和P=3替代
变量
1.wire型
常用来表示用以assign关键字指定的组合逻辑信号。Verilog程序模块中输入、输出信号类型默认为wire型。
2.reg型
常用来表示“always”模块内的指定信号。在“always”模块内被赋值的每一个信号都必须定义成reg型。
reg型数据可以赋正值也可以赋负值。但当一个reg型数据是一个表达式中的操作数时,它的值被当作是无符号值,即正值。 例如,当一个4位的寄存器用做表达式中的操作数时,如果开始寄存器被赋以值-1,则在表达式中进行运算时,其值被认为是+15。
3.memory型
当需要描述RAM型存储器、ROM存储器和reg文件时,可以采用如下格式:
reg[n-1:0] 存储器名[m-1:0];
或 reg[n-1:0] 存储器名[m:1];
reg[n-1:0]定义存储器的一个存储单元字长;[m-1:0]则定义有多少个存储单元。
注意reg型和memory型的区别
1.
reg[n-1:0] rega; //一个n位寄存器
reg mema[n-1:0]; //一个由n个1位寄存器构成的存储器组
rega=0; //合法赋值语句
mema=0; //非法赋值语句
一个n位的寄存器可以在一条赋值语句里进行赋值,而一个完整的存储器则不行。如果想对memory中的存储单元进行读写操作,必须指定该单元在存储器中的地址。如
mema[3]=0; //给memory中的第三个存储单元赋值为0