ADC128S022, National Semiconductor tarafından üretilen 14 bitlik ve 200ksps hızına sahip bir ADC entegresidir. Dahili multiplexer sayesinde 8 adet girişden veri okunabilir. İletişim olarak SPI'ı destekler. İç yapısı aşağıdaki gibidir:
İletişim protokolünün zamanlama diyagramı şu şekildedir:
ADC çevrim hızı 50ksps ile 200ksps arasında, SCLK sinyalin hızı ile ayarlanabilir. Her bir çevrim 16 clockda gerçekleşir. Bu uygulamada SCLK hızı 3.125Mhz olarak seçilmiş ve ADC hızı 195ksps olarak ayarlanmıştır. İletişimin 3, 4 ve 5. adımlarında DIN sinyalinde, okunmak istenen ADC kanalının adresi gönderilir. 12 bitlik ADC değeri 5. adımdan itibaren DOUT sinyalinden okunur. VHDL kodu:
--Kütüphaneler library IEEE; use IEEE.STD_LOGIC_1164.ALL; USE ieee.numeric_std.ALL; entity ADC is port(Clk : in std_logic; --Clock Girişi CS, SCLK, DIN : out std_logic; --ADC Entegresinin CS, SCLK ve DIN Girişleri DOUT : in std_logic; --ADC Entegresinin DOUT Çıkışı LedOut : out std_logic_vector(11 downto 0)); --ADC'den okunan 12 bitlik sinyal end ADC; architecture Behavioral of ADC is --SCLK sinyali signal ADCClock : std_logic := '1'; --Okunacak ADC kanalın adresi constant ADCChannel : std_logic_vector(2 downto 0) := "010"; begin --Sürekli veri okuma yapılacağından --CS biti '0' yapıldı CS <= '0'; --SCLK sinyal ataması SCLK <= ADCClock; --SCLK için clock bölücü process --50Mhz giriş sinyalini 3.125Mhz'e düşürür --Her bir ADC çevrimi 16 clockda yapılır --ADC örnekleme sayısı, 3.125Mhz / 16 = 195ksps process(Clk, ADCClock) variable ClkCnt : unsigned(3 downto 0) := (others => '0'); variable NextClkCnt : unsigned(3 downto 0) := "0001"; begin if rising_edge(Clk) then --Yükselen kenar ile sonraki count değerini, şimdiki count değerine yükle ClkCnt := NextClkCnt; --Eğer count değeri 7'ye ulaşmış ise ADCClock sinyalini tersle ve --sonraki count değerine '0' yükle if ClkCnt = 7 then NextClkCnt := (others => '0'); ADCClock <= not ADCClock; --Count değeri 15'e ulaşmamış ise sonraki count değerini 1 arttır else NextClkCnt := ClkCnt + 1; end if; end if; end process; --ADC entegresi ile iletişim kuran process process(ADCClock, DOUT) variable State : unsigned(4 downto 0) := (others => '0'); variable NextState : unsigned(4 downto 0) := "00001"; begin --Durum sayacı --1 ADC okuması toplamda 16 durumda gerçekleşir if falling_edge(ADCClock) then --Düşen kenar ile sonraki durumu, şimdiki duruma yükle State := NextState; --Eğer 16. duruma gelindi ise sonraki durumu 1 yap if State = 16 then NextState := "00001"; --16. duruma gelinmedi ise sonraki durumu 1 arttır else NextState := State + 1; end if; end if; --3, 4 ve 5. adımlarda okunacak ADC kanalının --adresi DIN sinyalinden gönderilir. if (State > 2) and (State < 6) then --ADC kanal bilgisinin ilk olarak 2. biti ve son olarak --0. biti gönderileceğinden dolayı, ADC kanal bilgisinin --bitleri terslenmiş şekilde DIN sinyaline gönderilir DIN <= ADCChannel(to_integer(5 - State)); else DIN <= '0'; end if; --5, 6, .. 16. adımlarda DOUT sinyalinden --veriler alınmaya başlar if (State > 4) and (State < 17) then if rising_edge(ADCClock) then --Veriler tersden geldiğinden, yani ilk olarak 11. bit --son olarak 0. bit geldiğinden dolayı gelen veriler --ters çevrilerek LedOut sinyaline atanır LedOut(to_integer(16 - State)) <= DOUT; end if; end if; end process; end Behavioral;
Tasarımın Quartus-II programı tarafından oluşturulmuş RTL şeması: