Verilog HDL是一种硬件设计语言. 可以采用三种不同方式: 行为描述方式, 数据流方式, 结构化方式对设计进行建模.
Verilog HDL语言设计入门
模块(module)是Verilog的基本描述单位, 一个模块可以在另一个模块中使用, module
和endmodule
进行定义.
Verilog HDL大小写敏感.
结构化描述
module decoder_2_to_4 (A, D) ;
input [1:0] A ;
output [3:0] D ;
assign D = (A == 2'b00) ? 4'b0001 :
(A == 2'b01) ? 4'b0010 :
(A == 2'b10) ? 4'b0100 :
(A == 2'b11) ? 4'b1000 : 4'b0000 ;
endmodule
主要用于层次化设计中.
数据流描述
一般使用连续赋值assign语句描述, 主要用于组合逻辑电路建模.
module mux2_1(out1, a, b, sel) ;
output out1;
input a, b;
input sel;
assign out1= sel ? b : a;
endmodule
行为描述
一般使用Initial或Always语句描述, 可以对组合、时序逻辑电路建模.
module mux2_1(out1, a, b, sel) ;
output reg out1;
input a, b;
input sel;
always @(sel or a or b)
begin
if (sel)
out1 = b; //在Initial或Always中赋值的变量需要为reg型
else
out1 = a;
end
endmodule
混合设计描述
来自always语句和initial语句(切记只有寄存器类型数据可以在这两种语句中赋值)的值能够驱动门或开关。
module FA_Mix(A,B,Cin,Sum,Cout);
input A,B,Cin;
output Sum,Cout;
reg Cout;
reg T1,T2,T3;
wire S1;
xor X1(S1,A,B); // 门实例语句
always @ (A or B or Cin) // always 语句
begin
T1 = A & B;
T2 = A & Cin;
T3 = B & Cin;
Cout = (T1 | T2) | T3;
end
assign Sum = S1 ^ Cin; // 连续赋值语句
endmodule
设计验证与仿真
要测试一个设计块是否正确,就要用Verilog再写一个测试模块。这个测试模块应包括以下三个方面的内容:
-
测试模块中要调用到设计块,只有这样才能对它进行测试;
-
测试模块中应包含测试的激励信号源;
-
测试模块能够实施对输出信号的检测,并报告检测结果。
`timescale 1ns / 1ps // ·(反引号)这个字符位于主键盘的左上角 module decoder_2_to_4_tb; // 测试模块没有输入输出端口 reg [1:0] x; wire [3:0] y; integer k; decoder_2_to_4 DUT (x, y); // Circuit under test initial begin x = 0; for (k=0; k < 4; k=k+1) #5 x=k; // 在5个时间单位后k赋值给x #10 $stop; // 在10个时间单位后暂停仿真 end endmodule
Vivado设计流程
步骤1 创建一个Vivado工程
步骤2 添加设计文件(.v)
步骤3 添加约束文件(.xdc-Xilinx Design Constraints)
步骤4 添加testbench文件(.v)
步骤5 仿真:测试设计块
步骤6 综合:将语言转化成电路(网表文件)
步骤7 实现:将网表配置到具体的FPGA芯片
步骤8 生成比特流,下载到板子进行功能验证
Verilog语言基础
注释
同C语言
标识符
可以是任意一组字母、数字、$符号和_(下划线)符号的组合;
数值常量
General format is: <size><’base><number>
d:十进制,h:十六进制,b:二进制
4’b1101 // this is a 4-bit binary number equal to 13
10’h2e7 // this is a 10-bit wide number specified in hex
参数parameter
有时候希望模块成为一般化的模块,即希望端口位数可选。parameter可实现此功能,在调用模块时可改变该参数的值.
module mux2_1(out1, a, b, sel) ;
parameter N=2; //本模块内不可变
output [N-1:0] out1;
input [N-1:0] a, b;
input sel;
assign out1= sel ? b : a;
endmodule
在顶层模块中:
mux2_1 #(4) dut0( out, x,y,s ); //实例化时参数N值为4
数据类型
- 线网类型(wire)
- 寄存器类型(reg):只能在
always
和initial
语句中被赋值
vector
向量拼接{}
时延
assign #2 Sum = A ^ B; // #2指2个时间单位。
and #1 A0(OUT, A, B);
缩位运算符
Reduction AND
assign all_ones = &accumulator; // are all bits set?
Reduction OR
assign not_zero = |accumulator; // are any bits set?
Reduction XOR
assign parity = ^data_out; // even parity bit