Verilog中Function的实际使用体验

1.前言

Verilog开发中,常常有一些功能,在多个地方会使用到;如同C语言一样,将其封装成函数,然后在每个需要使用地方调用他。

然而Verilog毕竟是用于硬件开发的,最终综合后形成电路才是硬道理。因此,上手采采坑,体验一下,摸索一下。

2.Function的属性

数字电路分为 时序逻辑电路 和 组合逻辑电路。Funciton综合后将会生成组合逻辑电路。这就是他的属性。所以如果想封装功能进Function一定要选择组合逻辑的功能进行封装。

3.Function的使用细节

下面先展示几个实际可以使用的Function。

3.1初识

    function [7:0]cm2tv;
        input [7:0]data_input;

        cm2tv[6:0] = ~data_input[6:0] + 1;
        cm2tv[7] = data_input[7]; 
    endfunction

首先,function 和endfunction成对出现,这是Verilog的老套路了。

其次,在function后定义的东西,可以理解成函数名,当然他也是返回值。

再次,在函数名下方以input开头添加输入参数,可以理解为函数的形参。

最后,编写函数体。

3.2 function中能装下什么

接下来看一个长一点的函数

    function [11:0]decoder_out;
        input [7:0]data_input;

        case (data_input[6:4])
            3'b000: decoder_out = 0;
            3'b001: decoder_out = 16;
            3'b010: decoder_out = 32;
            3'b011: decoder_out = 64;
            3'b100: decoder_out = 128;
            3'b101: decoder_out =  256;
            3'b110: decoder_out =  512;
            3'b111: decoder_out = 1024; 
            default: decoder_out = 0;
        endcase    
        if(data_input[3] == 1'b1)  
            decoder_out = decoder_out + decoder_table[data_input[6:4]][3];
        else
            decoder_out = decoder_out;
        if(data_input[2] == 1'b1) 
            decoder_out = decoder_out + decoder_table[data_input[6:4]][2];
        else
            decoder_out = decoder_out;
        if(data_input[1] == 1'b1)
            decoder_out = decoder_out + decoder_table[data_input[6:4]][1];
        else
            decoder_out = decoder_out;
        if(data_input[0] == 1'b1)
            decoder_out = decoder_out + decoder_table[data_input[6:4]][0];
        else
            decoder_out = decoder_out; 
        decoder_out[11] = data_input[7];       
    endfunction

    function [7:0]cm2tv;
        input [7:0]data_input;

        cm2tv[6:0] = ~data_input[6:0] + 1;
        cm2tv[7] = data_input[7]; 
    endfunction

由此可见函数中可以使用if\else\case等关键字组成的分支语句。

3.3 Function中的细节

再来看一段和前面那段短的函数类似的函数。

    function [11:0]tv2cm;
        input [11:0]data_input;

        tv2cm[10:0] = ~data_input[10:0] + 1;  
        tv2cm[11] = data_input[11];
    endfunction   

仔细看,tv2cm可以作为左值。同样,输入参数也可以作为左值。不过这也不能说明返回值和参数类型是reg。毕竟他们实现的是组合逻辑电路。而在时序逻辑中,wire类型变量由于不能锁存数据,所以时序逻辑中wire类型不能当左值。(wire线网类型,就是跟电线,电线只能导电,但不能留住电)

3.4 Function套娃

下面是一段A律13折线解码部分的函数代码。当前展示的函数所调用的,正是前面展示的三个函数。关于A律13折线编解码的内容敬请期待哦。

    function [7:0]negative_encoder_out;
        input [11:0]data_input;
        reg [11:0]data_in_reg;
        
        data_in_reg = cm2tv(data_input);  
        negative_encoder_out = encoder_out(data_in_reg);
        negative_encoder_out = tv2cm(negative_encoder_out);
    endfunction    

实测发现,函数调用函数时,不需要像C语言一样,写在后面的调用写在前面的。在这个文件内,位置没有限制。

猜你喜欢

转载自blog.csdn.net/Fairchild_1947/article/details/124411827