zoukankan      html  css  js  c++  java
  • (原创)task和function语法的使用讨论(Verilog,CPLD/FPGA)

    1. Abstract

      function和task语句的功能有很多的相似之处,在需要有多个相同的电路生成时,可以考虑使用它们来实现。因为个人使用它们比较少,所以对它们没有进行更深的了解,现在时间比较充裕,我想通过写几个简单的电路将它们二者的功能进行验证一下,看看究竟是怎么生成电路的。

    2. Contents

        主要为测试function和task各自生成的电路,所以电路设计功能比较简单——4位BCD码转换成4位余3码。

        文件开头的注释说明。

    /* --------------------------------------- 
        Module Name:         temp 
        Module Function:    将4位BCD码转换成为余3码,无效状态为4'b0000 
        Module Input:         4-bit data_in 
        Module Output:      4-bit data_out 
        Module Reference:    None 
        Note:                  码表如下 
    ######################################## 
              data_in        data_out    
        0      4'b0000        4'b0011 
        1      4'b0001        4'b0100    
        2      4'b0010        4'b0101    
        3      4'b0011        4'b0110 
        4      4'b0100        4'b0111 
        5      4'b0101        4'b1000 
        6      4'b0110        4'b1001 
        7      4'b0111        4'b1010 
        8      4'b1000        4'b1011 
        9      4'b1001        4'b1100 
        10      4'b1010        4'b0000        无效 
        11      4'b1011        4'b0000        无效 
        12      4'b1100        4'b0000        无效 
        13      4'b1101        4'b0000        无效 
        14      4'b1110        4'b0000        无效 
        15      4'b1111        4'b0000        无效 
       ---------------------------------------*/

        2.1 直接使用组合逻辑电路生成BCD码转余3码。

    module temp(data_in,data_out); 
    
    output reg [3:0] data_out; 
    input [3:0] data_in; 
    
    always @(data_in) 
    begin 
        if(data_in >=  4'd10) data_out = 4'b0000; 
        else  data_out = data_in + 4'd3; 
    end 
    
    endmodule

        用RTL视图查看一下生成出来的网表

    imageFIG2.1 直接用组合逻辑生成的逻辑图

        生成出来的电路由加法器、比较器和选择器构成,输入数据data_in + 3作为选择器的选择控制,下面做一下验证测试。

    image FIG2.2 测试仿真验证

        2.2 用task语句编写组合电路

    module temp(data_in,data_out); 
    
    output reg [3:0] data_out; 
    input [3:0] data_in; 
    
    always @(data_in) 
    begin 
        if(data_in >=  4'd10) data_out = 4'b0000; 
        else  BCD2Access3(data_out,data_in); 
    end 
    
    task BCD2Access3; 
    output [3:0] data_out; 
    input [3:0] data_in; 
    
        data_out = data_in + 4'd3; 
    endtask 
    endmodule

         用RTL视图查看一下最后生成的网表。

    imageFIG2.3 使用task语句生成出的逻辑图

        仔细对比,FIG2.3和FIG2.1是一模一样的,也就是说采用task语句可以生成预期的逻辑图,非常成功!既然生成出的逻辑图都是一样的,测试部分在此就省略了吧,和FIG2.2应该是一样的。

    2.3 用function语句编写组合逻辑

    module temp(data_in,data_out); 
    
    output reg [3:0] data_out; 
    input [3:0] data_in; 
    
    always @(data_in) 
    begin 
        if(data_in >=  4'd10) data_out = 4'b0000; 
        else  data_out = BCD2Access3(data_in); 
    end 
    
    function [3:0] BCD2Access3; 
    input [3:0] data_in; 
    
    BCD2Access3 = data_in + 4'd3; 
    endfunction 
    endmodule

        用RTL视图查看一下最后生成出来的网表。

    image FIG2.4 使用function语句生成出的逻辑图

        相信已经很熟悉这个逻辑图了,与前面的FIG2.1一模一样,也就是说使用function语句也是可以生成预期的电路的,而且也是非常成功的!既然逻辑图都是与前面一致的,故测试部分……也省去了吧。

       小结一下,用function和task语句都可以生成预期的逻辑电路,不过,查查语法书,可以知道task语句的适用性更广泛一点,更符合逻辑思维的习惯;function最大的好处就是可以有一个返回值,运算以后结果可以直接返回供调用的块使用。

      在组合逻辑设计的过程中,写成可综合的电路可以达到预期的生成电路逻辑,那么在时序逻辑设计中,function和task语句又会生成出怎样的电路呢?还是以这一个电路功能为模板,值得注意的是,得额外加一个时钟信号。

    2.4 直接使用时序逻辑编写的BCD码转余3码。

    module temp(data_in,data_out,clk); 
    
    output reg [3:0] data_out; 
    input [3:0] data_in; 
    input clk; 
    
    always @(posedge clk) 
    begin 
        if(data_in >=  4'd10) data_out = 4'b0000; 
        else  data_out <= data_in + 3'd3; 
    end 
    
    endmodule

        用RTL视图来看下生成出来的逻辑网表。

    imageFIG2.5 直接用时序逻辑编写生成的逻辑网表

        和上面生成的逻辑网表相比,多了一个锁存器,这也是典型的时序逻辑的特征,数据的变化只在clk的上升沿才有效。下面来做一下电路逻辑的验证。

    image FIG2.6 时序逻辑网表的验证

        图确实有点小,可能看起来有点不方便,但逻辑的功能是正确的,每到clk的上升沿,数据更新一次,译码是正确的,为了方便看,再截取一部分出来吧,作为一个局部放大图。

    image FIG2.7 时序逻辑验证的局部放大图

        直接用时序逻辑设计成功了,再尝试着用task语句和function语句实现,看看最后的效果会怎么样。

    2.5 时序逻辑下使用task语句实现电路

    module temp(data_in,data_out,clk); 
    
    output reg [3:0] data_out; 
    input [3:0] data_in; 
    input clk; 
    
    always @(posedge clk) 
    begin 
        if(data_in >=  4'd10) data_out = 4'b0000; 
        else  BCD2Access3(data_out,data_in); 
    end 
    
    task BCD2Access3; 
    output [3:0] data_out; 
    input [3:0] data_in; 
    
        data_out = data_in + 4'd3; 
    endtask 
    
    endmodule

        用RTL视图来看一下生成的逻辑网表。

    imageFIG2.8 使用task语句生成的逻辑网表

         同样,仔细对照一下,发现FIG2.8和FIG2.6是一样的,也就是说在时序逻辑中使用task语句也是可以实现预期的电路的,非常的成功!和上述讨论的一样,既然逻辑图相同的话,验证的部分就略去了吧。

    2.6 时序逻辑下用function语句实现电路

    module temp(data_in,data_out,clk); 
    
    output reg [3:0] data_out; 
    input [3:0] data_in; 
    input clk; 
    
    always @(posedge clk) 
    begin 
        if(data_in >=  4'd10) data_out = 4'b0000; 
        else  data_out <= BCD2Access3(data_in); 
    end 
    
    function [3:0] BCD2Access3; 
    input [3:0] data_in; 
    
    BCD2Access3 = data_in + 4'd3; 
    endfunction 
    
    endmodule

        跟上面一样,用RTL视图来看看最后生成出来的电路。

    image FIG2.9 时序逻辑下使用function语句生成的逻辑网表

        仔细对比,会发现跟如上的逻辑网表一样,也就是说在时序逻辑下使用function语句也是可以实现预期的电路的,非常的成功!逻辑网表一致的话,在此逻辑的验证容我略去吧。

        小结一下,在时序逻辑的电路设计中,也可以使用task语句和function语句来实现电路。

        在学习过程中,也不断的在看语法书,毕竟这一块是我不太熟悉的地方,现在将它们使用的一些要点整理出来,对如何使用和最后生成怎样的很有参考帮助。

    task语句要点 

    (1)若用于任务中的命名变量或参数没有在任务块中声明,则指的是在模块中声明的命名变量或参数。

    (2)任务中的input,output和inout的个数不受限制(也可以为0个)。(任务可以没有参数)

    (3)任务中的变量(包括输入(input)和双向端口(inout))可以声明为寄存器型。如果没有明确地声明,则默认为寄存器类型,且其位宽与相应的变量匹配。

    (4)当启动任务时,相应于任务的输入和双向端口(inout)的变量表达式的值被存入相应的变量寄存器中。当任务结束时,输入和双向端口(inout)的变量寄存器中的值又被代入启动任务的语句中相应的表达式。

    电路综合参考:包含时序控制语句的任务是不可综合的。启动的任务往往被综合成组合逻辑。 

    function语句要点

    (1)函数必须至少有一个输入变量,不能有任何输出或输入/输出双向变量(output 和inout类型)。

    (2)函数不能包含时间控制语句(如延迟#、事件控制@或者等待wait)。

    (3)函数是通过对函数名赋值的途径返回其值的,就好比是一个寄存器。

    (4)函数不能启动任务。

    (5)函数不能被禁用。(特指应用于编写测试文件)

        电路综合参考:函数的每一次调用都被综合为一个独立的组合逻辑电路块。

    3.Conclusion

        总体来说,task的功能更加符合硬件逻辑设计的习惯,而且语法中对它的限制比较少。而且它们最终生成的电路都是组合逻辑,所以在需要产生多个相同的模块时,可以采用由它们构成。

    4.Platform

      Quartus II 9.1 Build 222 Full Version

    5.Reference

    [1] Verilog 数字系统设计教程(第2版) 夏宇闻

    [2] Advanced Digital Design with the Verilog HDL (Second Edition) Michael D.Ciletti

  • 相关阅读:
    EOS之session的数据获取
    c# 数据库操作之ACCESS
    基础之创建与导出
    dotNET5的MVC页面传值方式总结
    dotNET开发之MVC中Controller返回值类型ActionResult方法总结
    C# 计算农历日期方法(2021版)
    普通邮箱设置客户端授权码并开启stmp服务以及关于QQ邮箱“命令顺序不正确。 服务器响应为:Error: need EHLO and AUTH first !”问题全指导
    13 张图,深入理解 Synchronized
    Springboot 注解大全
    python中的print()函数的学习-1
  • 原文地址:https://www.cnblogs.com/hechengfei/p/4104253.html
Copyright © 2011-2022 走看看