Verilog 基础模块参考,黑金动力社区
1、数据类型
**整数:**整数可以用二进制 b 或 B,八进制 o 或 O,十进制 d 或 D,十六进制 h 或 H 表示,例
如, 8’b00001111 表示 8 位位宽的二进制整数,4’ha 表示 4 位位宽的十六进制整数。
X 和 Z:X 代表不定值,z 代表高阻值,例如,5’b00x11,第三位不定值,3’b00z 表示最低位
为高阻值。
**下划线:**在位数过长时可以用来分割位数,提高程序可读性,如 8’b0000_1111
参数 parameter: parameter 可以用标识符定义常量,运用时只使用标识符即可,提高可读性
及维护性,如定义 parameter width = 8 ; 定义寄存器 reg [width-1:0] a; 即定义了 8 位宽度的寄存器。
**参数的传递:**在一个模块中如果有定义参数,在其他模块调用此模块时可以传递参数,并可
以修改参数,如下所示,在 module 后用#()表示。
例如定义模块如下
module rom
#(
parameter depth =15,
parameter width = 8
)
(
input [depth-1:0] addr ,
input [width-1:0] data ,
output result
) ;
endmodule
调用模块
module top() ;
wire [31:0] addr ;
wire [15:0] data ;
wire result ;
rom
#(
.depth(32),
.width(16)
)
r1
(.addr(addr) , .data(data) , .result(result) ) ;
endmodule
Parameter 可以用于模块间的参数传递,而 localparam 仅用于本模块内使用,不能用于参数
传递。Localparam 多用于状态机状态的定义。
2.2变量
变量是指程序运行时可以改变其值的量,下面主要介绍几个常用了变量类型。
2.2.1Wire型 Wire 类型变量,也叫网络类型变量,用于结构实体之间的物理连接,如门与门之间,不能储存值,用连续赋值语句 assign 赋值,定义为 wire [n-1:0] a ; 其中 n 代表位宽,如定义 wire a ; assign a = b ; 是将 b 的结点连接到连线 a 上。如下图所示,两个实体之间的连线即是 wire 类型变量。
2.2.2Reg 型
Reg 类型变量,也称为寄存器变量,可用来储存值,必须在 always 语句里使用。其定义为
reg [n-1:0] a ; 表示 n 位位宽的寄存器,如 reg [7:0] a; 表示定义 8 位位宽的寄存器 a。如下所示定
义了寄存器 q,生成的电路为时序逻辑,右图为其结构,为 D 触发器。
module top(d, clk, q) ;
input d ;
input clk ;
output reg q ;
always @(posedge clk)
begin
q <= d ;
end
endmodule
也可以生成组合逻辑,如数据选择器,敏感信号没有时钟,定义了 reg Mux,最终生成电路
为组合逻辑。
module top(a, b, c, d, sel, Mux) ;
input a ;
input b ;
input c ;
input d ;
input [1:0] sel ;
output reg Mux ;
always @(sel or a or b or c or d)
begin
case(sel)
2'b00 : Mux = a ;
2'b01 : Mux = b ;
2'b10 : Mux = c ;
2'b11 : Mux = d ;
endcase
end
endmodule
2.2.3Memory型
可以用 memory 类型来定义 RAM,ROM 等存储器,其结构为 reg [n-1:0] 存储器名[m-1:0],意义
为 m 个 n 位宽度的寄存器。例如,reg [7:0] ram [255:0]表示定义了 256 个 8 位寄存器,256 也即是存储器的深度,8 为数据宽度。
3 运算符
运算符可分为以下几类:
(1) 算术运算符(+,-,,/,%)
(2) 赋值运算符(=,<=)
(3) 关系运算符(>,<,>=,<=,==,!=)
(4) 逻辑运算符(&&,||,!)
(5) 条件运算符(?:)
(6) 位运算符(,|,^,&,^)
(7) 移位运算符(<<,>>)
(8) 拼接运算符({ })
3.1算术运算符
“+”(加法运算符),”-“(减法运算符),””(乘法运算符),”/”(除法运算符,如 7/3 =2),
“%”(取模运算符,也即求余数,如 7%3=1,余数为 1)
3.2赋值运算符
**“=”阻塞赋值,”<=”非阻塞赋值。阻塞赋值为执行完一条赋值语句,再执行下一条,可理解为顺序执行,而且赋值是立即执行;**非阻塞赋值可理解为并行执行,不考虑顺序,在 always 块语句执行完成后,才进行赋值。如下面的阻塞赋值:
代码如下:
module top(din,a,b,c,clk);
input din;
input clk;
output reg a,b,c;
always @(posedge clk)
begin
a = din;
b = a;
c = b;
end
endmodule
激励文件如下
`timescale 1 ns/1 ns
module top_tb() ;
reg din ;
reg clk ;
wire a,b,c ;
initial
begin
din = 0 ;
clk = 0 ;
forever
begin
#({$random}%100)
din = ~din ;
end
end
always #10 clk = ~clk ;
top t0(.din(din),.a(a),.b(b),.c(c),.clk(clk)) ;
endmodule
可以从仿真结果看到,在 clk 的上升沿,a 的值等于 din,并立即赋给 b,b 的值赋给 c。
如果改为非阻塞赋值,仿真结果如下,在 clk 上升沿,a 的值没有立即赋值给 b,b 为 a 原来
的值,同样,c 为 b 原来的值