目录
本专栏的前面几篇文章主要整理了常用的Verilog HDL 语法知识。最近有时间,刚好也想把 Verilog HDL 的函数和任务重新理清。就写这篇文章整理对应的语法同时也做一些实际的例子。
函数和任务基本还是在功能仿真环节,编写TESTBENCH时用的多。
语法说明:
function 位宽定义 输出信号名(或称函数名)
input 位宽定义 输入信号名1;//输入信号(端口)声明
input 位宽定义 输入信号名2;//输入信号(端口)声明
//其他输入端口声明
//函数内部变量声明
begin
//函数功能描述语句
end
endfunction
使用说明:
1、函数调用使用function 关键字后的输出信号名;
2、函数内部变量声明只能声明寄存器类型的变量;
3、函数体中的语句只能使用阻塞赋值;
4、函数调用时只能使用位置赋值,所以调用时,输入参数一定要注意一一对应;
5、函数调用可在串、并语句中;
6、函数可以调用别的函数;
7、函数支持递归(仅用于仿真);
8、函数不可以调用任务,因为任务中有定时相关的语句,但是函数中不存在;
下面举个栗子:
设计模块中用function设计一个8位宽的加法器组合逻辑:
`timescale 1ns / 1ps // 此模块使用 function 实现加法运算的组合逻辑 // 调用function 实现两数(有符号)相加的简单时序运算逻辑 // By:在路上,正出发 module FUNC_USE_EXM( input I_CLK, input I_RSTN, input [7:0] I_ADD_A, input I_VAL_A, input [7:0] I_ADD_B, input I_VAL_B, output [8:0]O_RES ); // FUNC 定义 function [8:0] O_ADD_RES; input [7:0] I_DATA_A; input [7:0] I_DATA_B; input I_VAL_A; input I_VAL_B; begin if(I_VAL_A & I_VAL_B) begin O_ADD_RES = {I_DATA_A[7],I_DATA_A} + {I_DATA_B[7],I_DATA_B}; end else begin O_ADD_RES = 9'b1_1111_1111; end end endfunction // 模块内部逻辑 reg [8:0] R_RES; always @ (posedge I_CLK) begin if(~I_RSTN) begin R_RES <= 9'b1_1111_1111; end else begin R_RES <= O_ADD_RES (I_ADD_A,I_ADD_B,I_VAL_A,I_VAL_B); end end assign O_RES = R_RES; endmoduleTEST BENCH模块:
`timescale 1ns / 1ps // 此模块测试模块 FUNC_USE_EXM 的功能 // By:在路上,正出发 module TB_FUNC_USE_EXM(); reg I_CLK; reg I_RSTN; reg [7:0] I_ADD_A; reg I_VAL_A; reg [7:0] I_ADD_B; reg I_VAL_B; wire [8:0]O_RES; initial I_CLK = 0; always #10 I_CLK = ~I_CLK; initial begin I_RSTN = 1'b0; I_ADD_A = 8'd0; I_VAL_A = 1'b0; I_ADD_B = 8'd0; I_VAL_B = 1'b0; #100; I_RSTN = 1'b1; #20; I_ADD_A = -8'd2; #20; I_VAL_A = 1'b1; #10; I_ADD_B = 8'd10; #50; I_VAL_B = 1'b1; repeat(100) begin @(posedge I_CLK); I_ADD_A = I_ADD_A + 1; @(posedge I_CLK); I_ADD_B = I_ADD_B + 1; end $finish; end // 模块例化 FUNC_USE_EXM inst_FUNC_USE_EXM ( .I_CLK (I_CLK), .I_RSTN (I_RSTN), .I_ADD_A (I_ADD_A), .I_VAL_A (I_VAL_A), .I_ADD_B (I_ADD_B), .I_VAL_B (I_VAL_B), .O_RES (O_RES) ); endmodule仿真波形:
语法说明:
task 任务名;
input 位宽定义 输入信号名1;//输入信号(端口)声明
input 位宽定义 输入信号名2;//输入信号(端口)声明
//其他输入端口声明
output 位宽定义 输出信号名1;//输入信号(端口)声明
output 位宽定义 输出信号名2;//输入信号(端口)声明
//其他输出端口声明
//任务内部变量声明
begin
//任务功能描述语句
end
endtask
使用说明:
1、与函数不同,任务可以有多个输出端口;
2、任务内部的变量只能是 reg 型;
3、任务中的语句可以使用阻塞赋值也可以使用非阻塞赋值。
4、任务调用时只能使用位置赋值,所以调用时,输入参数一定要注意一一对应;
5、任务调用只能用在串行语句中;
6、一个任务可以调用另一个或多个任务;
7、任务可以递归调用,仅用于仿真;
8、任务可以调用函数;
举个栗子:
功能同上面函数那个例子;
设计文件:
`timescale 1ns / 1ps // 此模块使用 task 实现加法运算的组合逻辑 // 调用 task 实现两数(有符号)相加的简单时序运算逻辑 // By:在路上,正出发 module TASK_USE_EXM( input I_CLK, input I_RSTN, input [7:0] I_ADD_A, input I_VAL_A, input [7:0] I_ADD_B, input I_VAL_B, output [8:0]O_RES, output O_RES_VAL ); // FUNC 定义 task ADD_TASK; input [7:0] I_DATA_A; input [7:0] I_DATA_B; input I_VAL_A; input I_VAL_B; output reg [8:0] O_ADD_RES; output reg O_ADD_VAL; begin if(I_VAL_A & I_VAL_B) begin O_ADD_RES <= {I_DATA_A[7],I_DATA_A} + {I_DATA_B[7],I_DATA_B}; O_ADD_VAL <= 1'b1; end else begin O_ADD_RES <= 9'b1_1111_1111; O_ADD_VAL <= 1'b0; end end endtask // 模块内部逻辑 reg [8:0] R_RES; reg R_RES_VAL; always @ (posedge I_CLK) begin if(~I_RSTN) begin R_RES <= 9'b1_1111_1111; end else begin ADD_TASK(I_ADD_A,I_ADD_B,I_VAL_A,I_VAL_B,R_RES,R_RES_VAL); end end assign O_RES = R_RES; assign O_RES_VAL = R_RES_VAL; endmoduleTEST BENCH文件:
`timescale 1ns / 1ps // 此模块测试模块 FUNC_USE_EXM 的功能 // By:在路上,正出发 module TB_FUNC_USE_EXM(); reg I_CLK; reg I_RSTN; reg [7:0] I_ADD_A; reg I_VAL_A; reg [7:0] I_ADD_B; reg I_VAL_B; wire [8:0]O_RES; wire O_RES_VAL; initial I_CLK = 0; always #10 I_CLK = ~I_CLK; initial begin I_RSTN = 1'b0; I_ADD_A = 8'd0; I_VAL_A = 1'b0; I_ADD_B = 8'd0; I_VAL_B = 1'b0; #100; I_RSTN = 1'b1; #20; I_ADD_A = -8'd2; #20; I_VAL_A = 1'b1; #10; I_ADD_B = 8'd10; #50; I_VAL_B = 1'b1; repeat(100) begin @(posedge I_CLK); I_ADD_A = I_ADD_A + 1; @(posedge I_CLK); I_ADD_B = I_ADD_B + 1; end $finish; end // 模块例化 TASK_USE_EXM inst_TASK_USE_EXM ( .I_CLK (I_CLK), .I_RSTN (I_RSTN), .I_ADD_A (I_ADD_A), .I_VAL_A (I_VAL_A), .I_ADD_B (I_ADD_B), .I_VAL_B (I_VAL_B), .O_RES (O_RES), .O_RES_VAL(O_RES_VAL) ); endmodule仿真波形:
【1】夏宇闻. Verilog 数字系统设计教程 第二版.
【2】狄超. FPGA之道.
【3】IEEE Standard for Verilog Hardware Description Language 1364-2005.
掌握了基本的Verilog语法,不去实战练习的话很难有大的突破。牛客网可以为大家提供一个免费的刷题练习的平台。非常推荐大家使用。
链接如下:牛客网-Verilog专项https://www.nowcoder.com/link/pc_csdncpt_zls_verilog这个里面有很多代码题目练习,对于新手来说可以快速掌握Verilog编程的基本语法,对于老手来说也可以巩固自己的编程能力。不用付费,免费使用哦。基本是每个即将找工作的人必备的刷题网站。快行动起来吧!