复位分支中加入额外逻辑是否为不良设计?同步与异步复位验证
同步/异步复位电路的代码写法争议与验证
一直以来我都被告知,复位分支中只应保留复位操作,加入其他逻辑属于不良设计。例如以下两个同步复位电路:
写法一
process (CLK) begin if rising_edge(CLK) then if (RST = '1') then Q0 <= '0'; else if (CLR = '1') then Q0 <= '0'; else Q0 <= D; end if; end if; end if; end process;
写法二
process (CLK) begin if rising_edge(CLK) then if (RST = '1' or CLR = '1') then Q1 <= '0'; else Q1 <= D; end if; end if; end process;
我被告知第一种写法更规范,但测试发现二者逻辑等价:
且综合与实现结果一致(Vivado甚至更倾向于第二种综合结果):
那么这种认知偏差源于何处?是旧版工具综合效果不佳?还是第二种写法确实属于不良设计?
结合已采纳的答案,我又测试了异步复位的情况:
异步复位写法对比
-- 写法一 process (CLK, RST) begin if (RST = '1') then Q0 <= '0'; else if rising_edge(CLK) then if (CLR = '1') then Q0 <= '0'; else Q0 <= D; end if; end if; end if; end process; -- 写法二 process (CLK, RST, CLR) begin if (RST = '1' or CLR = '1') then Q1 <= '0'; else if rising_edge(CLK) then Q1 <= D; end if; end if; end process;

异步复位的综合结果差异显著,从时序角度看这更合理,因为异步信号会影响时序。
同步复位最小可复现示例
top.vhd
library IEEE; use IEEE.std_logic_1164.all; entity top is port ( CLK : in std_logic; RST : in std_logic; CLR : in std_logic; D : in std_logic; Q0 : out std_logic; Q1 : out std_logic ); end top; architecture rtl of top is begin process (CLK) begin if rising_edge(CLK) then if (RST = '1') then Q0 <= '0'; else if (CLR = '1') then Q0 <= '0'; else Q0 <= D; end if; end if; end if; end process; process (CLK) begin if rising_edge(CLK) then if (RST = '1' or CLR = '1') then Q1 <= '0'; else Q1 <= D; end if; end if; end process; end architecture rtl;
tb.vhd
library IEEE; use IEEE.std_logic_1164.all; library std; use std.env.all; entity tb is end entity tb; architecture behav of tb is constant CLK_FREQ : real := 100.0e6; constant CLK_HALF_P : time := (((1.0/CLK_FREQ)*10.0e8)/2.0) * 1 ns; signal clk : std_logic; signal rst : std_logic; signal clr : std_logic; signal d : std_logic; signal q0 : std_logic; signal q1 : std_logic; begin dut : entity work.top(rtl) port map ( CLK => clk, RST => rst, CLR => clr, D => d, Q0 => q0, Q1 => q1 ); sysClkProc : process --------------------------------------------------------- begin clk <= '1'; wait for CLK_HALF_P; clk <= '0'; wait for CLK_HALF_P; end process sysClkProc; ------------------------------------------------------ stimulusProc : process ------------------------------------------------------- begin report ("Starting Simulation"); rst <= '1'; d <= '0'; clr <= '0'; wait for 100 ns; rst <= '0'; for i in 1 to 10 loop wait until rising_edge(clk); end loop; d <= '1'; for i in 1 to 10 loop wait until rising_edge(clk); end loop; d <= '0'; for i in 1 to 10 loop wait until rising_edge(clk); end loop; d <= '1'; for i in 1 to 5 loop wait until rising_edge(clk); end loop; clr <= '1'; for i in 1 to 5 loop wait until rising_edge(clk); end loop; clr <= '0'; for i in 1 to 5 loop wait until rising_edge(clk); end loop; d <= '0'; wait for 100 ns; finish(0); end process stimulusProc; ---------------------------------------------------- end architecture behav;
constr.xdc(目标板:Nexys A7-100T (xc7a100tcsg324-1))
create_clock -period 10.000 -name sys_clock [get_ports CLK] set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS18} [get_ports CLK] set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS18} [get_ports RST] set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS18} [get_ports CLR] set_property -dict {PACKAGE_PIN M13 IOSTANDARD LVCMOS18} [get_ports D ] set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS18} [get_ports Q0 ] set_property -dict {PACKAGE_PIN K15 IOSTANDARD LVCMOS18} [get_ports Q1 ]
内容的提问来源于stack exchange,提问作者nbstrong
相关产品推荐
相关产品推荐

