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

📄 ac97_fifo.vhd

📁 Viertex 2 开发板的接口程序
💻 VHD
📖 第 1 页 / 共 2 页
字号:
    end if;
  end process;
  


  status_reg(31 downto 22) <= out_fifo_level;
  status_reg(21 downto 12) <= in_fifo_level;

  --status_reg(11 downto 9) <= (others => '0');
  status_reg(10) <= out_fifo_interrupt_en;
  status_reg(9) <= in_fifo_interrupt_en;

  status_reg(8) <= IpClk_ac97_reg_error;
    
  status_reg(7) <= out_FIFO_Overrun;
  status_reg(6) <= in_FIFO_Underrun;
  status_reg(5) <= IpClk_codec_rdy;
  status_reg(4) <= register_access_busy; --IpClk_ac97_reg_busy;
  status_reg(3) <= out_Data_Exists;
  status_reg(2) <= out_fifo_empty;
  status_reg(1) <= in_fifo_empty;
  status_reg(0) <= in_FIFO_Full;

  process (Bus2IP_Clk) is
  begin
    if Bus2IP_Clk'event and Bus2IP_Clk = '1' then
      IpClk_codec_rdy <= BitClk_codec_rdy;
      IpClk_ac97_reg_busy <= BitClk_ac97_reg_busy;
      IpClk_ac97_reg_error <= BitClk_ac97_reg_error;
    end if;
  end process;

  -----------------------------------------------------------------------------
  -- AC97 Access Register
  -----------------------------------------------------------------------------

  -- The AC97 access register is used to initiate an AC97 register
  -- read or write command. This register holds the AC97 address to
  -- read/write as well as the direction (IpClk_ac97_reg_read).
  AC97_Access_Reg : process (Bus2IP_Clk) is
  begin  -- process AC97_Write_Reg_Data
    if Bus2IP_Clk'event and Bus2IP_Clk = '1' then
      if Bus2IP_Reset = '1' then
        IpClk_ac97_reg_addr <= (others => '0');
        IpClk_ac97_reg_read <= '0';
      else
        if Bus2IP_WrCE = '1' and AC97_CTRL_ADR = controller_addr then
          IpClk_ac97_reg_addr <= Bus2IP_Data(25 to 31);
          IpClk_ac97_reg_read <= Bus2IP_Data(24);
        end if;
      end if;
    end if;
  end process;

  -----------------------------------------------------------------------------
  -- AC97 Write data register
  -----------------------------------------------------------------------------

  -- AC97 Register Write Data: This register holds the data that is to
  -- be written to the AC97 internal register.
  --
  -- Writing to this register does not cause the actual 
  -- write process to the AC97.  Once this register has been written,
  -- a command must be written to the AC97_Access_Reg to initiate the
  -- actual write.
  AC97_Write_Reg : process (Bus2IP_Clk) is
  begin  -- process AC97_Write_Reg_Data
    if Bus2IP_Clk'event and Bus2IP_Clk = '1' then
      if Bus2IP_Reset = '1' then
        IpClk_ac97_reg_write_data <= (others => '0');
      else
        if Bus2IP_WrCE = '1' and controller_addr = AC97_WRITE_ADR then
          IpClk_ac97_reg_write_data <= Bus2IP_Data(16 to 31);
        end if;
      end if;
    end if;
  end process;

  -----------------------------------------------------------------------------
  -- AC97 Access initiate one shot
  -----------------------------------------------------------------------------

  -- This one bit signal is asserted when a write occurs to the AC97_CTRL_ADDR.
  -- This is a one-shot signal that is only asserted for one cycle
  -- (Bus2IP_Clk).

  -- This signal will initiate the AC97 register access state machine.
  AC97_Access_S_PROCESS : process (Bus2IP_Clk) is
  begin
    if Bus2IP_Clk'event and Bus2IP_Clk = '1' then
      if Bus2IP_WrCE = '1' and controller_addr = AC97_CTRL_ADR then
        IpClk_ac97_reg_access_S <= '1';  -- one shot
      else
        IpClk_ac97_reg_access_S <= '0';
      end if;
    end if;
  end process;

  -- busy signal
  process (Bus2IP_Clk) is
  begin

    if Bus2IP_Reset = '1' then
      ac97_register_access_sm <= IDLE;

    elsif Bus2IP_Clk'event and Bus2IP_Clk='1' then

      case ac97_register_access_sm is

        when IDLE =>
          if IpClk_ac97_reg_access_S = '1' then
            ac97_register_access_sm <= ISSUE_ACCESS;
          end if;
          
        when ISSUE_ACCESS =>
          -- TODO: add time out in case the codec is not hooked up
          if IpClk_ac97_reg_busy = '1' then
            ac97_register_access_sm <= PROCESS_ACCESS;
          end if;

        when PROCESS_ACCESS =>
          if IpClk_ac97_reg_busy = '0' then
            ac97_register_access_sm <= IDLE;
          end if;
          
      end case;
      
    end if;
  end process;
  register_access_busy <= '1' when (ac97_register_access_sm = ISSUE_ACCESS  or
                                    ac97_register_access_sm = PROCESS_ACCESS)
                          else '0';
  
  -----------------------------------------------------------------------------
  -- Clock crossing signals
  -----------------------------------------------------------------------------

  -- convert the one cycle strobe in the IpClk domain to
  -- the BitClk domain.
  fdcpe_1 : FDCPE
    port map (
      Q   => IpClk_access_request,
      C   => '0',
      CE  => '0',
      CLR => BitClk_ac97_reg_access_S,
      D   => '0',
      PRE => IpClk_ac97_reg_access_S
      );

  process (Bit_Clk) is
  begin
    if Bit_Clk'event and Bit_Clk='1' then
      BitClk_ac97_reg_access_St(0) <= IpClk_access_request;
      BitClk_ac97_reg_access_St(1) <= BitClk_ac97_reg_access_St(0);
      BitClk_ac97_reg_access_S <= BitClk_ac97_reg_access_St(0) and
                              (not BitClk_ac97_reg_access_St(1));
    end if;
  end process;
  BitClk_ac97_reg_read_strobe <= BitClk_ac97_reg_access_S and
                                 IpClk_ac97_reg_read;
  BitClk_ac97_reg_write_strobe <= BitClk_ac97_reg_access_S and
                                  (not IpClk_ac97_reg_read);
  

  BitClk_playback_left_valid <= '1';
  BitClk_playback_right_valid <= '1';

  -----------------------------------------------------------------------------
  -- Fifo Control Signals (asynchronous clock transfer)
  --
  -----------------------------------------------------------------------------

  -- BitClk is slower than IpClk.
  process (Bus2IP_Clk) is
  begin
    if Bus2IP_Clk'event and Bus2IP_clk='1' then
      IpClk_playback_accept_St(0) <= BitClk_playback_left_accept;
      IpClk_playback_accept_St(1) <= IpClk_playback_accept_St(0);
    end if;
    IpClk_playback_accept_S <= IpClk_playback_accept_St(0) and
                               (not IpClk_playback_accept_St(1));
  end process;

  process (Bus2IP_Clk) is
  begin
    if Bus2IP_Clk'event and Bus2IP_clk='1' then
      IpClk_record_valid_St(0) <= BitClk_record_left_valid;
      IpClk_record_valid_St(1) <= IpClk_record_valid_St(0);
    end if;
  end process;
  IpClk_record_accept_S <= IpClk_record_valid_St(0) and
                           (not IpClk_record_valid_St(1));

  in_FIFO_Read <= IpClk_playback_accept_S;
  out_FIFO_Write <= IpClk_record_accept_S;

  -----------------------------------------------------------------------------
  -- IN_FIFO
  --
  -- This fifo receives data directly from the OPB bus and performs a "fifo
  -- write" for each OPB write to the FIFO. The FIFO sends data directly to the
  -- AC97 core and performs a "fifo read" every time a new AC97 frame is sent.
  -- 
  -----------------------------------------------------------------------------

  Using_Playback_SRL : if (C_PLAYBACK = 1 and C_USE_BRAM = 0) generate
     
    IN_FIFO : SRL_FIFO
      generic map (
        C_DATA_BITS => 32,              -- Left and Right channel
        C_DEPTH     => 16)    
      port map (
         Clk         => Bus2IP_Clk,        
         Reset       => Bus2IP_Reset,        
         Clear_FIFO  => clear_in_fifo, 
         FIFO_Write  => in_FIFO_Write, 
         Data_In     => Bus2IP_Data,
         FIFO_Read   => in_FIFO_Read,
         Data_Out    => in_Data_FIFO,
         FIFO_Full   => in_FIFO_Full,
         Data_Exists => in_Data_Exists,
         FIFO_Level  => in_srl_fifo_level,
         Half_Full   => in_FIFO_Half_Full,
         Half_Empty  => in_FIFO_Half_Empty);

    in_fifo_level <= "000000" & in_srl_fifo_level;
    in_FIFO_Empty <= not in_Data_Exists;
  end generate Using_Playback_SRL;

  Using_Playback_BRAM : if (C_PLAYBACK = 1 and C_USE_BRAM = 1) generate
     
    IN_FIFO : BRAM_FIFO
      port map (
         Clk         => Bus2IP_Clk,        
         Reset       => Bus2IP_Reset,        
         Clear_FIFO  => clear_in_fifo, 
         FIFO_Write  => in_FIFO_Write, 
         Data_In     => Bus2IP_Data,
         FIFO_Read   => in_FIFO_Read,
         Data_Out    => in_Data_FIFO,
         FIFO_Level  => in_fifo_level,
         FULL   => in_FIFO_Full,
         HalfFull   => in_FIFO_HALF_FULL,
         HalfEmpty  => in_FIFO_Half_Empty,
         Overflow  => open,
         Underflow => open,
         Empty  => in_FIFO_Empty
         );
    in_Data_Exists <= not in_FIFO_Empty;
   end generate Using_Playback_BRAM;
    
  No_Playback : if (C_PLAYBACK = 0) generate
    in_Data_FIFO   <= (others => '0');
    in_FIFO_Full   <= '0';
    in_Data_Exists <= '0';
    in_FIFO_Empty <= '0';
    in_fifo_level <= (others => '0');
    out_fifo_level <= (others => '0');
  end generate No_Playback;

  -----------------------------------------------------------------------------
  -- OUT_FIFO
  --
  -- This fifo receives data directly from the AC97 and performs a "fifo
  -- write" for each AC97 frame. The FIFO sends data directly to the
  -- OPB Bus core and performs a "fifo read" every time data is read from the
  -- FIFO over the OPB bus.
  -- 
  -----------------------------------------------------------------------------
  Using_Recording_SRL : if (C_RECORD = 1 and C_USE_BRAM = 0) generate

    OUT_FIFO : SRL_FIFO
      generic map (
        C_DATA_BITS => 32,              -- [integer]
        C_DEPTH     => 16)              -- [integer]
      port map (
        Clk         => Bus2IP_Clk,         -- [in  std_logic]
        Reset       => Bus2IP_Reset,         -- [in  std_logic]
        Clear_FIFO  => clear_out_fifo,  -- [in  std_logic]
        FIFO_Write  => out_FIFO_Write,  -- [in  std_logic]
        Data_In     => out_Data_FIFO,
        FIFO_Read   => out_FIFO_Read,   -- [in  std_logic]
        Data_Out    => out_Data_Read,  -- [out std_logic_vector(0 to C_OPB_DWIDTH-1)]
        FIFO_Full   => out_FIFO_Full,   -- [out std_logic]
        Data_Exists => out_Data_Exists,       -- [out std_logic]
        FIFO_Level  => out_srl_fifo_level,
        Half_Full   => out_FIFO_Half_Full,    -- [out std_logic]
        Half_Empty  => open);  -- [out std_logic]

     out_fifo_level <= "000000" & out_srl_fifo_level;
     out_fifo_empty <= not out_Data_exists;
  end generate Using_Recording_SRL;

  Using_Recording_BRAM : if (C_RECORD = 1 and C_USE_BRAM = 1) generate

    OUT_FIFO : BRAM_FIFO
      port map (
         Clk         => Bus2IP_Clk,        
         Reset       => Bus2IP_Reset,        
         Clear_FIFO  => clear_out_fifo, 
         FIFO_Write  => out_FIFO_Write,
         Data_In     => out_Data_FIFO,
         FIFO_Read   => out_FIFO_Read,
         Data_Out    => out_Data_Read,
         FIFO_Level  => out_fifo_level,
         FULL   => out_FIFO_Full,
         HalfFull   => out_FIFO_HALF_FULL,
         HalfEmpty   => out_FIFO_HALF_Empty,
         Overflow => open,
         Underflow => open,
         Empty  => out_FIFO_Empty);  -- [out std_logic]

    out_Data_Exists <= not out_FIFO_Empty;
    
  end generate Using_Recording_BRAM;
  
  No_Recording : if (C_RECORD = 0) generate
    out_Data_Read   <= (others => '0');
    out_FIFO_Full   <= '0';
    out_Data_Exists <= '0';
  end generate No_Recording;

  
  -----------------------------------------------------------------------------
  -- Instanciating the core
  -----------------------------------------------------------------------------
  ac97_core_I : ac97_core 
  port map (

      Reset => ac97_core_reset,

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

      AC97_Reg_Addr                => IpClk_ac97_reg_addr,  -- async
      AC97_Reg_Write_Data          => IpClk_ac97_reg_write_data,  -- async
      AC97_Reg_Read_Data           => BitClk_ac97_Reg_Read_Data,
      AC97_Reg_Read_Strobe         => BitClk_ac97_reg_read_strobe,
      AC97_Reg_Write_Strobe        => BitClk_ac97_reg_write_strobe,
      AC97_Reg_Busy                => BitClk_ac97_reg_busy,
      AC97_Reg_Error               => BitClk_ac97_reg_error,
      AC97_Reg_Read_Data_Valid     => BitClk_ac97_reg_data_valid,
    
      PCM_Playback_Left            => in_Data_Fifo(16 to 31),
      PCM_Playback_Right           => in_Data_Fifo(0 to 15),
      PCM_Playback_Left_Valid      => BitClk_playback_left_valid,
      PCM_Playback_Right_Valid     => BitClk_playback_right_valid,
      PCM_Playback_Left_Accept     => BitClk_playback_left_accept,
      PCM_Playback_Right_Accept    => BitClk_playback_right_accept,

      PCM_Record_Left              => out_Data_Fifo(16 to 31),
      PCM_Record_Right             => out_Data_Fifo(0 to 15),
      PCM_Record_Left_Valid        => BitClk_record_left_valid,
      PCM_Record_Right_Valid       => BitClk_record_right_valid,

      DEBUG => debug_i,
      
      CODEC_RDY  => BitClk_codec_rdy

    );

                         
  -----------------------------------------------------------------------------
  -- Handling the interrupts
  -----------------------------------------------------------------------------
  Interrupt_Handle: process (in_FIFO_Half_Full, 
                              in_FIFO_Full, In_Data_Exists,
                              in_fifo_interrupt_en,
                              out_FIFO_Half_Full, out_FIFO_Half_Empty,
                              out_FIFO_Full, out_Data_Exists,
                              out_fifo_interrupt_en
                              ) is
   begin  -- process Playback_Interrupt_Handle
     if (C_INTR_LEVEL = 1) then
       Interrupt <=  (in_fifo_interrupt_en and in_FIFO_Half_Empty) or
                     (out_fifo_interrupt_en and out_FIFO_Half_Full);
     elsif (C_INTR_LEVEL = 2) then
       Interrupt <=  (in_fifo_interrupt_en and in_FIFO_Full) or
                     (out_fifo_interrupt_en and out_FIFO_Empty);
     elsif (C_INTR_LEVEL = 3) then
       Interrupt <=  (in_fifo_interrupt_en and in_FIFO_Half_Full) or
                     (out_fifo_interrupt_en and out_Fifo_Half_Empty);
       -- TODO: implement level 3
     else
       Interrupt <= '0';
     end if;
   end process Interrupt_Handle;
  
end architecture IMP;

⌨️ 快捷键说明

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