4位移位相加乘法器在Vivado仿真中陷入无限循环的问题
4位移位相加乘法器仿真无限循环的问题分析与修复
你的代码存在几个核心的VHDL行为模型错误,直接导致了while循环无法终止,具体问题和修复方案如下:
问题根源
信号赋值的非即时性
VHDL中进程内的信号赋值(<=)不会立即生效,所有赋值操作都会在整个进程执行完毕后才统一更新。你在while循环里对N、B、Q的赋值,在循环运行期间这些信号的当前值完全不会改变——N始终保持初始值4,所以N>0的循环条件永远成立,直接陷入死循环。组合逻辑建模的逻辑错误
移位相加乘法是多步迭代的时序逻辑,需要时钟驱动完成每一步的移位和相加操作,但你用了组合逻辑进程来实现。组合逻辑进程会在敏感列表中任意信号变化时反复执行,再加上错误的循环写法,必然导致仿真异常。信号初始化与重复触发的冲突
你将N声明为带初始值的信号并加入敏感列表,同时每次进程触发时都会重新把B、Q赋值为输入x、y的扩展值,相当于每次循环都重置了迭代的起始状态,完全违背了移位相加的迭代逻辑。
修复后的代码(时序逻辑实现)
改用时钟驱动的时序逻辑实现,用寄存器存储迭代状态,避免组合循环的死循环问题:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity four_bit_multiplier is Port ( clk : in STD_LOGIC; rst_n : in STD_LOGIC; -- 低有效复位信号 x : in STD_LOGIC_VECTOR(3 downto 0); y : in STD_LOGIC_VECTOR(3 downto 0); result : out STD_LOGIC_VECTOR(7 downto 0); done : out STD_LOGIC -- 乘法完成标志 ); end four_bit_multiplier; architecture Behavioral of four_bit_multiplier is component eight_bit_adder is Port ( x : in STD_LOGIC_VECTOR(7 downto 0); y : in STD_LOGIC_VECTOR(7 downto 0); c_in: in STD_LOGIC; c_out: out STD_LOGIC; sum : out STD_LOGIC_VECTOR(7 downto 0) ); end component; signal B_reg : STD_LOGIC_VECTOR(7 downto 0); signal A_reg : STD_LOGIC_VECTOR(7 downto 0); signal Q_reg : STD_LOGIC_VECTOR(7 downto 0); signal adder_out : STD_LOGIC_VECTOR(7 downto 0); signal c_out : STD_LOGIC; signal count : integer range 0 to 4; -- 迭代计数器 begin p1: eight_bit_adder port map(B_reg, A_reg, '0', c_out, adder_out); -- 时序进程:完成移位相加迭代 process(clk, rst_n) begin if rst_n = '0' then A_reg <= (others => '0'); B_reg <= (others => '0'); Q_reg <= (others => '0'); count <= 4; done <= '0'; result <= (others => '0'); elsif rising_edge(clk) then if count > 0 then -- 判断Q最低位,决定是否累加 if Q_reg(0) = '1' then A_reg <= adder_out; end if; -- 执行移位操作 B_reg <= B_reg(6 downto 0) & '0'; Q_reg <= '0' & Q_reg(7 downto 1); -- 计数器递减 count <= count - 1; else -- 迭代完成,输出结果 result <= A_reg; done <= '1'; end if; end if; end process; -- 输入加载进程:复位或迭代完成时重新加载输入 process(clk, rst_n) begin if rst_n = '0' then B_reg <= "0000" & x; Q_reg <= "0000" & y; elsif rising_edge(clk) then if count = 0 then B_reg <= "0000" & x; Q_reg <= "0000" & y; count <= 4; done <= '0'; end if; end if; end process; end Behavioral;
关键修复说明
- 改用时钟+复位的时序逻辑实现,符合数字电路的实际工作方式;
- 用寄存器信号(
A_reg、B_reg、Q_reg)存储每一步的迭代状态,在时钟沿更新; - 用
count计数器控制迭代次数,每次时钟沿递减,彻底避免组合循环的死循环问题; - 添加
done标志位,方便测试bench判断乘法运算是否完成。
内容的提问来源于stack exchange,提问作者Kudor
相关产品推荐
相关产品推荐

