0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

在Verilog中利用函数将重复性的行为级设计进行提取

冬至子 来源:数字IC与好好生活的两居室 作者:除夕之夜啊 2023-06-02 11:39 次阅读

Verilog 中,可以利用任务(关键字为 task)或函数(关键字为 function),将重复性的行为级设计进行提取,并在多个地方调用,来避免重复代码的多次编写,使代码更加的简洁、易懂。

函数

函数只能在模块中定义,位置任意,并在模块的任何地方引用,作用范围也局限于此模块。函数主要有以下几个特点:

1)不含有任何延迟、时序或时序控制逻辑

2)至少有一个输入变量

3)只有一个返回值,且没有输出

4)不含有非阻塞赋值语句

5)函数可以调用其他函数,但是不能调用任务

Verilog 函数声明格式如下:

function [range-1:0]     function_id ;
input_declaration ;
 other_declaration ;
procedural_statement ;
endfunction

函数在声明时,会隐式的声明一个宽度为 range、 名字为 function_id 的寄存器变量,函数的返回值通过这个变量进行传递。当该寄存器变量没有指定位宽时,默认位宽为 1。

函数通过指明函数名与输入变量进行调用。函数结束时,返回值被传递到调用处。

函数调用格式如下:

function_id(input1, input2, …);

下面用函数实现一个数据大小端转换的功能。

当输入为 4’b0011 时,输出为 4’b1100。例如:

module endian_rvs
    #(parameter N = 4)
       (
           input             en,     //enable control
           input [N-1:0]     a ,
           output [N-1:0]    b
    );

       reg [N-1:0]          b_temp ;
       always @(*) begin
        if (en) begin
               b_temp =  data_rvs(a);
           end
           else begin
               b_temp = 0 ;
           end
    end
       assign b = b_temp ;

    //function entity
       function [N-1:0]     data_rvs ;
           input     [N-1:0] data_in ;
           parameter         MASK = 32'h3 ; 
           integer           k ;
           begin
               for(k=0; k< N; k=k+1) begin
                   data_rvs[N-k-1]  = data_in[k] ;  
               end
           end
    endfunction

endmodule

函数里的参数也可以改写,例如:

defparam data_rvs.MASK = 32'd7 ;

但是仿真时发现,此种写法编译可以通过,仿真结果中,函数里的参数 MASK 实际并没有改写成功,仍然为 32’h3。这可能和编译器有关,有兴趣的学者可以用其他 Verilog 编译器进行下实验。

函数在声明时,也可以在函数名后面加一个括号,将 input 声明包起来。

例如上述大小端声明函数可以表示为:

function [N-1:0]     data_rvs (
input     [N-1:0] data_in 
    ......
       );

常数函数

常数函数是指在仿真开始之前,在编译期间就计算出结果为常数的函数。常数函数不允许访问全局变量或者调用系统函数,但是可以调用另一个常数函数。

这种函数能够用来引用复杂的值,因此可用来代替常量。

例如下面一个常量函数,可以来计算模块中地址总线的宽度:

parameter    MEM_DEPTH = 256 ;
reg  [logb2(MEM_DEPTH)-1: 0] addr ; //可得addr的宽度为8bit

    function integer     logb2;
    input integer     depth ;
       //2569bit,我们最终数据应该是8,所以需depth=2时提前停止循环
    for(logb2=0; depth >1; logb2=logb2+1) begin
        depth = depth > > 1 ;
    end
endfunction

automatic函数

在 Verilog 中,一般函数的局部变量是静态的,即函数的每次调用,函数的局部变量都会使用同一个存储空间。若某个函数在两个不同的地方同时并发的调用,那么两个函数调用行为同时对同一块地址进行操作,会导致不确定的函数结果。

Verilog 用关键字 automatic 来对函数进行说明,此类函数在调用时是可以自动分配新的内存空间的,也可以理解为是可递归的。因此,automatic 函数中声明的局部变量不能通过层次命名进行访问,但是 automatic 函数本身可以通过层次名进行调用。

下面用 automatic 函数,实现阶乘计算:

wire [31:0]          results3 = factorial(4);
function automatic   integer         factorial ;
    input integer     data ;
    integer           i ;
    begin
        factorial = (data >=2)? data * factorial(data-1) : 1 ;
    end
endfunction // factorial

下面是加关键字 automatic 和不加关键字 automatic 的仿真结果。

由图可知,信号 results3 得到了我们想要的结果,即 4 的阶乘。

而信号 results_noauto 值为 1,不是可预知的正常结果,这里不再做无用分析。

图片

数码管译码

上述中涉及的相关函数知识似乎并没有体现出函数的优越性。下面设计一个 4 位 10 进制的数码管译码器,来说明函数可以简化代码的优点。

◆数码管控制示意图如下。

每位数码显示端有 8 个光亮控制端(如图中 a-g 所示),可以用来控制显示数字 0-9 。

而数码管有 4 个片选(如图中 1-4),用来控制此时哪一位数码显示端应该选通,即应该发光。倘若在很短的时间内,依次对 4 个数码显示端进行片选发光,同时在不同片选下给予不同的光亮控制(各对应 4 位十进制数字),那么在肉眼不能分辨的情况下,就达到了同时显示 4 位十进制数字的效果。

图片

◆下面,我们用信号 abcdefg 来控制光亮控制端,用信号 csn 来控制片选,4 位 10 进制的数字个十百千位分别用 4 个 4bit 信号 single_digit, ten_digit, hundred_digit, kilo_digit 来表示,则一个数码管的显示设计可以描述如下:

module digital_tube
     (
      input             clk ,
      input             rstn ,
      input             en ,

      input [3:0]       single_digit ,
      input [3:0]       ten_digit ,
      input [3:0]       hundred_digit ,
      input [3:0]       kilo_digit ,

      output reg [3:0]  csn , //chip select, low-available
      output reg [6:0]  abcdefg        //light control
      );

    reg [1:0]            scan_r ;  //scan_ctrl
    always @ (posedge clk or negedge rstn) begin
        if(!rstn)begin
            csn            <= 4'b1111;
            abcdefg        <= 'd0;
            scan_r         <= 3'd0;
        end
        else if (en) begin
            case(scan_r)
            2'd0:begin
                scan_r    <= 3'd1;
                csn       <= 4'b0111;     //select single digit
                abcdefg   <= dt_translate(single_digit);
            end
            2'd1:begin
                scan_r    <= 3'd2;
                csn       <= 4'b1011;     //select ten digit
                abcdefg   <= dt_translate(ten_digit);
            end
            2'd2:begin
                scan_r    <= 3'd3;
                csn       <= 4'b1101;     //select hundred digit
                abcdefg   <= dt_translate(hundred_digit);
            end
            2'd3:begin
                scan_r    <= 3'd0;
                csn       <= 4'b1110;     //select kilo digit
                abcdefg   <= dt_translate(kilo_digit);
            end
            endcase
        end
    end

    /*------------ translate function -------*/
    function [6:0] dt_translate;
        input [3:0]   data;
        begin
        case(data)
            4'd0: dt_translate = 7'b1111110;     //number 0 - > 0x7e
            4'd1: dt_translate = 7'b0110000;     //number 1 - > 0x30
            4'd2: dt_translate = 7'b1101101;     //number 2 - > 0x6d
            4'd3: dt_translate = 7'b1111001;     //number 3 - > 0x79
            4'd4: dt_translate = 7'b0110011;     //number 4 - > 0x33
            4'd5: dt_translate = 7'b1011011;     //number 5 - > 0x5b
            4'd6: dt_translate = 7'b1011111;     //number 6 - > 0x5f
            4'd7: dt_translate = 7'b1110000;     //number 7 - > 0x70
            4'd8: dt_translate = 7'b1111111;     //number 8 - > 0x7f
            4'd9: dt_translate = 7'b1111011;     //number 9 - > 0x7b
        endcase
        end
    endfunction

endmodule

◆仿真结果如下。

由图可知,片选、译码等信号,均符合设计。实际中,4 位数字应当在一定的时间内保持不变,而片选信号不停的循环扫描,数码管才能给肉眼呈现一种静态显示的效果。

图片

◆小结

如果译码器设计没有使用函数 dt_translate,则在每个 case 选项里对信号 abcdefg 进行赋值时,还需要对 single_digit,ten_digit, hundred_digit, kilo_digit 进行判断。这些判断语句又会重复 4 次。虽然最后综合出的实际硬件电路可能是一样的,但显然使用函数后的代码更加的简洁、易读。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5290

    浏览量

    119792
  • Verilog
    +关注

    关注

    28

    文章

    1343

    浏览量

    109918
  • 数码管
    +关注

    关注

    32

    文章

    1873

    浏览量

    90862
  • 译码器
    +关注

    关注

    4

    文章

    310

    浏览量

    50258
收藏 人收藏

    评论

    相关推荐

    测量系统分析:测量系统的的重复性和重现性

    测量系统分析:测量系统的的重复性和重现性
    发表于 08-16 13:44

    大规模中文搜索日志查询重复性分析

    分析大规模中文搜索日志的查询重复性,通过对查询重复率和用户个体查询重复率等数据的统计发现:查询串的查询频率、文档的点击频率及用户查询频率均符合Zipf分布,查询重
    发表于 04-11 09:25 8次下载

    测量系统的的重复性和重现性

    测量系统的的重复性和重现性:MSA的相当重要的一部分是研究测量系统的重复性(Repeatability)和重现性(Reproducibility).
    发表于 08-16 13:14 17次下载

    相控阵探头的重复性与可靠性

    相控阵探头的重复性与可靠性 Over the past few years, new procedures involving phased array technology were
    发表于 03-20 10:45 24次下载

    并行传感器如何提高倾斜测量的精度和可重复性

    并行传感器如何提高倾斜测量的精度和可重复性?具体的跟随小编通过本文来详细的了解下。
    的头像 发表于 07-11 13:27 3335次阅读

    15年内人工智能将取代50%的重复性岗位

    创新工场CEO李开复近日表示,15年内,人工智能和自动化具备取代40-50%岗位的技术能力,主要集中重复性劳动、有固定台本和对白内容的各种互动、不需要与人进行大量面对面交流的工作等
    的头像 发表于 09-11 11:02 3465次阅读

    计量标准重复性的测量方法

    计量标准的重复性规定用测量结果的分散性来定量地表示,即用单次测量结果yi的实验标准差s(yi)来表示。当测量结果由单次测量得到时,它直接就是由重复性引入的不确定度分量。
    的头像 发表于 11-12 14:19 2w次阅读

    流量计重复性差的解决方法

    实际使用过程,流量计常会出现重复性差的问题,困惑了不少现场工程师。经过现场观察和总结,发现流量计和体积管内有气体,系统的压力、温度、流量不稳定,四通阀转换密封不合适,计量球的圆度和尺寸等情况都会
    发表于 01-05 11:37 1516次阅读

    计量标准的重复性考核要求

    计量标准的重复性规定用测量结果的分散性来定量地表示,即用单次测量结果yi的实验标准差s(yi)来表示。当测量结果由单次测量得到时,它直接就是由重复性引入的不确定度分量。当
    的头像 发表于 03-18 10:21 3213次阅读

    Verilog函数实现一个数据大小端转换的功能

    Verilog ,可以利用任务(关键字为 task)或函数(关键字为 function),
    的头像 发表于 06-01 16:31 1625次阅读
    用<b class='flag-5'>Verilog</b><b class='flag-5'>函数</b>实现一个数据大小端转换的功能

    计量标准的重复性考核要求

    进行重复性测量时,相同的测量程序,相同的观测者,使用相同的仪器,以及相同地点等要求一般均能得到满足而不会有任何问题。关键是如何理解“相同的条件下”以及“
    的头像 发表于 07-19 15:52 2026次阅读
    计量标准的<b class='flag-5'>重复性</b>考核要求

    PySnooper:替代print的重复性工作

    麻烦。 现在,有了PySnooper,您并不需要配置那么复杂的Debug工具,就能够完成对整个代码的分析。它能告诉您哪些代码正在运行,以及局部变量的值是什么。 其实,PySnooper 就是替代了一行一行print的重复性工作,给你的代码一个pysnooper装饰器,它能自动识别到语句和变量
    的头像 发表于 10-30 10:41 375次阅读

    verilog function函数的用法

    Verilog 中被广泛用于对电路进行模块化设计,以简化和组织代码。 本文详细介绍 Verilog 函数的用法,并探讨
    的头像 发表于 02-22 15:49 4782次阅读

    立仪科技光谱共焦应用之金属隔膜静态重复性测量

    01|检测需求:金属隔膜重复性测量   立仪科技光谱共焦应用之金属隔膜静态重复性测量 02|检测方式 为了保证精度,首先先用千分尺进行测量,得出相应的厚度数据,选择合适的侧头,根据结
    的头像 发表于 08-09 14:33 197次阅读
    立仪科技光谱共焦应用之金属隔膜静态<b class='flag-5'>重复性</b>测量

    MFC测量重复性不高怎么回事?

    真实案例: 某客户使用我们的MFC330时,发现重复性不佳;他多次测试,发现有时候重复性很好控制气流稳定,但有时候无法达标,,觉得这个现象非常奇怪,于是联系了我们的技术人员进行排查。 故障排查
    的头像 发表于 10-23 10:40 88次阅读
    MFC测量<b class='flag-5'>重复性</b>不高怎么回事?