📄 audiocontroller.vhd
字号:
--The entity used to control the generation of the sine signal
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity AudioController is
Port ( CLK : in std_logic; --CLK preferable 50MHz, otherwise
--division factors in the code should be adjusted!
SPK : out std_logic;
-- digital output to speaker / band-pass filter
RESET : in std_logic;
FREQ_STEP : in std_logic_vector(7 downto 0);
-- the number to add to the index used to lookup the current
-- amplitude in the ROM
TURN_OFF_COUNT : in std_logic_vector(7 downto 0);
-- A number specifying how long the current output should
-- be active
REAL_TURN_OFF_COUNT: out std_logic_vector(7 downto 0)
-- The current value of the down-counter
);
end AudioController;
architecture Behavioral of AudioController is
component FreqDivider is
generic ( division_factor: positive := 10);
Port ( CLK : in std_logic;
DIVIDED_CLK : out std_logic);
end component;
component sin_rom is
Port ( address : in std_logic_vector(9 downto 0);
sine_value : out std_logic_vector(7 downto 0));
end component;
component LimitCounter is
generic ( element_width: positive := 8);
Port ( RESET : in std_logic;
CLK : in std_logic;
SWITCH_LIMIT : in std_logic_vector(element_width-1 downto 0);
OUTPUT_SIGNAL : out std_logic);
end component;
signal DividedClk, DividedClk2: std_logic;
signal TempSpk: std_logic;
signal SinAngle: std_logic_vector(9 downto 0);
signal SinValue: std_logic_vector(7 downto 0);
signal OldTurnOffCount, TurnOffCount: std_logic_vector(7 downto 0);
begin
REAL_TURN_OFF_COUNT <= TurnOffCount;
--Used to generate the period for the down counter
FD2: FreqDivider generic map (division_factor => 19) port map (CLK, DividedClk2);
--The down-counter
process (RESET, DividedClk2)
begin
if (RESET = '0') then
if (DividedClk2'event) and (DividedClk2 = '1') then
if (OldTurnOffCount = TURN_OFF_COUNT) then
if (TurnOffCount = "11111111") then
--If TurnOffCount = MAX, don't decrease
elsif (TurnOffCount = "00000000") then
--If it's minimum, don't decrease to avoid underflow
else
--Otherwise decrease
TurnOffCount <= TurnOffCount - '1';
end if;
else
OldTurnOffCount <= TURN_OFF_COUNT;
TurnOffCount <= TURN_OFF_COUNT;
end if;
end if;
else
TurnOffCount <= (others => '1');
OldTurnOffCount <= (others => '1');
end if;
end process;
--Used to generate the clock signal on which to advance the address
--of the sine lookup table. Should be slow enough to allow the PWM
--a full cycle on the current amplitude value
FD: FreqDivider port map (CLK, DividedClk);
--The counter which determines the lookup address
process (RESET, DividedClk)
begin
if (RESET = '0') then
if (DividedClk'event) and (DividedClk = '1') then
SinAngle <= SinAngle + FREQ_STEP;
end if;
else
SinAngle <= (others => '0');
end if;
end process;
--The rom used to store the sine values
SR: sin_rom port map (SinAngle, SinValue);
--The PWM modulator
LC: LimitCounter port map (RESET, CLK, SinValue, TempSpk);
--Final filtering logic, which mutes the output in one of the following cases:
--The step for the lookup table index is 0 or the count-down has reached 0
process (TempSpk, FREQ_STEP, TurnOffCount)
begin
if (FREQ_STEP = "00000000") or (TurnOffCount = "00000000") then
SPK <= '0';
else
SPK <= TempSpk;
end if;
end process;
end Behavioral;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -