《设计一个字节(8位)比较器.ppt》由会员分享,可在线阅读,更多相关《设计一个字节(8位)比较器.ppt(56页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、EXERCISEVERILOGDESIGN四输入加法器nza+b+c+d;nz=(a+b)+(c+d);练习一简单的组合逻辑设计练习一简单的组合逻辑设计 目的:掌握基本组合逻辑电路的实现方法。设计一个可综合的数据比较器 模块源代码:/-compare.v-module compare(equal,a,b);input a,b;output equal;assign equal=(a=b)?1:0;/a等于b时,equal输出为1;a不等于b时,/equal输出为0。endmodule测试模块源代码:timescale 1ns/1ns /定义时间单位。include ./compare.v/包含
2、模块文件。在有的仿真调试环境中并不需要此语句。/而需要从调试环境的菜单中键入有关模块文件的路径和名称module comparetest;reg a,b;wire equal;initial /initial常用于仿真时信号的给出。begin a=0;b=0;#100 a=0;b=1;#100 a=1;b=1;#100 a=1;b=0;#100$stop;/系统任务,暂停仿真以便观察仿真波形。end compare compare1(.equal(equal),.a(a),.b(b);/调用模块。endmodule 仿真波形(部分):练习:设计一个字节(8位)比较器。要求:比较两个字节的大小,
3、如a7:0大于 b7:0输出高电平,否则输出低电平,改写测试模型,使其能进行比较全面的测试。练习二.简单时序逻辑电路的设计目的:掌握基本时序逻辑电路的实现。n设计1/2分频器的可综合模型/half_clk.v:module half_clk(reset,clk_in,clk_out);input clk_in,reset;output clk_out;reg clk_out;always(posedge clk_in)begin if(!reset)clk_out=0;else clk_out=clk_out;endendmodule在always块中,被赋值的信号都必须定义为reg型,这是由
4、时序逻辑电路的特点所决定的。对于reg型数据,如果未对它进行赋值,仿真工具会认为它是不定态。为了能正确地观察到仿真结果,在可综合风格的模块中我们通常定义一个复位信号reset,当reset为低电平时,对电路中的寄存器进行复位。测试模块的源代码:/-clk_Top.v-timescale 1ns/100psdefine clk_cycle 50module clk_Top;reg clk,reset;wire clk_out;always#clk_cycle clk=clk;initial begin clk=0;reset=1;#100 reset=0;#100 reset=1;#10000$
5、stop;endhalf_clk half_clk(.reset(reset),.clk_in(clk),.clk_out(clk_out);endmodule练习三.利用条件语句实现较复杂的时序逻辑电路目的:掌握条件语句在Verilog HDL中的使用。为了描述较为复杂的时序关系,Verilog HDL提供了条件语句供分支判断时使用。在可综合风格的Verilog HDL模型中常用的条件语句有ifelse和caseendcase两种结构 10M的时钟分频为500K的时钟。基本原理与1/2分频器是一样的,但是需要定义一个计数器,以便准确获得1/20分频模块源代码:/-fdivision.v-mo
6、dule fdivision(RESET,F10M,F500K);input F10M,RESET;output F500K;reg F500K;reg 7:0j;always(posedge F10M)if(!RESET)/低电平复位。begin F500K=0;j=0;end else begin if(j=19)/对计数器进行判断,以确定F500K信号是否反转。begin j=0;F500K=F500K;end else j=j+1;endendmodule测试模块源代码:/-fdivision_Top.v-timescale 1ns/100psdefine clk_cycle 50mo
7、dule division_Top;reg F10M_clk,RESET;wire F500K_clk;always#clk_cycle F10M_clk =F10M_clk;initial begin RESET=1;F10M=0;#100 RESET=0;#100 RESET=1;#10000$stop;endfdivision fdivision(.RESET(RESET),.F10M(F10M_clk),.F500K(F500K_clk);endmodule练习四.设计时序逻辑时采用阻塞赋值与非阻塞赋值的区别n目的:1.明确掌握阻塞赋值与非阻塞赋值的概念和区别;n 2.了解阻塞赋值的使
8、用情况。n在always块中,阻塞赋值可以理解为赋值语句是顺序执行的,而非阻塞赋值可以理解为赋值语句是并发执行的。实际的时序逻辑设计中,一般的情况下非阻塞赋值语句被更多地使用。(注意:在实现组合逻辑的assign结构中,无一例外地都必须采用阻塞赋值语句。模块源代码:/-blocking.v-module blocking(clk,a,b,c);output 3:0 b,c;input 3:0 a;input clk;reg 3:0 b,c;always(posedge clk)begin b=a;c=b;$display(Blocking:a=%d,b=%d,c=%d.,a,b,c);end
9、endmodule/-non_blocking.v-module non_blocking(clk,a,b,c);output 3:0 b,c;input 3:0 a;input clk;reg 3:0 b,c;always(posedge clk)begin b=a;c=b;$display(Non_Blocking:a=%d,b=%d,c=%d.,a,b,c);endendmodule测试模块源代码:/-compareTop.v-timescale 1ns/100psinclude./blocking.vinclude./non_blocking.vmodule compareTop;wi
10、re 3:0 b1,c1,b2,c2;reg 3:0 a;reg clk;initial begin clk=0;forever#50 clk=clk;end initial begin a=4h3;$display(_);#100 a=4h7;$display(_);#100 a=4hf;$display(_);#100 a=4ha;$display(_);#100 a=4h2;$display(_);#100$display(_);$stop;end non_blocking non_blocking(clk,a,b2,c2);blocking blocking(clk,a,b1,c1);
11、endmodule思考:在blocking模块中按如下写法,仿真与综合的结果会有什么样的变化?作出仿真 波形,分析综合结果。1 always(posedge clk)begin c=b;b=a;end2.always(posedge clk)b=a;always(posedge clk)c=b;练习五练习五.用用alwaysalways块实现较复块实现较复杂的组合逻辑电路杂的组合逻辑电路目的:1.掌握用always实现组合逻辑电路的方法;2.了解assign与always两种组合逻辑电路实现方法之间的区别。n一个简单的指令译码电路的设计示例/-/-alu.valu.v-define plus
12、3d0define plus 3d0define minus 3d1define minus 3d1define band 3d2define band 3d2define define borbor 3d3 3d3define define unegateunegate 3d4 3d4module module alu(out,opcode,a,balu(out,opcode,a,b););output7:0 out;output7:0 out;reg7:0 out;reg7:0 out;input2:0 input2:0 opcodeopcode;input7:0 a,b;/input7:
13、0 a,b;/操作数。操作数。always(opcodealways(opcode or a or b)/or a or b)/电平敏感的电平敏感的alwaysalways块块beginbegin case(opcodecase(opcode)plus:out=a+b;/plus:out=a+b;/加操作。加操作。minus:out=a-b;/minus:out=a-b;/减操作。减操作。band:out=a&b;/band:out=a&b;/求与。求与。borbor:out=a|b;/:out=a|b;/求或。求或。unegateunegate:out=a;/:out=a;/求反。求反。de
14、fault:out=8hx;/default:out=8hx;/未收到指令时,输出任意态。未收到指令时,输出任意态。endcaseendcaseendendendmoduleendmodule同一组合逻辑电路分别用always块和连续赋值语句assign描述时,代码的形式大相径庭,但是在always中适当运用default(在case结构中)和else(在ifelse结构中),通常可以综合为纯组合逻辑,尽管被赋值的变量一定要定义为reg型。不过,如果不使用default或else对缺省项进行说明,则易生成意想不到的锁存器,这一点一定要加以注意。指令译码器的测试模块源代码:/-alu_Top.v
15、-timescale 1ns/1nsinclude ./alu.vmodule alutest;wire7:0 out;reg7:0 a,b;reg2:0 opcode;parameter times=5;initial begin a=$random%256;/Give a radom number blongs to 0,255.b=$random%256;/Give a radom number blongs to 0,255.opcode=3h0;repeat(times)begin#100 a=$random%256;/Give a radom number.b=$random%25
16、6;/Give a radom number.opcode=opcode+1;end#100$stop;end alu alu1(out,opcode,a,b);endmodule练习六练习六.在在VerilogVerilog HDL HDL中使用函数中使用函数n目的:掌握函数在模块设计中的使用。n与一般的程序设计语言一样,Veirlog HDL也可使用函数以适应对不同变量采取同一运算的操作。Veirlog HDL函数在综合时被理解成具有独立运算功能的电路,每调用一次函数相当于改变这部分电路的输入以得到相应的计算结果。函数调用的一个简单示范,采用同步时钟触发运算的执行,每个clk时钟周期都会执
17、行一次运算。并且在测试模块中,通过调用系统任务$display在时钟的下降沿显示每次计算的结果。模块源代码:module tryfunct(clk,n,result,reset);output31:0 result;input3:0 n;input reset,clk;reg31:0 result;always(posedge clk)/clk的上沿触发同步运算。begin if(!reset)/reset为低时复位。result=0;else begin result=n*factorial(n)/(n*2)+1);end end function 31:0 factorial;/函数定义。
18、input 3:0 operand;reg 3:0 index;begin factorial=operand?1:0;for(index=2;index=operand;index=index+1)factorial=index*factorial;end endfunction endmodule测试模块源代码:include./step6.vtimescale 1ns/100psdefine clk_cycle 50module tryfuctTop;reg3:0 n,i;reg reset,clk;wire31:0 result;initial begin n=0;reset=1;cl
19、k=0;#100 reset=0;#100 reset=1;for(i=0;iy)begin tmp=x;/x与y变量的内容互换,要求顺序执行,所以采用阻塞赋值方式。x=y;y=tmp;end endtaskendmodule值得注意的是task中的变量定义与模块中的变量定义不尽相同,它们并不受输入输出类型的限制。如此例,x与y对于task sort2来说虽然是inout型,但实际上它们对应的是always块中变量,都是reg型变量。测试模块源代码:timescale 1ns/100psinclude sort4.vmodule task_Top;reg3:0 a,b,c,d;wire3:0
20、ra,rb,rc,rd;initial begin a=0;b=0;c=0;d=0;repeat(5)begin#100 a=$random%15;b=$random%15;c=$random%15;d=$random%15;end#100$stop;sort4 sort4(.a(a),.b(b),.c(c),.d(d),.ra(ra),.rb(rb),.rc(rc),.rd(rd);endmodule 仿真波形(部分):练习八.利用有限状态机进行复杂时序逻辑的设计n一个简单的状态机设计,功能是检测一个5位二进制序列“10010”。考虑到序列重叠的可能,有限状态机共提供8个状态(包括初始状态I
21、DLE)。n模块源代码:seqdet.vmodule seqdet(x,z,clk,rst,state);input x,clk,rst;output z;output2:0 state;reg2:0 state;wire z;parameter IDLE=d0,A=d1,B=d2,C=d3,D=d4,E=d5,F=d6,G=d7;nassign z=(state=E&x=0)?1:0;/当x=0时,状态已变为E,n /状态为D时,x仍为1。因此n /输出为1的条件为(state=E&x=0)。nalways(posedge clk)n if(!rst)n beginn state=IDLE;
22、n endn elsen casex(state)n IDLE:if(x=1)n state=A;n A:if(x=0)n n state=B;n elsen state=A;n B:if(x=0)n state=C;n elsen state=A;n nC:if(x=1)n beginn state=D;n endn elsen beginn state=G;n endn D:if(x=0)n beginn state=E;n endn elsen beginn state=A;n endn E:if(x=0)n beginn state=C;n endn elsen beginn stat
23、e=A;n endn F:if(x=1)n beginn state=A;n endn elsen beginn state=B;n endn G:if(x=1)n beginn state=F;n endn default:state=IDLE;/缺省状态为初始状态。n endcasenendmodule测试模块源代码:/-seqdet.v-timescale 1ns/1nsinclude./seqdet.vmodule seqdet_Top;reg clk,rst;reg23:0 data;wire2:0 state;wire z,x;assign x=data23;always#10 c
24、lk=clk;always(posedge clk)data=data22:0,data23;initial begin clk=0;rst=1;#2 rst=0;#30 rst=1;data=b1100_1001_0000_1001_0100;#500$stop;end seqdet m(x,z,clk,rst,state);endmodule 仿真波形:练习九练习九.利用状态机的嵌套实现层次结构化设计利用状态机的嵌套实现层次结构化设计目的:.运用主状态机与子状态机产生层次化的逻辑设计;.在结构化设计中灵活使用任务(task)结构。n在上一节,我们学习了如何使用状态机的实例。实际上,单个有限
25、状态机控制整个逻辑电路的运转在实际设计中是不多见,往往是状态机套用状态机,从而形成树状的控制核心。这一点也与我们提倡的层次化、结构化的自顶而下的设计方法相符,下面我们就将提供一个这样的示例以供大家学习。n该例是一个简化的EPROM的串行写入器。工作的步骤是:.地址的串行写入;.数据的串行写入;3.给信号源应答,信号源给出下一个操作对象;.结束写操作。通过移位令并行数据得以一位一位输出。模块源代码:module writing(reset,clk,address,data,sda,ack);input reset,clk;input7:0 data,address;output sda,ack;
26、/sda负责串行数据输出;/ack是一个对象操作完毕后,模块给出的应答信号。reg link_write;/link_write决定何时输出。reg3:0 state;/主状态机的状态字。reg4:0 sh8out_state;/从状态机的状态字。reg7:0 sh8out_buf;/输入数据缓冲。reg finish_F;/用以判断是否处理完一个操作对象。reg ack;parameter idle=0,addr_write=1,data_write=2,stop_ack=3;parameter bit0=1,bit1=2,bit2=3,bit3=4,bit4=5,bit5=6,bit6=7
27、,bit7=8;assign sda=link_write?sh8out_buf7:1bz;always(posedge clk)begin if(!reset)/复位。begin link_write=0;state =idle;finish_F=0;sh8out_state=idle;ack=0;sh8out_buf=0;end else case(state)idle:begin link_write =0;state =idle;finish_F=0;sh8out_state=idle;ack=0;sh8out_buf=address;state =addr_write;end add
28、r_write:/地址的输入。begin if(finish_F=0)begin shift8_out;end else begin sh8out_state=idle;sh8out_buf =data;state=data_write;finish_F=0;end end data_write:/数据的写入。begin if(finish_F=0)begin shift8_out;end else begin link_write=0;state=stop_ack;finish_F=0;ack=1;end end stop_ack:/完成应答。begin ack=0;state=idle;e
29、nd endcase end task shift8_out;/串行写入。begin case(sh8out_state)idle:begin link_write =1;sh8out_state=bit0;end bit0:begin link_write=1;sh8out_state=bit1;sh8out_buf=sh8out_buf1;end bit1:begin sh8out_state=bit2;sh8out_buf=sh8out_buf1;end bit2:begin sh8out_state=bit3;sh8out_buf=sh8out_buf1;end bit3:begin
30、sh8out_state=bit4;sh8out_buf=sh8out_buf1;end bit4:begin sh8out_state=bit5;sh8out_buf=sh8out_buf1;end bit5:begin sh8out_state=bit6;sh8out_buf=sh8out_buf1;end bit6:begin sh8out_state=bit7;sh8out_buf=sh8out_buf1;endbit7:begin link_write=0;finish_F=finish_F+1;end endcase endendtaskendmodule 测试模块源代码:time
31、scale 1ns/100psdefine clk_cycle 50module writingTop;reg reset,clk;reg7:0 data,address;wire ack,sda;always#clk_cycle clk=clk;initial begin clk=0;reset=1;data=0;address=0;#(2*clk_cycle)reset=0;#(2*clk_cycle)reset=1;#(100*clk_cycle)$stop;endalways(posedge ack)/接收到应答信号后,给出下一个处理对象。begin data=data+1;addre
32、ss=address+1;end writing writing(.reset(reset),.clk(clk),.data(data),.address(address),.ack(ack),.sda(sda);endmodule 仿真波形:练习十.通过模块之间的调用实现自顶向下的设计n目的:学习状态机的嵌套使用实现层次化、结构化设计。n现代硬件系统的设计过程与软件系统的开发相似,设计一个大规模的集成电路的往往由模块多层次的引用和组合构成。层次化、结构化的设计过程,能使复杂的系统容易控制和调试。n下面给出的例子是设计中遇到的一个实例,其功能是将并行数据转化为串行数据送交外部电路编码,并将解码
33、后得到的串行数据转化为并行数据交由CPU处理。显而易见,这实际上是两个独立的逻辑功能,分别设计为独立的模块,然后再合并为一个模块显得目的明确、层次清晰。/-p_to_s.v-modulep_to_s(D_in,T0,data,SEND,ESC,ADD_100);output D_in,T0;/D_in是串行输出,T0是移位时钟并给 /CPU中断,以确定何时给出下个数据。input7:0 data;/并行输入的数据。input SEND,ESC,ADD_100;/SEND、ESC共同决定是否进行并到串 /的数据转化。ADD_100决定何时置数。wire D_in,T0;reg7:0 DATA_Q
34、,DATA_Q_buf;assign T0=!(SEND&ESC);/形成移位时钟。.assign D_in=DATA_Q7;/给出串行数据。always(posedge T0 or negedge ADD_100)/ADD_100下沿置数,T0上沿移位。begin if(!ADD_100)DATA_Q=data;else begin DATA_Q_buf=DATA_Q1;/DATA_Q_buf作为中介,以令综合器 DATA_Q=DATA_Q_buf;/能辨明。end endendmodule在p_to_s.v中,由于移位运算虽然可综合,但是不是简单的RTL级描述,直接用DATA_Q=DATA
35、_Q1的写法在综合时会令综合器产生误解。另外,在该设计中,由于时钟T0的频率较低,所以没有象以往那样采用低电平置数,而是采用ADD_100的下降沿置数。/-s_to_p.v-module s_to_p(T1,data,D_out,DSC,TAKE,ADD_101);output T1;/给CPU中断,以确定CPU何时取转化 /得到的并行数据。output 7:0 data;input D_out,DSC,TAKE,ADD_101;/D_out提供输入串行数据。DSC、TAKE /共同决定何时取数。wire 7:0 data;wire T1,clk2;reg 7:0 data_latch,dat
36、a_latch_buf;assign clk2=DSC&TAKE;/提供移位时钟。assign T1=!clk2;assign data=(!ADD_101)?data_latch:8bz;always(posedge clk2)begin data_latch_buf=data_latch 1;/data_latch_buf作缓冲 data_latch =data_latch_buf;/,以令综合器能辩明。data_latch0=D_out;endendmodule将上面的两个模块合并起来的sys.v的源代码:/-sys.v-include./p_to_s.vinclude./s_to_p.
37、vmodule sys(D_in,T0,T1,data,D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101);input D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101;inout 7:0 data;output D_in,T0,T1;p_to_s p_to_s(.D_in(D_in),.T0(T0),.data(data),.SEND(SEND),.ESC(ESC),.ADD_100(ADD_100);s_to_p s_to_p(.T1(T1),.data(data),.D_out(D_out),.DSC(DSC),.TAKE(TA
38、KE),.ADD_101(ADD_101);Endmodule测试模块源代码:/-Top test file for sys.v-timescale 1ns/100psinclude./sys.vmodule Top;reg D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101;reg7:0 data_buf;wire 7:0 data;wire clk2;assign data=(ADD_101)?data_buf:8bz;/data在sys中是inout型变量,ADD_101 /控制data是作为输入还是进行输出。assign clk2=DSC&TAKE;init
39、ial begin SEND=0;ESC=0;DSC=1;TAKE=1;ADD_100=1;ADD_101=1;endinitial begin data_buf=8b10000001;#90 ADD_100=0;#100 ADD_100=1;endalways begin#50;SEND=SEND;ESC=ESC;endinitial begin#1500;SEND=0;ESC =0;DSC =1;TAKE=1;ADD_100=1;ADD_101=1;D_out=0;#1150 ADD_101=0;#100 ADD_101=1;#100$stop;end always begin#50;DSC=DSC;TAKE=TAKE;end always(negedge clk2)D_out=D_out;sys sys(.D_in(D_in),.T0(T0),.T1(T1),.data(data),.D_out(D_out),.ADD_101(ADD_101),.SEND(SEND),.ESC(ESC),.DSC(DSC),.TAKE(TAKE),.ADD_100(ADD_100);endmodule仿真波形:
限制150内