İletileri Göster

Bu özellik size üyenin attığı tüm iletileri gösterme olanağı sağlayacaktır . Not sadece size izin verilen bölümlerdeki iletilerini görebilirsiniz


Konular - muuzoo

Sayfa: [1]
1
Genel Uygulamalar / VHDL İle Clock Bölme
« : 25 Şubat 2016, 05:32:19 »
Yeni başlayanların ilk karşılaştığı şeylerden biri çoğunlukla daha yüksek frekansta çalışan clock üzerinden nasıl daha düşük frekanslar elde edeceğidir. Temelde frekans bölme işlemi basit bir sayıcı olarak düşünülebilir. Sayıcının ilgili bitleri kontrol edilerek clock frekansı 2 nin kuvvetleri cinsinden elde edilebilmektedir. Buna uygun bir kod parçası aşağıda verilmiştir. Basitçe açıklamak gerekirse "tmpCnt" sayacının 0. biti dikkate alınarak bir clock üretimi yapılırsa bu giriş clock işaretimizi ikiye bölecektir. Yani 50 MHz giriş uygulandığında 0. bit değişiminden 25 MHz, 1. bit değişiminden ise 12.5 Mhz işaret elde edilebilir.

Kod: VHDL
  1. library IEEE;
  2. use IEEE.STD_LOGIC_1164.all;
  3.  
  4. -- Uncomment the following library declaration if using
  5. -- arithmetic functions with Signed or Unsigned values
  6. use IEEE.NUMERIC_STD.all;
  7.  
  8. -- Uncomment the following library declaration if instantiating
  9. -- any Xilinx leaf cells in this code.
  10. --library UNISIM;
  11. --use UNISIM.VComponents.all;
  12.  
  13. entity clkManager is
  14.   port (
  15.     iClk     : in  std_logic;           -- Main System Clock
  16.     iRst     : in  std_logic;           -- Main Reset Signal
  17.     oClk25   : out std_logic);           -- 25 Mhz VGA Clock
  18. end clkManager;
  19.  
  20. architecture Behavioral of clkManager is
  21.   signal tmpCnt            : unsigned(1 downto 0) := '0';
  22.  
  23. begin
  24.  
  25.   -- purpose: Create 25 MHz From 50 Mhz Clock
  26.   -- type   : sequential
  27.   -- inputs : clk, rst
  28.   -- outputs: clk25
  29.   CLK_DIV : process (iclk, iRst) is
  30.   begin  -- process CLK_DIV
  31.     if iRst = '1' then           -- asynchronous reset (active low)
  32.       tmpCnt <= '0';
  33.     elsif iclk'event and iclk = '1' then  -- rising clock edge
  34.       tmpCnt <= tmpCnt + 1;
  35.     end if;
  36.   end process CLK_DIV;
  37.  
  38.   oClk25 <= tmpCnt(0);
  39.  
  40.  

Pekala ya 2'nin katları cinsinden bölmek istemezsek ? O zaman da bir sayıcının değerinin kontrolü ile istediğimiz frekans değerini elde etmek mümkün olacaktır. Basit matematik yapalım. 50 Mhz bir clock için her saat darbesi periyodu 20 ns süresindedir (20 * 10^-9 saniye). Peki biz eğer 1 sn periyoda sahip bir işaret elde etmek isteseydik? Yani 0.5 sn 0 değerine sahip 0.5 saniye 1 değerine sahip toplamda periyodu 1 sn olan bir işareti nasıl elde ederdik?

Cevap oldukça basit. Elimizdeki 20ns lik süreleri sayar ve toplam süreyi o şekilde bulabilirdik. 50 Mhz clock işareti demek o işaretin  saniyede 50.000.000 kez değiştiği manasına gelir. Eğer bir sayıcı yapıp 25  Milyon kez saydırıp, başka bir işareti değiştirirsek bu durumda 1 sn sürelik bir işaret elde etmiş oluruz. Bir önceki kodu bu şekilde güncellersek eğer:

Kod: VHDL
  1. library IEEE;
  2. use IEEE.STD_LOGIC_1164.all;
  3.  
  4. -- Uncomment the following library declaration if using
  5. -- arithmetic functions with Signed or Unsigned values
  6. use IEEE.NUMERIC_STD.all;
  7.  
  8. -- Uncomment the following library declaration if instantiating
  9. -- any Xilinx leaf cells in this code.
  10. --library UNISIM;
  11. --use UNISIM.VComponents.all;
  12.  
  13. entity clkManager is
  14.   generic (
  15.     freq : integer := 50);             -- Main Clock Frequency
  16.   port (
  17.     iClk     : in  std_logic;           -- Main System Clock
  18.     iRst     : in  std_logic;           -- Main Reset Signal
  19.     oClk25   : out std_logic;           -- 25 Mhz VGA Clock
  20.     oClkTime : out std_logic);          -- Ref. Clock For Time (1 Sec)
  21. end clkManager;
  22.  
  23. architecture Behavioral of clkManager is
  24.   constant periodConstTime : integer   := (freq*10**6)/2;  -- Total cycle for 0.5
  25.                                                            -- second timing.
  26.   constant periodConstDisp : integer   := (freq*10**3)/2;  -- Total cycle for 0.5
  27.                                                            -- milisecond timing.
  28.   signal oClkTimeTmp       : std_logic := '0';
  29.   signal tmpCnt            : std_logic := '0';
  30.  
  31. begin
  32.  
  33.   -- purpose: Create 25 MHz From 50 Mhz Clock
  34.   -- type   : sequential
  35.   -- inputs : clk, rst
  36.   -- outputs: clk25
  37.   CLK_DIV : process (iclk, iRst) is
  38.   begin  -- process CLK_DIV
  39.     if iRst = '0' then           -- asynchronous reset (active low)
  40.       tmpCnt <= '0';
  41.     elsif iclk'event and iclk = '1' then  -- rising clock edge
  42.       tmpCnt <= not tmpCnt;
  43.     end if;
  44.   end process CLK_DIV;
  45.  
  46.   oClk25 <= tmpCnt;
  47.  
  48.   -- purpose: 1 second ref. time.
  49.   -- type   : sequential
  50.   -- inputs : iClk, iRst
  51.   -- outputs: oClkTime
  52.   ClkTime1Sec : process (iClk, iRst) is
  53.     variable periodCounter : integer := 0;  -- Internal period counter.
  54.   begin  -- process FreqDivider
  55.     if iRst = '0' then                      -- asynchronous reset (active low)
  56.       oClkTimeTmp   <= '0';
  57.       periodCounter := 0;
  58.     elsif iClk'event and iClk = '1' then    -- rising clock edge
  59.       periodCounter := periodCounter + 1;
  60.       if (periodCounter = periodConstTime) then
  61.         oClkTimeTmp   <= not oClkTimeTmp;
  62.         periodCounter := 0;
  63.       end if;
  64.     end if;
  65.   end process ClkTime1Sec;
  66.  
  67.   oClkTime <= oClkTimeTmp;
  68.  
  69. end Behavioral;
  70.  

Görüleceği üzere "ClkTime1Sec" process yapısı içerisinde bulunan periodcounter sayıcısı sğrekli sayıyor ve bizim kodun üst kısmında tanımladığımız sabit değere ulaşıp ulaşmadığını kontrol ederek oClktimeTmp işaretini değiştirerek 1 sn lik bir işaret üretmiş oluyor. Böyle bir işaret mesela bir saat uygyulaması için kullanılabllir. Bu yüzden kod generic olarak tasarlanmış ve hangi giriş frekansında olursa olsun istenen çıkış değerinin elde edilmesi sağlanmış olur. Aynı kod yapısı kullanarak örneğin 7Segment uygulamaları için 1 KHz işaret üretmek isteseydik, kodumuz aşağıdaki şekilde olabilirdi.

Kod: VHDL
  1. library IEEE;
  2. use IEEE.STD_LOGIC_1164.all;
  3.  
  4. -- Uncomment the following library declaration if using
  5. -- arithmetic functions with Signed or Unsigned values
  6. use IEEE.NUMERIC_STD.all;
  7.  
  8. -- Uncomment the following library declaration if instantiating
  9. -- any Xilinx leaf cells in this code.
  10. --library UNISIM;
  11. --use UNISIM.VComponents.all;
  12.  
  13. entity clkManager is
  14.   generic (
  15.     freq : integer := 50);             -- Main Clock Frequency
  16.   port (
  17.     iClk     : in  std_logic;           -- Main System Clock
  18.     iRst     : in  std_logic;           -- Main Reset Signal
  19.     oClk25   : out std_logic;           -- 25 Mhz VGA Clock
  20.     oClk7Seg : out std_logic;           -- Clock source for 7 Segment Display
  21.     oClkTime : out std_logic);          -- Ref. Clock For Time (1 Sec)
  22. end clkManager;
  23.  
  24. architecture Behavioral of clkManager is
  25.   constant periodConstTime : integer   := (freq*10**6)/2;  -- Total cycle for 0.5
  26.                                                            -- second timing.
  27.   constant periodConstDisp : integer   := (freq*10**3)/2;  -- Total cycle for 0.5
  28.                                                            -- milisecond timing.
  29.   signal oClkTimeTmp       : std_logic := '0';
  30.   signal oClk7SegTmp       : std_logic := '0';
  31.   signal tmpCnt            : std_logic := '0';
  32.  
  33. begin
  34.  
  35.   -- purpose: Create 25 MHz From 50 Mhz Clock
  36.   -- type   : sequential
  37.   -- inputs : clk, rst
  38.   -- outputs: clk25
  39.   CLK_DIV : process (iclk, iRst) is
  40.   begin  -- process CLK_DIV
  41.     if iRst = '1' then           -- asynchronous reset (active low)
  42.       tmpCnt <= '0';
  43.     elsif iclk'event and iclk = '1' then  -- rising clock edge
  44.       tmpCnt <= not tmpCnt;
  45.     end if;
  46.   end process CLK_DIV;
  47.  
  48.   oClk25 <= tmpCnt;
  49.  
  50.   -- purpose: 1 second ref. time.
  51.   -- type   : sequential
  52.   -- inputs : iClk, iRst
  53.   -- outputs: oClkTime
  54.   ClkTime1Sec : process (iClk, iRst) is
  55.     variable periodCounter : integer := 0;  -- Internal period counter.
  56.   begin  -- process FreqDivider
  57.     if iRst = '1' then                      -- asynchronous reset (active low)
  58.       oClkTimeTmp   <= '0';
  59.       periodCounter := 0;
  60.     elsif iClk'event and iClk = '1' then    -- rising clock edge
  61.       periodCounter := periodCounter + 1;
  62.       if (periodCounter = periodConstTime) then
  63.         oClkTimeTmp   <= not oClkTimeTmp;
  64.         periodCounter := 0;
  65.       end if;
  66.     end if;
  67.   end process ClkTime1Sec;
  68.  
  69.   oClkTime <= oClkTimeTmp;
  70.  
  71.   -- purpose: 7 Segment Display Clock Generation (1Khz)
  72.   -- type   : sequential
  73.   -- inputs : iClk, iRst
  74.   -- outputs: oClk7Seg
  75.   Clk7SegGen : process (iClk, iRst) is
  76.     variable periodCounter : integer := 0;  -- Internal period counter.
  77.   begin  -- process Clk7SegGen
  78.     if iRst = '1' then                      -- asynchronous reset (active low)
  79.       oClk7SegTmp   <= '0';
  80.       periodCounter := 0;
  81.     elsif iClk'event and iClk = '1' then    -- rising clock edge
  82.       periodCounter := periodCounter + 1;
  83.       if (periodCounter = periodConstDisp) then
  84.         oClk7SegTmp   <= not oClk7SegTmp;
  85.         periodCounter := 0;
  86.       end if;
  87.     end if;
  88.   end process Clk7SegGen;
  89.  
  90.   oClk7Seg <= oClk7SegTmp;
  91.  
  92. end Behavioral;
  93.  

NOT: Bazı düzeltmeler eklendi, yazım hataları düzeltildi.

Sayfa: [1]