您好,欢迎访问三七文档
4.3行为级建模4.3.8.生成块:在仿真开始之前,在代码编写的仔细推敲过程中,生成语句可以动态地生成Verilog代码。这一声明语句方便了参数化模块的生成。当对向量中的多个位进行重复操作时,或者当进行多个模块的实例弓l用的重复操作时,或者在根据参数的定义来确定程序中是否应该包括某段Verilog代码的时候,使用生成语句能够大大简化程序的编写过程。生成语句能够控制变量的声明、任务或函数的调用,还能对实例引用进行全面的控制。编写代码时必须在模块中说明生成的实例范围,关键字generate-endgenerate用来指定该范围。生成实例可以是以下的一种或多种类型:•模块•用户自定义原语•门级原语•连续赋值语句•initial和always块生成的声明和生成的实例能够在设计中被有条件地调用(实例引用)。在设计中可以多次调用(实例引用)生成的实例和生成的变量声明_,生成的实例具有惟一的标识名,因此可以用层次命名规则引用。为了支持结构化的元件与过程块语句的相互连接,Verilog语言允许在生成范围内声明下列数据类型:•net(线网)和reg(寄存器)•integer(整型数)、real(实型数)、time(时间型)和realtime(实数时间型)•event(事件)生成的数据类型具有惟一的标识名,可以被层次引用。此外,究竟是使用按照次序或者参数名赋值的参数重新定义,还是使用defparam声明的参数重新定义,都可以在生成范围中定义。但需要注意的是,生成范围中定义的deparam语句所能重新定义的参数必须是在同一个生成范围内,或者是在生成范围的层次化实例当中。任务和函数的声明也允许出现在生成范围中,但是不能出现在循环生成当中。生成任务和函数同样具有惟一的标识符名称,可以被层次引用。不允许出现在生成范围中的模块项声明包括:•参数、局部参数•输人、输出和输入/输出声明•指定块生成模块实例的连接方法与常规模块实例相同。在Verilog中有三种创建生成语句的方法,它们是:•循环生成•条件生成•case生成1.循环生成语句循环生成语句允许使用者对下面的模块或模块项进行多次实例引用:•变量声明•模块•用户自定义原语、门级原语•连续赋值语句•initial和always块循环生成语句的使用是相当灵活的。各种Verilog语法结构都可以用在循环生成语句中;对于读者来说,重要的是能够想像出循环生成语句被展平之后的形式,这对于理解循环生成语句的作用是很有必要的。•在仿真开始之前,仿真器会对生成块中的代码进行确立(展平),将生成块转换为展开的代码,然后对展开的代码进行仿真。因此,生成块的本质是使用循环内的一条语句来代替多条重复的Verilog语句,简化用户的编程;•关键词genvar用于声明生成变量,生成变量只能用在生成块中;在确立后的仿真代码中,生成变量是不存在的;•一个生成变量的值只能由循环生成语句来改变;•循环生成语句可以嵌套使用。但是使用同一个生成变量作为索引的循环生成语句不能相互嵌套;•xor_loop是赋予循环生成语句的名字,目的在于通过它对循环生成语句中的变量进行层次化引用。因此,循环生成语句中各个异或门的相对层次名分别为:xor_loop[0].g1,xor_loop[1].g1,...xor_loop[31].g1。例1.用循环生成语句描述的脉动加法器//本模块生成一个门级脉动加法器moduleripple_adder(co,sum,a0,a1,ci);//参数声明语句.参数可以重新定义parameterN=4;//默认的总线位宽为4//端口声明语句output[N-1:0]sum;outputco;input[N-1:0]a0,a1;inputci;//本地线网声明语句wire[N-1:0]carry;//指定进位变量的第0位等于进位的输人assigncarry[0]=ci;//声明临时循环变量。该变量只用于生成块的计算/*由于在仿真之前循环生成己经展平,所以用Verilog对设计进行仿真时,该变量已经不再存在*/genvari;//用一个单循环生成按位异或门等逻辑generatefor(i=0;iN;i=i+1)begin:r_loopwiret1,t2,t3;xorg1(t1,a0[i],a1[i]);xorg2(sum[i],t1,carry[i]);andg3(t2,a0[i],a1[i]);andg4(t3,t1,carry[i]);org5(carry[i+1],t2,t3);end//生成块内部循环的结束endgenerate//生成块的结束//根据上面的循环生成,Verilog编译器会自动生成以下相对层次实例名//xor:r_loop[0].g1,r_loop[1].g1,r_loop[2].g1,r_loop[3].g1//r_loop[0].g2,r_loop[1].g2,r_loop[2].g2,r_loop[3].g2//and:r_loop[0].g3,r_loop[1].g3,r_loop[2].g3,r_loop[3].g3//r_loop[0].g4,r_loop[1].g4,r_loop[2].g4,r_loop[3].g4//or:r_loop[0].g5,r_loop[1].g5,r_loop[2].g5,r_loop[3].g5//上面生成的实例用下面这些生成的线网连接起来//Nets:r_loop[0].t1,r_loop[0].t2,r_loop[0].t3//r_loop[1].t1,r_loop[1].t2,r_loop[1].t3//r_loop[2].t1,r_loop[2].t2,r_loop[2].t3//r_loop[3].t1,r_loop[3].t2,r_loop[3].t3assignco=carry[N];endmodule2.条件生成语句:条件生成语句类似于if-else-if生成构造,该生成构造可以在设计模块中依据经过仔细推敲后编写的表达式值的真假,决定是否调用(实例引用)以下Verilog结构:•模块•用户自定义原语、门级原语•连续赋值语句•initial或always块例2:使用条件生成语句实现参数化乘法器//本模块实现一个参数化乘法器modulemultiplier(product,a0,a1);//参数声明。该参数可以重新定义porametera0_width,8;//8-bitbusbydefaultporametera1_width,8;//8-bitbusbydefault//本地参数声明//本地参数不能用参数重新定义(defparam)修改/*也不能在实例引用时通过传递参数语句,即#(参数1,参数2,...)的方法修改*/localparamproduct_width=a0_width+a1_width;//端口声明语句output[product_width-1:0]product;input[a0_width-1:0]a0;input[a1_width-1:0]a1;//有条件地调用(实例引用)不同类型的乘法器/*根据参数a0_width和a1_width的值,在调用时引用相对应的乘法器实例*/generateif(a0_width8)||(a1_width8)cla_multiplier#(a0_width,a1_width)m0(product,a0,a1);elsetree_multiplier#(a0_width,a1_width)m0(product,a0,a1);endgenerate//生成块的结束endmodule上例说明如何用条件生成语句实现参数化乘法器如果参数a0_width或a1_width小于8(生成实例的条件),则调用(实例引用)超前进位乘法器;否则调用(实例引用)树形乘法器一。3.case语句:case生成语句可以在设计模块中,经过仔细推敲确定多选一case构造,有条件地调用(实例引用)这些Verilog结构:•模块•用户自定义原语、门级原语•连续赋值语句•initial或always块例3.case生成语句举例//本模块生成N位的加法器moduleadder(co,sum,a0,a1,ci);//参数声明,本参数可以重新定义parameterN=4;//默认的总线位宽为4//端口声明output[N-1:0]sum;outputco;input[N-1:0]a0,a1;inputci;//根据总线的位宽,调用(实例引用)相应的加法器//参数如在调用(实例引用)时可以重新定义//调用(实例引用)不同位宽的加法器是根据不同的N来决定的generatecase(N)//当N=1或2时分别选用位宽为1位或2位的加法器1:adder_1bitadder1(c0,sum,a0,a1,ci);2:adder_2bitadder2(c0,sum,a0,a1,ci);//默认的情况下选用位宽为N位的超前进位加法器default:adder_cla#(N)adder3(c0,sum,a0,a1,ci);endcaseendgenerate//生成块的结束endmodule
本文标题:FPGA
链接地址:https://www.777doc.com/doc-4021811 .html