📄 ac97_fifo.vhd
字号:
-------------------------------------------------------------------------------
-- Filename: ac97_fifo.vhd
--
-- Description: This module provides a 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 provides a FIFO interface for both the incoming
-- data (playback data) and outgoing data (record data).
--
-- 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
--
--
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
-------------------------------------------------------------------------------
--
-------------------------------------------------------------------------------
entity ac97_fifo is
generic (
C_AWIDTH : integer := 32;
C_DWIDTH : integer := 32;
C_PLAYBACK : integer := 1;
C_RECORD : integer := 1;
-- Interrupt strategy
-- 0 = No interrupts
-- 1 = when fifos are half empty (in half empty, out is half full)
-- 2 = when fifos are empty (in is empty, out is full)
-- 3 = when fifos are equal to interrupt fifo depth
C_INTR_LEVEL : integer := 0;
-- Use block ram FIFOs if 1, otherwise use a shallow
-- SRL fifo.
C_USE_BRAM : integer := 1
);
port (
-- IP Interface
Bus2IP_Clk : in std_logic;
Bus2IP_Reset : in std_logic;
Bus2IP_Addr : in std_logic_vector(0 to C_AWIDTH-1);
Bus2IP_Data : in std_logic_vector(0 to C_AWIDTH-1);
Bus2IP_BE : in std_logic_vector(0 to C_DWIDTH/8-1);
Bus2IP_RdCE : in std_logic;
Bus2IP_WrCE : in std_logic;
IP2Bus_Data : out std_logic_vector(0 to C_DWIDTH-1);
Interrupt: out std_logic;
-- CODEC signals
Bit_Clk : in std_logic;
Sync : out std_logic;
SData_Out : out std_logic;
SData_In : in std_logic;
AC97Reset_n : out std_logic
);
end entity ac97_fifo;
library opb_ac97_v2_00_a;
use opb_ac97_v2_00_a.all;
library unisim;
use unisim.all;
architecture IMP of ac97_fifo 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;
DEBUG : out std_logic_vector(0 to 15);
CODEC_RDY : out std_logic
);
end component ac97_core;
component FDCPE
port(
Q : out std_ulogic;
C : in std_ulogic;
CE : in std_ulogic;
CLR : in std_ulogic;
D : in std_ulogic;
PRE : in std_ulogic
);
end component;
component SRL_FIFO is
generic (
C_DATA_BITS : integer;
C_DEPTH : integer);
port (
Clk : in std_logic;
Reset : in std_logic;
Clear_FIFO : in std_logic;
FIFO_Write : in std_logic;
Data_In : in std_logic_vector(0 to C_DATA_BITS-1);
FIFO_Read : in std_logic;
Data_Out : out std_logic_vector(0 to C_DATA_BITS-1);
FIFO_Full : out std_logic;
Data_Exists : out std_logic;
FIFO_Level : out std_logic_vector(0 to 3);
Half_Full : out std_logic;
Half_Empty : out std_logic
);
end component SRL_FIFO;
component BRAM_FIFO is
generic (
C_DATA_BITS : integer := 32;
C_ADDR_BITS : integer := 9
);
port (
Clk : in std_logic;
Reset : in std_logic;
Clear_FIFO : in std_logic;
FIFO_Write : in std_logic;
Data_In : in std_logic_vector(0 to C_DATA_BITS-1);
FIFO_Read : in std_logic;
Data_Out : out std_logic_vector(0 to C_DATA_BITS-1);
FIFO_Level : out std_logic_vector(0 to C_ADDR_BITS);
Full : out std_logic;
HalfFull : out std_logic;
HalfEmpty : out std_logic;
Overflow : out std_logic;
Underflow : out std_logic;
Empty : out std_logic
);
end component BRAM_FIFO;
-- OUT_FIFO: record data from out fifo (left and right)
-- IN_FIFO: playback data (left and right)
-- STATUS: status of FIFOs/AC97
-- CONTROL: overall controll. clear fifos, interrupts
-- AC97_READ_ADR: result of AC97 register read
-- AC97_WRITE_ADR: Value to send for a AC97 write
-- AC97_CTRL_ADR: write ac97 command
signal controller_addr : std_logic_vector(0 to 2);
-- Register Map
-- Addr Read Write
-- 0x0 OUT_FIFO IN_FIFO
-- 0x4 STATUS Control
-- 0x8 AC97_READ AC97_WRITE
-- 0xc N/A AC97_CNTRL
constant IN_FIFO_ADR : std_logic_vector(0 to 2) := "000"; -- x0000
constant OUT_FIFO_ADR : std_logic_vector(0 to 2) := "000"; -- x0000
constant STATUS_ADR : std_logic_vector(0 to 2) := "001"; -- x0004
constant CTRL_ADR : std_logic_vector(0 to 2) := "001"; -- x0004
constant AC97_READ_ADR : std_logic_vector(0 to 2) := "010"; -- x0008
constant AC97_WRITE_ADR : std_logic_vector(0 to 2) := "010"; -- x0008
constant AC97_CTRL_ADR : std_logic_vector(0 to 2) := "011"; -- x000C
constant DEBUG_ADR : std_logic_vector(0 to 2) := "011"; -- x000C
-- Fifo signals
signal in_FIFO_Write : std_logic;
signal in_FIFO_Read : std_logic;
signal in_Data_FIFO : std_logic_vector(0 to 31);
signal in_FIFO_Full : std_logic;
signal in_Data_Exists : std_logic;
signal in_FIFO_Empty : std_logic;
signal in_FIFO_Half_Full : std_logic;
signal in_FIFO_Half_Empty : std_logic;
signal out_FIFO_Write : std_logic;
signal out_FIFO_Read : std_logic;
signal out_Data_Read : std_logic_vector(0 to 31);
signal out_Data_FIFO : std_logic_vector(0 to 31);
signal out_FIFO_Full : std_logic;
signal out_Data_Exists : std_logic;
signal out_FIFO_Empty : std_logic;
signal out_FIFO_Half_Empty : std_logic;
signal out_FIFO_Half_Full : std_logic;
signal out_FIFO_Overrun : std_logic := '0';
signal in_FIFO_Underrun : std_logic := '0';
signal clear_in_fifo : std_logic;
signal clear_out_fifo : std_logic;
signal in_fifo_interrupt_en : std_logic;
signal out_fifo_interrupt_en : std_logic;
signal status_Reg : std_logic_vector(31 downto 0) := (others => '0');
signal IpClk_ac97_reg_addr : std_logic_vector(0 to 6);
signal IpClk_ac97_Reg_Write_Data : std_logic_vector(0 to 15);
signal IpClk_ac97_reg_read : std_logic;
signal BitClk_codec_rdy, IpClk_codec_rdy : std_logic := '0';
signal BitClk_ac97_Reg_Read_Data : std_logic_vector(0 to 15);
signal IpClk_ac97_reg_access_S : std_logic;
signal BitClk_ac97_reg_access_St : std_logic_vector(2 downto 0);
signal BitClk_ac97_reg_access_S : std_logic;
signal BitClk_ac97_reg_read_data_valid : std_logic;
signal in_fifo_level, out_fifo_level : std_logic_vector(0 to 9);
signal in_srl_fifo_level, out_srl_fifo_level : std_logic_vector(0 to 3);
signal BitClk_ac97_reg_data_valid : std_logic; -- ignore?
signal BitClk_record_left_valid,BitClk_record_right_valid : std_logic;
signal BitClk_playback_left_accept,BitClk_playback_right_accept : std_logic;
signal BitClk_ac97_reg_read_strobe : std_logic := '0';
signal BitClk_ac97_reg_write_strobe : std_logic := '0';
signal BitClk_playback_left_valid,BitClk_playback_right_valid : std_logic;
signal BitClk_ac97_reg_busy, IpClk_ac97_reg_busy : std_logic := '0';
signal BitClk_ac97_reg_error, IpClk_ac97_reg_error : std_logic := '0';
signal IpClk_access_request : std_logic;
signal IpClk_playback_accept_St : std_logic_vector(1 downto 0);
signal IpClk_playback_accept_S : std_logic;
signal IpClk_record_valid_St : std_logic_vector(1 downto 0);
signal IpClk_record_accept_S : std_logic;
signal ac97_reset_i : std_logic := '0';
signal register_access_busy : std_logic;
type register_access_state is (IDLE, ISSUE_ACCESS, PROCESS_ACCESS);
signal ac97_register_access_sm : register_access_state := IDLE;
signal debug_i : std_logic_vector(0 to 15);
signal ac97_core_reset : std_logic;
begin -- architecture IMP
------------------------------------------------------------
-- IP Interface
------------------------------------------------------------
-- Register address decoding bits
controller_addr <= Bus2IP_Addr(27 to 29);
-- Output multiplixer for read registers:
-- status register
-- AC97 register data
-- Audio data
OUT_MUX: process (controller_addr, status_reg, Bitclk_ac97_Reg_Read_Data,
out_Data_read) is
begin
IP2Bus_Data <= (others => '0');
case controller_addr is
when STATUS_ADR =>
IP2Bus_Data((32-status_reg'length) to 31) <= status_reg;
when AC97_READ_ADR =>
IP2Bus_Data(16 to 31) <= BitClk_ac97_Reg_Read_Data; -- todo: fix
when DEBUG_ADR =>
IP2Bus_Data(16 to 31) <= debug_i;
when others =>
IP2Bus_Data <= out_Data_Read;
end case;
end process OUT_MUX;
----------------------------------------------------------------
-- FIFO Control
----------------------------------------------------------------
-- Generating read and write pulses for FIFOs
in_FIFO_write <= '1' when ( Bus2IP_WrCE = '1'
and controller_addr = IN_FIFO_ADR)
else '0';
out_FIFO_read <= '1' when (Bus2IP_RdCE = '1'
and controller_addr = OUT_FIFO_ADR)
else '0';
clear_fifo_PROCESS : process (Bus2IP_WrCE, controller_addr,
Bus2IP_Data(30 to 31))
begin
if Bus2IP_WrCE = '1' and controller_addr = CTRL_ADR then
clear_in_fifo <= Bus2IP_Data(31);
clear_out_fifo <= Bus2IP_Data(30);
else
clear_in_fifo <= '0';
clear_out_fifo <= '0';
end if;
end process;
----------------------------------------------------------------
-- Interrupt enable register
----------------------------------------------------------------
fifo_interrupt_enable_proc : process (Bus2IP_Clk)
begin
if Bus2IP_Clk'event and Bus2IP_Clk = '1' then
if Bus2IP_Reset = '1' then
in_fifo_interrupt_en <= '0';
out_fifo_interrupt_en <= '0';
elsif Bus2IP_WrCE = '1' and controller_addr = CTRL_ADR then
in_fifo_interrupt_en <= Bus2IP_Data(29);
out_fifo_interrupt_en <= Bus2IP_Data(28);
end if;
end if;
end process fifo_interrupt_enable_proc;
----------------------------------------------------------------
-- AC97Reset control register
----------------------------------------------------------------
ac97_reset_n_PROCESS : process (Bus2IP_Clk)
begin
if Bus2IP_Clk'event and Bus2IP_Clk = '1' then
if Bus2IP_Reset = '1' then
ac97_reset_i <= '1';
elsif Bus2IP_WrCE = '1' and controller_addr = CTRL_ADR then
ac97_reset_i <= Bus2IP_Data(27);
end if;
end if;
end process;
AC97Reset_n <= not ac97_reset_i;
-- The reset signal to the core & timing module occurs when
-- the bus is reset or when the AC97 codec is reset
ac97_core_reset <= ac97_reset_i or Bus2IP_Reset;
-----------------------------------------------------------------------------
-- Status register
-----------------------------------------------------------------------------
FIFO_Error_PROCESS : process (Bus2IP_Clk) is
begin -- process AC97_Write_Reg_Data
if Bus2IP_Clk'event and Bus2IP_Clk='1' then
if Bus2IP_Reset = '1' then
out_FIFO_Overrun <= '0';
in_FIFO_Underrun <= '0';
else
if (clear_in_fifo = '1') then
in_FIFO_Underrun <= '0';
elsif (in_Data_Exists = '0') and (in_FIFO_Read = '1') then
in_FIFO_Underrun <= '1';
end if;
if (clear_out_fifo = '1') then
out_FIFO_Overrun <= '0';
elsif (out_FIFO_Full = '1') and (out_FIFO_Write = '1')
and (out_FIFO_read = '0') then
out_FIFO_Overrun <= '1';
end if;
end if;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -