欢迎访问九江学院电子信息工程学院网站!

当前位置: 首页   >   资源下载   >   学习资料   >   正文

FPGA学习--TLC549ADC控制

作者:    信息来源:    发布时间: 2014-04-20

LIBRARY IEEE;                     
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_Arith.ALL;
USE IEEE.STD_LOGIC_Unsigned.ALL;

ENTITY adc IS
GENERIC(
CLK_DIV_BITS: Integer:=5;
CLK_DIV_VALUE: Integer:=31
);
PORT(
clock:  IN STD_LOGIC;--系统时钟
reset:  IN STD_LOGIC;--复位,高电平有效
enable:  IN STD_LOGIC;--转换使能
sdat_in: IN STD_LOGIC;--TLC549串行数据输入
adc_clk: OUT STD_LOGIC;--TLC549 I/O时钟
cs_n:  OUT STD_LOGIC;--TLC549 片选控制
data_ready: OUT STD_LOGIC;--指示有新的数据输出
data_out: OUT STD_LOGIC_VECTOR(7 DOWNTO 0)--AD转换数据输出
);
END;

ARCHITECTURE one OF adc IS
SIGNAL adc_clk_r: STD_LOGIC;
SIGNAL cs_n_r:  STD_LOGIC;
SIGNAL data_ready_r:STD_LOGIC;
SIGNAL data_out_r: STD_LOGIC_VECTOR(7 DOWNTO 0);--AD转换数据输出.
SIGNAL sdat_in_r: STD_LOGIC;--数据输出锁存
SIGNAL q:   STD_LOGIC_VECTOR(7 DOWNTO 0);--移位寄存器,用于接收或发送数据
SIGNAL bit_count: STD_LOGIC_VECTOR(5 DOWNTO 0);--移位计数器
SIGNAL bit_count_rst:STD_LOGIC;--ADC时钟计数全能控制.
SIGNAL div_clk:  STD_LOGIC;
SIGNAL clk_count: STD_LOGIC_VECTOR(CLK_DIV_BITS-1 DOWNTO 0);--时钟盼频计数器
SIGNAL buf1,buf2: STD_LOGIC;
SIGNAL ready_done: STD_LOGIC;--cs_n拉低(大于1.4us)后的标志
SIGNAL rec_done: STD_LOGIC;--数据读取完毕的标志
SIGNAL conv_done: STD_LOGIC;--数据转换完毕的标志

--SIGNAL adc_state: STD_LOGIC_VECTOR(2 DOWNTO 0);--状态机ADC
--SIGNAL adc_next_state:STD_LOGIC_VECTOR(2 DOWNTO 0);
--CONSTANT idle:   STD_LOGIC_VECTOR(2 DOWNTO 0):="000";
--CONSTANT adc_ready:  STD_LOGIC_VECTOR(2 DOWNTO 0):="001";
--CONSTANT adc_receive: STD_LOGIC_VECTOR(2 DOWNTO 0):="011";
--CONSTANT adc_conversion: STD_LOGIC_VECTOR(2 DOWNTO 0):="010";
--CONSTANT adc_data_load: STD_LOGIC_VECTOR(2 DOWNTO 0):="110";
TYPE states IS(idle,adc_ready,adc_receive,adc_conversion,adc_data_load);
SIGNAL adc_state,adc_next_state:states;

BEGIN
adc_clk<=adc_clk_r;
cs_n<=cs_n_r;
data_out<=data_out_r;
data_ready<=data_ready_r;

PROCESS (clock)
BEGIN
 IF RISING_EDGE(clock) THEN
  sdat_in_r<=sdat_in;
 END IF;
END PROCESS;
-----------------------------------------<<时钟分频计数器
PROCESS (clock)
BEGIN
 IF RISING_EDGE(clock) THEN
  IF reset='1' THEN
   clk_count<="00000";
  ELSE
   IF clk_count< CLK_DIV_VALUE THEN
    clk_count<=clk_count+1;
    div_clk<='0';
   ELSE
    clk_count<="00000";
    div_clk<='1';
   END IF;
  END IF;  
 END IF;
END PROCESS;
--------------------------------------------<<状态机ADC
PROCESS (clock)
BEGIN
 IF RISING_EDGE(clock) THEN
  IF reset='1' THEN
   adc_state<=idle;
  ELSE
   adc_state<=adc_next_state;
  END IF;
 END IF;
END PROCESS;
---------------------------------------------<<ADC状态机转换逻辑
PROCESS (adc_state,ready_done,rec_done,conv_done,enable)
BEGIN
 cs_n_r<='0';
 bit_count_rst<='0';
 data_ready_r<='0';
 CASE adc_state IS   --初始状态
  WHEN idle=>
   cs_n_r<='1';
   bit_count_rst<='1'; --复位移位计数器.
   IF enable='1' THEN
    adc_next_state<=adc_ready;
   ELSE
    adc_next_state<=idle;
   END IF;
  WHEN adc_ready=> --准备接收
   IF ready_done='1' THEN
    adc_next_state<=adc_receive;
   ELSE
    adc_next_State<=adc_ready;
   END IF;   
  WHEN adc_receive=> --接收数据
   IF  rec_done='1' THEN 
    adc_next_state<=adc_conversion;
   ELSE
    adc_next_state<=adc_receive;
   END IF;
  WHEN adc_conversion=> --转换前的采样的数据.
   cs_n_r<='1';
   IF conv_done='1' THEN
    adc_next_state<=adc_data_load;
   ELSE
    adc_next_state<=adc_conversion;
   END IF;    
  WHEN adc_data_load=>
   data_ready_r<='1';--数据输出标志.
   adc_next_state<=idle;
  WHEN OTHERS=>adc_next_state<=idle;
 END CASE;
END PROCESS;

PROCESS (clock)--位移位计数器
BEGIN
 IF RISING_EDGE(clock) THEN
  IF reset='1' THEN
   bit_count<="000000";
  ELSIF bit_count_rst='1' THEN
   bit_count<="000000";
  ELSIF div_clk='1' THEN
   bit_count<=bit_count+1;
  END IF;
 END IF;
END PROCESS;

ready_done<='1'  WHEN bit_count=4 ELSE '0';--准备读取数据
rec_done<='1'   WHEN bit_count=19 ELSE '0';--接收数据完毕
conv_done<='1'   WHEN bit_count=63 ELSE '0';--接收数据完毕
---------------------<<在接收位计数器4-20间8个adc clk
PROCESS(bit_count)
BEGIN
 IF bit_count<20 AND bit_count>=4 THEN
  adc_clk_r<=NOT bit_count(0); 
 ELSE
  adc_clk_r<='0';
 END IF;
END PROCESS;

PROCESS(clock)
BEGIN
 IF RISING_EDGE(clock) THEN
  buf1<=adc_clk_r;
  buf2<=buf1;
 END IF;
END PROCESS;

PROCESS(clock)--读取数据
BEGIN
 IF RISING_EDGE(clock) THEN
  IF(buf1='1' AND buf2='0' )THEN--ADC时钟上升沿
   q<=q(6 DOWNTO 0) & sdat_in_r;
  ELSIF data_ready_r='1' THEN --输出读取的数据.
   data_out_r<=q;
  END IF;
 END IF;
END PROCESS;
END;

 

 Copyright© 2020 九江学院电子信息工程学院版权所有

联系电话:0792-8314446