vhdl硬件描述语言与数字逻辑电路设计 第三版 侯伯亨713 .ppt
1 1第10章 数字系统的实际设计技巧10.1 数字系统优化的基本方法数字系统优化的基本方法10.2 数字系统设计中的工程实际问题数字系统设计中的工程实际问题2 2在线教务辅导网:在线教务辅导网:http:/教材其余课件及动画素材请查阅在线教务辅导网教材其余课件及动画素材请查阅在线教务辅导网QQ:349134187 或者直接输入下面地址:或者直接输入下面地址:http:/3 3在数字系统设计初期,人们根据系统功能总会画出一些满足系统要求的电路框图,在这些电路框图中往往存在一些不合理或冗余的部分需要进行进一步优化,以提高系统的整体性能。这种冗余的部分在生成门级电路以后是很难去除的。因此,必须在电路框图阶段进行优化。10.1 数字系统优化的基本方法数字系统优化的基本方法4 410.1.1 相同电路的处理相同电路的处理在系统设计的前期,设计人员不一定预先知道有多处存在着相同的运算电路,只有在画出电路框图后才会发现它们的存在。例如在图10-1(a)中,2个状态都需进行B+1运算,要正确实现其功能需要3个B+1的运算电路。但是,进行优化以后实际上只要用1个B+1的运算电路就可以实现正确的逻辑功能,如图10-1(b)所示。5 5图10-1 多个相同运算电路优化实例(a)有多个相同运算的电路;(b)优化后采用一个运算电路6 6如图10-1(a)所示,未优化的VHDL语言程序清单如下:ARCHITECTURE rtl of test IS SIGNAL aReg,bReg,cReg:INTEGER RANGE 0 TO 1023;BEGINPROCESS(clk)ISBEGINIF(clk EVENT AND clk=1)THEN CASE stateReg IS7 7WHEN SO=aReg=bReg+1;bReg=bReg+1;cReg=aReg;stateRegaReg=aReg;bReg=cReg;cReg=bReg+1;stateReg=S0;8 8END CASE;END IF;END PROCESS;END ARCHITECTURE rtl 如图10-1(b)所示,优化后的VHDL语言程序清单如下:ARCHITECTURE rtl OF test IS SIGNAL node:INTEGER RANGE 0 TO 1023;BEGINnodeaReg=node;bReg=node;cReg=aReg;stateReg=S1;WHENaReg=aReg;bReg=cReg;10 10cReg=node;stateRegaReg=aReg*bReg;bReg=bReg;cReg=cReg;stateReg18 18aReg=aReg;bReg=cReg*dReg;cReg=cReg;stateReg=S0;END CASE;END IF;END PROCESS;如图10-3(b)所示,优化后的VHDL语言程序清单如下:SIGNAL multin1:INTEGER RANGE 0 TO 1023;SIGNAL multin2:INTEGER RANGE 0 TO 1023;19 19SIGNAL multiout:INTEGER RANGE 0 TO 1023;multin1=aReg WHEN stateReg=S0 ELSE cReg;multin2=bReg WHEN stateReg=S0 ELSE dReg;multout2020aReg=multout;bReg=bReg;cReg=cReg;dReg=dReg;stateRegaReg=aReg;bReg=multout;cReg=cReg;dReg=dReg;21 21stateReg2424aReg=aReg+bReg;bReg=bReg;stateReg=S1;WHEN aReg=aReg;bReg=aReg-bReg;stateReg=S0;END CASE;END IF;END PROCESS;2525如图10-4(b)所示,优化后的VHDL程序清单如下:SIGNAL addin1:INTEGER RANGE-512 TO 511;SIGNAL addin2:INTEGER RANGE-512 TO 511;SIGNAL addin3:INTEGER RANGE-512 TO 511;addin1=aReg;addin2=bReg WHEN stateReg=S0 ELSE-(bReg;)addoutaReg=addout;bReg=bReg;stateRegaReg=aReg;bReg=addout;2727stateRegaReg=in0;bReg=in1;cReg=in2;stateRegaReg=aReg*(bReg*cReg);临界路径bReg=bReg;cReg=cReg;3838stateRegaReg=aReg*2;bReg=bReg;cReg=cReg;stateReg=S0;END CASE;END IF;END PROCESS;3939从程序中可以看出,aReg=aReg*(bReg*cReg)的路径最长,因此,该系统的工作速度由该路径中信号传送的时间所确定。假设每个乘法器的运算时间需要100 ns,每个选择器的时间延时需要1 ns,那么只考虑2个乘法器所需的运算处理时间就不能小于200ns。由此推断,时钟频率一定不能高于5 MHz。40402)门电路之间延时时间的计算数字系统的延时也包含门电路之间的延时。门电路之间的延时由两部分组成:门电路本身所产生的延时和连线所产生的传输延时。门电路之间的延时时间如图10-5所示。一般来说,连线长度和门的扇出数成正比,当然也就和连线的延时时间成正比。如果某系统都是由门电路组成的,那么其系统总的延时时间应为系统总的延时时间=41 41使用逻辑单元和宏单元的FPGA和CPLD器件的延时,同样可以用下面公式去估算:延时=在ASIC芯片中,标准单元和门阵列的每个门延时约为0.10.5 ns;FPGA芯片中1个单元的延时约为几个ns;LSTTL芯片每个门延时约为10 ns;ASIC芯片如果按1 ns延时计算,则时钟频率可达1 GHz。由此可知,这就是ASIC芯片的工作速度比一般电路高得多的原因。42423)系统延时时间的评估在用EDA软件工具对系统进行综合时,软件会自动寻找系统的临界路径,并为设计者指出系统所能工作的最高频率。由于没有考虑系统的动态工作特性,只以电路图或网表为依据来寻找临界路径,因此把这种分析称为静态定时分析。例如,下面的VHDL语言程序清单中,EDA软件把经过2个乘法器的路径认定为该系统的临界路径,但是实际的信号传输路径是经过一个加法器和一个乘法器(见图10-6)。4343图10-6 实际信号传输路径示意图4444系统的VHDL语言程序描述如下:nodeaReg=node+cReg;bReg=node;cReg=cReg;4545stateRegaReg=node*cReg;bReg=node;cReg=cReg;stateRegaReg=in0;bReg=in1;cReg=in2;stateReg aReg=aReg*bReg;5050bReg=bReg;cReg=cReg;stateReg=S2;WHEN S2 aReg=aReg*(cReg*2);bReg=bReg;cReg=cReg;stateReg=S0;END CASE;END IF;END PROCESS;51 51经修改后,临界路径变为aRegaReg=aReg*bReg;bReg=bReg-1;stateRegaReg=aReg+1;bReg=bReg+2;stateReg=S0;END CASE;END IF;END PROCESS;6464利用多周期路径后的VHDL语言程序描述如下:SIGNAL node:INTEGER RANGE 0 TO(2*16-1);TYPE STATENAME IS(S0,Sadd,S1);SIGNAL stateReg:STATENAME;Node6565aReg=aReg;bReg=bReg;stateRegaReg=node;bReg=bReg-1;stateRegaReg=aReg+1;bReg=bReg+2;stateReg=S0;6666END CASE;END IF;END PROCESS;在例10-3修改前的S0状态中,aReg*bReg在1个时钟周期中是无法完成的,因此,在S0和S1状态之间插入一个中间状态Sadd。aReg*bReg在S0状态开始就进行运算,到Sadd状态结束,aReg*bReg的中间值node形成,在S1状态开始node值被赋予aReg,然后完成最后的运算。由VHDL语法知道,node=aReg*bReg语句和PROCESS语句是并发执行的,引入的Sadd状态是为了拉长乘法时间,并使node=aReg*bReg运算与PROCESS同步。6767假设aReg*bReg需2个时钟周期,那么这种修改是有效的。这样就缩短了临界路径长度,提高了系统的整体工作速度。68685)减少临界路径上部件的扇出数众所周知,一个部件的扇出数愈多,负载愈重,该部件对信号所产生的延时也就愈大。因此,减少临界路径上部件的扇出数无疑会提高系统的工作速度。图10-10是减少临界路径上部件的扇出数来提高系统工作速度的实例。图10-10(a)中,系统临界路径上部件的扇出数为3。将2个乘法器合并后,如图10-10(b)所示,部件的扇出数变为2。6969图10-10 减少临界路径上部件的扇出数来提高系统工作速度的实例(a)系统原部件连接情况;(b)利用共享乘法器减少扇出数情况7070利用计算系统的临界路径长度来评估系统的工作速度,在大多数情况下是可行的,但是也有例外。例如,当组合电路跨模块进行连接时,有可能使优化效果变差。也就是说,多个组合电路模块合并成一个模块进行优化,其临界路径肯定会更短。另外,多模块连接后的实际路径长度有可能比各模块临界路径长度之和要长。71 7110.2.2 缩小电路规模和降低功耗的方法缩小电路规模和降低功耗的方法1缩小电路规模的方法缩小电路规模的方法缩小电路规模的最基本方法是在设计时尽可能共享资源。1)共享组合电路的部件使用EDA软件达到理想的资源(部件)共享效果,这种情况大多是存在的。例如,在计算A+(BC)和(BC)2时,(BC)是相同的,可以用一个电路来实现。72722)共享寄存器在用VHDL语言设计电路时,要尽可能减少变量和信号量的设置,能共享的尽可能共享,因为冗余的寄存器将会增大电路规模和功耗,特别是位数较长的寄存器更是如此。假如现有100个32位的冗余寄存器,那么就需要3200个触发器。这样大的规模在当前条件下是不能忽视的。73733)共享连线连线也是一种资源。利用三态门使多个输出共享一条总线,这是共享总线的一种形式。当然,在CMOS电路中为了防止总线浮动,通常在输出端要接上拉电阻或者下拉电阻。为了降低功耗有时也不采用三态总线。74744)展开处理时间实现资源共享如果在一个状态中有几次相同种类的运算或译码,那么将几个相同运算依次分散到几个状态中进行处理,此时可以利用共享部件的方法使多个相同运算的电路用一个电路进行分时处理。75755)展开处理空间实现资源共享对数据流图的处理顺序进行适当调整就可以缩小数据流图的规模。(1)通过改变处理顺序来缩小电路规模。图10-11是通过改变处理顺序来缩小电路规模的数据流图。图10-11(a)是未进行修改的数据流图;图10-11(b)是修改处理顺序后的数据流图。两个图的不同点是后者先作加法,后作乘法。这样修改以后可以节省3个乘法器和1个加法器,从而缩小了电路规模。7676图10-11 通过改变处理顺序来缩小电路规模的数据流图(a)未进行修改的数据流图;(b)修改处理顺序后的数据流图7777(2)通过串行处理来缩小电路规模。图10-12是通过串行处理来缩小电路规模的数据流图。图10-12(a)是未进行修改前的数据流图,图10-12(b)是进行串行处理后的数据流图。图10-12(a)的运算公式为f1=3a+bf2=a+3bf3=f1+f2完成此运算需要2个乘法器和3个加法器。如果直接对f3进行运算:f3=3a+b+a+3b=4a+4b=4(a+b)那么完成4(a+b)运算只要1个加法器和进行2次移位操作即可,如图10-12(b)所示。这样就大大缩小了电路的规模。7878图10-12 通过串行处理缩小电路规模的数据流图(a)未修改前的数据流图;(b)进行串行处理后的数据流图7979(3)复杂运算化简成简单运算。复杂的运算通过适当改变顺序可以变成简单的运算。例如,(a+1)+b)+2)可以用(a+b)+3)来替代。这样就可以省掉1个加法器。(4)利用数据流图中的已有结果。在数据流图中某些分支可能会得到相同的结果,此时可省掉1个分支,利用1个分支已得到的结果参与下一级运算,从而减少重复的运算电路。80802在在RTL级上降低系统功耗的方法级上降低系统功耗的方法功耗是单片系统的一个很重要的指标,功耗愈低,系统的寿命、可靠性和体积也愈低。1)缩小电路的规模电路规模愈小,功耗也就愈小。前述的缩小电路规模的方法对降低功耗都有实际意义。81 812)停止不必要的运算处理下面是某系统的VHDL语言程序描述清单,它由S0S3四个状态组成。S0=1 WHEN stateReg=00 ELSE 0;S1=1 WHEN stateReg=01 ELSE 0;S2=1 WHEN stateReg=10 ELSE 0;S3=1 WHEN stateReg=11 ELSE 0;plus=aReg+bReg;minus=aReg-bReg;mult=aReg*bReg;nextA=plusWHEN S0=1 ELSE8282minusWHEN S1=1 ELSEmultWHEN S2=1 ELSEbReg;PROCESS(clk)IS BEGINIF(clkEVENT and clk=1)THENIF(reset=1)THENaReg=127;bReg=2;stateReg=00;ELSE8383aReg=nextA;bRegstateRegstateRegstateRegstateReg=00;END CASE END IF;END IF;END PROCESS;8484上述程序中,S0进行加法运算,S1进行减法运算,S2进行乘法运算。经编译综合后,其电路的基本结构如图10-13所示。这样结构的电路无论在何种状态下,所有运算电路都要进行工作。但是实际上S0状态下只要加法运算器工作,S1状态下乘法器就没有必要进行工作。这些运算器没有选择的无用工作会增加电路的功耗。采用下面方法可以停止不必要的运算处理。(1)只允许必要的运算电路工作。为了降低电路的功耗,只选择必要的运算电路进行工作,对图10-13进行修改后电路结构如图10-14所示。图10-14中,在各个运算器的输入端插入一个“与门”,在没有工作必要时使该电路输出为“0”。由此可知,S0状态下乘法运算器和减法运算器不工作,S1状态下乘法器不工作。8585图10-13 某系统的基本电路结构8686图10-14 图10-13修改后的电路结构8787图10-14对应的VHDL语言程序清单如下:LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_ARITH.ALL;ENTITY hazard3 ISPORT(reset :IN STD_LOGIC;clk :IN STD_LOGIC;(途中省略)8888plusOut :OUT INTEGER RANGE 0 to(2*8-1);s3out :OUT STD_LOGIC;);END ENTITY hazard3;ARCHITECTURE rtl OF hazard3 IS FUNCTION INTAND(val:INTEGER;cond:STD_LOGIC)RETURN INTEGER ISBEGINvec:=CONV_STD_LOGIC_VECTOR(val,8);FOR i IN 0 TO 7 LOOP8989vec(i):=vec(i)AND cond;END LOOP;RETURN CONV_INTEGER(UNSIGNED(vec);END FONCTION INTAND;FUNCTION INTOR4(val1,val2,val3,val4:INTEGER)RETURN INTEGER ISVARIABLE vec1,vec2,vec3,vec4:STD_LOGIC_VECTOR(7 DOWNTO 0);BEGINvec1:=CONV_STD_LOGIC_VECTOR(val1,8);vec2:=CONV_STD_LOGIC_VECTOR(val2,8);9090vec3:=CONV_STD_LOGIC_VECTOR(val3,8);vec4:=CONV_STD_LOGIC_VECTOR(val4,8);RETURN CONV_INTEGER(UNSIGNED(vec1 or vec2 or vec3 or vec4);END FONCTION INTOR4;SIGNAL aReg :INTEGER RANGE 0 to(2*8-1)(省略)SIGNAL S3:STD_LOGIC;BEGINS0=1 WHEN stateReg=00 ELSE 0;S1=1 WHEN stateReg=01 ELSE 0;S2=1 WHEN stateReg=11 ELSE 0;91 91S3=1 WHEN stateReg=10 ELSE 0;aRegSt0=INTAND(aReg,S0);aRegSt1=INTAND(aReg,S1);aRegSt2=INTAND(aReg,S2);aRegSt3=INTAND(bReg,S3);bRegSt0=INTAND(bReg,S0);bRegSt1=INTAND(bReg,S1);bRegSt2=INTAND(bReg,S2);plus =aRegSt0+bRegSt0;minus=aRegSt1-bRegSt1;mult=aRegSt2*bRegSt2;9292nextA=INTOR4(plus,minus,mult,aRegSt3);PROCESS (clk)IS(途中省略)END PROCESS;plusOut=plus;(省略)s3out =S3;END ARCHITECTURE rtl;9393(2)尽可能在数据流的前部分屏蔽数据流。数据流图中的一个管道增加的控制“与门”像一个阀门,不需要进行运算的数据流应尽可能早地在数据流的前部分屏蔽,这样可以降低功耗。在进行流水线操作时,在没有有效数据的情况下管道的输入侧如果屏蔽数据,则会停止后阶段的操作。如果控制数据流入的信号(如“与门”的输入)与数据信号相比滞后,则会出现竞争冒险现象,从而降低减小功耗的效果。因此,必须消除这种竞争冒险现象。有关细节将在10.2.3节详述。9494(3)寄存器的值没有必要改变时不要改变。若每个时钟到来时寄存器的输出值都要变化,那么它后面连接的组合电路也会随之工作。另外,像移位寄存器等那样的电路,即使没有和组合电路相连接,只要数据被移位,就会增加功耗。在运算器输入端设置专用的寄存器是一种降低功耗的方法。例如在图10-14中,各运算器在一个时钟周期内有2次动作:第一次是当数据输入时,第二次是当状态切换时。要使运算器在一个时钟周期只进行一次动作,就必须在运算器输入端设置专用寄存器。只有当需要进行运算时,才将其数据写入该寄存器。这样动作减少了,当然功耗也就降低了。95953)减少竞争冒险的总量由于组合电路的信号在多条路径中的传输延时不同,因而就会产生竞争冒险现象。譬如,冒险在信号流图的前部分发生,就会向后面部分传播,数量也会增加。特别地,多个处理串行连接时问题就会更大。图10-15是多个加法器串行连接的电路。图中,加法器产生的冒险现象从前面向后面传播,最后一个输出 node6out 比第一级加法器输出 node1out的冒险量增加了11倍。由此可见,这种串行工作的电路其最后一级输出的冒险量与串联的级数成正比。事实上,要完全消除冒险现象是困难的,但是使其减少却是完全可以做到的。9696图10-15对应的串接加法器的VHDL语言描述清单如下:node1=aReg+bReg;node2=cReg+node1;node3=dReg+node2;node4=eReg+node3;node11=fReg+node4;nextA=gReg+node11;通常减少串接电路数目就可以减少冒险总量。将图10-15所示的串接加法器的结构改为树型,结果使其级数从6级减少为3级,那么冒险总量就会减少一半。树型加法器连接的冒险现象如图10-16所示。9797图10-15 多个加法器串行连接的电路9898图10-16 树型加法器连接的冒险现象9999此外,还可以采取一些其它措施:减少参加运算输入信号到来的时间量;缩短频繁变化信号的传输路径;减少多位长度的运算;构筑防止冒险传播的防传输墙等。详细内容将在10.2.3节中讨论。图10-16对应的树型加法器连接的VHDL语言程序清单如下:node1=aReg+bReg;node2=cReg+dReg;node3=eReg+fReg;node4=node1+node2;node11=node3+gReg;nextA=node4+node11;1001004)控制时钟通过降低时钟频率,用“与门”控制某些工作单元,使其在不工作期间不提供时钟等措施,同样也可以降低系统的功耗。10110110.2.3 系统误操作的成因及其消除方法系统误操作的成因及其消除方法系统在工作过程中有可能出现误操作,其产生原因是多方面的。由于设计不当或存在的缺陷诱发的误操作大致有以下几种:(1)冒险现象。冒险现象通常在信号发生变化时产生,其产生原因主要是输入信号经不同路径传输而出现不同的延时所引起的。冒险的传播将危及后续的电路,特别是时序电路的正确工作。102102(2)不遵守既定的定时关系。在用边沿触发器作为数据寄存器时,触发器的数据输入端和时钟触发边沿应保持严格的定时关系。图10-17示出了寄存器的定时关系,在时钟上升沿到来之前,触发器的数据输入端(D端)所加的信号必须有一段稳定的时间,这段时间称为建立时间。在时钟上升沿到来以后,D端的输入信号仍需稳定地保持一段时间,该段时间称为保持时间。建立时间和保持时间对不同的触发器和不同工艺的电路都有明确不同的要求。如果在设计电路时破坏了这种定时关系,如建立时间不够或保持时间不够,则可能导致寄存器输出值不稳定,即“0”或“1”无法确定,从而使系统出现误操作。103103图10-17 寄存器的定时关系104104(3)数据和时钟的临界竞争。图10-18是数据和时钟的临界竞争实例及定时关系。电路输入信号在时钟上升沿到来时,多个寄存器或寄存器各位之间的值出现了参差不齐的变化,从而使输出出现不稳定,这种现象称为数据时钟的临界竞争,也称为竞争。105105图10-18 数据和时钟的临界竞争实例及定时关系(a)临界竞争电路实例;(b)定时关系106106上述三个原因有可能导致系统或电路的误操作。1设计时应重点注意的地方设计时应重点注意的地方上述导致误操作的因素并不是在所有场合都会起作用,例如,对于冒险现象来说,在寄存器与寄存器连接的同步电路中就可以不予考虑。下面列举一些应重点注意的场合。1)必须消除冒险现象的地方在与非同步电路的连接线上必须消除冒险现象。107107(1)控制存储器和触发器的控制信号。对于存储器或触发器,无论是边沿控制还是电平控制,如DRAM的RAS、CAS、WE及触发器的置位/复位端和锁存控制端,都不能有冒险信号出现,否则就会破坏存储器和触发器的正常数据。另外,边沿触发的触发器时钟端和CPU边沿触发的中断输入信号同样也不应混入冒险信号。108108(2)应保持数个时钟周期的信号。当CPU和存储器等设备连接时,对建立/保持时间都有严格规定。如果系统的时钟频率比较高,则建立/保持时间要跨越几个时钟周期。此时如果信号中混有冒险信号,那么有可能破坏这种定时关系。例如,所设计芯片与110ns建立时间的存储器相连,芯片时钟为100 MHz(周期为10 ns),如果数据总线混入了周期为10ns的冒险信号,那么就会使存储器产生读/写错误。1091092)必须消除亚稳定和竞争的地方需要接收来自非同步系统信号的地方必须考虑消除亚稳定和竞争。这里所说的非同步系统是指同一芯片内时钟不同的模块或芯片外连接的电路,而不是非同步电路。即使同一个时钟驱动的电路,如果位于其它芯片或端口上,也应看做非同步系统。这是因为芯片的输入和输出驱动等会使时钟和数据的相位产生延时。1101102消除冒险现象的方法消除冒险现象的方法消除冒险现象的方法很多,这里只举几个常用的方法。(1)利用专用寄存器输出信号。电路的输出信号不由组合电路输出,而是通过专用寄存器直接输出。图10-19是未使用专用寄存器出现冒险现象的实例。该实例的电路由一个八进制计数器和1个3-8译码器组成。当八进制计数器工作时,在其译码器输出端y(0)y(7)就会轮流出现1个时钟周期的低电平。从图10-19的仿真图中可以发现,在译码器的输出端出现了不应有的负向尖脉冲,也就是说出现了冒险现象。这些负向尖峰脉冲可能会对后接电路产生不利影响。为了消除这种冒险现象,在其各输出端加一个锁存寄存器,使它们通过寄存器输出,以消除冒险现象。111111图10-19 未使用专用寄存器出现冒险现象的实例112112图10-19对应的VHDL语言程序清单如下:LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_ARITH.ALL;ENTITY state_8 IS PORT(reset :IN STD_LOGIC;clk :IN STD_LOGIC;y :OUT STD_LOGIC_VECTOR(7 DOWNTO 0);113113END ENTITY state_8;ARCHITECTURE rtl OF state_8 IS SIGNAL S0,S1,S2,S3:STD_LOGIC;SIGNAL stateReg:STD_LOGIC_VECTOR(2 DOWNTO 0);BEGIN y(0)=0 WHEN statereg=000 ELSE 1;y(1)=0 WHEN statereg=001 ELSE 1;y(2)=0 WHEN statereg=010 ELSE 1;y(3)=0 WHEN statereg=011 ELSE 1;y(4)=0 WHEN statereg=100 ELSE 1;y(11)=0 WHEN statereg=101 ELSE 1;114114 y(6)=0 WHEN statereg=110 ELSE 1;y(7)=0 WHEN statereg=111 ELSE 1;PROCESS(clk)IS BEGIN IF(clkEVENT AND clk=1)THEN IF(reset=1)THEN stateReg stateReg stateReg stateReg stateReg stateReg stateReg stateReg stateReg y y y y y y y y y=11111111;END CASE;END IF;END PROCESS;PROCESS(clk)IS120120 BEGIN IF(clkEVENT AND clk=1)THEN IF(reset=1)THEN stateReg stateReg stateReg stateReg stateReg stateReg stateReg stateReg stateReg=000;END CASE;END IF;END IF;END PROCESS;END ARCHITECTURE rtl;122122图10-20是输出端插入专用寄存器清除冒险现象的实例。从图10-20中可以看出,在图10-19中所出现的冒险现象被专用寄存器屏蔽掉了。寄存器之所以能屏蔽冒险现象,是因为寄存器的输出值只在时钟上升沿到来时采样,在该时刻寄存器的数据输入端处于稳定的数据状态,从而避开了数据动态的变化过程。123123图10-20 输出端插入专用寄存器消除冒险现象的实例124124(2)输入至输出只经过一条传输路径。冒险现象是由于变化信号经过不同的路径,产生不同延时而引起的。因此,在组合电路设计时使变化信号只通过一条路径就可以消除冒险现象。图10-21(a)是输入至输出只经过一条传输路径消除冒险现象的实例。图10-21(a)中,输入信号b到达输出端有2条路径,这必定会发生冒险现象。现在假设只有输入信号b发生变化或a、b、c 3个信号只有一个信号发生变化,经调整后的逻辑电路如图10-21(b)所示,此时输入信号b从输入到输出只有一条传输路径,因此该电路就不会发生冒险现象。当然,如果c和a(或b)同时发生变化,则在输出端仍有可能发生冒险现象。125125图10-21 输入至输出只经过一条传输路径消除冒险现象的实例(a)原电路图;(b)修改后的电路图126126(3)组合电路输入信号同时只变化1位。如上所述,如果组合电路的多个输入信号只有1位同时发生变化,那么在逻辑设计时就容易做到无冒险现象出现。例如,数字系统中的状态机有多个状态,许多控制信号是对状态机不同的状态进行译码产生的。图10-22是8个状态的状态机编码实例。图10-22(a)是一般编码情况,从000111;图10-22(b)则是汉明距离为1的编码情况。前者在一个状态向另一个状态转移时有可能同时使编码值发生1位以上的变化,例如,111000就发生了3位变化;后者编码按000000010011110010000000的规律进行改变,状态在转移时状态编码只发生1位变化。127127当然,这种方法并不能完全消除冒险现象,通常要对状态译码电路进行分析,看在什么情况出现冒险。得到确定出现冒险现象的条件后,对逻辑电路进行适当修改,使其信号变化的输入只有一条传输路径,即可消除冒险现象。128128图10-22 8个状态的状态机编码实例(a)通常的编码;(b)汉明距离为1的编码129129在某些情况下,状态编码不能保证只有1位发生变化(即汉明距离超过1)时,有2种编码方法保证状态图编码仍维持1位变化,如图10-23所示。第一种方法是一个状态分配多个编码,如图10-23(b)所示。原001状态再分配1个010编码,这样可以保证汉明距离为1。例如,原110状态转移至001状态,状态编码发生了3位变化。现在加了010编码,那么该状态编码为001和010。110与该状态的010编码对照,只改变1位编码。其余依次类推,也可得到相似的结果。第二种方法是在状态译码时采用分组译码,如图10-23(c)所示。1011转移至0001时只对低2位译码,这样就保证了只有1位发生变化。130130(4)在译码输出端加选通电路。冒险现象通常发生在译码电路输入发生变化的时刻。如果待输入信号稳定以后,再输出译码信号,那么就可以屏蔽冒险现象。例如,在图10-19所示的仿真图中如果加上选通信号STB,那么此时译码输出就消除了,如图10-24所示。图10-24中,STB信号应相对clk前沿延时几十纳秒才行。在这里引入了一个比clk时钟信号频率高5倍的clk信号。131131图10-23 状态编码汉明距离超过1时的处理方法(a)汉明距离超过1的状态图;(b)多编码状态图;(c)分组译码状态图132132图10-24 加选通信号消除冒险现象的实例1331332个D触发器U1、U2连接产生一个周期为clk/5的选通脉冲STB。该STB在clk上升沿时变高,在经历一个clk/5的周期之后变低。将该信号与译码输出信号相“或”,即可屏蔽掉在clk上升沿之后出现的“1”冒险现象。同理,如果译码输出是“1”有效,那么可以将NOT STB与译码输出信号相“与”,从而消除“0”冒险现象。图10-24对应的加选通信号STB的VHDL语言程序清单如下:LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_ARITH.ALL;ENTITY cnt8_deco11 IS134134 PORT(reset,clk,clk11:IN STD_LOGIC;y_out:OUT STD_LOGIC_VECTOR(7 DOWNTO 0);END ENTITY cnt8_deco11;ARCHITECTURE rtl OF cnt8_deco11 IS COMPONENT cnt8 IS PORT(reset,clk:IN STD_LOGIC;q:OUT STD_LOGIC_VECTOR(2 DOWNTO 0);END COMPONENT cnt8;COMPONENT dff1 IS PORT(reset,clk,d:IN STD_LOGIC;q,qb:OUT STD_LOGIC);135135 END COMPONENT dff1;SIGNAL reset_s,reset1,clk_s,clk111,q1,q1b,q2,q2b,stb,vcc:STD_LOGIC;SIGNAL q_s:STD_LOGIC_VECTOR(2 DOWNTO 0);SIGNAL y_s,y:STD_LOGIC_VECTOR(7 DOWNTO 0);BEGIN reset_s=reset;clk_s=clk;y_out(0)=y(0)OR stb;y_out(1)=y(1)OR stb;y_out(2)=y(2)OR stb;136136 y_out(3)=y(3)OR stb;y_out(4)=y(4)OR stb;y_out(11)=y(11)OR stb;y_out(6)=y(6)OR stb;y_out(7)yyyyyyyyy=11111111;END CASE;END PROCESS;stb=q1;vcc=1;reset1=reset_s AND(q1 NAND q2);u0:cnt8 PORT MAP(reset_s,clk_s,q_s);138138 u1:dff1 PORT MAP(reset1,clk_s,vcc,q1,q1b);u2:dff1 PORT MAP(reset1,clk11,q1,q2,q2b);END ARCHITECTURE rtl;139139图10-26 非同步信号同步的实例140140(5)在译码逻辑中增加冗余项。若单个译码输入发生变化,则可以在译码逻辑电路中增加冗余项,从而达到消除冒险现象的目的。图10-25是增加冗余项消除“1”冒险现象的实例,其表达式为F=AB+AC。这是因为,当B=C=“1”时,F=A+A。若电路在某些输入组合情况下出现F=AA,那么该电路会产生“0”冒险现象。图10-25所示电路的逻辑表达式中如增加冗余项BC,则为F=AB+AC+BC。当B=C=1时,F=1,从而消除了“1”冒险现象(产生负向干扰脉冲)。141141图10-25 增加冗余项消除“1”冒险现象的实例(a)产生“1”冒险的电路;(b)增加冗余项消除“1”冒险的电路14214210.2.4 非同步信号的控制方法数字系统的外部输入和内部不同时钟模块之间连接的信号都属于非同步信号,系统只有采用适当的非同步信号控制方法才能保证可靠的工作。1431431将非同步信号变为同步信号的方法将非同步信号变为同步信号的方法将非同步信号变为同步信号的最简单办法是用D触发器锁存非同步信号,如图10-26所示。图10-26中,非同步输入信号与D触发器的D端相连,时钟端clk与系统时钟相连。这样,在时钟脉冲上升沿到来时就将非同步输入信号锁存于D触发器的Q输出端。在用VHDL语言描述时,表示锁存的代入语句