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

📄 ac97_if.vhd

📁 something is very important in life. So read it. Try reading it,. I do not care. Please read it/ Ple
💻 VHD
字号:
-------------------------------------------------------------------------------
-- Filename:        ac97_fifo.vhd
--
-- Description:     This module provides a simple FIFO interface for the AC97
--                  module and provides an asyncrhonous interface for a
--                  higher level module that is not synchronous with the AC97
--                  clock (Bit_Clk).
--
--                  This module will handle all of the initial commands
--                  for the AC97 interface.
--
--                  This module provides a bus independent interface so the
--                  module can be used for more than one bus interface.
--                  
-- VHDL-Standard:   VHDL'93
-------------------------------------------------------------------------------
-- Structure:   
--              ac97_core
--                 ac97_timing
--              srl_fifo
--
-------------------------------------------------------------------------------
-- Author:          Mike Wirthlin
-- Revision:        $$
-- Date:            $$
--
-- History:
--   Mike Wirthlin  
--
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

library opb_ac97_v2_00_a;
use opb_ac97_v2_00_a.all;

entity ac97_if is
  port (
    ClkIn : in std_logic;
    Reset : in std_logic;
    
    -- All signals synchronous to ClkIn
    PCM_Playback_Left: in std_logic_vector(15 downto 0);
    PCM_Playback_Right: in std_logic_vector(15 downto 0);
    PCM_Playback_Accept: out std_logic;
    
    PCM_Record_Left: out std_logic_vector(15 downto 0);
    PCM_Record_Right: out std_logic_vector(15 downto 0);
    PCM_Record_Valid: out std_logic;

    Debug : out std_logic_Vector(3 downto 0);
    
    AC97Reset_n : out std_logic;        -- AC97Clk
    AC97Clk   : in  std_logic;
    Sync      : out std_logic;
    SData_Out : out std_logic;
    SData_In  : in  std_logic

    );

end entity ac97_if;

library opb_ac97_v2_00_a;
use opb_ac97_v2_00_a.all;

library unisim;
use unisim.all;

architecture IMP of ac97_if is

  component ac97_core is
  generic (
    C_PCM_DATA_WIDTH : integer := 16
    );
  port (

    Reset : in std_logic;

    -- signals attaching directly to AC97 codec
    AC97_Bit_Clk   : in  std_logic;
    AC97_Sync      : out std_logic;
    AC97_SData_Out : out std_logic;
    AC97_SData_In  : in  std_logic;

    -- AC97 register interface
    AC97_Reg_Addr            : in  std_logic_vector(0 to 6);
    AC97_Reg_Write_Data      : in  std_logic_vector(0 to 15);
    AC97_Reg_Read_Data       : out std_logic_vector(0 to 15);
    AC97_Reg_Read_Strobe     : in  std_logic;  -- initiates a "read" command
    AC97_Reg_Write_Strobe    : in  std_logic;  -- initiates a "write" command
    AC97_Reg_Busy            : out std_logic;
    AC97_Reg_Error           : out std_logic;
    AC97_Reg_Read_Data_Valid : out std_logic;
    
    -- Playback signal interface
    PCM_Playback_Left: in std_logic_vector(0 to C_PCM_DATA_WIDTH-1);
    PCM_Playback_Right: in std_logic_vector(0 to C_PCM_DATA_WIDTH-1);
    PCM_Playback_Left_Valid: in std_logic;
    PCM_Playback_Right_Valid: in std_logic;
    PCM_Playback_Left_Accept: out std_logic;
    PCM_Playback_Right_Accept: out std_logic;

    -- Record signal interface
    PCM_Record_Left: out std_logic_vector(0 to C_PCM_DATA_WIDTH-1);
    PCM_Record_Right: out std_logic_vector(0 to C_PCM_DATA_WIDTH-1);
    PCM_Record_Left_Valid: out std_logic;
    PCM_Record_Right_Valid: out std_logic;

    -- 
    CODEC_RDY : out std_logic

    );
  end component ac97_core;

  component ac97_command_rom is
  port (
    ClkIn : in std_logic;

    ROMAddr : in std_logic_vector(3 downto 0);
    ROMData : out std_logic_vector(24 downto 0)

    );
  end component ac97_command_rom;

  signal pcm_playback_accept_ac97clk : std_logic;
  signal pcm_playback_accept_ClkIn_0 : std_logic;
  signal pcm_playback_accept_ClkIn_1 : std_logic;
  signal pcm_playback_accept_ClkIn : std_logic;
  
  signal pcm_record_valid_ac97clk, pcm_record_valid_ClkIn_0, pcm_record_valid_ClkIn_1 : std_logic;
  signal pcm_record_valid_ClkIn : std_logic;

  signal command_addr : std_logic_vector(6 downto 0);
  signal write_data : std_logic_vector(15 downto 0);
  signal read_data : std_logic_vector(15 downto 0);

  signal codec_rdy : std_logic;
  signal debug_i : std_logic_vector(3 downto 0);
  
  signal reg_write_strobe_ac97, reg_busy_ac97, reg_error_ac97 : std_logic;

  signal get_next_command : std_logic;
  signal valid_command : std_logic;
  signal command_num : unsigned(3 downto 0) := "0000";
  type read_access_states is (AC97_READY, WARM_START,
                              REVIEW_COMMAND,ISSUE_COMMAND,
                              WAIT_COMMAND, NEXT_COMMAND,
                              READ_COMMAND, DONE);
  signal command_SM : read_access_states;
  signal reset_counter : unsigned(10 downto 0) := (others => '0');
  signal AC97Reset_n_i : std_logic := '0';

  signal rom_data : std_logic_vector(24 downto 0);
  signal command_addr_i : std_logic_Vector(3 downto 0);

  signal start_frame_delay : natural range 0 to 3 := 0;

  attribute rom_style: string;
  --attribute rom_style of ac97_command_rom: entity is "distributed";
  
begin  -- architecture IMP

  -----------------------------------------------------------------------------
  -- Command loading
  -----------------------------------------------------------------------------
  load_commands_SM_PROCESS : process (AC97clk) is
  begin
    if AC97clk'event and AC97clk = '1' then

      if Reset = '1' then
        command_SM <= AC97_READY;
        command_num <= "0000";
      else
        
        case command_SM is

          -- Issue some reset?
          when AC97_READY =>
            -- wait until codec is ready
            if codec_rdy = '1' then
              command_SM <= REVIEW_COMMAND;
              start_frame_delay <= 0;
            end if;

          when WARM_START =>
            if pcm_playback_accept_ac97clk = '1' then
              if start_frame_delay = 3 then
                command_SM <= REVIEW_COMMAND;
              else
                start_frame_delay <= start_frame_delay + 1;
              end if;
            end if;
            
          when REVIEW_COMMAND =>
            -- if command is valid, go on to issue command. otherwise, go to
            -- end state.
            if valid_command = '1' then
              command_SM <= ISSUE_COMMAND;
            else
              command_SM <= DONE;
            end if;

          when ISSUE_COMMAND =>
            -- strobe is issued in output forming logic
            command_SM <= WAIT_COMMAND;

          when WAIT_COMMAND =>
            if reg_busy_ac97 = '0' then
              command_SM <= NEXT_COMMAND;
            end if;

          -- error processing?
          when NEXT_COMMAND =>
            command_SM <= READ_COMMAND;
            command_num <= command_num + 1;

          when READ_COMMAND =>
            command_SM <= REVIEW_COMMAND;
            
          when DONE =>
            -- do nothing
          when others => NULL;

        end case;
      end if;
    end if;
  end process;

  reg_write_strobe_ac97 <= '1' when command_SM = ISSUE_COMMAND else
                           '0';
  get_next_command <= '1' when command_SM = NEXT_COMMAND else
                      '0';
  

  --  ClkIn processes
  -- The AC97 reset signal needs to be driven by ClkIn
  -- (AC97 clock does not operate when reset asserted)
  reset_process : process (ClkIn)  is
  begin
    if Reset = '1' then
      reset_counter <= (others => '0');
      AC97Reset_n_i <= '0';
    elsif ClkIn'event and ClkIn='1' then
      if reset_counter(10) = '1' then
        AC97Reset_n_i <= '1';
      else
        reset_counter <= reset_counter+1;
        AC97Reset_n_i <= '0';
      end if;
    end if;
  end process;
  AC97Reset_n <= AC97Reset_n_i;

  process (ClkIn)
  begin
    if ClkIn'event and ClkIn='1' then
      pcm_playback_accept_ClkIn_0 <= pcm_playback_accept_ac97clk;  -- async
      pcm_playback_accept_ClkIn_1 <= pcm_playback_accept_ClkIn_0;
      pcm_playback_accept_ClkIn <= pcm_playback_accept_ClkIn_0 and not pcm_playback_accept_ClkIn_1;
    end if;
  end process;
  PCM_Playback_Accept <= pcm_playback_accept_ClkIn;
  
  process (ClkIn)
  begin
    if ClkIn'event and ClkIn='1' then
      pcm_record_valid_ClkIn_0 <= pcm_record_valid_ac97clk;  -- async
      pcm_record_valid_ClkIn_1 <= pcm_record_valid_ClkIn_0;
      pcm_record_valid_ClkIn <= pcm_record_valid_ClkIn_0 and not pcm_record_valid_ClkIn_1;
    end if;
  end process;
  PCM_Record_Valid <= pcm_record_valid_ClkIn;
  
  -----------------------------------------------------------------------------
  -- Command ROM
  -----------------------------------------------------------------------------
  ROM : ac97_command_rom
  port map (
    ClkIn => AC97Clk,

    ROMAddr => command_addr_i,
    ROMData => rom_data

    );
  command_addr_i <= CONV_STD_LOGIC_VECTOR(command_num, 4);
  
  write_data <= rom_data(15 downto 0);
  command_addr <= rom_data(22 downto 16);
  valid_command <= rom_data(24); 

--   debug_i(0) <= codec_rdy;
--   debug_i(1) <= '1' when command_SM = DONE else
--               '0';
--   debug_i(2) <= AC97Reset_n_i;
--   debug_i(3) <= reg_error_ac97;
  debug_i <= command_addr_i;

  debug <= debug_i;
  
  -----------------------------------------------------------------------------
  -- Instantiating the core
  -----------------------------------------------------------------------------
  ac97_core_I : ac97_core
  port map (

      Reset => Reset,

      AC97_Bit_Clk => AC97Clk,
      AC97_Sync => Sync,
      AC97_SData_Out => SData_Out,
      AC97_SData_In => SData_In,

      AC97_Reg_Addr => command_addr,
      AC97_Reg_Write_Data => write_data,
      AC97_Reg_Read_Data  => open, -- No reading from AC97
      AC97_Reg_Read_Strobe => '0', -- No reading from AC97
      AC97_Reg_Write_Strobe => reg_write_strobe_ac97, -- do
      AC97_Reg_Busy         => reg_busy_ac97, -- do
      AC97_Reg_Error        => reg_error_ac97, -- do
      AC97_Reg_Read_Data_Valid => open,  -- No reading from AC97
    
      PCM_Playback_Left => PCM_Playback_Left,  -- async
      PCM_Playback_Right => PCM_Playback_right,  -- async
      PCM_Playback_Left_Valid => '1',
      PCM_Playback_Right_Valid => '1',
      PCM_Playback_Left_Accept => pcm_playback_accept_ac97clk,
      PCM_Playback_Right_Accept => open,           -- use left_accept

      PCM_Record_Left => PCM_Record_Left,
      PCM_Record_Right => PCM_Record_Right,
      PCM_Record_Left_Valid => pcm_record_valid_ac97clk,
      PCM_Record_Right_Valid => open,   -- use left_valid

      CODEC_RDY  => codec_rdy

    );

--   leds(3) <= not codec_rdy; -- and (command_SM = DONE);
--   leds(2) <= '0' when command_SM = INIT else '1';
--   leds(1) <= '0';
--   leds(0) <= AC97Clk; -- '0' when command_SM = DONE else '1';
  

end architecture IMP;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -