⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.vhd

📁 audio file on virtex
💻 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 + -