非门~ y=~x
与门& z=x&y
或门| z=x|y
与非门 z=~(x&y)
或非门 z=~(x|y)
异或门 z=(~x&y)|(x&~y)
同或门 z=(~x&~y)|(x&y)
Verilog模块声明
module<模块名>(<模块端口列表>)
…
<模块的内容>
…
…
endmodule
Verilog端口声明
端口是模块与外界环境交互的接口
端口的三种类型:
1)input:模块从外界读取数据的接口,在模块内不可写
2)output:模块往外界发送数据的接口,在模块内不可读
3)inout:可读取数据,也可以送出数据,数据可双向流动
下面以全加器为例:
module fullAdder(a, b, cin,sum,cout);
//端口声明的开始
input a,b,cin;
output sum,cout;
//端口声明的结束
wire a, b, cin;
wire sum , cout;
assign sum= (a^b)^c;
assign cout = cin&(a^b)|(a&b);
endmodule
端口默认是wire型,要保存数据则声明成reg型,
input类型端口不能声明为reg
端口连接规则:
1)位宽匹配
2)未连接端口
3)端口与外部信号的连接:顺序连接或者按名字连接,两种方法不能混用
4)顺序端口的连接:连接到模块实例的信号必须与模块声明时目标端口列表中的位置保持一致。下面以顶层模块调用全加器为例进行说明,其代码如下:
module Top;
reg A,B;
reg CIN;
wire SUM,COUT;
...
//实例化顺序连接
//信号按照端口列表中的次序连接,在本模块中把它命名为adder
fullAdder adder(A, B, CIN,SUM, COUT);
...
endmodule
module fullAdder(a, b, cin,sum,cout);
//端口声明的开始
input a, b, cin;
output sum,cout;
//端口声明的结束
wire a,b,cin;
wire sum , cout;
assign sum = (a^b)^cin;
assign cout = cin&(a^b)|(a&b);
endmodule
5)命名端口连接
代码示例如下:
//实例化顺序连接
//信号按照端口列表中的次序连接,在本模块中把它命名为adder
fullAdder adder( .sum(SUM),.cout(COUT),.a(A),.b(B),.cin(CIN),);
Verilog数据类型
1)wire型
wire型信号可以用作方程式的输人,也可以用作 assign语句或者实例元件的输出。
wire型信号的定义格式如下:
wire[n-1:0] 数据名1,数据名2,…,数据名N;
这里,总共定义了N条线,每条线的位宽为n。例如:
wire[2:0] a,b,c;
2)reg型
reg是寄存器数据类型变量的关键字。reg型数据常用来表示always模块内的指定信号,代表触发器。在always块内被赋值的每一个信号都定义为reg型,即赋值操作符的有效变量必须是reg型。
reg型信号的定义格式如下:
reg[n- 1:0]数据名1,数据名2,…,数据名N;
这里,总共定义了N个寄存器变量,每个寄存器的位宽为n。例如:
reg[2:0] a,b,C;
reg d;
reg型和 wire型的区别在于:reg型保持最后一次赋值,而wire型需要持续的驱动。
3)memory型
memory型通过扩展reg型数据的地址范围来达到二维数组的效果,其定义格式如下:
reg[n-1:0]存储器名[m-1:0];
reg[15:0]ROMA [7:0];
这个例子定义了一个存储位宽为16位,存储深度为8的存储器,该存储器的地址范围是0~7。
4)parameter型
定义常量
parametet 参数名1=数据名1;
5)其他类型
integer:整型变量
real:双精度浮点数
realtime: 与real相同,不同之处是realtime是以实数形式存储实践的值
wand:表示线与网,任意一个驱动为0,线网值0
wor:表示线与网,任意一个驱动为1,线网值1
scalared:用于声明一个线性变量,这个变量中的比特可以单独选中或部分选中
Verilog运算操作
表达式位宽调整:
(1)确定上下文操作数的最大位宽,包括表达式右端和左端信号;
(2)扩展右端表达式位宽至最大位宽;
(3)将结果赋给左端信号,如果左端信号位宽较小,则截断相应的高位信号。