基于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开发的主要内容,如果未能解决你的问题,请参考以下文章