这个程序是在上一篇和AVR通讯 以及PWM控制的基础之上写的,这个程序是有问题的,具体问题在8364的EOC信号低电平时间只有不到1us,时间很短,而他的时钟信号不能超过5M,这个eoc信号触发外部中断来读取数据没有问题,但是在这个程序的第二第三个状态机中病没有检测到这个信号,所以出现的状况就是一直卡在第二个状态机。
另外由于每个状态机可能有不同的延迟,通过仿真发现毛刺现象比较突出,现在正在写改进的程序,这个程序仅作参考。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity kbctest is
port(
rst,clk : in std_logic; --时钟和复位信号
--avr 读写相关信号线
ale,rd,wr : in std_logic; --地址锁存、读、写信号
ad : inout std_logic_vector(7 downto 0); --地址数据信号线
--指示灯
led1,led2 : out std_logic;
--pwm
pwm1,pwm2 : out std_logic;
--ad8364信号线
adc_d: in std_logic_vector(15 downto 0);
adc_a: out std_logic_vector(2 downto 0); --a2,a1,a0
adc_reset: out std_logic;
adc_cs: out std_logic;
adc_wr: out std_logic;
adc_rd: out std_logic;
adc_hold: out std_logic_vector(2 downto 0); --只用两路ad 开启一路hold信号
adc_eoc: in std_logic;
adcclk_out: out std_logic;
statepoint: out std_logic_vector(3 downto 0)--用来指示处于第几个状态,方便调试
--放大增益控制
);
end kbctest;
architecture art of kbctest is
------------------------------------------------全局信号定义-------------------------------------------------------------------
--avr访问操作相关信号
signal adr : std_logic_vector(7 downto 0); --地址寄存器
signal data_buf : std_logic_vector(7 downto 0);
signal data_outctl : std_logic;
--pwm部分相关寄存器定义 寄存器暂时定义为8位
signal pwmfreq_reg : std_logic_vector(7 downto 0);
signal pwmocr1_reg : std_logic_vector(7 downto 0);
signal pwmocr2_reg : std_logic_vector(7 downto 0);
signal pwm_cnt : std_logic_vector(7 downto 0);
--时钟分频相关变量
signal clkcnt : std_logic_vector(16 downto 0);
signal adc_clk : std_logic; --adc时钟信号
signal pwm_clk : std_logic; --pwm时钟信号
--led指示相关变量
signal led_clk : std_logic; --led时钟信
signal led1_cnt : std_logic_vector(7 downto 0);
signal led2_cnt : std_logic_vector(7 downto 0);
signal led1s : std_logic;
signal led2s : std_logic;
--ads8364信号
type states is (st0,st1,st2,st3,st4,st5,st6,st7,st8,st9,st10,st11,st12,st13,st14,st15); --定义各状态的子类型
signal adcdata0h_reg,adcdata0l_reg,adcdata1h_reg,adcdata1l_reg : std_logic_vector(7 downto 0);
signal current_state,next_state: states:=st0;
begin
------------------------------------------------时钟分频-------------------------------------------------------------------
process(rst,clk) is
begin
if rst='0' then
clkcnt <= "00000000000000000";
elsif(clk'event and clk = '1') then
if(clkcnt = "11111111111111111") then
clkcnt<= "00000000000000000";
else
clkcnt <= clkcnt+1;
end if;
end if;
end process;
--pwm_clk <= clkcnt(7); --分频pwm时钟
--led_clk <= clkcnt(16); --分频led时钟
pwm_clk <= clkcnt(6); --分频pwm时钟
led_clk <= clkcnt(15); --分频led时钟
adc_clk <= clkcnt(2);
adcclk_out <= clkcnt(2);
------------------------------------------------avr访问操作----------------------------------------------------------------
data_outctl <= (not ale) and (not rd) and (wr);
ad <= data_buf when (data_outctl='1') else "ZZZZZZZZ";
--锁存avr地址数据
process(rst,ale) is
begin
if rst='0' then
adr <= "00000000";
elsif(ale'event and ale='0') then --在ale信号的下降沿锁存地址数据
adr <= ad;
end if;
end process;
-------------------------------------avr写数据-----------------------------------
process(rst,wr,ale) is
begin
if rst='0' then --对各寄存器给定初值
pwmfreq_reg <= "11111111";
pwmocr1_reg <= "01000000";
elsif (wr='1' and wr'event) then --在wr信号上升沿进行写操作
if ale = '0' then
case adr is
when "00000001" => pwmfreq_reg <= ad;
when "00000010" => pwmocr1_reg <= ad;
when others =>
pwmfreq_reg <= pwmfreq_reg;
end case;
end if;
end if;
end process;
------------------------------------avr读数据-------------------------------------
process(rst,rd,ale) is
begin
if rst='0' then
data_buf<="00000000";
elsif (rd='0'and rd'event) then
case adr is
when "00000001" => data_buf <= adcdata0h_reg;--1
when "00000010" => data_buf <= adcdata0l_reg;--2
when "00000011" => data_buf <= adcdata1h_reg;--3
when "00000100" => data_buf <= adcdata1l_reg;--4
when "00000101" => data_buf <= "00110011"; --5
when others =>
data_buf <= "ZZZZZZZZ";
end case;
end if;
end process;
------------------------------------led指示-------------------------------------
process(led_clk)is
begin
if(led_clk'event and led_clk='1') then
led1_cnt <= led1_cnt+1;
if (led1_cnt >= pwmfreq_reg) then
led1s <= not led1s;
led1_cnt <="00000000";
end if;
end if;
end process;
led1<=led1s;
--process(led_clk)is
--begin
-- if(led_clk'event and led_clk='1') then
-- led2_cnt <= led2_cnt+1;
-- if (led2_cnt >= pwmocr1_reg) then
-- led2s <= not led2s;
-- led2_cnt <="00000000";
-- end if;
-- end if;
--end process;
--led2<=led2s;
--------------------------------------pwm---------------------------------------
process(pwm_clk) is
begin
if rst='0' then
pwm_cnt<="00000000";
elsif(pwm_clk'event and pwm_clk='1') then
if(pwm_cnt > pwmfreq_reg) then
pwm_cnt <= "00000000";
else
pwm_cnt<=pwm_cnt+1;
end if;
--数据比较模块
if(pwm_cnt>=pwmocr1_reg) then
pwm1<= '1';
else
pwm1<= '0';
end if;
end if;
end process;
--------------------------------------ads8364------------------------------------
--ads8364控制,默认byte=0,add=0
adc_cs <= '0'; --片选一直选中
adc_wr <= '1';
--ads状态转移
process(rst,adc_clk) is
begin
if rst = '0' then
adc_reset<='0';
current_state <= st0;
elsif(adc_clk'event and adc_clk='1') then
current_state <= next_state;
adc_reset<='1';
end if;
end process;
process(current_state,adc_eoc) is
begin
case current_state is
when st0=>
adc_hold <= "111";
adc_rd <= '1';
adc_a <="000";
statepoint <= "0000";
led2<='1';
next_state <= st1;
when st1=>
adc_hold <= "000";
adc_rd <= '1';
adc_a <="000";
statepoint <= "0001";
led2<='1';
next_state <= st2; --启动转换
when st2=>
adc_hold <= "111";
adc_rd <= '1';
adc_a <="000";
statepoint <= "0010";
led2<='0';
--检测adc_eoc下降沿
if adc_eoc = '1' then
next_state <= st2;
else
next_state <= st3;
end if;
when st3=>
adc_hold <= "111";
adc_rd <= '1';
adc_a <="000";
statepoint <= "0011";
led2<='1';
--检测adc_eoc上升沿
if adc_eoc = '0' then
next_state <= st3;
else
next_state <= st4;
end if;
when st4=>
adc_hold <= "111";
adc_rd <= '0';--使能读信号 读取数据
adc_a <="000";
statepoint <= "0100";
adcdata0h_reg <= adc_d(15 downto 8);
adcdata0l_reg <= adc_d(7 downto 0);
led2<='1';
next_state <= st5;
when st5=>
adc_hold <= "111";
adc_rd <= '1';
adc_a <="001";--rd上升沿之后给出下一通道读取地址
statepoint <= "0101";
next_state <= st6;
led2<='1';
when st6=>
adc_hold <= "111";
adc_a <="001";
adc_rd <= '0'; --读ch1数据
adcdata1h_reg <= adc_d(15 downto 8);
adcdata1l_reg <= adc_d(7 downto 0);
statepoint <= "0110";
led2<='1';
next_state <= st7;
when st7=>
adc_hold <= "111";
adc_rd <= '1';
adc_a <="001";
statepoint <= "0111";
led2<='1';
next_state <= st0;
when others=>
adc_hold <= "111";
adc_rd <= '1';
adc_a <="000";
next_state <= st0;
end case;
end process;
end;