• Verilog HDL 语法整理 (五)





    目录

    引言

    函数

    任务

    参考声明

    文末推荐




    引言

    本专栏的前面几篇文章主要整理了常用的Verilog HDL 语法知识。最近有时间,刚好也想把 Verilog HDL 的函数和任务重新理清。就写这篇文章整理对应的语法同时也做一些实际的例子。

    函数和任务基本还是在功能仿真环节,编写TESTBENCH时用的多。


    函数

    语法说明

    function  位宽定义 输出信号名(或称函数名)

            input 位宽定义 输入信号名1;//输入信号(端口)声明

            input 位宽定义 输入信号名2;//输入信号(端口)声明

            //其他输入端口声明

            //函数内部变量声明

            begin

                    //函数功能描述语句

            end

    endfunction

    使用说明:

    1、函数调用使用function 关键字后的输出信号名;

    2、函数内部变量声明只能声明寄存器类型的变量;

    3、函数体中的语句只能使用阻塞赋值;

    4、函数调用时只能使用位置赋值,所以调用时,输入参数一定要注意一一对应;

    5、函数调用可在串、并语句中;

    6、函数可以调用别的函数;

    7、函数支持递归(仅用于仿真);

    8、函数不可以调用任务,因为任务中有定时相关的语句,但是函数中不存在;

    下面举个栗子:

    设计模块中用function设计一个8位宽的加法器组合逻辑:

    1. `timescale 1ns / 1ps
    2. // 此模块使用 function 实现加法运算的组合逻辑
    3. // 调用function 实现两数(有符号)相加的简单时序运算逻辑
    4. // By:在路上,正出发
    5. module FUNC_USE_EXM(
    6. input I_CLK,
    7. input I_RSTN,
    8. input [7:0] I_ADD_A,
    9. input I_VAL_A,
    10. input [7:0] I_ADD_B,
    11. input I_VAL_B,
    12. output [8:0]O_RES
    13. );
    14. // FUNC 定义
    15. function [8:0] O_ADD_RES;
    16. input [7:0] I_DATA_A;
    17. input [7:0] I_DATA_B;
    18. input I_VAL_A;
    19. input I_VAL_B;
    20. begin
    21. if(I_VAL_A & I_VAL_B)
    22. begin
    23. O_ADD_RES = {I_DATA_A[7],I_DATA_A} + {I_DATA_B[7],I_DATA_B};
    24. end
    25. else
    26. begin
    27. O_ADD_RES = 9'b1_1111_1111;
    28. end
    29. end
    30. endfunction
    31. // 模块内部逻辑
    32. reg [8:0] R_RES;
    33. always @ (posedge I_CLK)
    34. begin
    35. if(~I_RSTN)
    36. begin
    37. R_RES <= 9'b1_1111_1111;
    38. end
    39. else
    40. begin
    41. R_RES <= O_ADD_RES (I_ADD_A,I_ADD_B,I_VAL_A,I_VAL_B);
    42. end
    43. end
    44. assign O_RES = R_RES;
    45. endmodule

    TEST BENCH模块:

    1. `timescale 1ns / 1ps
    2. // 此模块测试模块 FUNC_USE_EXM 的功能
    3. // By:在路上,正出发
    4. module TB_FUNC_USE_EXM();
    5. reg I_CLK;
    6. reg I_RSTN;
    7. reg [7:0] I_ADD_A;
    8. reg I_VAL_A;
    9. reg [7:0] I_ADD_B;
    10. reg I_VAL_B;
    11. wire [8:0]O_RES;
    12. initial I_CLK = 0;
    13. always #10 I_CLK = ~I_CLK;
    14. initial
    15. begin
    16. I_RSTN = 1'b0;
    17. I_ADD_A = 8'd0;
    18. I_VAL_A = 1'b0;
    19. I_ADD_B = 8'd0;
    20. I_VAL_B = 1'b0;
    21. #100;
    22. I_RSTN = 1'b1;
    23. #20;
    24. I_ADD_A = -8'd2;
    25. #20;
    26. I_VAL_A = 1'b1;
    27. #10;
    28. I_ADD_B = 8'd10;
    29. #50;
    30. I_VAL_B = 1'b1;
    31. repeat(100)
    32. begin
    33. @(posedge I_CLK);
    34. I_ADD_A = I_ADD_A + 1;
    35. @(posedge I_CLK);
    36. I_ADD_B = I_ADD_B + 1;
    37. end
    38. $finish;
    39. end
    40. // 模块例化
    41. FUNC_USE_EXM inst_FUNC_USE_EXM
    42. (
    43. .I_CLK (I_CLK),
    44. .I_RSTN (I_RSTN),
    45. .I_ADD_A (I_ADD_A),
    46. .I_VAL_A (I_VAL_A),
    47. .I_ADD_B (I_ADD_B),
    48. .I_VAL_B (I_VAL_B),
    49. .O_RES (O_RES)
    50. );
    51. endmodule

    仿真波形:

     

    任务

    语法说明

    task 任务名;

            input 位宽定义 输入信号名1;//输入信号(端口)声明

            input 位宽定义 输入信号名2;//输入信号(端口)声明

            //其他输入端口声明

            output 位宽定义 输出信号名1;//输入信号(端口)声明

            output 位宽定义 输出信号名2;//输入信号(端口)声明

            //其他输出端口声明

            //任务内部变量声明

            begin

                    //任务功能描述语句

            end

    endtask

    使用说明:

    1、与函数不同,任务可以有多个输出端口;

    2、任务内部的变量只能是 reg 型;

    3、任务中的语句可以使用阻塞赋值也可以使用非阻塞赋值。

    4、任务调用时只能使用位置赋值,所以调用时,输入参数一定要注意一一对应;

    5、任务调用只能用在串行语句中;

    6、一个任务可以调用另一个或多个任务;

    7、任务可以递归调用,仅用于仿真;

    8、任务可以调用函数;

    举个栗子:

    功能同上面函数那个例子;

    设计文件:

    1. `timescale 1ns / 1ps
    2. // 此模块使用 task 实现加法运算的组合逻辑
    3. // 调用 task 实现两数(有符号)相加的简单时序运算逻辑
    4. // By:在路上,正出发
    5. module TASK_USE_EXM(
    6. input I_CLK,
    7. input I_RSTN,
    8. input [7:0] I_ADD_A,
    9. input I_VAL_A,
    10. input [7:0] I_ADD_B,
    11. input I_VAL_B,
    12. output [8:0]O_RES,
    13. output O_RES_VAL
    14. );
    15. // FUNC 定义
    16. task ADD_TASK;
    17. input [7:0] I_DATA_A;
    18. input [7:0] I_DATA_B;
    19. input I_VAL_A;
    20. input I_VAL_B;
    21. output reg [8:0] O_ADD_RES;
    22. output reg O_ADD_VAL;
    23. begin
    24. if(I_VAL_A & I_VAL_B)
    25. begin
    26. O_ADD_RES <= {I_DATA_A[7],I_DATA_A} + {I_DATA_B[7],I_DATA_B};
    27. O_ADD_VAL <= 1'b1;
    28. end
    29. else
    30. begin
    31. O_ADD_RES <= 9'b1_1111_1111;
    32. O_ADD_VAL <= 1'b0;
    33. end
    34. end
    35. endtask
    36. // 模块内部逻辑
    37. reg [8:0] R_RES;
    38. reg R_RES_VAL;
    39. always @ (posedge I_CLK)
    40. begin
    41. if(~I_RSTN)
    42. begin
    43. R_RES <= 9'b1_1111_1111;
    44. end
    45. else
    46. begin
    47. ADD_TASK(I_ADD_A,I_ADD_B,I_VAL_A,I_VAL_B,R_RES,R_RES_VAL);
    48. end
    49. end
    50. assign O_RES = R_RES;
    51. assign O_RES_VAL = R_RES_VAL;
    52. endmodule

    TEST BENCH文件:

    1. `timescale 1ns / 1ps
    2. // 此模块测试模块 FUNC_USE_EXM 的功能
    3. // By:在路上,正出发
    4. module TB_FUNC_USE_EXM();
    5. reg I_CLK;
    6. reg I_RSTN;
    7. reg [7:0] I_ADD_A;
    8. reg I_VAL_A;
    9. reg [7:0] I_ADD_B;
    10. reg I_VAL_B;
    11. wire [8:0]O_RES;
    12. wire O_RES_VAL;
    13. initial I_CLK = 0;
    14. always #10 I_CLK = ~I_CLK;
    15. initial
    16. begin
    17. I_RSTN = 1'b0;
    18. I_ADD_A = 8'd0;
    19. I_VAL_A = 1'b0;
    20. I_ADD_B = 8'd0;
    21. I_VAL_B = 1'b0;
    22. #100;
    23. I_RSTN = 1'b1;
    24. #20;
    25. I_ADD_A = -8'd2;
    26. #20;
    27. I_VAL_A = 1'b1;
    28. #10;
    29. I_ADD_B = 8'd10;
    30. #50;
    31. I_VAL_B = 1'b1;
    32. repeat(100)
    33. begin
    34. @(posedge I_CLK);
    35. I_ADD_A = I_ADD_A + 1;
    36. @(posedge I_CLK);
    37. I_ADD_B = I_ADD_B + 1;
    38. end
    39. $finish;
    40. end
    41. // 模块例化
    42. TASK_USE_EXM inst_TASK_USE_EXM
    43. (
    44. .I_CLK (I_CLK),
    45. .I_RSTN (I_RSTN),
    46. .I_ADD_A (I_ADD_A),
    47. .I_VAL_A (I_VAL_A),
    48. .I_ADD_B (I_ADD_B),
    49. .I_VAL_B (I_VAL_B),
    50. .O_RES (O_RES),
    51. .O_RES_VAL(O_RES_VAL)
    52. );
    53. 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编程的基本语法,对于老手来说也可以巩固自己的编程能力。不用付费,免费使用哦。基本是每个即将找工作的人必备的刷题网站。快行动起来吧!

  • 相关阅读:
    Sonarqube-8.9版本测试单元测试覆盖率
    基于暗原色先验的单幅图像去雾——算法复现
    Fouier Net和DeepOnet等求解器算法解读和代码
    企业经营异常查询API:保障供应链的可靠性与稳定性
    leetcode - 1647. Minimum Deletions to Make Character Frequencies Unique
    linux 搭建mycat
    ke9案例三:页面提交文件,我服务器端接收
    Maven的初使用
    java基础入门(一)
    java File、io篇
  • 原文地址:https://blog.csdn.net/qq_43045275/article/details/126586350