📄 audio.vhd
字号:
-------------------------------------------------------------------------------
-- audio.vhd
--
-- Author(s): Jorgen Peddersen
-- Created: Dec 2000
-- Last Modified: Jan 2001
--
-- Maps together the recorder and player files to allow recording and playback
-- of files. Using separate banks of RAM for each channel, audio data is
-- sampled at 48.8kHz and stored with 16 bit precision. Several inputs allow
-- properties of playback to be altered e.g. volume, direction and speed.
-- These do not affect the recording of the signal in any way. This design
-- requires a 50MHz clock. The design can store just over 10 sec of audio.
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity audio is
port (
clk: in STD_LOGIC; -- 50MHz Clock
rstn: in STD_LOGIC; -- asynchronous active-low reset
sdout: in STD_LOGIC; -- incoming serial data
recordStart: in STD_LOGIC; -- assert to start recording
recordStop: in STD_LOGIC; -- assert to stop recording
playStart: in STD_LOGIC; -- assert to start playback
playStop: in STD_LOGIC; -- assert to stop playback
direction: in STD_LOGIC; -- high = forward, low = backward
speed: in STD_LOGIC_VECTOR(1 downto 0); -- choose speed of playback
precision: in STD_LOGIC; -- high = 16-bit, low = 8-bit
volume: in STD_LOGIC_VECTOR(1 downto 0);-- choose volume of playback
dataIn: in STD_LOGIC_VECTOR(31 downto 0);-- playback data from RAM
mclk: out STD_LOGIC; -- audio device master clock
lrck: buffer STD_LOGIC; -- audio device Left/Right clock
sclk: buffer STD_LOGIC; -- audio device sampling clock
sdin: out STD_LOGIC; -- outgoing serial data
recordAddress: out STD_LOGIC_VECTOR(18 downto 0);-- RAM write address
playAddress: out STD_LOGIC_VECTOR(18 downto 0);-- RAM read address
dataOut: out STD_LOGIC_VECTOR(31 downto 0);-- record data to RAM
read: out STD_LOGIC; -- RAM read signal
write: out STD_LOGIC; -- RAM write signal
full: out STD_LOGIC; -- high after record fills buffer
done: out STD_LOGIC -- high after playback exhausts buffer
);
end audio;
architecture audio_arch of audio is
signal count : STD_LOGIC_VECTOR(9 downto 0); -- clock dividing counter
-- The following signals alter playback data according to inputs
signal playAddressInt1 : STD_LOGIC_VECTOR(18 downto 0);
signal playAddressInt2 : STD_LOGIC_VECTOR(18 downto 0);
signal dataInInt1 : STD_LOGIC_VECTOR(31 downto 0);
signal dataInInt2 : STD_LOGIC_VECTOR(31 downto 0);
component recorder
port (
start: in STD_LOGIC;
stop: in STD_LOGIC;
rstn: in STD_LOGIC;
sclk: in STD_LOGIC;
lrck: in STD_LOGIC;
sdin: in STD_LOGIC;
dataOut: out STD_LOGIC_VECTOR (31 downto 0);
address: out STD_LOGIC_VECTOR (18 downto 0);
full: out STD_LOGIC;
write: out STD_LOGIC
);
end component;
component player is
port (
start: in STD_LOGIC;
stop: in STD_LOGIC;
rstn: in STD_LOGIC;
sclk: in STD_LOGIC;
lrck: in STD_LOGIC;
dataIn: in STD_LOGIC_VECTOR (31 downto 0);
address: out STD_LOGIC_VECTOR (18 downto 0);
done: out STD_LOGIC;
read: out STD_LOGIC;
sdout: out STD_LOGIC
);
end component;
begin
-- clock division process
process(clk,rstn)
begin
if rstn = '0' then
count <= (others => '0');
lrck <= '0';
elsif clk'event AND clk = '1' then
count <= count + 1;
-- lrck will get a value based on the previous value of count.
-- this ensures it can be read properly byt the player and recorder
-- which are both clocked directly off sclk.
lrck <= count(9);
end if;
end process;
mclk <= count(1);
sclk <= count(3);
-- recording device
recordDevice : recorder port map(
start => recordStart,
stop => recordStop,
rstn => rstn,
sclk => sclk,
lrck => lrck,
sdin => sdout,
dataOut => dataOut,
address => recordAddress,
full => full,
write => write
);
-- playback device
playDevice : player port map(
start => playStart,
stop => playStop,
rstn => rstn,
sclk => sclk,
lrck => lrck,
dataIn => dataInInt2,
address => playAddressInt1,
done => done,
read => read,
sdout => sdin
);
-- alter playback address based on input selection
process (playAddressInt1, speed)
begin
case speed is
when "11" =>
-- normal playback speed
playAddressInt2 <= playAddressInt1;
when "10" =>
-- doubled playback speed, buffer is read twice
playAddressInt2 <= playAddressInt1(17 downto 0) & '0';
when others =>
-- halved playback speed, only half of the buffer is read
-- speed(0) determines which half.
playAddressInt2 <= speed(0) & playAddressInt1(18 downto 1);
end case;
end process;
-- reverse playback direction depending on input
playAddress <= playAddressInt2 when direction = '1' else "111" & X"FFFF" - playAddressInt2;
-- alter playback data based on input selection
process (dataIn, volume)
begin
case volume is
when "11" =>
-- normal volume
dataInInt1 <= dataIn;
when "10" =>
-- doubled volume with capping for overflow
if dataIn(30) = dataIn(31) then
dataInInt1 <= dataIn(30 downto 16) & '0' & dataIn(14 downto 0) & '0';
else
dataInInt1 <= (31 => dataIn(31), others => NOT dataIn(31));
end if;
when "01" =>
-- halved volume
dataInInt1 <= dataIn(31) & DataIn(31 downto 17) & dataIn(15) & dataIn(15 downto 1);
when "00" =>
-- quadrupled volume with capping for overflow
if dataIn(29) = dataIn(30) and dataIn(29) = dataIn(31) then
dataInInt1 <= dataIn(29 downto 16) & "00" & dataIn(13 downto 0) & "00";
else
dataInInt1 <= (31 => dataIn(31), others => NOT dataIn(31));
end if;
when others =>
dataInInt1 <= dataIn;
end case;
end process;
-- changes data precision of playback data.
dataInInt2 <= dataInInt1 when precision = '1' else dataInInt1(31 downto 24) & X"00" & dataInInt1(15 downto 8) & X"00";
end audio_arch;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -