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

📄 pcm1804_i2s_data_adjust2.vhd

📁 用于pcm1804调整I2S的数据
💻 VHD
字号:
-- ************************************* 文件名 ************************************* 
--pcm1804_i2s_data_adjust2.vhd							    creatby:liubingyang


-- *************************************程序功能*************************************
--	用于pcm1804调整I2S的数据,使I2S的音频同步并且在FIFO中不溢出。能够自动判断FIFO
--中的状态,通过调整从FIFO中输出的数据的个数来使FIFO既不上溢也不下溢。
--	为了达到更高的精度要求,可以通过加大采样时钟clk的频率。


-- *************************************程序说明*************************************
--1.将左右声道标志也存入FIFO中,从FIFO中直接输出数据和lrck信息。通过改变输出无效数据
--  的个数来达到延迟或者提前输出lrck的目的,以达到fifo不溢出而又是同步的。
--2.采用12.288MHz的时钟,在计数到128时时钟正好为48kHz,若为127则48.377KHz,为129则是
--  47.627。若测试无效,则直接增加clk的时钟频率
--3.采用更高频率的时钟时,需保证,这个时钟的上升延是产生时钟bck变化的延,到时候直接修
--  改compare_cnt和clk_cnt的位数,和相应的修改计数达到的比较值即可。
--4.例如:108MHz时钟,计数到1125就产生2分频的48KHz时钟,如果计数到1126,则产生时钟是
--108M/1126/2=47.9573kHz,计数到1124则产生时钟48.0427kHz。精度可以达到40Hz。


-- *************************************修改纪录*************************************		
--2007年11月9日
--首次创建
--	第一个版本的机制是直接去改变输出的lrck,第二版则是通过改变等待时间来延迟或提前。

--2007年11月10日
--	加入了另一个采样时钟clk,以提高改变lrck频率的精度。通过clk计数,根据FIFO的状态来
--多计或者少计,达到比较值时让产生读FIFO的使能复位。



library ieee ;
use ieee.std_logic_1164.all ;
use ieee.std_logic_arith.all ;
use ieee.std_logic_unsigned.all ;


entity pcm1804_i2s_data_adjust2 is
port(
	data		: in 	std_logic ;				--输入数据
	lrck		: in	std_logic ;				--输入的左右声道
	bck			: in	std_logic ;				--输入的时钟
	read_bck	: in	std_logic ;				--3.072MHz
	clk			: in	std_logic ;				--12.288MHz
	
	--指示
	wrempty		: out	std_logic ;				--全空标志
	wrfull		: out	std_logic ;				--全满标志
--	wren_out	: out	std_logic ;
--	rden_out	: out	std_logic ;				--读使能 test
	--输出
	data_out	: out	std_logic ;	
	lrck_out	: out	std_logic ;				
	bck_out		: out	std_logic 
	);
end pcm1804_i2s_data_adjust2 ;


architecture behave of pcm1804_i2s_data_adjust2 is


component fifo1k 
	PORT
	(
		data		: IN STD_LOGIC_VECTOR (1 DOWNTO 0);
		rdclk		: IN STD_LOGIC ;
		rdreq		: IN STD_LOGIC ;
		wrclk		: IN STD_LOGIC ;
		wrreq		: IN STD_LOGIC ;
		q			: OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
		rdusedw		: OUT STD_LOGIC_VECTOR (9 DOWNTO 0);
		wrempty		: OUT STD_LOGIC ;
		wrfull		: OUT STD_LOGIC 
	);
END component;



signal left_count		: std_logic_vector ( 4 downto 0 ) ;
signal right_count		: std_logic_vector ( 4 downto 0 ) ;
signal wren				: std_logic ;
signal rden				: std_logic ;
signal fifo_rd_start	: std_logic := '0' ;	
signal rd_cnt			: std_logic_vector ( 5 downto 0 ) ;
signal compare_cnt		: std_logic_vector ( 7 downto 0 ) ;
signal rdusedw			: std_logic_vector ( 9 downto 0 ) ;
signal data_reg			: std_logic_vector ( 1 downto 0 ) ;
signal data_in			: std_logic_vector ( 1 downto 0 ) ;
signal clk_cnt			: std_logic_vector ( 7 downto 0 ) ;


begin


fifo:fifo1k
port map(
	data	=> data_in,
	rdclk	=> not (read_bck),
	rdreq	=> rden,
	wrclk	=> bck,
	wrreq	=> wren,
	q		=> data_reg,
	rdusedw	=> rdusedw,
	wrempty	=> wrempty,	
	wrfull	=> wrfull			
	);
	
--******************************************************************************************	
	data_in		<= lrck & data ;
	data_out	<= data_reg(0) ;
	lrck_out	<= data_reg(1) ;
	bck_out		<= read_bck ;

--	rden_out	<= rden ;
--	wren_out	<= wren ;
--产生FIFO写使能的左右声道计数	
process(lrck,bck,left_count)
begin
	if lrck = '1' then
		left_count	<= "00000" ;
	elsif bck'event and bck = '0' then
		if left_count < "11111" then
			left_count	<=	left_count + 1 ;
		else
			left_count	<=	left_count ;
		end if ;
	end if ;
end process ;

process(lrck,bck,right_count)
begin
	if lrck = '0' then
		right_count	<= "00000" ;
	elsif bck'event and bck = '0' then
		if right_count < "11111" then
			right_count	<=	right_count + 1 ;
		else
			right_count	<=	right_count ;
		end if ;
	end if ;
end process ;


--FIFO的写使能
process(lrck,left_count,right_count)
begin
	case lrck is
		when '0' =>
			if left_count <= "11000" then			--0到24产生写使能,正好25个数
				wren	<= '1' ;
			else
				wren	<= '0' ;
			end if ;
		when '1' =>
			if right_count <= "11000" then
				wren	<= '1' ;
			else
				wren	<= '0' ;
			end if ;
		when others =>
			null ;
	end case ;
end process ;	


--FIFO的读开始标志
process(read_bck)
begin
	if read_bck'event and read_bck = '0' then
		if rdusedw( 9 downto 0 ) = "0110011001" then				--1kfifo的4/10
			fifo_rd_start	<= '1' ;								--产生开始读取fifo的标志。
		end if ;
	end if ;
end process ;


--clk 12.488MHz时钟的计数
process(fifo_rd_start,clk)
begin
	if fifo_rd_start = '0' then										--	采样计数从1到要调整的值依次循环以控制FIFO中数据输出。
		clk_cnt	<= "00000000" ;										--当计数等于比较值时,既始FIFO的读使能计数清零,开始新一轮
	elsif clk'event and clk = '0' then								--的从FIFO中读取数据。改变比较值的大小就可以达到自动调整
		if clk_cnt < compare_cnt then								--的作用了。
			clk_cnt	<= clk_cnt + 1 ;
		else
			clk_cnt	<= "00000001" ;
		end if ;
	end if ;
end process ;

	
--FIFO的读计数
process(fifo_rd_start,read_bck,clk_cnt,compare_cnt)
begin
	if fifo_rd_start = '0' or clk_cnt = compare_cnt then			--当采样计数达到比较的那个值时,产生读使能的计数复位归零。
		rd_cnt	<= "000000" ;
	elsif read_bck'event and read_bck = '1' then
		if rd_cnt < "111111" then
			rd_cnt	<= rd_cnt + 1 ;
		else
			rd_cnt	<= rd_cnt ;
		end if ;
	end if ;
end process ;




--FIFO的读使能的产生  fifo读时钟not(read_bck)
process(fifo_rd_start,rd_cnt)
begin
	if fifo_rd_start = '0' then 
		rden	<= '0' ;
	else
		if rd_cnt >= "000001" and rd_cnt <= "011001" then		--1到25产生读使能,正好25个数。
			rden	<= '1' ;
		else
			rden	<= '0' ;
		end if ;
	end if ;
end process ;


--改变读数长度的计数比较的产生
process(read_bck,rd_cnt)
begin
	if read_bck'event and read_bck = '0' then						--根据FIFO的读状态来改变比较数的数值。
		if rd_cnt = "011001" then
			if rdusedw( 9 downto 0 ) <= "0110011001" then
				compare_cnt	<= "10000001" ;
			elsif rdusedw( 9 downto 0 ) <= "1001100110" then
				compare_cnt	<= "10000000" ;
			else
				compare_cnt	<= "01111111" ;
			end if ;
		end if ;
	end if ;
end process ;


end behave ;

⌨️ 快捷键说明

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