module <模块名> (<端口列表>)
<内部信号声明>
<功能定义>
endmodule
module 模块名(口 1,口 2,口 3,口 4, ...);
(1)在引用时,严格按照模块定义的端口顺序来连接,不用标明原模块定义时规定的端口名。
(2)在引用时用"."符号,标明原模块是定义时规定的端口名。于可以用端口名与被引用模块的端口相对应,而不必严格按端口顺序对应,提高了程序的可读性和可移植性。
MyDesignMK M1(.sin(SerialIn), .pout(ParallelOut), ...);
.sin 和.pout 都是M1的端口名,而M1则是MyDesignMK完全一样的模块,MyDesignMK已经在另一个模块中定义过,它有两个端口,即.sin和.pout。与sin端口连接的信号名为SerialIn, 与pout 端口连接的是信号名为ParallelOut。
1.I/O说明格式
input [2,0]a; //表示声明一个3bit的输入变量,命名为a
//3bit是2-0+1,例如[a,b]长度即为a-b+1
input cin; //表示声明一个1bit的输入变量,命名为cin
output count;
output [2,0]sum;
input[width-1:0] Inputi;//第i个输入口
output[width-1:0] Outputj;//第j个输出口
inout[width-1;0] Inoutk;//第k个双向总线端口
//width为信号位宽
也可以写在端口声明语句中:
module module_name(input port1, input port2, ...
output port1, output port2...);
2.内部信号说明
在模块内用到的和与端口有关的wire,reg类型变量的声明:
reg [width-1:0] r1, r2...;
wire [width-1:0] w1, w2...;
3.功能定义
模块中最重要的部分。
(1)用assign声明语句
assign a = b & c;
(2)实例元件
and # 2 u1( q, a, b);//用到一个叫u1的与门,输入a,b,输出q
//2为输出延迟单位时间数
每个实例元件的名字(u1)必须是唯一的,以避免与其他调用与门 (and) 的实例混淆
(3)always块
always @(posedge clk or posedge clr);
begin
if(clr) q <= 0;
else if(en) q <= d;
end
always块内部语句顺序执行,因此又被称为“过程块”。
以上3种功能定义之间是并行的。
1.数字
(1)整数
进制有二、十、十六、八进制。默认位宽(2进制下的位数)由机器决定(至少32位),默认进制为十进制。
8'b10101100 //位宽为8,'b表示2进制
8'ha2 //位宽为8,16进制
(2)x和z值
x代表不定值,z(又写作?)代表高阻值。
4’b10x0 位宽4的二进制数右起第二位为不定值
4'b101z 位宽4的二进制数最低位为高阻值
12'dz、12'd? 位宽12的十进制数,值为高阻值
8h'4x 位宽8的十六进制数,低4位为不定值
(3)负数
在位宽表达式前加一个减号。减号必须在数字定义表达式最前面。
(4)下划线
分隔数的表达,提高程序可读性。不可在位宽和进制处。
16b'1010_1011_1111_1010 合法
8'b_0011_1010 非法
2.参数型
符号常量,用标识符代表常量,提高程序可读性和可维护性。
parameter msb = 7;
parameter e = 25, f = 29;
parameter r = 5.7;
parameter byte_size = 8, byte_msb = byte_size - 1;
parameter average_delay = (r + f) / 2;
常用于定义延迟时间和变量宽度。
1.wire型
常用来表示用以assign关键字指定的组合逻辑信号,是verilog程序模块输入、输出信号的默认类型。
wire a; //一个1位
wire [7:0] b; //一个8位
wire [4:1] c, d; //两个4位
2.reg型
默认初始值为不定值x。常用来表示always模块内的指定信号,always模块中被赋值的每一个信号都必须定义为reg型。
reg rega;
reg [3:0] regb;
reg [4:1] regc, regd;
reg型数据可赋值为正或负,但作为表达式中的操作数时被当作无符号数。例如,一个4位寄存器被赋值-1,则在表达式中视作+15。
3.memory型
通过对reg型变量建立数组来对存储器建模,每一个单元通过一个数组索引进行寻址。通过扩展reg地址范围生成memory型数据。Verilog中没有多维数组。
reg [n-1:0] MemName1[m-1:0];
reg [n-1:0] MemName1[m:1];
//每个存储单元n位,存储器中有m个存储单元
对存储器进行地址索引的表达式必须是常数表达式。
同一个数据类型声明语句里可同时定义memory和reg型数据:
parameter wordsize = 16,
memsize = 256;
reg [wordsize-1:0] mem[memsize-1:0], writereg, readreg;
加、减、乘、除、模。
整数除法结果只保留整数部分。取模运算结果符号位与运算式中第一个操作数符号位相同,如-10%3=-1,11%-3=2。当操作数中有不定值x,整个结果也为不定值。
取反( ~ ),( ! ),与( & ),或( | ),异或( ^ ),同或( ^~ )。
其中“!”表示逻辑取反,“~”表示按位取反
当面对位宽为1时:两个操作符的作用相同。
当位宽不为1时:
“~”会将变量的各个位依次取反如:a[3:0] ={1,0,0,1} , ~a ={0,1,1,0};
“!”会将变量作为一个值去做处理,非0为1:a[3:0] ={1,0,0,1} ,a=5,!a=0。a[3:0] ={0,0,0,0} ,a=0,!a=1
不同长度数据进行位运算会先右端对齐,再在位数少的操作数左侧补0填充高位
(1)所有过程块、连续赋值语句、实例引用并行,它们表示一种通过变量名相互连接的关系。
(2)同一模块中它们的次序没有关系。
(3)只有连续赋值语句(assign语句)和实例引用语句可独立于过程块存在于模块功能定义。
(4)被实例引用的模块,其端口可以通过不同名的连线或寄存器类型变量连接到别的模块相应的输出、输入信号端。
(5)"always"模块内被赋值的信号必须为reg型。
许多与C语言类似的语句只能出现在过程块中。