General Description: When implementing a VHDL counter in the following manner, the counter does not operate correctly; it continually adds "1" to the sum, even when the loaded value to add is not equal to one, or is "0". This problem is illustrated in the following VHDL code:
(NOTE: This problem is fixed in the 4.1i software release.)
library IEEE; use IEEE.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.std_logic_unsigned.all;
entity accumulator_20 is port ( RESET : in STD_LOGIC; CLK : in STD_LOGIC; AUDIO_IN : in STD_LOGIC_VECTOR (19 downto 0); ACCU_LOAD : in std_logic; ADD_EN : in STD_LOGIC; AUDIO_OUT_A : out STD_LOGIC_VECTOR (19 downto 0); AUDIO_OUT_B : out STD_LOGIC_VECTOR (19 downto 0) ); end accumulator_20;
architecture accumulator_20_arch of accumulator_20 is
signal AUDIO_OUT_INT_A : std_logic_vector (19 downto 0);
begin AUDIO_OUT_A <= AUDIO_OUT_INT_A;
process (CLK, RESET ) begin if RESET = '1' then AUDIO_OUT_INT_A <= ( others => '0' ); elsif rising_edge(CLK) then if ACCU_LOAD = '1' then AUDIO_OUT_INT_A <= AUDIO_IN; elsif ADD_EN = '1' then AUDIO_OUT_INT_A <= AUDIO_IN + AUDIO_OUT_INT_A; end if; end if; end process;
end architecture;
ソリューション
This problem occurs because XST has difficulty with the counter declaration:
audio_out_int_a <= audio_in + audio_out_int_a
This line of code implements an inverter onto the LSB of the counter, thus causing the counter to increment by 1.
The solution is to use an intermediate signal to perform this operation, as illustrated below:
library IEEE; use IEEE.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.std_logic_unsigned.all;
entity accumulator_20 is port ( RESET : in STD_LOGIC; CLK : in STD_LOGIC; AUDIO_IN : in STD_LOGIC_VECTOR (19 downto 0); ACCU_LOAD : in std_logic; ADD_EN : in STD_LOGIC; AUDIO_OUT_A : out STD_LOGIC_VECTOR (19 downto 0); AUDIO_OUT_B : out STD_LOGIC_VECTOR (19 downto 0) ); end accumulator_20;
architecture accumulator_20_arch of accumulator_20 is
signal AUDIO_OUT_INT_A : std_logic_vector (19 downto 0); signal AUDIO_OUT_INT_B : std_logic_vector (19 downto 0); signal ADD : std_logic_vector (19 downto 0);
begin
AUDIO_OUT_B <= AUDIO_OUT_INT_B;
ADD <= AUDIO_IN + AUDIO_OUT_INT_B;
process (CLK, RESET ) begin if RESET = '1' then AUDIO_OUT_INT_B <= ( others => '0' ); elsif rising_edge(CLK) then if ACCU_LOAD = '1' then AUDIO_OUT_INT_B <= AUDIO_IN; elsif ADD_EN = '1' then AUDIO_OUT_INT_B <= ADD; end if; end if; end process;