问:使用SPI协议的PMOD AD1(ADC)驱动程序

时间:2018-10-08 11:16:37

标签: deserialization vhdl fpga adc

我对VHDL中的代码有疑问;我想在Arty板上实现ADC(AD7476A)的驱动程序以及标有sDATA的16位输出矢量。

我希望ADC是可配置的(选择我们想要的数量),这就是为什么我制作了一个包装。

我的代码AD747_CTRL存在问题,它是反序列化器;我想在16位的临时寄存器中设置Shift寄存器,但是如何在12位的寄存器中设置数据呢?

此外,我想在测试台上测试我的代码,以发送数据(例如,斜坡)并查看波形上的串行数据。你能帮助我吗?非常感谢。

AD747XA_pkg.vhd:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

package AD747X is

  SUBTYPE ad747X_sample IS std_logic_vector( 11 downto 0 );
  TYPE ad747X_sample_v IS ARRAY (natural range<>) OF ad747X_sample;

end package;

AD747XA.vhd:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity AD747XA is

   Port (  
       serial_clk : in STD_LOGIC;  --ADC serial clock
       sdata     : out STD_LOGIC; 
       cs_n       : in STD_LOGIC
       );

end AD747XA;

architecture Behavioral of AD747XA is

    --Timing specifications
    constant tsclk : time := 1 sec/20000000;  --Fsclk -> 20 MHz
    constant tconvert : time := 16*tsclk; 
    constant tquiet : time := 50 ns;
    constant tpowerup :  time := 1 us;
    constant t1 :  time := 10 ns;
    constant t2 :  time := 10 ns;
    constant t3 :  time := 22 ns;
    constant t4 :  time := 40 ns;
    constant t5 :  time := 0.4*tsclk;
    constant t6 :  time := 0.4*tsclk;
    constant t7 :  time := 9.5 ns; --To modify according to the value of VDD
    constant t8 :  time := 36 ns; --max value

    --Signals declaration
      signal data : STD_LOGIC_VECTOR(15 downto 0) := (others=>'0');   


begin
    process
        begin

            wait until falling_edge(cs_n);
            wait for t2;
            for i in 0 to 3 loop 
                        wait until falling_edge(serial_clk);   
                        wait for t4;
                        sdata <= data(i); 
            end loop; 
            for i in 3 to 15 loop 
                        wait until falling_edge(serial_clk);   
                        wait for t7;
                        sdata <= data(i); 
            end loop; 

            data <= STD_LOGIC_VECTOR(unsigned(data) + 1);


   end process;


end Behavioral;

AD747XA_CTRL.vhd:

library IEEE;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_1164.ALL;
library WORK;
use WORK.AD747X.all;

entity AD747XA_CTRL is
generic ( 
    chan_count : integer := 2

       );
    Port ( clk        : in STD_LOGIC;
           rstn       : in STD_LOGIC;
           serial_clk : in STD_LOGIC;
           sdata      : in ad747X_sample_v(chan_count-1 downto 0);
           ready      : out STD_LOGIC;
           data       :  out ad747X_sample_v(chan_count-1 downto 0)
           );

end AD747XA_CTRL;

architecture Behavioral of AD747XA_CTRL is
signal rx_counter         : integer   := 0 ;
signal reg                : ad747X_sample_v (chan_count-1 downto 0);
type   TYPE_STATE is (Idle,ShiftIn); 
type   temp is array (0 to chan_count-1) of std_logic_vector(15 downto 0);
signal temp_reg : temp;
signal CURRENT_STATE      : TYPE_STATE := Idle;
signal i_enable_conv : std_logic := '0';

begin 

process(clk,rstn)
    begin
        if (rstn = '0') then
            for i in chan_count-1 downto 0 loop
            reg(i) <= (others => '0');
            end loop;
            rx_counter <= 0;
            i_enable_conv <='0';
            CURRENT_STATE <= Idle;

        elsif (clk = '1' and clk'event) then     
            case CURRENT_STATE is 

                when Idle =>
                     rx_counter <= 0;
                     if (i_enable_conv  = '1' ) then
                         CURRENT_STATE <= ShiftIn;
                     end if;

                when ShiftIn =>
                         i_enable_conv <= '0';
                         for i in chan_count-1 downto 0 loop      
                              temp_reg(i) <= sdata(i) & temp_reg(i)(15 downto 1);                                      
                         end loop;
                         rx_counter <= rx_counter + 1;      
                     if (rx_counter = 15) then
                         CURRENT_STATE <= Idle;
                         rx_counter <= 0;
                     else   
                         CURRENT_STATE <= ShiftIn;
                         rx_counter <= rx_counter + 1;
                     end if;  
            end case;
        end if;    

end process;
data <= reg;

end Behavioral;

tb_AD747XA.vhd:

entity tb_AD747XA is
end tb_AD747XA;

architecture Behavioral of tb_AD747XA is

constant chan_count : integer := 2 ;

COMPONENT AD747XA_CTRL is
generic (chan_count : integer := 2 );
    Port (
            clk        : in STD_LOGIC;
            rstn       : in STD_LOGIC;
            serial_clk : in STD_LOGIC;
            enable     : in STD_LOGIC;
            data       : in ad747X_sample_v(chan_count-1 downto 0);
            sdata      : out ad747X_sample_v(chan_count-1 downto 0)
          );  
end COMPONENT;

signal  clk        : STD_LOGIC := '1';
signal  rstn       : STD_LOGIC;
signal enable      : std_logic := '0';
signal serial_clk  : STD_LOGIC; 
signal sdata       : ad747X_sample_v(chan_count-1 downto 0);
signal data        : ad747X_sample_v(chan_count-1 downto 0);


SIGNAL end_of_simu : STD_LOGIC := '0';

begin

--AD1.vhd

ad747X : AD747XA_CTRL
generic map(chan_count  => 2)
Port map(
    clk         => clk,
    rstn        => rstn ,
    enable      => enable ,
    serial_clk  => serial_clk,
    sdata       => sdata ,
    data        => data
      );


process
    begin

    enable <= '0';
    wait for 150 ns;
    enable <= '1';
    wait;

end process; 



process
    begin
        rstn <= '0';
        wait for 100 ns;
        rstn <= '1';

        if enable = '0' then 
          wait until enable = '1';
       end if;

      data(0) <= "000000000000";
      wait for 50 ns;
      data(0) <= "000000000001";
      wait for 50 ns;
      data(0) <= "000000000010";
      wait for 50 ns;
      data(0) <= "000000000100";
      wait for 50 ns;
      data(0) <= "000000001000";

      end_of_simu <= '1';  
     wait;

end process;

process                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
begin
    IF end_of_simu /= '1' THEN
        clk <= not clk;
        wait for 5 ns;
    ELSE
         assert false report "end of test" severity note;
         WAIT;
    END IF;
    end process;
    end Behavioral;

0 个答案:

没有答案