您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 管理学资料 > 第17章-Verilog中的高级结构
第17章Verilog中的高级结构学习内容:•任务和函数的定义和调用•怎样使用命名块•怎样禁止命名块和任务•有限状态机(FSM)及建模Verilog的任务及函数结构化设计是将任务分解为较小的,更易管理的单元,并将可重用代码进行封装。这通过将设计分成模块,或任务和函数实现。•任务(task)通常用于调试,或对硬件进行行为描述可以包含时序控制(#延迟,@,wait)可以有input,output,和inout参数可以调用其他任务或函数•函数(function)通常用于计算,或描述组合逻辑不能包含任何延迟;函数仿真时间为0只含有input参数并由函数名返回一个结果可以调用其他函数,但不能调用任务Verilog的任务及函数•任务和函数必须在module内调用•在任务和函数中不能声明wire•所有输入/输出都是局部寄存器•任务/函数执行完成后才返回结果。例如,若任务/函数中有forever语句,则永远不会返回结果任务下面的任务中含有时序控制和一个输入,并引用了一个module变量,但没有输出、输入输出和内部变量,也不显示任何结果。时序控制中使用的信号(例如ck)一定不能作为任务的输入,因为输入值只向该任务传送一次。moduletop;regclk,a,b;DUTu1(out,a,b,clk);always#5clk=!clk;taskneg_clocks;input[31:0]number_of_edges;repeat(number_of_edges)@(negedgeclk);endtaskinitialbeginclk=0;a=1;b=1;neg_clocks(3);//任务调用a=0;neg_clocks(5);b=0;endendmodule任务•任务可以有input,output和inout参数。•传送到任务的参数和与任务I/O说明顺序相同。尽管传送到任务的参数名称与任务内部I/O说明的名字可以相同,但在实际中这通常不是一个好的方法。参数名的唯一性可以使任务具有好的模块性。•可以在任务内使用时序控制。•在Verilog中任务定义一个新范围(scope)•要禁止任务,使用关键字disable。主要特点:从代码中多处调用任务时要小心。因为任务的局部变量的只有一个拷贝,并行调用任务可能导致错误的结果。在任务中使用时序控制时这种情况时常发生。在任务或函数中引用调用模块的变量时要小心。如果想使任务或函数能从另一个模块调用,则所有在任务或函数内部用到的变量都必须列在端口列表中。任务下面的任务中有输入,输出,时序控制和一个内部变量,并且引用了一个module变量。但没有双向端口,也没有显示。任务调用时的参数按任务定义的顺序列出。modulemult(clk,a,b,out,en_mult);inputclk,en_mult;input[3:0]a,b;output[7:0]out;reg[7:0]out;always@(posedgeclk)multme(a,b,out);//任务调用taskmultme;//任务定义input[3:0]xme,tome;output[7:0]result;wait(en_mult)result=xme*tome;endtaskendmodule函数(function)函数中不能有时序控制,但调用它的过程可以有时序控制。函数名f_or_and在函数中作为register使用moduleorand(a,b,c,d,e,out);input[7:0]a,b,c,d,e;output[7:0]out;reg[7:0]out;always@(aorborcordore)out=f_or_and(a,b,c,d,e);//函数调用function[7:0]f_or_and;input[7:0]a,b,c,d,e;if(e==1)f_or_and=(a|b)&(c|d);elsef_or_and=0;endfunctionendmodule函数主要特性:•函数定义中不能包含任何时序控制语句。•函数至少有一个输入,不能包含任何输出或双向端口。•函数只返回一个数据,其缺省为reg类型。•传送到函数的参数顺序和函数输入参数的说明顺序相同。•函数在模块(module)内部定义。•函数不能调用任务,但任务可以调用函数。•函数在Verilog中定义了一个新的范围(scope)。•虽然函数只返回单个值,但返回的值可以直接给信号连接赋值。这在需要有多个输出时非常有效。{o1,o2,o3,o4}=f_or_and(a,b,c,d,e);函数要返回一个向量值(多于一位),在函数定义时在函数名前说明范围。函数中需要多条语句时用begin和end。不管在函数内对函数名进行多少次赋值,值只返回一次。下例中,函数还在内部声明了一个整数。modulefoo;input[7:0]loo;output[7:0]goo;//可以持续赋值中调用函数wire[7:0]goo=zero_count(loo);function[3:0]zero_count;input[7:0]in_bus;integerI;beginzero_count=0;for(I=0;I8;I=I+1)if(!in_bus[I])zero_count=zero_count+1;endendfunctionendmodule函数函数返回值可以声明为其它register类型:integer,real,或time。在任何表达式中都可调用函数modulechecksub(neg,a,b);outputneg;regneg;inputa,b;functionintegersubtr;input[7:0]in_a,in_b;subtr=in_a-in_b;//结果可能为负endfunctionalways@(aorb)if(subtr(a,b)0)neg=1;elseneg=0;endmodule函数函数中可以对返回值的个别位进行赋值。函数值的位数、函数端口甚至函数功能都可以参数化。...parameterMAX_BITS=8;reg[MAX_BITS:1]D;function[MAX_BITS:1]reverse_bits;input[MAX_BITS-1:0]data;integerK;for(K=0;KMAX_BITS;K=K+1)reverse_bits[MAX_BITS-(K+1)]=data[K];endfunctionalways@(posedgeclk)D=reverse_bits(D);...命名块(namedblock)•在关键词begin或fork后加上:块名称对块进行命名modulenamed_blk;...begin:seq_blk...end...fork:par_blk...join...endmodule•在命名块中可以声明局部变量•可以使用关键词disable禁止一个命名块•命名块定义了一个新的范围•命名块会降低仿真速度禁止命名块和任务moduledo_arith(out,a,b,c,d,e,clk,en_mult);inputclk,en_mult;input[7:0]a,b,c,d,e;output[15:0]out;reg[15:0]out;always@(posedgeclk)begin:arith_block//***命名块***reg[3:0]tmp1,tmp2;//***局部变量***{tmp1,tmp2}=f_or_and(a,b,c,d,e);//函数调用if(en_mult)multme(tmp1,tmp2,out);//任务调用endalways@(negedgeen_mult)begin//中止运算disablemultme;//***禁止任务***disablearith_block;//***禁止命名块***end//下面[定义任务和函数……endmodule禁止命名块和任务•disable语句终结一个命名块或任务的所有活动。也就是说,在一个命名块或任务中的所有语句执行完之前就返回。语法:disable块名称或disable任务名称•当命名块或任务被禁止时,所有因他们调度的事件将从事件队列中清除•disable是典型的不可综合语句。•在前面的例子中,只禁止命名块也可以达到同样的目的:所有由命名块、任务及其中的函数调度的事件都被取消。有限状态机隐式状态机FSM•不需要声明状态寄存器•仿真效率高•只适合于线性的状态改变•大多数综合工具不能处理显式FSM:•利于结构化•易于处理缺省条件•能处理复杂的状态改变•所有综合工具都支持有限状态机•在隐式FSM中,只要数据在一个时钟沿写入并在另一个周期读出,则会生成寄存器。•所有FSM必须有复位,且状态改变必须在单一时钟信号的同一边沿。•通常,如果状态改变简单明确,且综合工具接受隐式状态机,就可以使用隐式类型。如果状态改变很复杂,则显式类型更加有效。•隐式状态机是一个行为级而非RTL代码的典型例子。这种代码依赖循环和内嵌时序控制,有时也有命名事件、wait和disable语句。因此,隐式状态机在综合时通常不被支持。•线性FSM是指从一个状态到下一个状态的转换不需要任何条件。显式有限状态机moduleexp(out,datain,clk,rst);inputclk,rst,datain;outputout;regout;regstate;always@(posedgeclkorposedgerst)if(rst){state,out}=2'b00;elsecase(state)1'b0:beginout=1'b0;if(!datain)state=1'b0;elsestate=1'b1;end1'b1:beginout=datain;state=1'b0;enddefault:{state,out}=2'b00;endcaseendmodule显式有限状态机•可以在过程块中用单一时钟边沿和case语句显式地描述FSM。•必须声明定义状态机的状态状态变量。•要改变当前状态,必须在时钟边沿改变状态变量的值。•给通常不会发生的条件指定缺省动作是一个很好的描述方式。隐式有限状态机moduleimp(out,datain,clk,rst);outputout;regout;inputclk,datain,rst;always@(rst)//Synergyresetmethodif(rst)assignout=1’b0;elsebegindeassignout;disableseq_block;//返回初始状态endalways@(posedgeclk)begin:seq_blockout=1’b0;if(!datain)//状态1:output=0disableseq_block;//状态2:output=2ndbit@(posedgeclk)out=datain;endendmodule隐式有限状态机•可以在过程块中用多个时钟边沿(每个状态一个),条件语句,循环,和disable语句隐式地描述一个FSM。通常不可综合。•不必声明状态变量。•在下一个时钟边沿改变状态,除非迫使状态重复。例如在一个循环中或用一个disable语句。下一个状态可以由条件语句决定。复习1.在Verilog中什么结构能产生一个新的“范围”?2.哪些结构可以被禁止?3.什么时候一个函数比一个任务更合适?反过来呢?解答1.模块,任务,函数,和命名块。Verilog中模块作为主要层次分割方法。函数和任务提供附加的代码分割和封装方法。2.命名块和任务可以被禁止。3.函数更适用于组合逻辑描述,并且使用灵活(例如在一个持续赋值的右边或在一个端口列表里)。如果需要时序控制,则任务更适合。任务还可以被禁止。
本文标题:第17章-Verilog中的高级结构
链接地址:https://www.777doc.com/doc-4769198 .html