تبلیغات
باران الکترونیک - قسمت سوم: برنامه تقسیم کننده فرکانس به زبان VHDL
جمعه 1 آذر 1392  01:36 ق.ظ
نوع مطلب: (FPGA ،VHDL ،Xilinx ،Altera ،) توسط: امیرحسین رستمی

می­خواهیم برنامه­ای بنویسیم که در آن رابطه بین ورودی و خروجی به صورت زیر باشد:

یعنی فرکانس کلاک خروجی برابر با تقسیم دلخواهی از فرکانس ورودی می­باشد. برای این منظور باید یک شمارنده تعریف کنیم که با آمدن پالس­های بالارونده ورودی یک واحد زیاد می­شود. سه حالت مختلف به وجود می­آید.

الف) m توانی از 2 باشد:

فرض کنید  باشد. n=3 یعنی فرکانس پالس خروجی  1/8 فرکانس پالس ورودی می­باشد. یک شمارنده 3 بیتی تعریف می­کنیم. شمارنده از 0 تا 7 می­شمارد. با توجه به شکل اگر با ارزش­ترین بیت MSB شمارنده را به خروجی بدهیم، به هدف خود رسیده­ایم.

برنامه تقسیم کننده فرکانس در ادامه آمده است:

به ادامه مطلب مراجعه کنید.
دانلود فایل PDF در ادامه مطلب

divider.vhd--

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

-- arithmetic functions with Signed or Unsigned values

use IEEE.NUMERIC_STD.ALL;

----------------------------------------------------

entity divider is

     generic(N: integer := 2);  --DIVIDE 2^(N+1)

    Port ( clk_in : in  STD_LOGIC;

                reset : in STD_LOGIC;

           clk_out : out  STD_LOGIC);

end divider;

-----------------------------------------------------

architecture Behavioral of divider is

     signal temp_q : unsigned(N downto 0);

begin

 

     process(clk_in)

     begin

          if (reset = '1') then

              temp_q <= (others => '0');

          elsif (rising_edge(clk_in)) then

              temp_q <= temp_q + 1;

          end if;

     end process;

    

     clk_out <= temp_q(N);

    

end Behavioral;

برنامه test bench

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

 

-- Uncomment the following library declaration if using

-- arithmetic functions with Signed or Unsigned values

--USE ieee.numeric_std.ALL;

 

ENTITY tb_clock_div IS

END tb_clock_div;

 

ARCHITECTURE behavior OF tb_clock_div IS

 

    -- Component Declaration for the Unit Under Test (UUT)

 

    COMPONENT divider

    PORT(

         clk_in : IN  std_logic;

              reset  : IN  std_logic;

         clk_out : OUT  std_logic

        );

    END COMPONENT;

   

 

   --Inputs

   signal clk_in : std_logic := '0';

     signal reset   : std_logic;

     signal clk_out : std_logic;

   -- Clock period definitions

   constant clk_in_period : time := 10 ns;

 

BEGIN

 

     -- Instantiate the Unit Under Test (UUT)

   uut: divider PORT MAP (

          clk_in => clk_in,

               reset  => reset,

          clk_out => clk_out

        );

 

   -- Clock process definitions

   clk_in_process :process

   begin

          clk_in <= '0';

          wait for clk_in_period/2;

          clk_in <= '1';

          wait for clk_in_period/2;

   end process;

 

 

   -- Stimulus process

   stim_proc: process

   begin     

      -- hold reset state for 100 ns.

          reset <= '1';

      wait for 100 ns; 

          reset <= '0';

      wait for clk_in_period*10;

 

      -- insert stimulus here

 

      wait;

   end process;

END;

نتیجه شبیه سازی در برنامه ISE در شکل زیر نشان داده شده است.

نکات مربوط به برنامه

در این برنامه از کتابخانه numeric استفاده کردیم. ابتدا به بررسی کتابخانه­های موجود در VHDL می­پردازیم:

انواع کتابخانه­ها

در برنامه نویسی VHDL، 5 کتابخانه اصلی وجود دارند که عبارتند از:

use IEEE.std_logic_1164.all;

use IEEE.std_logic_arith.all;

use IEEE.numeric_std.all;

use IEEE.std_logic_signed.all;

use IEEE.std_logic_unsigned.all;

در کتابخانه IEEE std_logic_1164 چهار عمل اصلی برای متغییر نوع integer، عملیات شرطی برای تمام متغییرها و عملیات منطقی برای متغییرهای نوع بیتی و برداری تعریف شده است. به جدول 1 نگاه کنید.

جدول 1: IEEE std_logic_1164 package

فرض کنید می­خواهیم دو متغییر برداری (std_logic_vector) را با هم جمع کنیم. برای این منظور نیاز به اضافه کردن کتابخانه دیگری داریم که یکی از چهار کتابخانه باقی مانده می­باشد. کتابخانه­های std_logic_signed، std_logic_unsigned و std_logic_arith گرچه ما را  آسان­تر به این هدف می­رسانند اما استاندار ieee نمیباشند و استفاده از این کتابخانه­ها توصیه نمی­شود. در نتیجه تنها کتابخانه numeric_std باقی می­ماند. در این کتابخانه همان طور که در جدول 2 نشان داده شده است، سه عمل اصلی و عملیات شرطی برای متغییرهای نوع integer, natural, signed و  unsigned تعریف شده است.

جدول 2 IEEE numeric-std package

اکنون برای این که دو متغییر برداری (‏std_logic_vector‏) را با هم جمع کنیم‏ باید آن ها را به یکی انواع ‏تعریف شده در این کتابخانه تعریف کنیم. برای این منظور باید از توابع تبدیل استفاده کنیم. خلاصه این ‏توابع در جدول 3 آمده است.‏

http://baranelec.persiangig.com/PDF/freq_div/img6.jpg

در ادامه چند مثال نشان داده شده است.

در برنامه تقسیم کننده فرکانس شمارنده را یک سیگنال از نوع UNSIGNED تعریف کردیم چون با آمدن لبه بالارونده کلاک، یک واحد به مقدار قبلی آن اضافه می­شود.

ب) m مضربی از 2 باشد

فرض کنید می­خواهیم فرکانس ورودی را تقسیم بر 6 کنیم. کافی است وقتش شمارنده سه عدد شمارد، وضعیت کلاک خروجی را برعکس کنیم.

در ادامه برنامه نوشته شده آمده است. برنامه تست مانند حالت قبل می­باشد. 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

-- arithmetic functions with Signed or Unsigned values

use IEEE.NUMERIC_STD.ALL;

----------------------------------------------------

entity divider is

     generic(N: integer := 4);

    Port ( clk_in : in  STD_LOGIC;

                reset : in STD_LOGIC;

           clk_out : out  STD_LOGIC);

end divider;

-----------------------------------------------------

architecture Behavioral of divider is

     signal temp_q : unsigned(N downto 0);

     signal temp_clk_out: STD_LOGIC;

begin

 

     process(clk_in)

     begin

          if (reset = '1') then

              temp_q <= (others => '0');

              temp_clk_out <= '0';

          elsif (rising_edge(clk_in)) then

              if temp_q >= "10" then  ---divide by 6 (=[2+1]x2)

                   temp_clk_out <= not(temp_clk_out);

                   temp_q <= (others => '0');

              else

                   temp_q <= temp_q + 1;

              end if;

          end if;

     end process;

     clk_out <= temp_clk_out;

end Behavioral;

ج) m عدد دلخواهی باشد.

در این حالت بهتر است زیاد به مغزمان فشار نیاورده و از PLL داخلی FPGA استفاده کنیم. وظیفه PLL (Phase Lock Loop) این است تا کلاک خارجی را زیاد کند. به بیان ساده­تر PLL یک واحد ضرب کنند فرکانس می­باشد. می­توان از PLL به عنوان تقسیم کننده فرکانس استفاده کرد و فرکانس مورد نظر را از آن ایجاد کرد.

در Xilinx واحد PLL، DCM (Digital Clock Manager) نامیده می­شود و به صورت IP Core توسط نرم­افزار Core Generation در اختیار برنامه نویس قرار داده شده است.

برای کسب اطلاعات بیش­تر و چگونگی برنامه ریزی آن به Help نرم افزار مراجعه کنید.


دانلود فایل PDF


نظرات()   
   
علیرضا
جمعه 5 خرداد 1396 08:46 ب.ظ
سلام.خیلی خوب بود.فقط تقسیم فرکانسی با چه نوع فلیپ فلاپی بود؟
پاسخ امیرحسین رستمی : با تشکر ار نظر شما.
با D-FF
 
لبخندناراحتچشمک
نیشخندبغلسوال
قلبخجالتزبان
ماچتعجبعصبانی
عینکشیطانگریه
خندهقهقههخداحافظ
سبزقهرهورا
دستگلتفکر
آخرین پست ها