Verilog语法之函数function的讲解
2023-12-13 04:32:44
function讲解:
在verilog语言中,函数与任务是可综合的。
可以用function与task,将重复性的行为级设计(就是rtl描述)进行提取,并在多个地方调用,来避免重复代码的多次编写,可使代码更加的简洁易懂。
函数特点说明:
- 函数只能在模块内部,任意位置,定义与使用。作用范围也仅限于此模块;
- 不能有任何延迟,时序或者时序逻辑控制;
- 至少有一个输入变量;
- 只有一个返回值,没有输出;
- 不能含有非阻塞赋值语句;
- 函数可以调用其他函数,不能调用任务。
函数定义格式:
?
? // ?定义格式:
? ? function [range-1:0] ? ?function_id ? ? ? ? ; ? // 没有输出但是有一个返回值,就是这个函数名称(function_id),range 定义位宽。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 函数的返回值通过这个变量进行传递。当该寄存器变量没有指定位宽时,默认位宽为 1。
? ? ? ? input ? ? ? ? ? ? ? input_declaration ? ; ? // 输入端口。可以有多个输入。
? ? ? ? ? ? ? ? ? ? ? ? ? ? other_declaration ? ; ? // 其他描述
? ? ? ? ? ? ? ? ? ? ? ? ? ? procedural_statement; ? // 工序过程要素
? ? endfunction
函数调用格式:
? ? // 函数调用格式:
? ? function_id(input_data1, input_data2);
下面用函数实现一个数据大小端转换的功能:
// 大小端转换,就是把低位变高位,高位变低位。
module endian_rvs #(parameter N = 4) (
? ? input ? ? ? wire ? ? ? ? ? ? ? ? ? ?en ?, ? //enable control
? ? input ? ? ? wire ? ?[N-1:0] ? ? ? ? a ? ,
? ? output ? ? ?wire ? ?[N-1:0] ? ? ? ? b
?);
? ? // reg signal descrioption
? ? 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 ? ?wire ? ?[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 ;
函数声明还可以在函数名称后面加上括号,把输入端口包含进入:
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 ;
? ? ? ? //256为9bit,我们最终数据应该是8,所以需depth=2时提前停止循环
? ? for(logb2=0; depth>1; logb2=logb2+1) begin
? ? ? ? depth = depth >> 1 ;
? ? end
endfunction
automatic 函数:
用得很少。
在 Verilog 中,一般函数的局部变量是静态的,即函数的每次调用,函数的局部变量都会使用同一个存储空间。若某个函数在两个不同的地方同时并发的调用,那么两个函数调用行为同时对同一块地址进行操作,会导致不确定的函数结果。
Verilog 用关键字 automatic 来对函数进行说明,此类函数在调用时是可以自动分配新的内存空间的,也可以理解为是可递归的。因此,automatic 函数中声明的局部变量不能通过层次命名进行访问,但是 automatic 函数本身可以通过层次名进行调用。
文章来源:https://blog.csdn.net/Meng_long2022/article/details/134959451
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!