基于VHDL的双环形振荡器及异或输出实现问题咨询
VHDL双环形振荡器异或输出异常排查与实现指导
问题背景
已基于板载内部时钟实现单环形振荡器且运行正常,现需添加第二个环形振荡器,将两者输出异或后存入trn向量,但多次尝试出现输出异常。实体已引入外部时钟clk,疑惑是否只需在进程中调用即可。
现有代码
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.ALL; entity RO_TRNG is Port ( trn : out std_logic_vector(20 downto 0); reset : in STD_LOGIC; sample: in STD_LOGIC; clk : in std_logic); end entity RO_TRNG; architecture Behavioral of RO_TRNG is component iclk is port( iclk_clk : out std_logic; iclk_en_oscena : in std_logic); end component; signal ring : std_logic_vector(20 downto 0):= "100101101011011101001"; signal clk_int : std_logic; attribute KEEP : string; attribute KEEP of ring : signal is "true"; begin u0 : COMPONENT iclk port map (iclk_clk=>clk_int,iclk_en_oscena=>'1'); assert ring'length mod 2 = 1 report "Length of ring must be an odd number!" severity failure; trn <= ring when sample ='0'; process (clk_int,ring,reset) begin if reset='0' then ring <= "100101101011011101001"; else if rising_edge(clk_int) then for i in ring'range loop if i = ring'left then ring(i) <= not ring(0) after 1ns; else ring(i) <= not ring(i+1) after 1ns; end if; end loop; end if; end if; end process; end Behavioral;
问题分析与修正方案
核心问题点
- 异步逻辑隐患:原有进程敏感列表包含
ring,导致每次ring变化都会触发进程,形成异步更新逻辑,易产生毛刺和不稳定输出。 - 仿真与综合行为不一致:
after 1ns延时仅在仿真中有效,综合工具会直接忽略,导致硬件实际运行行为和仿真结果不符。 - 缺乏同步采样机制:直接将环形振荡器输出赋值给
trn,未利用外部时钟同步,易引发亚稳态问题;且未实现双振荡器异或逻辑。 - 未添加独立的第二振荡器:缺少第二个物理独立的环形振荡器模块,无法实现异或所需的两路独立随机信号。
修正后代码示例
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity RO_TRNG is Port ( trn : out std_logic_vector(20 downto 0); reset : in STD_LOGIC; sample: in STD_LOGIC; clk : in std_logic); end entity RO_TRNG; architecture Behavioral of RO_TRNG is component iclk is port( iclk_clk : out std_logic; iclk_en_oscena : in std_logic); end component; -- 第一个环形振荡器信号 signal ring1 : std_logic_vector(20 downto 0):= "100101101011011101001"; signal clk_int1 : std_logic; attribute KEEP : string; attribute KEEP of ring1 : signal is "true"; -- 第二个环形振荡器信号 signal ring2 : std_logic_vector(20 downto 0):= "011010010100100010110"; signal clk_int2 : std_logic; attribute KEEP of ring2 : signal is "true"; -- 采样后的异或结果寄存器 signal xor_result : std_logic_vector(20 downto 0); begin -- 实例化两个独立的内部振荡器 u0 : iclk port map (iclk_clk=>clk_int1, iclk_en_oscena=>'1'); u1 : iclk port map (iclk_clk=>clk_int2, iclk_en_oscena=>'1'); -- 环形振荡器长度校验 assert ring1'length mod 2 = 1 report "Length of ring1 must be an odd number!" severity failure; assert ring2'length mod 2 = 1 report "Length of ring2 must be an odd number!" severity failure; -- 第一个环形振荡器逻辑(同步更新) process (clk_int1, reset) begin if reset='0' then ring1 <= "100101101011011101001"; elsif rising_edge(clk_int1) then for i in ring1'range loop if i = ring1'left then ring1(i) <= not ring1(0); else ring1(i) <= not ring1(i+1); end if; end loop; end if; end process; -- 第二个环形振荡器逻辑(同步更新) process (clk_int2, reset) begin if reset='0' then ring2 <= "011010010100100010110"; elsif rising_edge(clk_int2) then for i in ring2'range loop if i = ring2'left then ring2(i) <= not ring2(0); else ring2(i) <= not ring2(i+1); end if; end loop; end if; end process; -- 外部时钟同步采样异或结果并控制输出 process (clk, reset) begin if reset='0' then xor_result <= (others => '0'); trn <= (others => '0'); elsif rising_edge(clk) then -- 计算两个环形振荡器的异或结果 xor_result <= ring1 xor ring2; -- 根据sample信号控制trn输出更新 if sample = '0' then trn <= xor_result; end if; end if; end process; end Behavioral;
关键修正说明
- 同步逻辑规范:移除进程敏感列表中的
ring信号,同步逻辑仅保留时钟和复位作为触发条件,避免异步更新隐患。 - 移除仿真延时:删除
after 1ns语句,确保综合后硬件行为与逻辑设计一致。 - 独立双振荡器:添加独立的
ring2信号和iclk实例,FPGA实现时需添加布局约束,防止工具将两个振荡器合并优化,保证物理独立性。 - 外部时钟同步采样:用外部
clk采样两路振荡器输出并计算异或,规避亚稳态问题;通过sample信号同步控制trn的输出时机,符合同步设计要求。
内容的提问来源于stack exchange,提问作者Anuel Abrah
相关产品推荐
相关产品推荐

