verilog模块的调用、任务和函数

天资达人 科技创新 2025-05-04 4988 0

模块的调用(上层模块对底层模块的调用)

在做模块划分时,通常会出现这种情形,某个大的模块中包含了一个或多个功能子模块,verilog是通过模块调用或称为模块实例化的方式来实现这些子模块与高层模块的连接的

调用模块实例化的一般形式为:

<模块名> <参数列表> <实例名> ( <端口列表> );

其中参数列表是传递到子模块的参数值,参数传递的典型应用是定义门级时延。

信号端口可以通过位置或名称关联,但是关联方式不能够混合使用

名称关联&位置关联

定义模块:module Design(端口1,端口2,端口3...)

位置关联:

引用时,严格按照模块定义的端口顺序来连接,不用标明元模型定义时规定的端口名。

Designu1(u1的端口1,u1的端口2,u1的端口3)

名称关联:

引用时用“.”符号,标明原模型定义时规定的端口名:

Designu2(.端口1(u1的端口1), .端口2(u1的端口2), .端口3(u1的端口3) )

eg:

moduleand(C,A,B)input A,B;output C; 位置相关andA1(T3,A,B)名称相关andA2(   .C(T3),   .A(A),   .B(B))

模块的调用---参数传递

//子模块moduleDecode(A,F);  parameterwidth =1,polarity=1;endmodule//顶层模块moudle top;  wire[3:0] A4;  wire[4:0] A5;  wire[15:0] F16;  wire[31:0] F32;   Decode#(4,0) D1(A4,F16);endmodule

ps:在top模块中引用Decode实例时,可通过参数的传递来改变定义时已规定的参数值,即通过

#(4,0),实例D1实际引用的是参数width和polarity分别为4与0时的Decode模块

传递参数的另一种方法

module_name#(.parametername(para_value),.parametername(para_value))inst_name(port_map) 实际就为: Decode#(.width(4),.polarity(0))D1(A4,F16)

注意事项

位选择,如.C(D[0]),C端口接到了D信号的第0bit位;

部分选择,如.Bus(Din[5:4])

上述类型的合并,如.Addr({A1,A2[1:0]})

悬空端口的处理:

在实例化中,可能有些管脚没用到,可在映射中留白处理

DFF d1(.Q(QS),.Qbar(),.Data(D),.Preset(),//该管脚悬空.clock(CK); )

PS:输入管脚悬空,该管脚输入为高阻Z,输出管脚悬空,该管脚废弃不用

任务和函数

task和function语句分别用来由用户定义任务和函数;

任务和函数往往时大的程序模块中在不同地点多次用到的相同的程序段

利用任务和函数可将一个很大的程序模块分解为许多较小的任务和函数,便于理解和调试

任务定义

task
 <任务名>
  ;   端口及数据类型声明语句;   其他语句;endtask
 

任务调用

<任务名> (端口1,端口2,......);

task语句

任务的定义与调用必须在一个module模块内

任务被调用时,需列出端口名列表,且必须与任务定义中的I/0变量一一对应

一个任务可以调用其他任务和函数

//任务定义task my_task;   input a,b;  inoutc;//一个三态门,由一个开关控制这个门是输入还是输出  output d,e;   ......   
 <语句>
  //执行任务工作相应的语句  .....   c = foo1;   d = foo2;   e = foo3;//对任务变量进行赋值endtask//任务调用my_task(v,w,x,y,z)//为位置关联,v对应a,w对应b,c对应x,y对应d,z对应e
 

0f532724-218a-11f0-9310-92fbcf53809c.png

函数function(可以综合)

函数的目的是通过返回一个用于某表达式的值,来响应输入信号(适于对不同变量采取同一运算的操作)

函数在模块内部定义,通常在本模块中调用,也能根据按模块层次分级命名的函数名从其他模块调用。而任务只能在同一模块内定义与调用

function
 <返回值位宽或类型说明>
  函数名;//如缺少位宽定义,则默认为一 端口声明; 局部变量定义; 其他语句;endfunction
 

函数的调用 <函数名> ( <表达式> <表达式> )

注:函数的调用是通过将函数作为调用函数的表达式中的操作数来实现的

函数规则

函数不能包含任何时间控制的语句,如#,@,wait,poesdge,negedege

函数不能调用任务,因为任务可以包含时间控制语句,但是可以调用其他函数

函数应该至少有一个输入

函数不能有非阻塞性的赋值或force....release或assign...deassign

函数不能有任何触发器

函数不能有output或inout

函数的声明:

function[7:0] sum;  input[7:0] a, b;  begin    sum = a + b;  endendfunctionfunction[7:0] sum (input[7:0] a, b);  begin    sum = a + b;  endendfunction———————————————— 版权声明:本文为CSDN博主「李锐博恩」的原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/Reborn_Lee/article/details/107447734

函数的调用:

reg [7:0]result; reg [7:0] a, b;initialbegin  a=4;   b=5;   #10result=sum(a, b);end

利用一个函数对一个8位二进制数中为0的位进行计数

//count the numbers of 0 in rega[7:0]modulecount_0 (numbers,rega);  output[7:0] numbers;  input[7:0] rega;  function[7:0] get_n_of_0;//define a function   input[7:0] x;    reg[7:0] count;    integeri;      begin        count =0;        for(i=0;i<=7;i++)                     if(x[i] == 1'b0)                          count = count +1;                     get_n_of_0 = count; //函数名就相当于输出变量;                end;     endfunctionassign number = get_n_of_0(rega);endmodule

ps:函数名就相当于输出变量

函数和任务