如何判断VHDL中std_logic_vector乘法运算完成?及无时钟时乘法失效原因咨询
Let's break down your problems one by one, and fix the multiplier logic step by step:
1. Why Your Second Approach Failed (Sequential Signal Assignment)
The core issue here is how VHDL handles non-blocking assignments (<=): all non-blocking assignments in a process are scheduled to update after the process finishes executing, not immediately. In your code:
working <= '1'; temp <= std_logic_vector(unsigned(input_1)*unsigned(input_2)); result <= temp(15 downto 0); done <= '1'; working <= '0';
The final working <= '0' overwrites the earlier working <= '1'—so working never actually switches to 1. Additionally, result <= temp(15 downto 0) uses the old value of temp (since the new product hasn't been written to temp yet), leading to incorrect output.
2. Why Your Third Approach Didn't Work (Result-Only Sensitivity List)
A process's sensitivity list should include all inputs that affect its outputs—not the output itself. If you only listen to result, the process will only trigger when result changes, but result only changes because of updates to input_1, input_2, or the clock. This creates a circular dependency that simulators and synthesizers can't resolve correctly.
3. Why Multiplication Fails Without a Clock
Most FPGA/ASIC multipliers are implemented as sequential circuits (with register outputs) for timing and area efficiency. Without a clock, you're trying to build a combinational multiplier, which has two critical issues:
- Combinational multipliers create extremely long signal paths that are almost impossible to meet timing requirements for even moderately sized bit widths.
- If you miss any input signals in the combinational process's sensitivity list, you'll get stale or incorrect values in simulation/synthesis.
Correct Solution: Sequential Multiplier with Done Signal
Here's a fixed version of your code that properly tracks multiplication completion using a simple state machine (the working flag):
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.all; entity multiplier is Port ( input_1 : in STD_LOGIC_VECTOR (8 downto 0); --max input = 128 (9 bit) input_2 : in STD_LOGIC_VECTOR (8 downto 0); start : in STD_LOGIC; reset : in STD_LOGIC; result : out STD_LOGIC_VECTOR (15 downto 0); --max output = 128*128 = 16384 (16 bit) done : out STD_LOGIC; clk : in STD_LOGIC); end multiplier; architecture Behavioral of multiplier is signal working : STD_LOGIC := '0'; signal temp : STD_LOGIC_VECTOR (17 downto 0); begin process (clk, reset) begin if reset = '1' then -- Switched to active-high reset (standard practice; adjust if needed) result <= (others => '0'); temp <= (others => '0'); working <= '0'; done <= '0'; elsif rising_edge(clk) then if working = '1' then -- Second clock cycle: output result and flag completion result <= temp(15 downto 0); done <= '1'; working <= '0'; elsif start = '1' then -- First clock cycle: trigger multiplication and enter working state temp <= std_logic_vector(unsigned(input_1)*unsigned(input_2)); working <= '1'; done <= '0'; -- Reset done when starting a new operation else -- Idle state: keep done low done <= '0'; end if; end if; end process; end Behavioral;
Key Fixes:
- Used a two-cycle state flow: trigger multiplication on the first clock edge when
startis high, then output the result and setdoneon the next edge. - Ensured
doneis reset when starting a new multiplication and during idle state. - Fixed signal update order to avoid overwriting values prematurely.
Bonus: Single-Cycle Multiplier (For Modern FPGAs)
Most modern FPGAs support single-cycle multipliers for small bit widths (like 9x9). If your target device allows this, you can simplify the code to generate done in the same cycle as the result:
process (clk, reset) begin if reset = '1' then result <= (others => '0'); done <= '0'; elsif rising_edge(clk) then done <= '0'; if start = '1' then result <= std_logic_vector(unsigned(input_1)*unsigned(input_2))(15 downto 0); done <= '1'; end if; end if; end process;
This works because the multiplier completes its calculation in one clock cycle, so result and done update simultaneously when start is asserted.
内容的提问来源于stack exchange,提问作者Jack

