------------------------------------------------------------------------------- -- File: mp3_decode.vhd -- -- Project: Porta-AMP (MP3 player) -- Created by: Daniel Leder -- Date: 10/9/99 -- -- Purpose: to stream data that is received into the MP3 decoder chip -- one bit at a time with a clock running at ~1MHz. -- The data going out must be valid on the falling edge of the clock. -- -- Inputs: mp3_datain <- master_control -- mp3_clock <- ALTERA -- mp3_reset <- master_control -- mp3_enable <- master_control -- mp3_done <- MP3 decoder chip -- -- Outputs: mp3_chipclk -> MP3 decoder chip -- mp3_dataout -> MP3 decoder chip -- mp3_ready -> master_control -- mp3_chipresetn -> MP3 decoder chip -- -- External Connections: -- mp3_dataout, mp3_chipreset, mp3_chipclk, mp3_done -- ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library work; use work.mp3_decode_pkg.all; entity mp3_decode is generic ( datawidth : positive := 16; -- size of the datapath coming in clockdivider : positive := 5); -- value to divide incoming clock -- by to create new clock of ~1MHz port ( --------------------------------------------------------------------------- -- Master Control connections --------------------------------------------------------------------------- mp3_datain : in std_logic_vector(datawidth-1 downto 0); -- input from MC - data from -- RAM/CD-ROM/lpt streaming mp3_enable : in std_logic; -- input from MC - mp3_datain is valid mp3_ready : out std_logic; -- output to MC - request data from RAM -- to pass to decoder chip --------------------------------------------------------------------------- -- ALTERA system signals --------------------------------------------------------------------------- mp3_clock : in std_logic; -- input of system clock mp3_reset : in std_logic; -- reset decoder chip -- and state of mp3decode --------------------------------------------------------------------------- -- External connections to the MP3 decoder chip --------------------------------------------------------------------------- mp3_demand : in std_logic; -- input from MP3 chip - mp3_decoder -- requires data (1) mp3_chipclk : out std_logic; -- output to MP3 chip - new clock ~1MHz mp3_chipresetn: out std_logic; -- output to MP3 chip - reset the MP3 -- decoder chip mp3_dataout : out std_logic -- output to MP3 chip - output a single -- bit which is valid on falling -- edge of mp3_chipclk -- clock_enable, loadreg: buffer std_logic ); end mp3_decode; architecture behavioural of mp3_decode is -- signals to use for clock_divider signal part1, part2: std_logic_vector(3 downto 0); -- state definitions type statetype is (startstate, wait_for_mp3,loaddata, shift1, shiftout81, shift2, shiftout82, needdata); -- state signal signal state: statetype; -- intermediate signals signal clk_reg, regempty, regdone, reset, zero: std_logic; signal resetchipn, ready: std_logic; signal loadreg, clock_enable: std_logic; signal mp3_stream: std_logic_vector(datawidth-1 downto 0); signal mp3_data_enable, mp3_init: std_logic; signal datain : std_logic_vector(7 downto 0); -- signals used to correspond to bytes to be put into shift register signal EMPTYBYTE : std_logic_vector(7 downto 0); alias LOWBYTE : std_logic_vector(7 downto 0) is mp3_stream(7 downto 0); alias HIGHBYTE : std_logic_vector(7 downto 0) is mp3_stream(15 downto 8); begin -- behavioural -- divide clock of 10 MHz into 1 MHz clock using 5 as dividing value -- create full 1MHz clock (rising and falling edges at 1MHz) zero <= '0'; part1 <= "1001"; part2 <= "0100"; -- create a zero byte EMPTYBYTE <= (others => '0'); -- create two new clocks of the same frequency and feed them -- to two different destinations -- one destination is to be the clock for the mp3 chip divide_clock1 : clock_divide generic map (counterwidth => 4) port map (clock => mp3_clock, reset => reset, enable => clock_enable, count_part1 => part1, count_part2 => part2, divided_clock => mp3_chipclk); -- one destination is to be the clock for the shift register divide_clock2 : clock_divide generic map (counterwidth => 4) port map (clock => mp3_clock, reset => reset, enable => clock_enable, count_part1 => part1, count_part2 => part2, divided_clock => clk_reg); -- shift register instantiation 8 bit register shiftreg: shift8bitreg generic map (regwidth => 8) port map (data => datain, -- data to load clock => clk_reg, -- clock for register reset => mp3_reset, -- reset for register load => loadreg, -- if we are loading register msb => mp3_dataout, -- msb shifted out done => regdone, -- has shift register rx data empty => regempty); -- has shift register completed -- intermediate signal that will be latched on rising edges of clocks -- whether the mp3 chip should be held in reset until data is actually to -- be passed to it (the mp3 chip has an active low reset thus the 'n') with state select resetchipn <= '0' when startstate, '1' when loaddata, '1' when shift1, '1' when shiftout81, '1' when shift2, '1' when shiftout82, '1' when needdata, '1' when others; -- used to tell the master controller that data is needed since have -- completed streaming to the mp3 chip with state select ready <= '0' when startstate, '1' when wait_for_mp3, '0' when loaddata, '0' when shift1, '0' when shiftout81, '0' when shift2, '0' when shiftout82, '1' when needdata, '0' when others; -- used to load the shift register with the necessary byte of data_in with state select loadreg <= '0' when startstate, '1' when loaddata, '1' when shift1, '0' when shiftout81, '1' when shift2, '0' when shiftout82, '0' when needdata, '0' when others; -- used to enable the clock_dividers so that the clock is only active when -- there is active data to send to the mp3 chip with state select clock_enable <= '0' when startstate, '0' when loaddata, '0' when shift1, '1' when shiftout81, '0' when shift2, '1' when shiftout82, '0' when needdata, '0' when others; -- used to reset the clock_divider so that clock is stuck at zero until turn -- enable the clock_dividers to run with state select reset <= '1' when startstate, '1' when loaddata, '1' when shift1, '0' when shiftout81, '1' when shift2, '0' when shiftout82, '1' when needdata, '1' when others; -- used to select parts of the 16 bit input data that is received when the -- mp3_enable line is set high with state select datain <= HIGHBYTE when shift1, -- set the data for register to highest -- byte of input data LOWBYTE when shift2, -- set the data to lowest byte datain when others; -- send an empty byte since don't care -- purpose: latch values regs: process(mp3_clock, mp3_reset) begin if mp3_reset = '1' then -- asychronous reset mp3_ready <= '0'; -- want data so make it one elsif rising_edge(mp3_clock) then -- rising edge triggering mp3_chipresetn <= resetchipn; -- latch value out to the mp3 chip, -- used to make synchronous and to -- eliminate glitches mp3_ready <= ready; -- make synchronous signal if mp3_enable = '1' then mp3_stream <= mp3_datain; -- latch data in since its valid end if; end if; end process regs; -- purpose: state machine comb_logic : process(mp3_clock, mp3_reset) begin if mp3_reset = '1' then -- asynchronous reset state <= startstate; -- move to start state elsif rising_edge(mp3_clock) then -- rising edge triggered case state is when startstate => if mp3_init = '1' then state <= wait_for_mp3; else state <= startstate; end if; when wait_for_mp3 => if mp3_enable = '1' and mp3_demand = '1' then -- is data valid state <= loaddata; -- move to state to load data else state <= wait_for_mp3; end if; when loaddata => state <= shift1; -- move to state where shift in first -- byte, state drops mp3_ready line when shift1 => -- ensure that the register has completed its task and is no longer -- empty before proceed if regdone = '1' and regempty = '0' then state <= shiftout81; else state <= shift1; end if; when shiftout81 => -- wait until register is empty if regempty = '1' then state <= shift2; else state <= shiftout81; end if; when shift2 => -- ensure that register is done if regdone = '1' and regempty = '0' then state <= shiftout82; else state <= shift2; end if; when shiftout82 => -- does the mp3 player want more data and have we emptied the -- register,if we have proceed if regempty = '1' and mp3_demand = '1' then state <= needdata; elsif regempty = '1' then state <= needdata; else state <= shiftout82; end if; when needdata => -- wait for enable (latch value) and do we want the more data if mp3_enable = '1' and mp3_demand = '1' then state <= loaddata; else state <= needdata; end if; end case; end if; end process comb_logic; init_regs: process (mp3_clock, mp3_reset) variable count : std_logic_vector(17 downto 0); begin if mp3_reset = '1' then -- mp3_datain_int <= (others => '0'); count := (others => '0'); -- mp3_chipresetn <= '0'; mp3_init <= '0'; elsif rising_edge(mp3_clock) then -- mp3_chipresetn <= mp3_chiprst; -- if mp3_enable = '1' and (state = load_ahead) then -- mp3_datain_int <= mp3_datain; -- elsif mp3_enable = '1' and (state = loaddata) then -- mp3_datain_int <= mp3_datain; -- end if; if count = "111101000010010000" then -- if count = "000000000000000001" then mp3_init <= '1'; count := (others => '0'); else count := count + '1'; end if; end if; end process init_regs; end behavioural;