HMECMicroElectronicsCenterVerilog中的always过程块是通用的,不能反映准确的设计意图,SystemVerilog增加了硬件专用类型的过程块,能够准确反映设计意图,使模拟、综合、形式检查、lint检查等EDA工具精确地完成任务,并使不同的EDA工具保持一致性;SystemVerilog对任务和函数进行了许多改进,增强了任务和函数对大规模、复杂设计建模能力。组合逻辑过程块锁存逻辑过程块时序逻辑过程块任务与函数的改进第6章SystemVerilog过程块、任务和函数HMECMicroElectronicsCenter6.1Verilog通用目的always过程块always过程块是一个能重复执行的语句块的无限循环,循环包括了时间控制或事件控制以使模拟时间向前推进。always过程块用于对象建模,可以用作组合逻辑、锁存逻辑和时序逻辑的RTL建模,也可用于对算法建模及在测试平台中时钟的建模。always过程块通常包括敏感表,只有敏感表中的信号发生变化时,过程块才能被触发执行。由于always过程块是通用的,工具必须从过程块内容推断设计意图,加大软件工具的负担。VerilogRTL综合的IEEE1364.1标准中给出了always过程块的组合逻辑、锁存逻辑和时序逻辑的综合指导方针,但并不要求强制执行,且always的模拟与综合不依照同样的语法规则,使得模拟与综合结果不一致!HMECMicroElectronicsCenter6.2SystemVerilog特有的过程块SystemVerilog增加了3个能够明确表示设计意图的过程块:always_comb、always_latch和always_ff;如果特有的过程块的内容与其相应逻辑不匹配,软件工具会发出警告信息;特有过程块与always一样是无限循环的,在特有块中加入了限制建模类型的句法和语义的规则,从而与IEEE1364.1综合标准一致。通过使用always_comb、always_latch和always_ff过程块,不仅是软件工具,其它查看或维护此模型的设计人员也能够很清楚地了解设计思路,提高了代码的文档性。注意:并不是使用了always_comb、always_latch、always_ff过程块就一定会综合出对应的组合、锁存、触发电路!HMECMicroElectronicsCenter6.2.1组合逻辑过程块always_comb过程块表示建立组合逻辑模型,always_comb能推断出其敏感表,推断的敏感表包括所有在过程块外赋值并被过程块读取的信号及过程块中调用函数的有所信号(但局部的临时变量除外)。禁止出现共享变量:always_comb过程要求被赋值的变量不能再次在其它过程块被赋值,以符合综合要求。always_comb过程块在所有的initial和always过程块启动后,会在模拟的0时刻自动触发,该特殊主义确保了组合逻辑在0时刻产生与输入相对应的输出结果尤其是在使用两态变量建模时,0时刻自动求值显得尤为重要!HMECMicroElectronicsCenter6.2.1组合逻辑过程块packagechip_types;typedefenum{FETCH,WRITE,ADD,SUB,MULT,DIV,SHIFT,NOP}instr_t;endpackageimportchip_types::*;modulecontroller(outputlogicread,write,inputinstr_tinstruction,inputwireclk,resetN);enum{WAIT,LOAD,STORE}state,nextState;always@(posedgeclk,negedgeresetN)if(!resetN)state=WAIT;elsestate=nextState;always@(state)begincase(state)WAIT:nextState=LOAD;LOAD:nextState=STORE;仅当state变化时才触发HMECMicroElectronicsCenter6.2.1组合逻辑过程块STORE:nextState=WAIT;endcaseendalways@(state,instruction)beginread=0;write=0;if(state==LOAD&&instruction==FETCH)read=1;if(state==STORE&&instruction==WRITE)write=1;endendmodulestate和nextState为枚举类型,枚举标签WAIT代表的值为0,无论resetN有效否,state的值不会改变,why?HMECMicroElectronicsCenter6.2.1组合逻辑过程块packagechip_types;typedefenum{FETCH,WRITE,ADD,SUB,MULT,DIV,SHIFT,NOP}instr_t;endpackageimportchip_types::*;modulecontroller(outputlogicread,write,inputinstr_tinstruction,inputwireclk,resetN);enum{WAIT,LOAD,STORE}state,nextState;always@(posedgeclk,negedgeresetN)if(!resetN)state=WAIT;elsestate=nextState;always_combbegincase(state)WAIT:nextState=LOAD;LOAD:nextState=STORE;推断出@(state),即使不被触发,在0时刻也会自动执行。HMECMicroElectronicsCenter6.2.1组合逻辑过程块always_combandalways@*1.always@*没有组合逻辑语义,只能是在敏感表有变化时才执行2.@*仅仅是一种推断事件控制列表信号的语句,可在过程块内部使用3.@*推断的敏感表可能不完整:不能推断出函数调用引用的模块级信号always@*begina1=data1;b1=decode();…endalways_combbegina2=data1;b2=decode();…endfunctiondecode;begincase(sel)2’b01:decode=d|e;2’b11:decode=d&e;default:decode=c;endcaseendendfunction只推断出@(data)推断出@(data,sel,d,e,c)HMECMicroElectronicsCenter6.2.2锁存逻辑过程块always_latch过程块表示描述的是基于锁存器的逻辑,always_latch过程块的语义规则与always_comb一样,能够推断出敏感表;在锁存逻辑中,过程块的输出变量不需要对所有可能的输入条件响应;同样always_latch中赋值的变量不能再次在其它过程块被赋值;always_latch过程块也会在0时刻自动执行一次。//使用always_latch过程块锁存输入脉冲moduleregister_reader(outputlogic[4:0]read_p,inputclk,ready,resetn);logicenable,overflow;always_latchbeginif(!resetn)enable=0;elseif(ready)enable=1;elseif(overflow)enable=0;endalways@(posedgeclk,negedgeresetn)beginif(!resetn){overflow,read_p}=0;elseif(enable){overflow,read_p}=read_p+1;endendmodulealways_latchif(enable)q=d;//always_comb//if(enable)q=d;HMECMicroElectronicsCenter6.2.3时序逻辑过程块always_ff过程块描述时序逻辑,always_ff过程块的敏感表必须列出,以确定时序逻辑的置位/复位是同步还是异步的,如果代码不能综合出时序逻辑时,软件工具能够报告警告信息。always_ff过程块要求明确指定敏感表中的信号是posedge还是negedge,这是对时序逻辑敏感列表的综合要求,以确保模拟结果与综合结果一致。always_ff过程块禁止在块开头以外的地方使用事件控制!always_ff@(posedgeclk,negedgeresetn)if(!resetn)state=st0;elsestate=next_state;HMECMicroElectronicsCenter6.3对任务和函数的改进任务和函数的隐式语句组:Verilog中,如果任务或函数包含多条语句时必须写在begin…end之间,对任务也允许使用fork…join结构,对SystemVerilog则可以省略begin…end。functionstates_tnextState(states_tstate);nextState=state;case(state)WAIT:if(start)nextState=LOAD;LOAD:if(done)nextState=STORE;STORE:nextState=WAIT;endcaseendfunctionHMECMicroElectronicsCenter6.3对任务和函数的改进返回函数值:return语句的优先级高于用函数名返回值functionadd_and_inc(input[31:0]a,b);beginadd_and_inc=a+b+1;endendfunctionfunctionadd_and_inc(input[31:0]a,b);returna+b+1;endfunctionfunctionadd_and_inc(input[31:0]a,b);add_and_inc=a+b;return++add_and_inc;endfunctionHMECMicroElectronicsCenter6.3对任务和函数的改进在任务和函数结束前返回:Verilog必须到达任务或函数结尾才能退出functionautomaticintlog2(inputintn);if(n=1)log2=1;elsebeginlog2=0;while(n1)beginn=n/2;log2=log2+1;endendendfunctionfunctionautomaticintlog2(inputintn);if(n=1)return1;log2=0;while(n1)beginn=n/2;log2++;endendfunctionHMECMicroElectronicsCenter6.3对任务和函数的改进void类型函数:void函数无返回值;与通常函数语法和语义限制一样,如不能包含任何类型的延迟或事件控制,也不能使用非阻塞赋值语句;void函数可以象任务一样被调用;void函数可以有output和inout的形式参数;void函数克服了函数不能调用任务的缺陷。typedefstruct{logicvalid;logic[7:0]check;logic[63:0]data;}packet_t;functionvoidfill_packet(inputlogic[63:0]data_in,outputpacket_tdata_out);data_out.data=data_in;foreach(data_out.check[i])data_out.check[i]=^data_in[(8*i)+:8];data_out.valid=1;endfunctionHMECMicroEl