版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
语法进阶语法详细讲解
第一部分Verilog测试模块的编写目的:
复习如何编写较复杂的测试文件,对所做的设计进行完整的测试和验证。掌握组织模块测试的常用方法;学会编写常用的测试代码。语法详细讲解
用Verilog设计的步骤
注:虚线表示编译器能检查输入文件的可读性和是否存在以及是否允许生成输出文件include文件设计文件厂家元件库文件输入文件:激励和期望的输出信号输出文件:激励和实际输出的信号编译器仿真器仿真器语法详细讲解
测试平台的组成
激励信号需要验证的设计激励信号和用于验证的结果数据需要验证的设计简单的测试平台复杂的测试平台语法详细讲解
并行块在测试块中常用到fork…join块。用并行块能表示以同一个时间起点算起的多个事件的运行,并行地执行复杂的过程结构,如循环或任务。举例说明如下:moduleinline_tb;reg[7:0]data_bus;initialforkdata_bus=8’b00;#10data_bus=8’h45;#20repeat(10)#10data_bus=data_bus+1;#25repeat(5)#20data_bus=data_bus<<1;#140data_bua=8’h0f;joinendmodule//这两个repeat开始执行时间不同,但能同时运行。语法详细讲解
并行块时间
data_bus08’b0000_0000108’b0100_0101308’b0100_0110408’b0100_0111458’b1000_1110508’b1000_1111608’b1001_0000658’b0010_0000708’b0010_0001时间
data_bus808’b0010_0010858’b0100_0100908’b0100_01011008’b0010_00011058’b0100_01101108’b1000_11001208’b1000_11101258’b0001_11001408’b0000_1111上面模块的仿真输出如下:语法详细讲解
强制激励在一个过程块中,可以用两种不同的方式对信号变量或表达式进行连续赋值。过程连续赋值往往是不可以综合的,通常用在测试模块中。两种方式都有各自配套的命令来停止赋值过程。两种不同方式均不允许赋值语句间的时间控制。
assign和deassign适用于对寄存器类型的信号(例如:RTL级上的节点或测试模块中在多个地方被赋值的信号)进行赋值。
initialbegin#10assigntop.dut.fsml.state_reg=`init_state;#20deassigntop.dut.fsml.state_reg;endforce和release用于寄存器类型和网络连接类型(例如:门级扫描寄存器的输出)的强制赋值,强制改写其它地方的赋值。
initialbegin#10forcetop.dut.counter.scan_reg.q=0;#20releasetop.dut.counter.scan_reg.q;end
在以上两个例子中,在10到20这个时间段内,网络或寄存器类型的信号被强制赋值,而别处对该变量的赋值均无效。force的赋值优先级高于assign。如果先使用assign,再使用force对同一信号赋值,则信号的值为force所赋的值,
语法详细讲解
强制激励语法详细讲解
强制激励
当执行release后,则信号的值为assign所赋的值。如果用force对同一个信号赋了几次值,再执行release,则所有赋的值均不再存在。可以对信号的某(确定)位、某些(确定)位或拼接的信号,使用force和release赋值;但不能对信号的可变位使用force和release来赋值。不能对寄存器类型的信号某位或某些位使用assign和deassign来赋值。
虽然有时在设计中会包含时钟,但时钟通常用在测试模块中。下面三个例子分别说明如何在门级和行为级建立不同波形的时钟模型。[例1]简单的对称方波时钟:regclk;alwaysbegin#period/2clk=0;#period/2clk=1;endreggo;wireclk;nand#(period/2)ul(clk,clk,go);initialbegingo=0;#(period/2)go=1;end注:在有些仿真器中,如果设计所用的时钟是由与其相同抽象级别的时钟模型产生的,则仿真器的性能就能得到提高。语法详细讲解
建立时钟[例2]简单的带延迟的对称方波时钟:语法详细讲解
建立时钟
regclk;initialbeginclk=0;#(period)forever#(period/2)clk=!clkendreggo;wireclk;nand#(period/2)ul(clk,clk,go);initialbegingo=0;#(period)go=1;end注:这两个时钟模型有些不同,行为描述的模型延迟期间一直是低电平,而门级描述的模型开始延迟有半个周期是不确定的。[例3].带延迟、头一个脉冲不规则的、占空比不为1的时钟:regclk;initialbegin#(period+1)clk=1;#(period/2-1)foreverbegin#(period/4)clk=0;#(3*period/4)clk=1;endendreggo;wireclk;nand#(3*period/4,period/4)ul(clk,clk,go);initialbegin#(period/4+1)go=0;#(5*period/4-1)go=1;end注:这两个时钟模型也有些不同,行为描述的模型一开始就有确定的电平,而门级描述的模型有延迟,开始时电平是不确定的。语法详细讲解
建立时钟[例2]简单的带延迟的对称方波时钟:语法详细讲解
建立时钟
regclk;initialbeginclk=0;#(period)forever#(period/2)clk=!clkendreggo;wireclk;nand#(period/2)ul(clk,clk,go);initialbegingo=0;#(period)go=1;end注:这两个时钟模型有些不同,行为描述的模型延迟期间一直是低电平,而门级描述的模型开始延迟有半个周期是不确定的。语法详细讲解
怎样使用任务举例说明如何使用任务:modulebus_ctrl_tb;reg[7:0]data;regdata_valid,data_rd;cpuul(data_valid,data,data_rd);initialbegincpu_driver(8’b0000_0000);cpu_driver(8’b1010_1010);cpu_driver(8’b0101_0101);end语法详细讲解
怎样使用任务taskcpu_driver;input[7:0]data_in;begin#30data_valid=1;wait(data_rd==1);#20data=data_in;wait(data_rd==0);#20data=8’hzz;#30data_valid=0;endendtaskendmodule语法详细讲解
怎样使用任务
在测试模块中使用任务可以提高程序代码的效率,可以用任务把多次重复的操作包装起来。waitwaitwaitwaitdata1data2data3data4cpu_dataclkdata_validdata_rdread_cpu_state语法详细讲解
存储建模目标学会如何用Verilog对存储器建模。学会如何用Verilog中对双向(即输入/输出)端口,(inout)建模。存储器建模必须注意以下两个方面的问题:声明存储器容量的大小。明确对存储器访问操作的权限。例如:指出可以对存储器做以下哪几种操作:
1)只读
2)读写
3)同步读写
4)多次读,同时进行一次写
5)多次同步读写,同时提供一些方法保证一致性语法详细讲解
存储器建模`timescale1ns/10psmodulemyrom(read_data,addr,read_en_);inputread_en_;input[3:0]addr;output[3:0]read_data;reg[3:0]read_data;reg[3:0]mem[0:15];initial$readmemb(“my_rom_data”,mem);always@(addrorread_en_)if(!read_en_)read_data=mem[addr];endmodule语法详细讲解
简单ROM建模my_rom_data0000010111000011110100100011111110001001100000011101101000011101ROM的数据存储在另外的一个独立的文件中语法详细讲解
简单ROM建模上页所示的ROM模型说明:如何在Verilog中用二维的寄存器组来定义存储器。ROM中的数据保存在一个独立的文件中,如上页的右边的虚线方框所示。这是一种保存ROM数据的通用的方法,它可以使数据和ROM模型分开。语法详细讲解
简单RAM建模`timescale1ns/1nsmodulemymem(data,addr,read,write);inout[3:0]data;inout[3:0]addr;inputread,write;reg[3:0]memory[0:15];//4bits,16words//从存储器读出到总线上
assigndata=read?memory[addr]:4’bz;//从总线写入存储器
always@(posedgewrite)memory[addr]=data;endmodule语法详细讲解
简单RAM建模RAM模型比ROM模型稍微复杂:它必须具有读写能力;进行读写时通常使用相同的数据总线;需要新技术来处理双向总线;当读信号无效时,RAM模型与总线脱离,如果此时写信号也无效,总线无驱动源,则总线进入高阻状态,这就避免了RAM中的读写竞争。上页的RAM模块是可综合的,但综合出来是一大堆寄存器,占比较大的面积,经济上不太合算。例:modulescalable_ROM(mem_word,address);parameteraddr_bits=8;//sizeofaddressbusparameterwordsize=8;//widthofawordparameterwords=(1<<addr_bits);//sizeofmemoutput[wordsize:1]mem_word;//wordofmemoryinput[addr_bits:1]address;//addressbus
reg[wordsize:1]mem[0:words-1];//memdeclaration//outputonewordofmemorywire[wordsize:1]mem_word=mem[address];endmodule语法详细讲解
存储量可变的只读存储器建模语法详细讲解
存储量可变的只读存储器建模
上述的例子演示了怎样通过设置字长和地址位数来编写只读存储器的行为模块。
[注意]!!在上例中,存储字的范围从0开始的,而不是从1开始,这是因为存储单元是直接通过地址线寻址定位的。同样地,也可以用下面的方法来定义存储器和寻址:
reg[wordsize:1]mem[1:words];//存储器地址从1开始
//地址一个一个地增加直到包含了每个地址对应的存储器
wire[wordsize:1]mem_word=mem[address+1];
可以在初始化块中用一个循环或系统任务把初始数据存入存储器的每个单元。
使用循环把值赋给存储器数组。
for(i=0;i<memsize;i=i+i)//initializememorymema[i]={wordsize{1’b1}};调用$readmem系统任务。
//从文件mem_file.txt中,把初始数据存入存储器(mem)的每个单元
$readmemb(“mem_file.txt”,mem);注意:上面两项必须写在initial块中,加载这些初始化数据不需要时间。
语法详细讲解
存储器的加载语法详细讲解
第三部分怎样使用双向口使用inout关键字声明端口为双向口。
inout[7:0]databus;使用双向口必需遵循下面的规则:inout口只能声明为网络连接类型,不允许把它声明为寄存器类型。(所以仿真器能确定多个驱动源的最终值。)在设计中,每次只能从一个方向来驱动inout口。
例如:当使用总线读RAM中的数据时,如果同时又向RAM模型的双向数据总线写数据,就会产生逻辑竞争,导致总线数据无法确定。所以必须为inout口设计控制逻辑,只有这样才能保证正确的操作。语法详细讲解
怎样使用双向口[注意]:声明一个inout口,可以用来输入或输出数据。inout口默认为网络连接类型。不允许在过程块(initial或always块)中对网络连接类型的数据进行过程赋值;但可以在过程块外把一个寄存器数据类型通过连续赋值语句赋给它(inout口),或者把它与用户定义的源语(UDP)相连。必须为inout口设计控制逻辑,用来保证正确的操作。当把inout口作为输入口时,必须通过控制逻辑禁止输出到inout口。使用Verilog中的基本元件(bufif1)为双向口建模:语法详细讲解
双向口建模b2b1en_a_ben_b_abus_abus_bmodulebus_xcvr(bus_a,bus_b,en_a_b,en_b_a);inoutbus_a,bus_b;inputen_a_b,en_b_a;bufiflb1(bus_b,bus_a,en_a_b);bufiflb2(bus_a,bus_b,en_b_a);//结构模块逻辑endmodule
当en_a_b=1时,元器件b1激活,bus_a的值传到bus_b上
当en_b_a=1时,元器件b1激活,bus_b的值传到bus_a上语法详细讲解
双向口建模[注意]:
在上页的例子中,使用en_a_b和en_b_a来控制元器件bufifl,如果控制信号同时有效,则结果无法确定。所以必须把控制信号en_a_b和en_b_a在时间上分开。使用连续赋值为双向口建模:en_a_ben_b_abus_abus_bmodulebus_xcvr(bus_a,bus_b,en_a_b,en_b_a);inoutbus_a,bus_b;inputen_a_b,en_b_a;assignbus_b=en_a_b?bus_a:’bz;assignbus_a=en_b_a?bus_b:’bz;//结构模块逻辑endmodule当en_a_b=1时,bus_a的值传到bus_b上当en_b_a=1时,bus_b的值传到bus_a上语法详细讲解
双向口建模b2b1[注意]:在assign语句中,通过en_a_b和en_b_a控制bus_a与bus_b之间的数据交换。如果控制信号同时有效,则结果不能确定。所以必须把控制信号en_a_b和en_b_a在时间上分开。语法详细讲解
双向口建模存储器的端口建模:语法详细讲解
双向口建模moduleram_cell(databus,rd.wr);inoutdatabus;inputrd,wr;regdatareg;assigndatabus=rd?datareg:’bz;always@(negedgewr)datareg<=databus;endmodule当rd等于1时datareg的值被赋给databus当wr的下降沿到达时,databus的值被写入datareg测试模块RAM单元数据总线数据寄存器rdwr[注意]:上页中存储单元在wr的下降沿到达时存入数据。上页模块在wr处于高电平时,通过数据总线写入数据,但必须保证wr的高电平维持时间长于数据的写入时间。在rd处于高电平时,上述存储单元通过数据总线读出数据。由于此模型为单口存储模型,因此wr变低电平时,rd不能同时为高电平,否则就无法确定存储器的读出/写入的结果。语法详细讲解
双向口建模目标:学会怎样定义或调用任务和函数。学会怎样使用命名块。学会怎样禁止命名块和任务。理解有限状态机的作用,学会如何显式地为有限状态机建模。语法详细讲解
第四部分Verilog中的高级结构
通过把代码分成小的模块或者使用任务和函数,可把一项任务分成许多较小的、易于管理的部分,从而提高代码的可读性、可维护性和可重用性。任务一般用于编写测试模块,或者行为描述的模块。其中可以包含时间控制(如:#delays,@,wait);也可以包含input,output、inout端口定义和参数;也可以调用其他的任务或函数函数一般用于计算,或者用来代替组合逻辑。不能包含任何延迟;函数在零时间执行。函数只有input变量,虽然没有output变量,但可以通过函数名返回一个值。可以调用其他的函数,但不可以调用任务语法详细讲解
Verilog中的高级结构[注意]:只能调用本模块内的任务和函数。在任务和函数中不能声明网络连接类型的变量。所有的输入和输出变量实际上都是本地寄存器。只有当任务或函数调用并执行完后,才能有返回值。
[举例说明]:若任务或函数中包含一个forever循环时,永远无法执行完,就不可能有返回值。语法详细讲解
Verilog中的高级结构语法详细讲解
Verilog任务
下面模块中的任务含有定时控制和一个输入,并且引用了一个本模块的变量,但是没有输出,也没有双向总线和内部变量,不显示任何内容。用于定时控制的信号,例如clk,绝对不能作为任务的输入,这是因为输入值只向任务内部传递一次。
moduletop;regclk,a,b;DUTu1(out,a,b,clk);always#5clk=!clk;
语法详细讲解
Verilog任务
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要点:任务调用是通过在Verilog模块中写入任务名来实现的。任务中可以包含input,output和inout端口变量的声明。传递给任务的变量与任务I/O端口变量的声明次序相同。虽然传递给任务的变量名可以和任务内声明的I/O端口变量名相同,但是为了使任务成为一个独立的可共用的任务块,建议不要使用与任务内声明的I/O端口变量名相同的变量名,最好给传递到任务的变量起新的不同的名字。在任务中可以使用时间控制。任务使Verilog有更广阔的适用范围。关键字disable可以用来禁止任务的执行。语法详细讲解
Verilog任务[注意]:
不要在程序的不同部分同时调用同一个任务。这是因为任务只有一组本地变量,同一时刻调用两次相同的任务将会导致错误。这种情况常发生在使用定时控制的任务中。
在任务或函数中,引用父模块中声明的变量时要特别注意(即注意变量的层次命名规则)。若想在其它模块中调用任务或函数,该任务和函数中所使用的变量必须全都包含在输入/输出口列表中。语法详细讲解
Verilog任务
下面模块中的任务只含有一个双向总线(inout)端口和一个内部变量,没有其它输入端口、输出端口和定时控制,没有引用模块变量,不显示任何内容。
在任务调用时,任务的输入变量(端口)在任务内部被当作寄存器类型变量处理。
parameterMAX_BITS=8;reg[MAX_BITS:1]D;taskreverse_bits;inout[7:0]data;//双向总线端口被当作寄存器类型!
integerK;for(k=0;k<MAX_BITS;K=K+1)reverse_bits[MAXBITS–(K+1)]=data[K];endtaskalways@(posedgeclk)reverse_bits(D);
……语法详细讲解
Verilog任务
下面模块中定义的任务含有输入、输出、时间控制和一个内部变量,并且引用了一个本模块的变量,但是没有输出,不显示任何内容。任务调用时变量顺序应与任务定义中声明的顺序相同。
modulemult(clk,a,b,out,en_mult);inputclk,en_mult;input[3:0]a,b;output[7:0]out;reg[15:0]out;always@(posedgeclk)multme(a,b,out);//任务调用语法详细讲解
Verilog任务
taskmultme;//任务定义
input[3:0]xme,tome;output[7:0]result;wait(en_mult)result=xme*tome;endtaskendmodule语法详细讲解
Verilog任务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语法详细讲解
Verilog函数
虽然函数不能包含定时控制,但是可以在包含定时控制的过程块中调用函数。
在模块中,使用名为f_or_and的函数时,是把它作为名为f_or_and的寄存器类型变量来处理的。要点函数定义不能包含任何定时控制语句。函数必须至少有一个输入,但绝不能含有任何输出和总线口;一个函数只能返回一个值,该值的变量名与函数同名,数据类型默认为reg类型。传递给函数的变量顺序与函数输入口声明的顺序相同。函数定义必须包含在模块定义之内。函数不能调用任务,但任务可以调用函数。函数使Verilog有更广阔的适用范围。语法详细讲解
Verilog函数虽然函数只能返回一个值,但是它的返回值可以直接赋给一个由多个子信号拼接构成的信号变量,使其实际等效于产生了多个输出。
{o1,o2,o3,o4}=f_or_and(a,b,c,d,e);语法详细讲解
Verilog函数在函数定义时,如果在函数名前面定义了位宽,该函数就可以返回由多位构成的矢量。如果定义函数的语句比较多时,可以用begin和end把它们组合起来。在函数内,无论以函数名命名的变量被赋了多少次值,函数只有一个返回值。下例中的函数,声明了一个内部整型变量。举例说明如下:
modulefoo;input[7:0]loo;//也可以用连续赋值语句调用函数
wire[7:0]goo=zero_count(loo);function[3:0]zero_count;input[7:0]in_bus;integerI;beginzero_count=0;for(I=0;I<8;I=I+1)if(!in_bus[I])zero_count=zero_count+1;endendfunctionendmodule语法详细讲解
Verilog函数
若把函数定义为整型、实型或时间类型,就可以返回相应类型的数据。我们可以在任何类型的表达式中调用函数。
modulechecksub(neg,in_a,in_b);outputneg;inputa,b;regneg;functionintegersubtr;input[7:0]in_a,in_b;subtr=in_a–in_b;//运算结果可以为负数
endfunctionalways@(aorb)beginif(subtr(a,b)<0)neg=1;elseneg=0;endendmodule
语法详细讲解
Verilog函数
函数类型、端口和行为定义时也可以使用参数,这样就可以构成参数化函数使其返回的数据类型、输入端口的位宽等很容易做修改。所以参数化函数就有更广泛的适用范围。
….parameterMAX_BITS=8;reg[MAX_BITS:1]D;function[MAX_BIT:1]reverse_bits;input[7:0]data;for(K=0;K<MAX_BITS;K=K+1)reverse_bits[MAX_BITS–(K+1)]=data[K];endfunctionalways@(posedgeclk)begin….D=reverse_bits(D);
…..end
………
语法详细讲解
Verilog函数语法详细讲解
命名块可以通过在关键字begin或fork后加上:〈块名〉来给块命名。
modulenamed_blk;
……begin:seq_blk
……end
……fork:par_blk
……join
……endmodule可以在命名块中声明本地变量。可以使用disable禁止命名块。注意:命名块使Verilog有更广阔的适用范围。命名块的使用缩短了仿真的时间。语法详细讲解
命名块语法详细讲解
禁止命名块和任务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[14:0]out;always@(posedgeclk)begin:arith_block//***命名名为arith_block的块***reg[3:0]tmp1,tmp2;//***本地变量***{tmp,tmp2}=f_or_and(a,b,c,d,e);//函数调用
if(en_mult)multme(tmp1,tmp2,out);//任务调用
endalways@(negedgeen_mult)begin//停止计算
disablemultme;//***禁止任务的执行***diablearith_block;//***禁止命名块的执行***end//在此定义任务和函数
…………..endmodle注意:disable语句用来终止命名块或任务的执行。这是指在尚未执行该命名块或任务任何一条语句前,就从该命名块/任务执行中返回。语法:
disable〈块名〉或disable〈任务名〉禁止执行命名块或任务后,所有在事件队列中由该命名块/任务安排的事件都将被删除。一般情况下disable语句是不可综合的。在上页的例子中,只禁止命名块也可以得到预期的结果:命名块中所有的事件,包括任务和函数的执行都将被取消。语法详细讲解
禁止命名块和任务语法详细讲解
有限状态机(FSM)隐式FSM:不需要状态寄存器仿真更加有效只能很好地处理线性的状态改变大部分综合工具不支持隐式FSMstate1state2state3state4语法详细讲解
有限状态机(FSM)显式FSM:结构比较复杂可以很方便地用来处理默认状态能够处理复杂的状态改变所有的综合工具均支持显式FSM的综合stateAstateB1stateB2stateCstateD注意:在隐式状态机中,只要发生在一个时钟周期内写数据,在另一个时钟周期内读数据的情况,都会生成寄存器。任何状态机都必须有复位控制信号,状态的改变必需只与某单一时钟信号沿同步。一般情况下,如果状态改变比较简单,又定义得比较好,而且综合工具支持隐式状态机的综合,就可以使用隐式状态机。如果状态改变比较复杂,最好使用显式状态机,这样效果更好。隐式状态机属于行为级,不属于RTL级。代码中主要包含循环语句、嵌入的定时控制,有时也含有命名事件、wait和disable语句。一般情况下,常用的综合工具不支持隐式状态机的综合。语法详细讲解
有限状态机(FSMs)语法详细讲解
显式有限状态机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’b1begin状态变量case语句01datain=0datain=1out=datain;state=1’b0;enddefault:{state,out}=2’b00;endcaseendmodule注:在过程块中可以使用一个时钟沿和case语句来描述一个显式状态机。必须指定一个状态变量,来记录状态机的状态。要改变当前的状态,必须改变状态变量的值,其改变要与时钟沿同步。写得比较好的状态机常为不应产生的条件规定一个默认动作。语法详细讲解
显式有限状态机转到下一个状态默认状态指针01101识别11序列clkrstoutbegin:seq_blockout=1’b0;if(!datain)//状态一:输出零
disableseq_block;@(posedgeclk)//状态二:输出第二位
out=datain;endendmodule语法详细讲解
隐式有限状态机01101识别11序列clkrstout注意:在过程块中可以使用多个时钟沿(即每次状态改变都用一个新的时钟沿)、条件语句、循环语句、disable语句来描述隐式FSM。隐式FSM往往是不可综合的。隐式FSM不必指定状态变量。当下一个激活时钟沿到达时,状态就有可能发生改变。下一个状态是否改变,将由条件语句决定;除非用强制性语句使状态重复(例如:用循环语句或用disable语句来强制改变状态),在隐式状态机中,很难规定一个默认动作。语法详细讲解
隐式有限状态机目标学会怎样使用用户定义的原语来创建逻辑。用户定义的原语元件
(UDP)其行为与Verilog语法中本来就存在的primitive(原语元件)相似,它用一个表格来定义它的逻辑功能。语法详细讲解
第五部分用户定义的原语在Verilog结构建模时,可以使用:二十多个门级源语元件(primitives)。用户定义的源语元件(UDP)。UDP可用于ASIC库中的基本元件(cell)设计,以及小规模芯片和中规模芯片的设计。使用UDP可以在现有的Verilog语言支持的源语元件的基础上编写新的源语元件。UDP是一个独立元件,不能用实例调用的方法调用其他的模块。UDP既可以用来表示时序逻辑元件,也可以表示组合逻辑元件。UDP的行为是使用真值表来描述的。调用UDP的方式与调用Verilog语言提供的源语元件的方式相同。语法详细讲解
什么是UDP?注意:UDP是一种紧凑的表示简单逻辑关系部件的方法。在Verilog语言提供的几种基本源语元件中,若在输入中包含不确定值x,则在输出时可能出现不确定值x;而在UDP中则不允许出现此种情况。由几个原语元件组成的逻辑可以用一个UDP表示。在仿真时使用这样的UDP来代替分散的原语元件可以节省计算资源,加快仿真速度。一般的仿真器处理行为模型表示的逻辑所需时间比处理用门级语句表示的相同逻辑所需时间少;而硬件仿真器正好相反。语法详细讲解
什么是UDP?UDP只能有一个输出端,而且必须是端口说明列表的第一项。UDP可以有多个输入端,最多允许有10个。UDP所有端口变量必须是标量,不允许使用双向端口。UDP不支持Z(高阻)逻辑值。在仿真的开始时刻,可以使用initial语句把UDP的输出初始化为一个已知值。UDP不支持综合,即不能通过综合把它转变为门级结构逻辑。语法详细讲解
UDP的特点注:UDP只能有一个输出。如果逻辑功能要求有多个输出端时,则需要把其它的原语元件连接到UDP的输出,或同时使用多个UDP,保证其最终输出只有一个。UDP输入端最多可以有10个,但是当输入端的个数多于5个时,仿真时需要的内存个数将呈现近似指数的增加。下表列出了当输入数目不同时,在仿真过程中,对每个输入信号,计算机中所需要开销的内存数目。语法详细讲解
UDP的特点语法详细讲解
UDP的特点
输入端口的个数所需内存的字节数1-5<165717856918710623组合逻辑示例:2-1多路器语法详细讲解
举例说明primitivemultiplexer(o,a,b,s);outputo;inputs,a,b;table//abs:o0?1:0;1?1:1;?00:0;?10:1;00x:0;11x:1;endtableendprimitive原语名输出端口必须为第一个端口注:在模块外定义UDP。如果在表中没有规定输入组合,将输出不确定逻辑值(x)。表的列中元素的顺序应与端口列表中的一致。表中的?的意义是:重复的输入0,1或任意不确定逻辑值(x)。表中开始两行表示:当s等于1时,不管b逻辑值如何变化,输出o将与输入a保持一致。表中的下两行表示:当s等于0时,不管a逻辑值如何变化,输出o将与输入b保持一致。表中的最后两行使此器件的描述更加的全面、准确。它们表示:当输入a和b的逻辑值相同时,如果sel逻辑值不确定,则输出o的值将与输入a和b的值相同。这种行为不能使用Verilog语言提供的基本原语元件进行建模。UDP将x作为实际的未知值,而不是Verilog语言逻辑值来进行处理,因此使其比Verilog语言提供的基本原语元件更加准确。语法详细讲解
举例说明可以只使用两个UDP来描述全加器的逻辑功能。//全加器进位实现部分primitiveU_ADDR2_C(CO,A,B,CI);outputCO;inputA,B,CI,table//ABCI:CO11?:1;1?1:1;?11:1;00?:0;0?0:0;?00:0;endtalbeendprimitive语法详细讲解
组合逻辑示例:全加器向上一级进位下一级来的进位//全加器求和实现部分primitiveU_ADDR2_S(S,A,B,CI);outputS;inputA,B,CI;table//ABCI:S000:0;001:1;010:1;011:0;100:1;101:0;110:0;111:1;endtableendprimitive语法详细讲解
组合逻辑示例:全加器
若使用UDP设计全加器,仅需要两个UDP;而使用Verilog原语元件,则需要5个Verilog语言提供的基本原语元件。当设计需要使用大量全加器时,采用UDP来表示全加器,将大大减少内存的需要。事件的数目将大大降低。?表示逻辑值可以为0,1或x。语法详细讲解
组合逻辑示例:全加器primitivelatch(q,clock,data);outputq;regq;inputclock,data;initialq=1’b1;table//clockdatacurrentnext//statestate01:?1;00:?0;1?::-;endtableendprimitive语法详细讲解
电平敏感的时序逻辑示例:锁存器注意此寄存器的用法,此寄存器用来存储。输出初始化为1‘b1.?表示无须考虑输入和当前状态的值注:锁存器的动作行为如下:当时钟信号为0时,输入数据的值直接传给输出。当时钟信号为1时,输出保持当前状态不变。nextstate栏中的“-”表示输出保持不变。输出必须定义为寄存器类型,用来保存前一个状态。initialq=1’b1;
是时序UDP的初始化语句。使用此语句可以在仿真的开始对输出进行赋值。在实际的部件模型中,很少使用初始赋值。但在测试UDP的功能时,初始赋值相当有用。语法详细讲解
电平敏感的时序逻辑示例:锁存器primitived_edge_ff(q,clk,data);outputq;inputclk,data;regq;table//clkdatstatenext(01)0:?:0;(01)1:?:1;(0x)1:1:1;(0x)0:0:0;(x1)0:0:0;(x1)1:1:1;语法详细讲解
跳边沿敏感的时序逻辑示例:D触发器//忽略时钟的下降沿
(?0)?:?:-;(1x)?:?:-;//忽略时钟稳定时的数据改变
endtableendprimitive在大多数情况下,可以在任何表入口语句中规定一个输入过渡。如果规定了任何输入过渡,则必须规定所有输入的所有过渡。语法详细讲解
跳边沿敏感的时序逻辑示例:D触发器可综合建模类型只有两种:组合逻辑:
任何时候,如果输出信号直接由当前的输入信号的组合决定,则此逻辑为组合逻辑。时序逻辑: 如果逻辑中具有记忆功能,则此逻辑为时序逻辑。在任何给定的时刻,如果输出不能完全由输入信号确定,则此逻辑具有记忆功能。语法详细讲解
第六部分可综合风格的Verilog建模类型综合工具不支持下面的Verilog结构:
initial
循环语句:
repeatforeverwhile
for的非结构用法一部分数据类型
eventrealtime语法详细讲解
不能综合的Verilog结构UDPsfork…join块
wait
过程连续赋值语句
assign和deassignforce和release
部分操作符
===
!==语法详细讲解
不能综合的Verilog结构由输入信号中任意一个电平发生变化所引起的过程块:由输入信号中的某一个电平发生变化启动的过程块,可以通过综合产生组合逻辑。该过程块称为组合块。如下例所示:
always@(aorb)//实现与门
y=a&b;由单个跳变沿引起的过程块:由控制信号的跳变沿(下降沿或上升沿)启动的过程块通过综合可以生成同步逻辑。该过程块称为同步块。如下例所示:
always@(posedgeclk)//实现D触发器
q<=d;语法详细讲解
可综合的过程块在同步块中可以添加异步复位,举例说明如下:
always@(posedgeclkornegedgerst_)if(!rst_)q<=0;elseq<=d;语法详细讲解
过程块在同步块中使用reg类型变量:如果在一个时钟沿对reg变量赋值,而在下一个时钟沿对其采样,则综合器把该reg变量转换为硬件寄存器。如果只把reg变量作为基本输出,则综合器不一定把它转换为硬件寄存器。如果不属于上述两种情况,同步块中的reg变量有可能被优化掉。在组合块中使用reg类型变量:当组合块中任何一个输入变量的值改变时,reg变量的值也随之改变,则综合器不会把该reg变量转换为硬件寄存器。当块的某一个输入的值改变时,reg变量的值不一定立即改变,而要等其他输入信号的值改变时才改变,则综合器将把该reg变量转换为锁存器。语法详细讲解
过程块中寄存器类型的信号变量同步寄存器示例:在下面的例子中,rega仅用作临时存储器,因此在综合时它将被优化掉。moduleex1reg(d,clk,q);inputd,clk;outputq;regq,rega;always@(posedgeclk)beginrega=0;if(d)rega=1;q=rega;endendmodule语法详细讲解
寄存器在下面的例子中,用两个always块,它们的触发条件是相同的:即用同一时钟沿来处理两个存储元素,这样就可以使综合器在综合过程中保留rega,使它不被优化掉。moduleex2reg(d,clk,q);inputd,clk;outputq;regq,rega;always@(posedgeclk)beginrega=0;if(d)rega=1;end语法详细讲解
寄存器always@(posedgeclk)q=rega;endmodule注:在后面的always块中,块执行的顺序是不确定的,因此q可以获得在前一个周期中赋给
rega
的值。语法详细讲解
寄存器组合寄存器示例:
下面的两个例子中,rega
都是临时变量,在综合中它们都会被优化掉。在本例中,y和rega
不断被赋新值(因为语句中有elserega=0;),综合出的电路是一个纯组合逻辑。moduleex3reg(y,a,b,c);inputa,b,c;outputy;regy,rega;always@(aorborc)begin语法详细讲解
寄存器if(a&b)rega=c;elserega=0;y=rega;endendmodule在下面的例子中,rega
只是有时被赋新值(没有else语句,rega在条件不符合时保持原值);因此综合出来的是一个以y作为输出的锁存器。语法详细讲解
寄存器mouduleex4reg(y,a,b,c);inputa,b,c;outputy;regy,rega;always@(aorborc)beginif(a&b)rega=c;y=rega;endendmodule语法详细讲解
寄存器在下面的例子中,a、b和sl均是块的输入。在两个例子中,sl均为always块的条件。在第二个例子中,a和b也用作always块的条件。不完整电平敏感列表:modulesens(a,q,b,sl);inputa,b,sl;outputq;regq;always@(sl)begin语法详细讲解
电平敏感列表if(!sl)q=a;elseq=b;endendmodule完整的电平敏感列表:modulesens(q,a,b,sl);inputa,b,sl;outputq;语法详细讲解
电平敏感列表regq;always@(sloraorb)beginif(!sl)q=a;elseq=b;endendmodule注:在电平敏感列表中最好包括所有的输入。对于不完整的列表,不同的综合工具处理的方法不同:有些综合工具认为不完整列表是语法详细讲解
电平敏感列表不合法的,而另外一些综合工具则发出警告并将其当作完整列表处理。因此,综合出来的电路功能可能与程序模块的描述有所不同。语法详细讲解
电平敏感列表用连续赋值语句表达的是:任何一个输入的改变都将立即导致输出更新;与理想的与、或、非门的线路连接一致。moduleorand(out,a,b,c,d,e);inputa,b,c,d,e;outputout;assignout=3&(a|b)&(c|d);endmodule语法详细讲解
连续赋值过程连续赋值是在过程块(always和initial块)内部对寄存器类型的变量进行的连续赋值。modulelatch_quasi(q,en,d);inputen,d;outputq;regq;always@(en)if(en)assignq=d;elsedeassignq;endmodule语法详细讲解
过程连续赋值大部分综合工具都能按照约定,正确地处理在源代码中用注释行表示的指导综合器如何转换到门级网表的指令即综合指令。可以在Verilog语句之间用注释行嵌入综合指令,Verilog仿真器运行时将忽略嵌入的指令,而当综合工具编译时,这些符合约定的综合指令是有意义的,能对综合过程进行干预和指导。不同的综合工具有不同的综合指令集,使用综合指令为的是:使同样的RTL代码能综合出更高质量优化的门级网表。下面列出了一部分Cadence综合工具支持的综合指令,它们与其他综合工具(例如:SynopsysDC)中的指令非常相似。//ambitsynthesison//ambitsynthesisoff//ambitsynthesiscase=full、parallel、mux语法详细讲解
综合指令结构指令//ambitsynthesisarchitecture=claorrpl有限状态机指令//ambitsynthesisenumxyz//ambitsynthesisstat_vectorsigstate_vector_flag注:指令中通常包括综合工具或公司的名称,例如:上面指令中的ambit表示使用的综合器是EnvisiaAmbit公司的产品。语法详细讲解
综合指令当Verilog模块中case–endcase块被综合时,有多种门级实现方法可供选择:综合指令case可以用来干预综合过程。让由case指定的编译方式被综合器优先考虑,即采用case=后列出的方法转换为门级电路。case
综合指令的含义如下所示://ambitsynthesiscase=parallel
对解码逻辑进行并行编译,没有优先级。//ambitsynthesiscase=mux
如果库中含有多路器,则使用多路器编译解码逻辑。//ambitsynthesiscase=full
不用考虑没有包含在case条件语句中的情形(即这些情形不会发生),这样设定,可以综合出的优化的门级逻辑,并可避免发生状态机死锁。语法详细讲解
综合指令条件完整的case语句举例:[例1]modulecomcase(a,b,c,d,e);inputa,b,c,d;outpute;rege;always@(aorborcord)case({a,b})2’b11:e=d;2’b10:e=~c;2’b01:e=1’b0;2’b00:e=1’b1;endcase
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年度城市供水供电供气合同3篇
- 2024年度房屋买卖合同:购房人与开发商就房屋买卖所签订的合同3篇
- 2024年企业贷款合同模板一
- 2024全新运输快递合同下载
- 2024年新能源汽车电池技术转让合同
- 2024年国际物流运输服务协议版
- 石家庄医学院新校区建设合同三篇
- 2024企业融资合同
- 2024专业猎头服务招聘合作合同版
- 2024年度人工智能语音助手技术开发与授权合同3篇
- 英国留学文书申请范文(6篇)
- 临沂球迷协会筹备申请书
- 部编版六年级道德与法治上册第5课《国家机构有哪些》优秀课件
- 公司设计师合作合同
- 卫生管理统计及软件应用-贺佳-课后习题答案
- 铁路工程定额电子版(Excel版)
- 全过程工程咨询服务大纲
- q gw2sjss.65金风风力发电机组防腐技术rna部分归档版
- 高中英语新课标新增词汇汇总1
- GB/T 20197-2006降解塑料的定义、分类、标志和降解性能要求
- 西子奥的斯电梯ACD2调试说明书
评论
0/150
提交评论