//与门modulezxhand2(c,a,b);inputa,b;outputc;assignc=a&b;endmodule//或门modulezxhor2(c,a,b);inputa,b;outputc;assignc=a|b;endmodule//非门modulezxhnot2(c,b);inputb;outputc;assignc=~b;endmodule////异或门modulezxhxro2(c,a,b);inputb;outputc;assignc=a^b;endmodule两选一电路moduledata_scan(d0,d1,sel,q);outputq;inputd0,d1,sel;wiret1,t2,t3;n1zxhand2(t1,d0,sel);n2zxhnot2(t4,sel);n3zxhand2(t2,d1,t4);n4zxhor2(t3,t1,t2);assignq=t1;endmoduleverilogHDL实例(一)练习一.简单的组合逻辑设计目的:掌握基本组合逻辑电路的实现方法。这是一个可综合的数据比较器,很容易看出它的功能是比较数据a与数据b,如果两个数据相同,则给出结果1,否则给出结果0。在VerilogHDL中,描述组合逻辑时常使用assign结构。注意equal=(a==b)?1:0,这是一种在组合逻辑实现分支判断时常使用的格式。模块源代码://---------------compare.v-----------------modulecompare(equal,a,b);inputa,b;outputequal;assignequal=(a==b)?1:0;//a等于b时,equal输出为1;a不等于b时,//equal输出为0。endmodule测试模块用于检测模块设计得正确与否,它给出模块的输入信号,观察模块的内部信号和输出信号,如果发现结果与预期的有所偏差,则要对设计模块进行修改。测试模块源代码:`timescale1ns/1ns//定义时间单位。modulecomparetest;rega,b;wireequal;initial//initial常用于仿真时信号的给出。begina=0;b=0;#100a=0;b=1;#100a=1;b=1;#100a=1;b=0;#100$stop;//系统任务,暂停仿真以便观察仿真波形。endcomparecompare1(.equal(equal),.a(a),.b(b));//调用模块。Endmodule【例3.1】4位全加器moduleadder4(cout,sum,ina,inb,cin);output[3:0]sum;outputcout;input[3:0]ina,inb;inputcin;assign{cout,sum}=ina+inb+cin;endmodule【例3.2】4位计数器modulecount4(out,reset,clk);output[3:0]out;inputreset,clk;reg[3:0]out;always@(posedgeclk)beginif(reset)out=0;//同步复位elseout=out+1;//计数endendmodule09.04.07【例5.11】模为60的BCD码加法计数器modulecount60(qout,cout,data,load,cin,reset,clk);output[7:0]qout;outputcout;input[7:0]data;inputload,cin,clk,reset;reg[7:0]qout;always@(posedgeclk)//clk上升沿时刻计数beginif(reset)qout=0;//同步复位elseif(load)qout=data;//同步置数elseif(cin)beginif(qout[3:0]==9)//低位是否为9,是则beginqout[3:0]=0;//回0,并判断高位是否为5if(qout[7:4]==5)qout[7:4]=0;elseqout[7:4]=qout[7:4]+1;//高位不为5,则加1endelse//低位不为9,则加1qout[3:0]=qout[3:0]+1;endendassigncout=((qout==8'h59)&cin)?1:0;//产生进位输出信号endmodule【例9.10】奇偶校验位产生器moduleparity(even_bit,odd_bit,input_bus);outputeven_bit,odd_bit;input[7:0]input_bus;assignodd_bit=^input_bus;//产生奇校验位assigneven_bit=~odd_bit;//产生偶校验位endmoduleVerilogHDL实例(二)练习二.简单时序逻辑电路的设计目的:掌握基本时序逻辑电路的实现。在VerilogHDL中,相对于组合逻辑电路,时序逻辑电路也有规定的表述方式。在可综合的VerilogHDL模型,我们通常使用always块和@(posedgeclk)(上升沿)或@(negedgeclk)(下降沿)的结构来表述时序逻辑。下面是一个1/2分频器的可综合模型。//half_clk.v:modulehalf_clk(reset,clk_in,clk_out);inputclk_in,reset;outputclk_out;regclk_out;always@(posedgeclk_in)beginif(!reset)clk_out=0;elseclk_out=~clk_out;endendmodule在always块中,被赋值的信号都必须定义为reg型,这是由时序逻辑电路的特点所决定的。对于reg型数据,如果未对它进行赋值,仿真工具会认为它是不定态。为了能正确地观察到仿真结果,在可综合风格的模块中我们通常定义一个复位信号reset,当reset为低电平时,对电路中的寄存器进行复位。测试模块的源代码://-------------------clk_Top.v-----------------------------`timescale1ns/100ps`defineclk_cycle50moduleclk_Top.v;regclk,reset;wireclk_out;always#`clk_cycleclk=~clk;initialbeginclk=0;reset=1;#100reset=0;#100reset=1;#10000$stop;endhalf_clkhalf_clk(.reset(reset),.clk_in(clk),.clk_out(clk_out));endmoduleVerilogHDL实例(三)练习三.利用条件语句实现较复杂的时序逻辑电路目的:掌握条件语句在VerilogHDL中的使用。与常用的高级程序语言一样,为了描述较为复杂的时序关系,VerilogHDL提供了条件语句供分支判断时使用。在可综合风格的VerilogHDL模型中常用的条件语句有if…else和case…endcase两种结构,用法和C程序语言中类似。两者相较,if…else用于不很复杂的分支关系,实际编写可综合风格的模块、特别是用状态机构成的模块时,更常用的是case…endcase风格的代码。这一节我们给的是有关if…else的范例,有关case…endcase结构的代码已后会经常用到。下面给出的范例也是一个可综合风格的分频器,是将10M的时钟分频为500K的时钟。基本原理与1/2分频器是一样的,但是需要定义一个计数器,以便准确获得1/20分频模块源代码://---------------fdivision.v-----------------------------modulefdivision(reset,f10m,f500k);inputf10m,reset;outputf500k;regf500k;reg[7:0]j;always@(posedgef10m)if(!RESET)//低电平复位。beginf500k=0;j=0;endelsebeginif(j==19)//对计数器进行判断,以确定F500K信号是否反转。beginj=0;f500k=~f500k;endelsej=j+1;endendmodule测试模块源代码://---------------fdivision_Top.v------------------------`timescale1ns/100ps`defineclk_cycle50moduledivision_Top;regf10m=0,reset;wiref500k;always#`clk_cyclef10m=~f10m;initialbeginreset=1;#100reset=0;#100reset=1;#10000$stop;endfdivisionfdivision(.reset(reset),.f10m(f10m),.f500k(f500k));endmoduleVerilogHDL实例(四)练习四.设计时序逻辑时采用阻塞赋值与非阻塞赋值的区别目的:1.明确掌握阻塞赋值与非阻塞赋值的概念和区别;2.了解阻塞赋值的使用情况。阻塞赋值与非阻塞赋值,在教材中我们已经了解了它们之间在语法上的区别以及综合后所得到的电路结构上的区别。在always块中,阻塞赋值可以理解为赋值语句是顺序执行的,而非阻塞赋值可以理解为赋值语句是并发执行的。实际的时序逻辑设计中,一般的情况下非阻塞赋值语句被更多地使用,有时为了在同一周期实现相互关联的操作,也使用了阻塞赋值语句。(注意:在实现组合逻辑的assign结构中,无一例外地都必须采用阻塞赋值语句。下例通过分别采用阻塞赋值语句和非阻塞赋值语句的两个看上去非常相似的两个模块blocking.v和non_blocking.v来阐明两者之间的区别。模块源代码://-------------blocking.v---------------moduleblocking(clk,a,b,c);output[3:0]b,c;input[3:0]a;inputclk;reg[3:0]b,c;always@(posedgeclk)beginb=a;c=b;endendmodule//-------------non_blocking.v-------------------modulenon_blocking(clk,a,b,c);output[3:0]b,c;input[3:0]a;inputclk;reg[3:0]b,c;always@(posedgeclk)beginb=a;c=b;endendmodule测试模块源代码://-------------compareTop.v-----------------------------`timescale1ns/100ps`include./blocking.v`include./non_blocking.vmodulecompareTop;wire[3:0]b1,c1,b2,c2;reg[3:0]a;regclk;initialbeginclk=0;forever#50clk=~clk;endinitialbegina=4'h3;$display(____________________________);#100a=4'h7;$display(____________________________);#100a=4'hf;$display(____________________________);#100a=4'ha;$display(____________________________);#100a=4'h2;$display(____________________________);#100$displ