数字系统设计教学第四章时序逻辑电路1课件.ppt
本章目录,时序电路概述同步电路基本存储单元的引用简单的设计例子时序分析一段式代码风格时序电路中变量的使用,本章目录时序电路概述,组合电路和时序电路时序电路:输出是输入和当前状态的函数基本记忆单元D 锁存器D 触发器RAM,时序电路概述,组合电路和时序电路时序电路概述,D锁存器是电平敏感的记忆单元,而D触发器是边沿敏感的记忆单元,对于D锁存器,当时钟信号c为高电平时,下一个状态q*=d,当时钟信号c为低电平时,q*=q(保持),d,c,q,(a)D 锁存器,D锁存器,D锁存器是电平敏感的记忆单元,而D触发器是边沿敏感的记忆单元,D锁存器的时序图(d在c的下降沿处被采样和保存),D锁存器,D锁存器的时序图(d在c的下降沿处被采样和保存)D锁存器,D触发器只有在clk信号的跳变沿处有效(01或10),d,clk,q,(b)上升沿D 触发器,d,clk,q,(c)下降沿D 触发器,“有效”的含义是指:d的值只有在clk的边沿处被采样和保存,并更新输出q,D触发器,D触发器只有在clk信号的跳变沿处有效(01或10)dc,D触发器的优点d端口小小的毛刺不会影响到存储的状态消除了竞争的条件,交换数据的电路可以工作D触发器的缺点是D锁存器的两倍大小,D触发器,D触发器的优点D触发器,时序图如下:,Clock-to-q 延时(Tcq):信号d被采样到更新q的延时建立时间(Tsetup):在时钟的上升沿来临之前,d必须保持稳定的时间保持时间(Thold):在时钟上升沿到来之后,d必须保持稳定的时间,D触发器,时序图如下:Clock-to-q 延时(Tcq):信号d,时序图如下:(续),Tcq代表组合电路的传播延时Tsetup 和Thold 是时序约束,d必须在clk的时间间隔内保持稳定。如果d在这个时隙内改变,这样就会违反建立时间和保持时间的规则,导致触发器进入亚稳态(q不是0也不是1),D触发器,时序图如下:(续)Tcq代表组合电路的传播延时D触发器,在时序电路中,时钟信号扮演着一个很重要的角色系统可以根据时钟的布局来分类,全局同步电路所有的存储单元都在同一个全局时钟的控制下工作,全局异步-局部同步电路(GALS)设计的器件传输分开得太远,无法使用单个同步时钟的情况下,只能使用一个全局的异步时钟然而,较小的子系统内部使用一个同步的时钟在子系统之间需要特殊的电路接口来保证正常的工作,时钟信号,在时序电路中,时钟信号扮演着一个很重要的角色全局同步电路全局,全局异步电路没有时钟来协调存储单元的工作,大致分为两类。时钟 的使用是没有规律的,例如行波计数器:触发器的时钟端口连接上一个触发器的输出q端口。(这种设计并不完美,不推荐)系统带有不需要时钟的存储单元(如D锁存器)或者带有反馈回路的组合电路(异步电路)。,时钟信号,合理的异步电路设计和同步电路完全不同,而且HDL的综合工具不太推荐,全局异步电路时钟信号合理的异步电路设计和同步电路完全不同,而,状态寄存器(state_reg):代表存储单元的状态下一个状态逻辑(Next state logic):代表决定state_next的组合电路,同步电路,状态寄存器(state_reg):代表存储单元的状态同步电,操作如下:在时钟信号的上升沿,state_next 被采样和保存在寄存器中,成为新的state_reg的值。外部输入和state_reg 信号传输到next-state 和输出来决定新的next-state 和新的输出信号在时钟信号的上升沿,新的state_next重新被采样和保存,然后重复进程,需要注意的是时钟周期需要足够大来适应触发器的next-state 逻辑传播延时、clock-to-q 延时、建立时间延时,同步电路,操作如下:需要注意的是时钟周期需要足够大来适应触发器的nex,同步设计的优势单个的全局时钟让成千上万个触发器构建的电路能够统一控制和满足时序约束。一个同步的模块把组合逻辑器件从存储单元中分离出来,实现组合逻辑部分的单独优化。传播延时的反常情况很容易通过分析最差的时序行为来处理,因此,同步模块把一个复杂的时序电路变为单个的闭环反馈回路和简化设计的流程,同步电路,同步设计的优势因此,同步模块把一个复杂的时序电路变为单个的闭,同步电路的类型常规的时序电路状态表示,转变和下个状态逻辑有一个简单,常规的模式,例如一个自增的计数器或者一个移位寄存器。随机的时序电路(FSM)更复杂的状态迁移且状态和它们的二进制表示没有特殊的联系。即,下一个状态逻辑是随机的。组合成的时序逻辑(带有数据通路的FSM,FSMD-RTL)组合常规时序电路和有限状态机,用有限状态机来控制时序电路的行为,同步电路,同步电路的类型同步电路,当你需要创建D锁存器和D触发器的时候,可以使用下面的语法样式,综合工具会自动推断出来,生成合适的器件。,D锁存器隐含的else语句会产生D锁存器,library ieee;use ieee.std_logic_1164.all;entity dlatch isport(c:in std_logic;d:in std_logic;q:out std_logic);end dlatch;architecture arch of dlatch is begin-c and d in sens.list b/c process sens.to bothprocess(c,d)beginif(c=1)then q=d;end if;end process;end arch;,d,c,q,(a)D 锁存器,基本存储单元的引用,当你需要创建D锁存器和D触发器的时候,可以使用下面的语法样式,当你需要创建D锁存器和D触发器的时候,可以使用下面的语法样式,综合工具会自动推断出来,生成合适的器件。,上升沿D触发器没有else语句且对时钟跳变信号敏感,library ieee;use ieee.std_logic_1164.all;entity dff isport(clk:in std_logic;d:in std_logic;q:out std_logic);end dff;architecture arch of dff is beginprocess(clk)begin-when d changes(unlike latch)if(clkevent and clk=1)then-can also use q=d;-rising_edge(clk)end if;end process;end arch;,d,clk,q,(b)上升沿D 触发器,基本存储单元的引用,当你需要创建D锁存器和D触发器的时候,可以使用下面的语法样式,下降沿D触发器只需要上升沿的程序稍作修改即可(红色为修改的部分),library ieee;use ieee.std_logic_1164.all;entity dff isport(clk:in std_logic;d:in std_logic;q:out std_logic);end dff;architecture arch of dff is beginprocess(clk)begin-when d changes(unlike latch)if(clkevent and clk=0)then-can also use q=d;-falling_edge(clk)end if;end process;end arch;,d,clk,q,(c)下降沿D 触发器,基本存储单元的引用,下降沿D触发器library ieee;dclkq(c)下降,带异步复位的D触发器,library ieee;use ieee.std_logic_1164.all;entity dffr isport(clk:in std_logic;reset:in std_logic;d:in std_logic;q:out std_logic);end dffr;architecture arch of dffr is beginprocess(clk,reset)beginif(reset=1)then q=0;elsif rising_edge(clk)then q=d;end if;end process;end arch;,d,clk,q,(d)带异步复位的D 触发器,reset,基本存储单元的引用,带异步复位的D触发器library ieee;dclkq(d,寄存器由多个共用同样时钟信号和复位信号的D触发器并联而成,library ieee;use ieee.std_logic_1164.all;entity reg8 isport(clk,reset:in std_logic;d:in std_logic_vector(7 downto 0);q:out std_logic_vector(7 downto 0);end reg8;architecture arch of reg8 is beginprocess(clk,reset)beginif(reset=1)then q 0);elsif(clkevent and clk=1)then q=d;end if;end process;end arch;,基本存储单元的引用,寄存器library ieee;基本存储单元的引用,最简单的设计时序电路的方法是根据框图来搭建,构建寄存器编写下一个状态和输出逻辑(组合电路)的代码,简单的设计例子,最简单的设计时序电路的方法是根据框图来搭建构建寄存器简单的设,带有同步使能端的D触发器注意:en的值在clk的上升沿被采样,当en=0,或者由0变为1,触发器保持输出q不变当en=1,或者由1变为0,触发器保存q_next的值,简单的设计例子,带有同步使能端的D触发器当en=0,或者由0变为1,触发器保,带有同步使能端的D触发器(代码),library ieee;use ieee.std_logic_1164.all;entity dff_en isport(clk:in std_logic;reset:in std_logic;en:in std_logic;d:in std_logic;q:out std_logic);end dff_en;architecture two_seg_arch of dff_en issignal q_reg:std_logic;signal q_next:std_logic;begin-D FFprocess(clk,reset)beginif(reset=1)then q_reg=0;elsif(clkevent and clk=1)then q_reg=q_next;end if;end process;-next-state logic q_next=d when en=1 else q_reg;-output logic q=q_reg;end two_seg_arch;,简单的设计例子,带有同步使能端的D触发器(代码)library ieee;简,T触发器注意:t的值在clk的上升沿被采样,简单的设计例子,T触发器简单的设计例子,T触发器(代码),library ieee;use ieee.std_logic_1164.all;entity tff isport(clk:in std_logic;reset:in std_logic;t:in std_logic;q:out std_logic);end tff;architecture two_seg_arch of tff issignal q_reg:std_logic;signal q_next:std_logic;begin-D FFprocess(clk,reset)beginif(reset=1)then q_reg=0;elsif(clkevent and clk=1)then q_reg=q_next;end if;end process;-next-state logic q_next=q_reg when t=0 elsenot(q_reg);-output logic q=q_reg;end two_seg_arch;,简单的设计例子,T触发器(代码)library ieee;简单的设计例子,移位寄存器(无控制信号),我们可以重新调整触发器使其成为一列然后把它看成一个存储器块,如下图所示。,简单的设计例子,移位寄存器(无控制信号)我们可以重新调整触发器使其成为一列然,移位寄存器(无控制信号),简单的设计例子,移位寄存器(无控制信号)简单的设计例子,移位寄存器(无控制信号)代码,library ieee;use ieee.std_logic_1164.all;entity shift_right_register isport(clk,reset:in std_logic;d:in std_logic;q:out std_logic);end shift_right_register;architecture two_seg_arch of shift_right_register issignal r_reg:std_logic_vector(3 downto 0);signal r_next:std_logic_vector(3 downto 0);begin-registerprocess(clk,reset)beginif(reset=1)then r_reg 0);elsif(clkevent and clk=1)then r_reg=r_next;end if;end process;-next-state logic(shift right 1 bit)r_next=d,简单的设计例子,移位寄存器(无控制信号)代码library ieee;简单的,通用移位寄存器设计为4个操作方式:并行、左移、右移、暂停,简单的设计例子,通用移位寄存器简单的设计例子,通用移位寄存器(代码),library ieee;use ieee.std_logic_1164.all;entity shift_register isport(clk,reset:in std_logic;ctrl:in std_logic_vector(1 downto 0);d:in std_logic_vector(3 downto 0);q:out std_logic_vector(3 downto 0);end shift_register;architecture two_seg_arch of shift_register issignal r_reg:std_logic_vector(3 downto 0);signal r_next:std_logic_vector(3 downto 0);begin-registerprocess(clk,reset)beginif(reset=1)then r_reg 0);elsif(clkevent and clk=1)then r_reg=r_next;end if;end process;-next-state logicwith ctrl select r_next=r_reg when 00,-no op r_reg(2 downto 0),简单的设计例子,通用移位寄存器(代码)library ieee;简单的设计例,任意序列计数器,library ieee;use ieee.std_logic_1164.all;entity arbi_seq_counter4 isport(clk,reset:in std_logic;q:out std_logic_vector(2 downto 0);end arbi_seq_counter4;architecture two_seg_arch of arbi_seq_counter4 issignal r_reg:std_logic_vector(2 downto 0);signal r_next:std_logic_vector(2 downto 0);begin-registerprocess(clk,reset)beginif(reset=1)then,简单的设计例子,任意序列计数器Input patternOutput pat,任意序列计数器(续),r_reg 0);elsif(clkevent and clk=1)then r_reg=r_next;end if;end process;-next-state logic r_next=011 when r_reg=000 else 110 when r_reg=011 else 101 when r_reg=110 else 111 when r_reg=101 else 000;-r_reg=111-output logic q=r_reg;end two_seg_arch;,简单的设计例子,任意序列计数器(续)r_reg,自由运行的二进制计数器当计数器的值全部为1时,输出最大脉冲,并自动轮回,library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;entity binary_counter4_pulse isport(clk,reset:in std_logic;max_pulse:out std_logic;q:out std_logic_vector(3 downto 0);end binary_counter4_pulse;architecture two_seg_arch of binary_counter4_pulse issignal r_reg:unsigned(3 downto 0);signal r_next:unsigned(3 downto 0);begin-registerprocess(clk,reset)beginif(reset=1)then r_reg 0);elsif(clkevent and clk=1)then r_reg=r_next;end if;end process;-next-state logic r_next=r_reg+1;-output logic q=std_logic_vector(r_reg);max_pulse=1 when(r_reg=1111)else 0;end two_seg_arch;,简单的设计例子,自由运行的二进制计数器library ieee;简单的设计例,自由运行的二进制计数器RTL原理图,简单的设计例子,自由运行的二进制计数器简单的设计例子,二进制计数器,简单的设计例子,二进制计数器Syn_clrloadenq*操作1-00.,二进制计数器,library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;entity binary_counter4_feature isport(clk,reset:in std_logic;syn_clr,en,load:in std_logic;d:in std_logic_vector(3 downto 0);q:out std_logic_vector(3 downto 0);end binary_counter4_feature;architecture two_seg_arch of binary_counter4_feature issignal r_reg:unsigned(3 downto 0);signal r_next:unsigned(3 downto 0);begin-registerprocess(clk,reset)beginif(reset=1)then r_reg 0);elsif(clkevent and clk=1)then r_reg 0)when syn_clr=1 else unsigned(d)when load=1 else r_reg+1 when en=1 else r_reg;-output logic q=std_logic_vector(r_reg);end two_seg_arch;,简单的设计例子,二进制计数器library ieee;简单的设计例子,十进制计数器,library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;entity mod10_counter isport(clk,reset:in std_logic;q:out std_logic_vector(3 downto 0);end mod10_counter;architecture two_seg_arch of mod10_counter isconstant TEN:integer:=10;signal r_reg:unsigned(3 downto 0);signal r_next:unsigned(3 downto 0);begin-registerprocess(clk,reset)beginif(reset=1)then r_reg 0);elsif(clkevent and clk=1)then r_reg 0)when r_reg=(TEN-1)else r_reg+1;-output logic q=std_logic_vector(r_reg);end two_seg_arch;,简单的设计例子,十进制计数器library ieee;简单的设计例子,可编程的m进制计数器可以通过改变一个常数m来改变计数器的进制,范围为“0010”“1111”,library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;entity prog_counter isport(clk,reset:in std_logic;m:in std_logic_vector(3 downto 0);q:out std_logic_vector(3 downto 0);end prog_counter;architecture two_seg_clear_arch of prog_counter issignal r_reg:unsigned(3 downto 0);signal r_next:unsigned(3 downto 0);begin-registerprocess(clk,reset)beginif(reset=1)then r_reg 0);elsif(clkevent and clk=1)then r_reg 0)when r_reg=(unsigned(m)-1)else,简单的设计例子,可编程的m进制计数器library ieee;简单的设计例子,可编程的m进制计数器(续)可以通过改变一个常数m来改变计数器的进制,范围为“0010”“1111”,r_reg+1;-output logic q 0);elsif(clkevent and clk=1)then r_reg 0)when r_inc=unsigned(m)else r_inc;-output logic q=std_logic_vector(r_reg);end two_seg_effi_arch;,简单的设计例子,可编程的m进制计数器(续)r_reg+1;简单的设计例,简单的设计例子,可编程的m进制计数器(续)RTL原理图,简单的设计例子可编程的m进制计数器(续),组合电路用传播延时来描述时序电路必须要满足建立和保持时间,用最大时钟频率来描述(例如:200MHz的计数器,2.4GHz的奔腾II)建立时间、寄存器的clock-to-q延时和下一个状态的传播延时,都嵌套在时钟频率中。,时序分析,State_next信号必须满足触发器的时序约束,组合电路时序分析State_next信号必须满足触发器的时序,state_next的延迟受三个源影响state_reg的输出(部分相同反馈回路和同步时钟)和外部使用相同时钟的子系统输入同步和外部输入异步对于前两个项目,我们可以调节时钟的频率来阻止时序违反请看下面的时序图(展示了闭环反馈系统的时序行为),在t0时刻,时钟由0变为1。我们假设state_next在建立和保持的周期内不会改变在clock-to-q(Tcq)延迟之后,寄存器的输出state_reg在时刻t1(t0+Tcq)保持稳定,时序分析,state_next的延迟受三个源影响时序分析,因为state_reg是state_next逻辑的输入,state_next逻辑的输出在时间Tnext(min)和Tnext(max)改变,分别表示最快和最慢的路径。因此,state_next在t2(t1+Tnext(min))时刻改变,在t3(t1+Tnext(max))时刻稳定。,时序分析,因为state_reg是state_next逻辑的输入,s,在t5时刻,一个新的上升沿时钟到达且当前的时钟周期结束。state_next在t5时刻被采样。,时序分析,在t5时刻,一个新的上升沿时钟到达且当前的时钟周期结束。s,下面来考虑一下建立时间的约束,state_next信号在下一个采样边沿t5到来之前的Tsetup时间内必须保持稳定。(t5由时序图中的t4给定)t3t4从时序图可以看出:t3=t0+Tcq+Tnext(max)t4=t5-Tsetup=t0+Tc-Tsetup上面的不等式可以改写为t0+Tcq+Tnext(max)t0+Tc-Tsetup可以化简为Tcq+Tnext(max)+Tsetup Tc因此,最小的时钟周期是Tc(min)=Tcq+Tnext(max)+Tsetup,时序分析,下面来考虑一下建立时间的约束,state_next信号在下一,时序分析,对于特定的技术,D触发器的Tcq和Tsetup可以从数据手册获得。,让Tcq=1ns,Tsetup=0.5ns,因为1位的移位逻辑仅仅包含线网,所以假设它线网的连接延时 是0,因此其最高的频率为1/1.5 ns=666.7 MHz下文讲述一下和其它组合块联合的例子,其延时大于0.,时序分析对于特定的技术,D触发器的Tcq和Tsetup可以从,时序分析,保持时间违反,输入的信号在采样沿之后必须要保持一段时间,start_next 在t0 和 th(t0+Thold)内必须保持稳定。,时序分析保持时间违反输入的信号在采样沿之后必须要保持一段时间,时序分析,保持时间违反,state_next 最早改变的时刻是t2th t2 且 t2=t0+Tcq+Tnext(min)th=t0+Thold所以 t0+Thold t0+Tcq+Tnext(min)化简得 Thold Tcq+Tnext(min)因为触发器的输出驱动下一级的输入,Tnext(min)约等于0且Thold Tcq器件厂商通常会保证触发器这些内在参数的满足关系,但时钟偏斜问题是值得我们考虑的。,时序分析保持时间违反state_next 最早改变的时刻是t,时序分析,我们也需要考虑外部输入输出的时钟特征(除了刚才提到的闭环反馈回路),电路的输出可以分为:摩尔(Moore)输出和米利(Mealy)输出,对于摩尔输出,输出的信号取决于当前系统的状态,而米利输出取决于当前系统的状态和外部输入。,这两种输出可以同时存在于同一个电路中。,这两种输出主要时间参数是Tco(在时钟的上升沿后获得一个有效输出所需要的时间),时序分析我们也需要考虑外部输入输出的时钟特征(除了刚才提到的,时序分析,Tco 是触发器的clock-to-q延时和输出的传播延时之和Tco=Tcq+Toutput对于米利型输出,输入可以直接影响输出。,时序分析Tco 是触发器的clock-to-q延时和输出的传,一段式代码风格,尽管可以把下一个状态的存储单元和输出都写在同一段代码中,但尽可能避免这样的写法,因为很容易出错。,思考一下这段带使能信号的D触发器代码。,architecture one_seg_arch of dff_en is beginprocess(clk,reset)beginif(reset=1)then q=0;elsif(clkevent and clk=1)thenif(en=1)then q=d;end if;end if;end process;end one_seg_arch;,在elsif里面多加了一行if(en=1),我们可以解释为,当在时钟的上升沿到来的时候,如果en=1,则q=d。缺少的else语句隐含着当en不等于1时,q的值要保持。,一段式代码风格尽管可以把下一个状态的存储单元和输出都写在同一,一段式代码风格,再思考一下T触发器的代码。,architecture one_seg_arch of tff issignal q_reg:std_logic;beginprocess(clk,reset)beginif(reset=1)then q_reg=0;elsif(clkevent and clk=1)thenif(t=1)then q_reg=not q_reg;end if;end if;end process;q=q_reg;end one_seg_arch;,这里的内部信号q_reg代表着触发器的输出。“q_reg=not q_reg;”这句一眼看上去很奇怪,其实它可以解释为:左边的是新的值(结果为not q_reg),右边的是当前值(q_reg)。,一段式代码风格再思考一下T触发器的代码。architectu,一段式代码风格,思考一下自由运行的二进制计数器,下面是一段错误的一段式代码。,architecture not_work_one_seg_glitch_archof binary_counter4_pulse issignal r_reg:unsigned(3 downto 0);beginprocess(clk,reset)beginif(reset=1)then r_reg 0);elsif(clkevent and clk=1)then r_reg=r_reg+1;if(r_reg=1111)then max_pulse=1;else max_pulse=0;end if;end if;end process;q=std_logic_vector(r_reg);end not_work_one_seg_glitch_arch;,一段式代码风格思考一下自由运行的二进制计数器,下面是一段错误,一段式代码风格,错误的原因是,if(r_reg=1111)then max_pulse=1;else max_pulse=0;end if;,这段代码在输出端多增加了一个缓冲,输出结果会有一个时钟的延时。其综合出来的结果如图所示。,这个不可以有,一段式代码风格错误的原因是if(r_reg=1111,一段式代码风格,修改的方法是把输出逻辑在进程中移除出去。,architecture work_one_seg_glitch_archof binary_counter4_pulse issignal r_reg:unsigned(3 downto 0);beginprocess(clk,reset)beginif(reset=1)then r_reg 0);elsif(clkevent and clk=1)then r_reg=r_reg+1;end if;end process;q=std_logic_vector(r_reg);max_pulse=1 when r_reg=1111 else 0;end work_one_seg_glitch_arch;,一段式代码风格修改的方法是把输出逻辑在进程中移除出去。arc,一段式代码风格,再举一个例子可编程的计数器,architecture not_work_one_arch of prog_counter issignal r_reg:unsigned(3 downto 0);beginprocess(clk,reset)beginif(reset=1)then r_reg 0);elsif(clkevent and clk=1)then r_reg 0);end if;end if;end process;q=std_logic_vector(r_reg);end not_work_one_arch;,这个计数器并没有按照预期的目的工作,因为里面有一个信号直到进程的结束才会更新。,一段式代码风格再举一个例子可编程的计数器architec,一段式代码风格,因为r_reg在r_reg=r_reg+1这句执行后,还没有来得及更新,我们就用它来进行“r_reg=unsigned(m)”比较,这个是旧的值,这样设计出来的计数器会比预设的多一个数。(例如本来想设计8进制的,现在就变成9进制了),为了修改,我们把自增的操作移到进程外面。,architecture work_one_arch of prog_counter issignal r_reg:unsigned(3 downto 0);signal r_inc:unsigned(3 downto 0);beginprocess(clk,reset)beginif(reset=1)then r_reg 0);elsif(clkevent and clk=1)thenif(r_inc=unsigned(m)then r_reg 0);else r_reg=r_inc;end if;end if;end process;r_inc=r_reg+1;q=std_logic_vector(r_reg);end work_one_arch;,一段式代码风格因为r_reg在r_reg=r_reg,在时序电路描述中使用变量,变量可以在clkevent and clk=1条件下被赋值,但是否生成触发器就要看它是怎么使用的。如果变量在其使用之前就被赋值,它会在每个进程调用的时候获得一个新的值,因此,它不需要记住之前的值。,另一方面,如果在变量在赋值之前需要被读取,它需要使用之前进程执行产生的值,因此需要保存。,使用变量的时候会不小心生成存储单元,最好使用信号来代替它。变量最恰当的使用方法是用来保存中间结果。,在时序电路描述中使用变量变量可以在clkevent and,在时序电路描述中使用变量,为了凸显变量的使用误区,请看下面的三种操作。,library ieee;use ieee.std_logic_1164.all;entity varaible_ff_demo isport(a,b,clk:in std_logic;q1,q2,q3:out std_logic);end varaible_ff_demo;architecture arch of varaible_ff_demo issignal tmp_sig1:std_logic;begin-attempt 1process(clk)beginif(clkevent and clk=1)then tmp_sig1=a and b;q1=tmp_sig1;end if;end process;,在时序电路描述中使用变量为了凸显变量的使用误区,请看下面的三,在时序电路描述中使用变量,为了凸显变量的使用误区,请看下面的三种操作。,-attempt 2process(clk)variable tmp_var2:std_logic;beginif(clkevent and clk=1)then tmp_var2:=a and b;q2=tmp_var2;end if;end process;-attempt 3process(clk)variable tmp_var3:std_logic;beginif(clkevent and clk=