资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第17章,Verilog中的高级结构,学习内容:,任务和函数的定义和调用,怎样使用命名块,怎样禁止命名块和任务,有限状态机(,FSM,)及建模,Verilog的任务及函数,结构化设计是将任务分解为较小的,更易管理的单元,并将可重用代码进行封装。这通过将设计分成模块,或任务和函数实现。,任务(,task),通常用于调试,或对硬件进行行为描述,可以包含时序控制(,#,延迟,,wait,),可以有,input,,,output,,和,inout,参数,可以调用其他任务或函数,函数,(function),通常用于计算,或描述组合逻辑,不能包含任何延迟;函数仿真时间为,0,只含有,input,参数并由函数名返回一个结果,可以调用其他函数,但不能调用任务,Verilog的任务及函数,任务和函数必须在,module,内调用,在任务和函数中不能声明,wire,所有输入,/,输出都是,局部,寄存器,任务,/,函数执行完成后才返回结果。,例如,若任务,/,函数中有,forever,语句,则永远不会返回结果,任务,下面的任务中含有时序控制和一个输入,并引用了一个module变量,但没有输出、输入输出和内部变量,也不显示任何结果。,时序控制中使用的信号(例如ck)一定不能作为任务的输入,因为输入值只向该任务传送一次。,module top;,reg clk,a,b;,DUT u1(out,a,b,clk);,always#5 clk=!clk;,task,neg_clocks;,input 31:0 number_of_edges;,repeat(number_of_edges)(negedge clk);,endtask,initial begin,clk=0;a=1;b=1;,neg_clocks(3);/任务调用,a=0;neg_clocks(5);,b=0;,end,endmodule,任务,任务可以有,input,output,和,inout,参数。,传送到任务的参数和与任务,I/O,说明顺序相同。尽管传送到任务的参数名称与任务内部,I/O,说明的名字可以相同,但在实际中这通常不是一个好的方法。参数名的唯一性可以使任务具有好的模块性。,可以在任务内使用时序控制。,在,Verilog,中任务定义一个新范围(,scope),要禁止任务,使用关键字,disable,。,主要特点:,从代码中多处调用任务时要小心。,因为任务的局部变量的只有一个拷贝,并行调用任务可能导致错误的结果。在任务中使用时序控制时这种情况时常发生。,在任务或函数中引用调用模块的变量时要小心。,如果想使任务或函数能从另一个模块调用,则所有在任务或函数内部用到的变量都必须列在端口列表中。,函数,主要特性:,函数定义中不能包含任何时序控制语句。,函数至少有一个输入,不能包含任何输出或双向端口。,函数只返回一个数据,其缺省为,reg,类型。,传送到函数的参数顺序和函数输入参数的说明顺序相同。,函数在模块(,module),内部定义。,函数不能调用任务,但任务可以调用函数。,函数在,Verilog,中定义了一个新的范围(,scope),。,虽然函数只返回单个值,但返回的值可以直接给信号连接赋值。这在需要有多个输出时非常有效。,o1,o2,o3,o4=f_ or_ and(a,b,c,d,e);,函数,要返回一个向量值(多于一位),在函数定义时在函数名前说明范围。函数中需要多条语句时用begin和end。,不管在函数内对函数名进行多少次赋值,值只返回一次。下例中,函数还在内部声明了一个整数。,module,foo;,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;,integer,I;,begin,zero_count,=0;,for(I=0;I 8;I=I+1),if(!in_bus I),zero_count,=zero_count+1;,end,endfunction,endmodule,函数,函数返回值可以声明为其它register类型:integer,real,或time。,在任何表达式中都可调用函数,module,checksub(neg,a,b);,output,neg;,reg,neg;,input,a,b;,function,integer,subtr,;,input,7:0 in_a,in_b;,subtr,=in_a-in_b;/结果可能为负,endfunction,always,(a,or,b),if,(,subtr,(a,b)0),neg=1;,else,neg=0;,endmodule,函数,函数中可以对返回值的个别位进行赋值。,函数值的位数、函数端口甚至函数功能都可以参数化。,.,parameter,MAX_BITS=8;,reg,MAX_BITS:1 D;,function,MAX_BITS:1,reverse_bits,;,input,MAX_BITS-1:0 data;,integer,K;,for,(K=0;K MAX_BITS;K=K+1),reverse_ bits MAX_BITS-(K+1)=data K;,endfunction,always,(,posedge,clk),D=,reverse_bits,(D);,.,命名块(named block),在关键词,begin,或,fork,后加上,:,对块进行命名,module named_ blk;,.,begin,:seq_blk,.,end,.,fork:,par_blk,.,join,.,endmodule,在命名块中可以声明局部变量,可以使用关键词,disable,禁止一个命名块,命名块定义了一个新的范围,命名块会降低仿真速度,禁止命名块和任务,module,do_arith(out,a,b,c,d,e,clk,en_mult);,input,clk,en_mult;,input,7:0 a,b,c,d,e;,output,15:0 out;,reg,15:0 out;,always,(,posedge,clk),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);/任务调用,end,always,(,negedge,en_mult),begin,/中止运算,disable,multme;/*禁止任务*,disable,arith_block,;/*禁止命名块*,end,/下面定义任务和函数,endmodule,禁止命名块和任务,disable,语句终结一个命名块或任务的所有活动。也就是说,在一个命名块或任务中的所有语句执行完之前就返回。,语法:,disable,或,disable,当命名块或任务被禁止时,所有因他们调度的事件将从事件队列中清除,disable,是典型的不可综合语句。,在前面的例子中,只禁止命名块也可以达到同样的目的:所有由命名块、任务及其中的函数调度的事件都被取消。,有限状态机,隐式状态机FSM,不需要声明状态寄存器,仿真效率高,只适合于线性的状态改变,大多数综合工具不能处理,显式,FSM,:,利于结构化,易于处理缺省条件,能处理复杂的状态改变,所有综合工具都支持,有限状态机,在隐式,FSM,中,只要数据在一个时钟沿写入并在另一个周期读出,则会生成寄存器。,所有,FSM,必须有复位,且状态改变必须在单一时钟信号的同一边沿。,通常,如果状态改变简单明确,且综合工具接受隐式状态机,就可以使用隐式类型。如果状态改变很复杂,则显式类型更加有效。,隐式状态机是一个行为级而非,RTL,代码的典型例子。这种代码依赖循环和内嵌时序控制,有时也有命名事件、,wait,和,disable,语句。因此,隐式状态机在综合时通常不被支持。,线性,FSM,是指从一个状态到下一个状态的转换不需要任何条件。,显式有限状态机,module,exp(out,datain,clk,rst);,input,clk,rst,datain;,output,out;,reg,out;,reg,state;,always,(posedge clk,or,posedge rst),if,(rst)state,out=2b00;,else,case,(state),1b0:,begin,out=1b0;,if,(!datain)state=1b0;,else,state=1b1;,end,1b1:,begin,out=datain;,state=1b0;,end,default,:state,out=2b00;,endcase,endmodule,显式有限状态机,可以在过程块中用单一时钟边沿和,case,语句显式地描述,FSM,。,必须声明定义状态机的状态状态变量。,要改变当前状态,必须在时钟边沿改变状态变量的值。,给通常不会发生的条件指定缺省动作是一个很好的描述方式。,隐式有限状态机,module,imp(out,datain,clk,rst);,output,out;,reg,out;,input,clk,datain,rst;,always,(rst)/Synergy reset method,if,(rst)assign out=1b0;,else,begin,deassign out;,disable,seq_block,;/返回初始状态,end,always,(posedge clk),begin,:,seq_block,out=1b0;,if(!datain)/状态1:output=0,disable seq_block;,/状态2:output=2nd bit,(posedge clk)out=datain;,end,endmodule,隐式有限状态机,可以在过程块中用多个时钟边沿(每个状态一个),条件语句,循环,和,disable,语句隐式地描述一个,FSM,。通常不可综合。,不必声明状态变量。,在下一个时钟边沿改变状态,除非迫使状态重复。例如在一个循环中或用一个,disable,语句。下一个状态可以由条件语句决定。,复习,在,Verilog,中什么结构能产生一个新的“范围”?,哪些结构可以被禁止?,什么时候一个函数比一个任务更合适?反过来呢?,解答,模块,任务,函数,和命名块。,Verilog,中模块作为主要层次分割方法。函数和任务提供附加的代码分割和封装方法。,命名块和任务可以被禁止。,函数更适用于组合逻辑描述,并且使用灵活(例如在一个持续赋值的右边或在一个端口列表里)。如果需要时序控制,则任务更适合。任务还可以被禁止。,第18章,用户定义基本单元,学习内容:,学习如何使用用户定义基本单元进行逻辑设计,术语及定义,UDP:,用户定义基本单元,其行为和,Verilog,内部的基本单元相似。其功能用真值表定义。,什么是UDP,在Verilog结构级描述中,可以使用:,二十多个内部门级基本单元,用户自定义基本单元,UDP,在,ASIC,库单元开发、中小型芯片设计中很有用,可以使用,UDP,扩充已定义的基本单元集,UDP,是自包容的,也就是不需要实例化其它模块,UDP,可以表示时序元件和组合元件,UDP,的行为由真值表表示,UDP,实例化与基本单元实例化相同,什么是UDP,可以使用,UDP,扩充已定义的基本单元集,UDP,是一种非常紧凑的逻辑表示方法。,UDP,可以减少消极(,pessimism,)因素,因为一个,input,上的,x,不会像基本单元那样自动传送到,output,。,一个,UDP,可以替代多个基本单元构成的逻辑,因此可以大幅减少仿真时间和存储需求。相同逻辑的行为级模型甚至可以更快,这取决于仿真器。,UDP的特点,UDP,只能有一个输出,如果在功能上要求有多个输出,则需要在,UDP,输出端连接其它的基本单元,或者同时使用几个,UDP,。,UDP,可以有,1,到,10,个输入,若输入端口超过,5,,存储需求会大幅增加。下表列出输入端口数与存储需求的关系。,所有端口必须为标量且不允许双向端口,不支持逻辑值,Z,输出端口必须列为端口列表的第一个,时序,UDP,输出端可以用,initial,语句初始化为一个确定值。,UDP,不可综合,#输入,存储器(KB),#输入,存储器(KB),1-5,1,8,56,6,5,9,187,7,17,10,623,这两行用于减少消极因素。表示若a,b有相同逻辑值,即使sel=x,o也输出与a,b相同的值。Verilog内部基本单元不能描述这种行为。,UDP将X作为真实世界的未知值(0或1),,而不是Verilog值,描述也更为精确。,这两行表示不管a为何值,若s为o,o输出b值,组合逻辑举例:2-1多路器,UDP,在模块,(module),外部定义。,没有在真值表中说明的输入组合,输出,X,。,真值表中输入信号按端口列表顺序给出。,primitive,multiplexer,(,o,a,b,s);,output o;,input s,a,b;,table,/a b s :o,0?1 :0;,1?1 :1;,?0 0 :0;,?1 0 :1;,0 0 x :0;,1 1 x :1;,endtable,endprimitive,UDP名称,输出端口,真值表中?表示的逻辑值为:0、1或x,这两行表示不管b为何值,若s为1,o输出a值,组合逻辑,举例,:全加器,/FULL ADDER CARRY-OUT TERM,primitive U_ADDR2_C(CO,A,B,CI);,output CO;,input A,B,Ci;,table/A B CI :CO,1 1?:1;,1?1 :1;,?1 1 :1;,0 0?:0;,0?0 :0;,?0 0 :0;,endtable,endprimitive,全加器可以由两个组合逻辑UDP实现,/FULL ADDER SUM TERM,primitive U_ADDR2_S(S,A,B,CI);,output S;,input A,B,CI;,table/A B CI :S,0 0 0 :0;,0 0 1 :1;,0 1 0 :1;,0 1 1 :0;,1 0 0 :1;,1 0 1 :0;,1 1 0 :0;,1 1 1 :1;,endtable,endprimitive,组合逻辑举例:全加器,当需要大量全加器时,可以大幅度减少存储器需求,大幅减小事件数目。使用内部基本单元时,事件通过,3,个基本单元后才能到达进位输出;而使用,UDP,,事件只需经过一个基本单元。,全加器可以由两个组合逻辑UDP实现,而不使用内部基本单元。,电平敏感时序元件举例:锁存器latch,锁存器的行为如下:,当时钟输入为,0,时,,data,输入的值传送到输出。,当时钟输入为,1,时,输出不变。,这种加电初始化在实际元件中很少见,但在,UDP,功能测试时很有用。,primitive latch(q,clock,data);,output q;,reg q;,input clock,data;,initial q=1b1;,table,/clock data current next,/state state,0 1 :?:1;,0 0 :?:0;,1?:?:-;,endtable,endprimitive,输出必须声明为reg以保存前一状态,时序UDP初始化语句,将输出初始化为1,输入及当前状态中的?表示无关值,用另一个场表示下一状态,-状态值表示输出没有变化,边沿敏感时序元件举例:D触发器,在任何一个真值表入口语句中只能说明一个输入跳变。,如果说明了任何输入跳变,则必须说明所有输入上的所有跳变。,primitive d_edge_ff(q,clk,data);,output q;,input clk,data;,reg q;,table/clk dat state next,(01)0 :?:0;,(01)1 :?:1;,(0 x)1 :1 :1;,(0 x)0 :0 :0;,(x1)0 :0 :0;,(x1)1 :1 :1;,/忽略时钟下降沿,(?0)?:?:-;,(1x)?:?:-;,/时钟稳定时忽略data变化,?(?):?:-;,endtable,endprimitive,表里有边沿项表示输入跳变。,在一条入口语句中只能说明一个输入跳变,因为,Verilog,仿真是基于事件,一次只允许一个事件发生。,在每个时间步中,电平入口优先于边沿入口,因为电平最后处理。因此,下面的出口:,(?0)?:?:-;,可由下式取代,:,0?:?:-;,两个都给出时,只有后者起作用,提高可读性的简写形式,Verilog中有一些符号可用于UDP真值表中以提高可读性,符号,表示,解释,-,没有变化,时序元件输出的下一个值与当前值相同,?,0、1或x,任何值,b,0或1,任何确定值,r,(01),0-1跳变,f,(10),1-0跳变,p,(01)、(0 x)或(x1),任何上升沿(posedge),n,(10)、(1x)或(x0),任何下降沿(negedge),*,(?),任何跳变,提高可读性的简写形式,table,/clk dat state next,r,0 :?:0;,r,1 :?:1;,(0 x)1 :1 :1;,(0 x)0 :0 :0;,(x1)1 :1 :1;,(x1)0 :0 :0;,/忽略时钟的下降沿,n,?:?:-;,/忽略时钟稳定时的任何数据变化,?,*,:?:-;,endtable,带同步复位的D触发器,primitive U_ff_p_cl(q,d,clk,cl);,input d,clk,cl;,output q;,reg q;,table,/dclk cl:q:q+1,1r 1:?:1;/clock 1,0 r?:?:0;/clock 0,?r 0:?:0;/reset,?p 0:0:-;/reducing pessimism,1 p 1:1:-;,0 p?:0:-;,?n?:?:-;/ignore falling clk,*?:?:-;/ignore changes on d,?*:?:-;/ignore changes on clk,endtable,endprimitive,带使能和复位的锁存器,primitive u_latch_cl(q,d,g,cl);,output q;,input d,g,cl;,reg q;,table,/dgcl:q:q+1,01?:?:0;,11?:?:1;,1?0:1:1;/reducing pessimism,0?0:0:0;/reducing pessimism,0?1:?:0;/reducing pessimism,0?:0:0;/reducing pessimism,?00:?:-;/latch disabled,?01:?:0;/clear,endtable,endprimitive,当使能g为高(H)时,锁存器锁存d;只有当g为低时复位信号cl才有效(高有效)。,使用通报符(notifier)的寄存器,timescale 1ns/1ns,module dff_nt(q,ck,d,rst);,input ck,d,rst;,output q;,reg nt;,U_FFD_RB i1(q,d,ck,rst,nt);,specify,specparam tsu=2;,(ck=q)=(2:3:4);,$setup(d,posedge ck,tsu,nt);,endspecify,endmodule,下面的例子是异步复位的上升沿D触发器,有时序检查和路径延迟。这个模型使用了一个UDP,并将通报符作为UDP的一个输入。,primitive U_ FFD_ RB(Q,D,CP,RB,NT);,output Q;reg Q;,input D,CP,RB,NT;,table,/D CP RB NT :Q :Q+1,0 r?:?:0;,/clock a 0,1 r 1?:?:1;,/clock a 1,1 p 1?:1 :-;,/reducing pessimism,0 p?:0 :-;,/reducing pessimism,?0?:?:0;,/asynchronous reset,?x?:0 :-;,/reducing pessimism,?n?:?:-;,/ignore falling clock,*?:?:-;,/ignore rising edges on D,?*?:?:-;,/ignore changes on reset,?*:?:x;,/NT变化使Q产生x,endtable,endprimitive,第19章,Verilog的可综合描述风格,学习目标:,学习组合逻辑和时序逻辑的可综合的描述风格及技术,包括:,不支持的,Verilog,结构,过程块,寄存器,敏感列表,持续赋值,综合指导,条件结构,阻塞及非阻塞赋值,锁存器,/MUX,推断,函数,function,任务,task,复位,有限状态机,FSM,宏库及设计复用,描述风格简介,如果逻辑输出在任何时候都直接由当前输入组合决定,则为,组合逻辑,。,如果逻辑暗示存储则为,时序逻辑,。如果输出在任何给定时刻不能由输入的状态决定,则暗示存储。,通常综合输出不会只是一个纯组合或纯时序逻辑。,一定要清楚所写的源代码会产生什么类型输出,,并能够反过来确定为什么所用的综合工具产生这个输出,,这是非常重要的。,不支持的Verilog结构,综合工具通常不支持下列Verilog结构:,initial,循环,:,repeat,forever,while,非结构化的for语句,数据类型,:,event,real,time,UDP,forkjoin块,wait,过程持续赋值:,assign deassign,force release,操作符:,=,!=,过程块,任意边沿,在所有输入信号的任意边沿进入的过程块产生组合逻辑。这种过程块称为组合块。,always(a or b)/,与门,y=a,单个边,沿,在一个控制信号的单一边沿上进入的过程块产生同步逻辑。这种过程块称为同步块。,always(posedge clk)/D flip-flop,q =d;,同步块也可以对异步复位信号的变化产生敏感,always(posedge clk or negedge rst_),if(!rst_)q=0;,else q=d;,过程块中的寄存器类型,若同步块中使用一个,reg,,则:,如果在一个时钟周期赋值并在另一个周期被采样,则只能以硬件寄存器实现。,如果,reg,还是一个基本输出,它会出现在综合网表中,但不一定是一个硬件寄存器。,若两者都不是,该信号可能被优化掉。,若组合块中使用一个,reg,,,则:,如果,reg,值随块的任何一个输入的变化而改变,则在综合时不会产生硬件寄存器。,如果,reg,值并不总是随块的输入变化而改变,则综合时会产生一个锁存器。,同步寄存器举例,在这个例子中,rega只作暂存,因此会被优化掉。,module ex1reg(d,clk,q);,input d,clk;,output q;,reg q,rega;,always(,posedge,clk),begin,rega=0;,if(d)rega=1;,q=rega;,end,endmodule,在这个例子中,rega产生一个寄存器,不会被优化掉。,module ex2reg(d,clk,q);,input d,clk;,output q;,reg q,rega;,always(,posedge,clk),begin,rega=0;,if(d)rega=1;,end,always(,posedge,clk),q=rega;,endmodule,组合逻辑中的寄存器类型举例,在这个例子中,y和rega总是赋新值,因此产生一个纯组合逻辑。,module ex3reg(y,a,b,c);,input a,b,c;,output y;,reg y,rega;,always(a or b or c),begin,if(a&b),rega=c;,else,rega=0;,y=rega;,end,endmodule,在这个例子中,rega不总是产生新值,因此会产生一个锁存器,y是锁存器的输出,module ex4reg(y,a,b,c);,input a,b,c;,output y;,reg y,rega;,always(a or b or c),begin,if(a&b),rega=c;,y=rega;,end,endmodule,在下面的例子,rega是暂存变量,并被优化掉,敏感列表,敏感表不完全:,module sens(a,q,b,sl);,input a,b,sl;,output q;,reg q;,always(sl),begin,if(!sl),q=a;,else,q=b;,end,endmodule,完全的敏感列表,module sensc(q,a,b,sl);,input a,b,sl;,output q;,reg q;,always(sl or a or b),begin,if(!sl),q=a;,else,q=b;,end,endmodule,在下面的例子,a,b,sl是块的输入,sl,用作条件,a,、,b,用在过程赋值语句的右边,将块的所有输入都列入敏感表是很好的描述习惯。不同的综合工具对不完全敏感表的处理有所不同。有的将不完全敏感表当作非法。其他的则产生一个警告并假设敏感表是完全的。在这种情况下,综合输出和RTL描述的仿真结果可能不一致。,敏感列表,将块的所有输入都列入敏感表是很好的描述习惯。不同的综合工具对不完全敏感表的处理有所不同。有的将不完全敏感表当作非法。其他的则产生一个警告并假设敏感表是完全的。在这种情况下,综合输出和RTL描述的仿真结果可能不一致。,上述两例综合结果(SYNOPSYS)相同,但RTL描述的仿真结果不同。也就是左边的敏感表不完全的例子的RTL描述和综合出的网表的仿真结果不同。,module sens_t;,reg a,b,sl;,sens u1(a,q,b,sl);,sensc u2(qc,a,b,sl);,initial,begin,$monitor($time,%b%b%b%b%b,a,b,sl,q,qc);,a=0;b=0;sl=0;,#10 a=1;,#10 sl=1;,#10 sl=0;,#10$finish;,end,endmodule,0 0 0 0 0 0,10 1 0 0 0 1,20 1 0 1 0 0,30 1 0 0 1 1,持续赋值,module orand(out,a,b,c,d,e);,input a,b,c,d,e;,output out;,assign out=e,endmodule,持续赋值驱动值到net上。因为驱动是持续的,所以输出将随任意输入的改变而随时更新,因此将产生组合逻辑。,过程持续赋值,module latch_quasi(q,en,d);,input en,d;,output q;,reg q;,always(en),if(en),assign q=d;,else,deassign q;,endmodule,过程持续赋值是在过程块(always或initial)内给一个寄存器数据类型进行的持续赋值。这在大多数综合工具中是非法的。,综合指示,大多数综合工具都能处理综合指示。,综合指示可以嵌在,Verilog,注释中,因此他们在,Verilog,仿真时忽略,只在综合工具解析时有意义。,不同工具使用的综合指示在语法上不同。但其目的相同,都是在,RTL,代码内部进行最优化。,通常综合指示中包含工具或公司的名称。例如,下面介绍的,Envisia Ambit synthesis,工具的编译指示都以,ambit synthesis,开头。,综合指示,这里列出部分Cadence综合工具中综合指示。这些与其他工具,如Synopsys Design Compiler,中的指示很相似。,/ambit synthesis on,/ambit synthesis off,/ambit synthesis case=full,parallel,mux,结构指示,/ambit synthesis architecture=cla or rpl,FSM指示,/ambit synthesis enum xyz,/ambit synthesis state_vector sig state_vector_ flag,综合指示 case指示,case语句通常综合为一个优先级编码器,列表中每个case项都比后面的case项的优先级高。,Case指示按下面所示指示优化器:,/ambit synthesis case=parallel,建立并行的编码逻辑,彼此无优先级。,/ambit synthesis case=mux,若库中有多路器,使用多路器建立编码逻辑。,/ambit synthesis case=full,假定所有缺少的,case,项都是“无关”项,使逻辑更为优化并避免产生锁存器。,条件语句,自然完全的条件语句,module comcase(a,b,c,d,e);,input a,b,c,d;,output e;,reg e;,always(a or b or c or d),case(a,b),2b11:e=d;,2b10:e=c;,2b01:e=1b0;,2b00:e=1b1;,endcase,endmodule,module compif(a,b,c,d,e);,input a,b,c,d;,output e;,reg e;,always(a or b or c or d),if(a&b),e=d;,else if(a&b),e=c;,else if(a&b),e=1b0;,else if(a&b),e=1b1;,endmodule,例中定义了所有可能的选项,综合结果是纯组合逻辑,没有不期望的锁存器产生。,不完全条件语句,module inccase(a,b,c,d,e);,input a,b,c,d;,output e;,reg e;,always(a or b or c or d),case(a,b),2b11:e=d;,2b10:e=c;,endcase,endmodule,module incpif(a,b,c,d,e);,input a,b,c,d;,output e;,reg e;,always(a or b or c or d),if(a&b),e=d;,else if(a&b),e=c;,endmodule,在上面的例子中,当a变为零时,不对e赋新值。因此e保存其值直到a变为1。这是锁存器的特性。,若 a 变为 0,,e,为何值,default完全条件语句,module comcase(a,b,c,d,e);,input a,b,c,d;,output e;,reg e;,always(a or b or c or d),case(a,b),2b11:e=d;,2b10:e=c;,default:e=bx;,endcase,endmodule,module compif(a,b,c,d,e);,input a,b,c,d;,output e;,reg e;,always(a or b or c or d),if(a&b),e=d;,else if(a&b),e=c;,else,e=bx;,endmodule,综合工具将 bx作为无关值,因此if语句类似于“full case”,可以进行更好的优化。,例中没有定义所有选项,但对没有定义的项给出了缺省行为。同样,其综合结果为纯组合逻辑没有不期望的锁存器产生。,指示完全条件语句,module dircase(a,b,c,d);,input b,c;,input 1:0 a;,output d;,reg d;,always(a or b or c),case(a)/,ambit synthesis case=full,2b00:d=b;,2b01:d=c;,endcase,endmodule,和前例一样,没有定义所有case项,但综合指示通知优化器缺少的case项不会发生。结果也为纯组合逻辑,没有不期望锁存器产生。注意如果缺少的case项发生,而其结果未定义,综合结果和RTL的描述的行为可能不同。,case指示例外,module select(a,b,sl);,input 1:0 sl;,output a,b;,req a,b;,always(sl),case(sl)/ambit synthesis case=full,2b00:begin a=0;b=0;end,2b01:begin a=1;b=1;end,2b10:begin a=0;b=1;end,2b11:b=1;,default:begin a=bx;b=bx;end,endcase,endmodule,有时使用了case full指示,case语句也可能综合出latch。,下面的描述综合时产生了一个latch。,函数,module orand(out,a,b,c,d,e);,input a,b,c,d,e;,output out;wire out;,assign out=,forand,(a,b,c,d,e);,function,forand,;,input a,b,c,d,e;,if(e=1),forand=(a|b),else,forand=0;,endfunction,endmodule,函数没有时序控制,因此综合结果为组合逻辑。函数可以在过程块内或持续赋值语句中调用。,下例中的or/and块由持续赋值语句调用函数实现,任务,module orandtask(out,a,b,c,d,e);,input a,b,c,d,e;,output out;reg out;,always(a or b or c or d or e),orand(out,a,b,c,d,e);,task orand;,input a,b,c,d,e;,output out;,if(e=1),out=(a|b),else,out=0;,endtask,endmodule,任务一般只在测试基准使用,因为:,没有时序控制的任务如同函数,带有时序控制的任务不可综合,下面是用任务描述的,or/and,块:,锁存器(latch)推断,module latch(q,data,enable);,input data,enable;,output q;,reg q;,always(enable or data),if(enable),q=data;,endmodule,在always块中,如果没有说明所有条件,将产生latch。,在下面的例子中,由于没有定义enable为低电平时data的状态,因此enable为低电平时data的值必须保持,综合时将产生一个存储元件,同步反馈(feedback)推断,有反馈:,module dffn(q,d,clk,en);,input d,clk,en;,output q;,reg q;,always(negedge clk),if(en),q=d;,endmodule,综合工具一般不支持组合逻辑反馈,但支持同步反馈。,在同步过程块中,如果条件语句的一个分支没有给所有输出赋值,则推断出反馈。,无反馈:,module dffn(q,d,clk,en);,input d,clk,en;,output q;,reg q;,always(negedge clk),if(en),
展开阅读全文