原创 Verilog中的任务与函数(转)

2010-12-26 11:50 5669 18 18 分类: FPGA/CPLD

任务和函数有助于简化程序,有点类似与Fortran语言的subroutine和function。


任务和函数的共同点:


1.任务和函数必须在模块内定义,其作用范围仅适用于该模块,可以在模块内多次调用。


2.任务和函数中可以声明局部变量,如寄存器,时间,整数,实数和事件,但是不能声明线网类型的变量。


3.任务和函数中只能使用行为级语句,但是不能包含always和initial块,设计者可以在always和initial块中调用任务和函数。


任务和函数的不同点:


函数任务
函数能调用另一个函数,但是不能调用任务任务可以调用另一个任务,也可以调用函数
函数总是在仿真时刻0开始任务可以在非零时刻开始执行
函数一定不能包含任何延迟,事件或者时序控制声明语句任务可以包含延迟,事件或者时序控制声明语句
函数至少要有一个输入变量,也可以有多个输入变量任务可以没有或者有多个输入,输出,输入输出变量
函数只能返回一个值,函数不能有输出或者双向变量任务不返回任何值,或者返回多个输出或双向变量值

由上述的特点决定:函数用于替代纯组合逻辑的verilog代码,而任务可以代替verilog的任何代码。


8.2任务


任务使用关键字task和endtask来进行声明,如果子程序满足下面任何一个条件,则必须使用任务而不能使用函数。


1.子程序中包含有延迟,时序或者事件控制结构


2.没有输出或者输出变量超过一个


3.没有输入变量


例:


module operation;
parameter delay=10;
reg [15:0] A,B, AB_AND,AB_OR,AB_XOR;
always @(A or B)
begin
     bitwise_ope(AB_AND,AB_OR,AB_XOR,A,B);
end
task  bitwise_oper;
output [15:0] ab_and,ab_or,ab_xor;
input [15:0] a,b;
begin
     #delay ab_and=a&b;
     ab_or=a|b;
     ab_xor=a^b;
end
endtask
always @(posedge clk)
    bitwise_xor(ef_xor,e,f);
always @(posedege clk2)
    bitwise_xor(cd_xor,c,d)
task autumatic bitwise_xor;
output ab_xor;
input  a,b;
begin
      ab_xor=a^b;
end
endtask
endmodule

自动(可重入)任务:verilog任务中所有声明的变量地址空间都是静态分配的,因此如果在一个模块中多次调用任务时,可能会造成地址空间的冲突,为了避免这个问题,verilog通过在task关键字后面添加automatic使任务称为可重入的,这时在调用任务时,会自动给任务声明变量分配动态地址空间,这样有效避免了地址空间的冲突。


8.3 函数


函数使用关键字function和endfunction定义,对于子程序,如果满足下述所有条件则可以用函数来完成:


1.在子程序中不含有延迟时序或者控制结构
2.子程序只有一个返回值
3.至少有一个输入变量
4.没有输出或者双向变量
5.不含有非阻塞赋值语句

例:


module parity;
reg [31:0] addr;
reg parity;
always @(addr)
begin
  parity=calc_parity(addr);
end
function calc_parity;
input [31:0] addr;
begin
calc_parity=^addr;
end
endfunction
endmodule

跟任务调用一样,在模块中如果调用多次函数,也会碰到地址冲突的问题,因此也引入automatic关键字来对函数可重用性声明。没有进行可重用性声明的函数不可以多次或者递归调用,进行了可重用性声明的函数可以递归调用。


常量函数和带符号函数(函数声明时加signed关键字说明)


module ram;
parameter RAM_DEPTH=256;
input [clogb2(RAM_DEPTH)-1:0] addr;//clogb2函数返回值为8
function integer clogb2(input integer depth);
begin
   for(clogb2=0; depth>0;clogb2=clogb2+1)
             depth=depth>1;
end
endfunction
endmodule

 


练习:用两种不同的方法设计一个功能相同的模块,完成4个8位2进制输入数据的冒泡排序。第一种,用纯组合逻辑实现;第二种,假设8位数据按照时钟节拍串行输入,要求时钟触发任务的执行,每个时钟周期完成一次数据交换的操作。


 


 


 


//----------------- 第一种 ------------------


module sort4(ra,rb,rc,rd,a,b,c,d);


 


output[7:0] ra,rb,rc,rd;


input[7:0] a,b,c,d;


reg[7:0] ra,rb,rc,rd;


reg[7:0] va,vb,vc,vd;


 


always @ (a or b or c or d)


 begin


   {va,vb,vc,vd}={a,b,c,d};


   


    change(va,vb);


    change(vb,vc);


    change(vc,vd);


   


    change(va,vb);


    change(vb,vc);


   


    change(va,vb);


    


    {ra,rb,rc,rd}={va,vb,vc,vd};


 end


 


task change;  //make a task of comparing


inout[7:0] x,y; 


reg[7:0] tmp;


   if(x>y) 


     begin


       tmp=x; 


       x=y;


       y=tmp;


     end


endtask


 


endmodule


 


 


 


//----------------- 第二种 ------------------


module sort4(clk,reset,ra,rb,rc,rd,a);


 


output[7:0] ra,rb,rc,rd;


input[7:0] a;


input clk,reset;


reg[7:0] ra,rb,rc,rd;


reg[7:0] va,vb,vc,vd;


 


always @ (posedge clk)


 begin


    if(!reset)


      begin


        va<=0;vb<=0;vc<=0;vd<=0;


      end


    else


      va<=a;


 end


        


always @ (posedge clk)


 begin


   


    change(va,vb);


    change(vb,vc);


    change(vc,vd);


   


    change(va,vb);


    change(vb,vc);


   


    change(va,vb);


    


    {ra,rb,rc,rd}={va,vb,vc,vd};


 end


 


task change;  //make a task of comparing


inout[7:0] x,y; 


reg[7:0] tmp;


   if(x>y) 


     begin


       tmp=x; 


       x=y;


       y=tmp;


     end


endtask


 


endmodule

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
18
关闭 站长推荐上一条 /3 下一条