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语言一样,写在后面的调用写在前面的。在这个文件内,位置没有限制。