基于FPGA的AD7303/ADCS7476模拟数字转换VHDL开发

Posted fpga和matlab

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于FPGA的AD7303/ADCS7476模拟数字转换VHDL开发相关的知识,希望对你有一定的参考价值。

欢迎订阅《FPGA学习入门100例教程》、《MATLAB学习入门100例教程

目录

一、理论基础

二、核心程序

三、测试结果


一、理论基础

       在Altera Nios板上设计和实现一个格式转换系统,该系统读取模拟输入,将其转换为数字数据,然后将其反向转换为模拟格式。这将通过使用SPI MCP3202 12位A/D转换器进行模拟输入来实现,以生成数字数据流,然后使用Analog Devices 8位SPI AD7303 D/A转换器将数字数据用于生成模拟输出。数字输出还通过中间的低通滤波器(FIR)。分配给我的采样频率和截止频率分别为23 kHz和2.3 kHz。

12bit位宽的ADCS7476,根据技术文档datasheet可知:

      主要接口包括CS片选接口,SCLK时钟,SDATA数据,然后这个芯片是2路信号,然后我这里接口都预留了,然后实际用一个就可以了。

      他的时序如下所示:

然后看AD7303。

这个的话,确实得按这个状态图进行设计。通过状态机的方式实现。

二、核心程序

 
LIBRARY ieee;
   USE ieee.std_logic_1164.all;
   USE ieee.std_logic_unsigned.all;

ENTITY adcs7476 IS
   PORT (
      
      clk        : IN STD_LOGIC;
      rst        : IN STD_LOGIC;
      adc_cs_b   : OUT STD_LOGIC;
      adc_clk    : OUT STD_LOGIC;
      adc_data0  : IN STD_LOGIC;
      adc_data1  : IN STD_LOGIC;
      v0         : OUT STD_LOGIC_VECTOR(11 DOWNTO 0);
      v1         : OUT STD_LOGIC_VECTOR(11 DOWNTO 0);
      rdy        : OUT STD_LOGIC;
      delay      : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
      count      : OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
   );
END adcs7476;

ARCHITECTURE trans OF adcs7476 IS
   
   SIGNAL tmp0           : STD_LOGIC_VECTOR(11 DOWNTO 0);
   SIGNAL tmp1           : STD_LOGIC_VECTOR(11 DOWNTO 0);
   
   -- Declare intermediate signals for referenced outputs
   SIGNAL adc_cs_b_Reg1 : STD_LOGIC;
   SIGNAL adc_clk_Reg0  : STD_LOGIC;
   SIGNAL v0_Reg5       : STD_LOGIC_VECTOR(11 DOWNTO 0);
   SIGNAL v1_Reg6       : STD_LOGIC_VECTOR(11 DOWNTO 0);
   SIGNAL rdy_Reg4      : STD_LOGIC;
   SIGNAL delay_Reg3    : STD_LOGIC_VECTOR(31 DOWNTO 0);
   SIGNAL count_Reg2    : STD_LOGIC_VECTOR(6 DOWNTO 0);
BEGIN
   -- Drive referenced outputs
   adc_cs_b <= adc_cs_b_Reg1;
   adc_clk <= adc_clk_Reg0;
   v0 <= v0_Reg5;
   v1 <= v1_Reg6;
   rdy <= rdy_Reg4;
   delay <= delay_Reg3;
   count <= count_Reg2;
   PROCESS (clk, rst)
   BEGIN
      IF (rst = '1') THEN
         delay_Reg3 <= "00000000000000000000000000000000";
      ELSIF (clk'EVENT AND clk = '1') THEN
         IF (delay_Reg3 = "00000000000000000000000000000010") THEN
            delay_Reg3 <= "00000000000000000000000000000000";
         ELSE
            delay_Reg3 <= delay_Reg3 + "00000000000000000000000000000001";
         END IF;
      END IF;
   END PROCESS;
   
	
	
   PROCESS (clk, rst)
   BEGIN
      IF (rst = '1') THEN
         count_Reg2 <= "0000000";
      ELSIF (clk'EVENT AND clk = '1') THEN
         IF (delay_Reg3 = "00000000000000000000000000000000") THEN
            IF (count_Reg2 = "0101110") THEN
               count_Reg2 <= "0000000";
            ELSE
               count_Reg2 <= count_Reg2 + "0000001";
            END IF;
         END IF;
      END IF;
   END PROCESS;
   
   PROCESS (clk, rst)
   BEGIN
      IF (rst = '1') THEN
         adc_cs_b_Reg1 <= '0';
         adc_clk_Reg0 <= '0';
         rdy_Reg4 <= '0';
      ELSIF (clk'EVENT AND clk = '1') THEN
         IF (count_Reg2 < "0100000") THEN
            adc_cs_b_Reg1 <= '0';
         ELSE
            adc_cs_b_Reg1 <= '1';
         END IF;
         IF (count_Reg2 = "0100000") THEN
            rdy_Reg4 <= '1';
         ELSE
            rdy_Reg4 <= '0';
         END IF;
         adc_clk_Reg0 <= count_Reg2(0);
      END IF;
   END PROCESS;
   
   
   PROCESS (clk, rst)
   BEGIN
      IF (rst = '1') THEN
         tmp0 <= "000000000000";
         tmp1 <= "000000000000";
      ELSIF (clk'EVENT AND clk = '1') THEN
         IF (delay_Reg3 = "00000000000000000000000000000000") THEN
            IF (((NOT(adc_clk_Reg0)) = '1' OR adc_cs_b_Reg1 = '1') = true) THEN
               tmp0 <= tmp0;
            ELSE
               tmp0 <= (tmp0(10 DOWNTO 0) & adc_data0);
            END IF;
            
            IF (((NOT(adc_clk_Reg0)) = '1' OR adc_cs_b_Reg1 = '1') = true) THEN
               tmp1 <= tmp1;
            ELSE
               tmp1 <= (tmp1(10 DOWNTO 0) & adc_data1);
            END IF;
         END IF;
      END IF;
   END PROCESS;
   
   
   PROCESS (clk, rst)
   BEGIN
      IF (rst = '1') THEN
         v0_Reg5 <= "000000000000";
         v1_Reg6 <= "000000000000";
      ELSIF (clk'EVENT AND clk = '1') THEN
         IF (delay_Reg3 = "00000000000000000000000000000000") THEN
            IF (rdy_Reg4 = '1') THEN
               v0_Reg5 <= tmp0;
            ELSE
               v0_Reg5 <= v0_Reg5;
            END IF;
            
            IF (rdy_Reg4 = '1') THEN
               v1_Reg6 <= tmp1;
            ELSE
               v1_Reg6 <= v1_Reg6;
            END IF;
         END IF;
      END IF;
   END PROCESS;
   
   
END trans;






LIBRARY ieee;
   USE ieee.std_logic_1164.all;
   USE ieee.std_logic_unsigned.all;

ENTITY AD7303 IS
   PORT (
      
      CS        : OUT STD_LOGIC;
      done      : OUT STD_LOGIC;
      MOSI      : OUT STD_LOGIC;
      SCLK      : OUT STD_LOGIC;
      count     : OUT STD_LOGIC_VECTOR(4 DOWNTO 0);
      state     : OUT STD_LOGIC_VECTOR(5 DOWNTO 0);
      start     : IN STD_LOGIC;
      clock     : IN STD_LOGIC;
      reset     : IN STD_LOGIC;
      data_out  : IN STD_LOGIC_VECTOR(7 DOWNTO 0)
   );
END AD7303;

ARCHITECTURE trans OF AD7303 IS
   

   
   SIGNAL next_state     : STD_LOGIC_VECTOR(5 DOWNTO 0);
   SIGNAL next_count     : STD_LOGIC_VECTOR(4 DOWNTO 0);
   SIGNAL next_shift_out : STD_LOGIC_VECTOR(15 DOWNTO 0);
   SIGNAL shift_out      : STD_LOGIC_VECTOR(15 DOWNTO 0);
   SIGNAL next_MOSI      : STD_LOGIC;
   SIGNAL next_CS        : STD_LOGIC;
   SIGNAL next_SCLK      : STD_LOGIC;
   SIGNAL temp           : STD_LOGIC_VECTOR(15 DOWNTO 0);
   
   -- Declare intermediate signals for referenced outputs
   SIGNAL CS_xhdl0       : STD_LOGIC;
   SIGNAL MOSI_xhdl1     : STD_LOGIC;
   SIGNAL SCLK_xhdl2     : STD_LOGIC;
   SIGNAL count_xhdl3    : STD_LOGIC_VECTOR(4 DOWNTO 0);
   SIGNAL state_xhdl4    : STD_LOGIC_VECTOR(5 DOWNTO 0);
BEGIN
   -- Drive referenced outputs
   CS <= CS_xhdl0;
   MOSI <= MOSI_xhdl1;
   SCLK <= SCLK_xhdl2;
   count <= count_xhdl3;
   state <= state_xhdl4;
   
   PROCESS (clock, reset)
   BEGIN
      IF (reset = '1') THEN
         state_xhdl4 <= "000001";
         SCLK_xhdl2 <= '0';
         CS_xhdl0 <= '1';
         count_xhdl3 <= "00000";
      ELSIF (clock'EVENT AND clock = '1') THEN
         state_xhdl4 <= next_state;
         shift_out <= next_shift_out;
         MOSI_xhdl1 <= next_MOSI;
         SCLK_xhdl2 <= next_SCLK;
         count_xhdl3 <= next_count;
         CS_xhdl0 <= next_CS;
      END IF;
   END PROCESS;
   
   
   PROCESS (state_xhdl4, start, count_xhdl3, data_out, shift_out, MOSI_xhdl1, SCLK_xhdl2, CS_xhdl0, temp)
   BEGIN
      
      done <= '0';
      next_state <= state_xhdl4;
      next_MOSI <= MOSI_xhdl1;
      next_SCLK <= SCLK_xhdl2;
      next_CS <= CS_xhdl0;
      next_count <= count_xhdl3;
      next_shift_out <= shift_out;
      temp(15 DOWNTO 8) <= "01100000";
      temp(7 DOWNTO 0) <= data_out;
      
      CASE state_xhdl4 IS
         WHEN "000001" =>
            
            IF (start = '1') THEN
               
               next_CS <= '0';
               next_state <= "000010";
               next_shift_out <= temp;
               
               next_SCLK <= '0';
            ELSE
               next_CS <= '1';
               next_state <= "000001";
            END IF;
            next_count <= "00000";
         WHEN "000010" =>
            next_MOSI <= shift_out(15);
            next_shift_out <= (shift_out(14 DOWNTO 0) & '0');
            next_state <= "000100";
            next_count <= count_xhdl3 + "00001";
            next_SCLK <= '1';
            next_CS <= '0';
         WHEN "000100" =>
            
            IF (count_xhdl3 = "10000") THEN
               next_state <= "010000";
            ELSE
               next_state <= "000010";
            END IF;
         WHEN "010000" =>
            done <= '1';
            next_CS <= '1';
            next_SCLK <= '0';
            next_state <= "100000";
         WHEN "100000" =>
            next_CS <= '1';
            next_SCLK <= '0';
            IF (start = '1') THEN
               next_state <= "100000";
            ELSE
               next_state <= "000001";
            END IF;
         WHEN OTHERS =>
            next_state <= "000001";
      END CASE;
   END PROCESS;
   
   
END trans;


三、测试结果

ADCS7476然后位宽是12位,根据这些信息,我们的测试仿真结果如下所示:

AD7303

A28-63

以上是关于基于FPGA的AD7303/ADCS7476模拟数字转换VHDL开发的主要内容,如果未能解决你的问题,请参考以下文章

FPGA在AD采集中的应用

求一个fpga高速信号采集设计方案

基于AD936X+Intel FPGA的射频方案

用51单片机处理音频信号

基于DSP+FPGA+AD9238的冲击波超压测试系统设计与实现

基于FPGA 做一个数据采集模块 用Modelsim仿真