Xilinx FPGA पर VHDL में 50MHz को 2Hz तक कैसे विभाजित करें


13

मेरे पास एक Xilinx FPGA बोर्ड है, जिसमें 50MHz क्रिस्टल है। मुझे वीएचडीएल में इसे 2 हर्ट्ज तक विभाजित करने की आवश्यकता है। मैं यह कैसे करु?


13
तो आपने वास्तव में क्या प्रयास किया है?
मैट यंग

Xilinx घड़ी प्रबंधक IP का उपयोग क्यों नहीं किया जाता है?
आर्टर्स वैंकेन

जवाबों:


19

मूल रूप से, ऐसा करने के दो तरीके हैं। पहला Xilinx देशी घड़ी सिंथेसाइज़र कोर का उपयोग करना है। इसका एक फायदा यह है कि Xlinx टूल्स घड़ी को इस तरह से पहचानेंगे और इसे आवश्यक रास्तों से गुजरेंगे। उपकरण किसी भी समय की कमी को संभालेंगे (वास्तव में इस मामले में लागू नहीं है, क्योंकि यह 2Hz घड़ी है)

दूसरा तरीका यह है कि आपके क्लॉक क्लॉक की आधी अवधि बीत जाने तक तेज घड़ी दालों की संख्या गिनने के लिए एक काउंटर का उपयोग किया जाए। उदाहरण के लिए, आपके मामले के लिए, धीमी गति के चक्र की एक घड़ी की अवधि बनाने वाली तेज़ घड़ी दालों की संख्या 50000000/2 = 25000000 है। चूंकि हम आधी घड़ी की अवधि चाहते हैं, इसलिए प्रत्येक आधे चक्र के लिए 25000000/2 = 12500000 है। । (प्रत्येक उच्च या निम्न की अवधि)।

यहां VHDL में ऐसा दिखता है:

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 scale_clock is
  port (
    clk_50Mhz : in  std_logic;
    rst       : in  std_logic;
    clk_2Hz   : out std_logic);
end scale_clock;

architecture Behavioral of scale_clock is

  signal prescaler : unsigned(23 downto 0);
  signal clk_2Hz_i : std_logic;
begin

  gen_clk : process (clk_50Mhz, rst)
  begin  -- process gen_clk
    if rst = '1' then
      clk_2Hz_i   <= '0';
      prescaler   <= (others => '0');
    elsif rising_edge(clk_50Mhz) then   -- rising clock edge
      if prescaler = X"BEBC20" then     -- 12 500 000 in hex
        prescaler   <= (others => '0');
        clk_2Hz_i   <= not clk_2Hz_i;
      else
        prescaler <= prescaler + "1";
      end if;
    end if;
  end process gen_clk;

clk_2Hz <= clk_2Hz_i;

end Behavioral;

ध्यान देने योग्य बातें:

  • रीसेट के दौरान उत्पन्न घड़ी शून्य है। यह कुछ अनुप्रयोगों के लिए ठीक है, और दूसरों के लिए नहीं, यह सिर्फ इस बात पर निर्भर करता है कि आपको किस घड़ी की आवश्यकता है।
  • उत्पन्न घड़ी Xilinx संश्लेषण उपकरण द्वारा एक सामान्य संकेत के रूप में रूट की जा रही है।
  • 2 हर्ट्ज बहुत धीमा है। एक सेकंड के लिए अनुकरण करने में कुछ समय लगने वाला है। यह कोड की एक छोटी राशि है, इसलिए 1 सेकंड के लिए भी अनुकरण करना अपेक्षाकृत जल्दी होना चाहिए, लेकिन यदि आप कोड जोड़ना शुरू करते हैं, तो 2 हर्ट्ज के एक घड़ी चक्र को अनुकरण करने के लिए लिया गया समय काफी लंबा हो सकता है।

EDIT: clk_2Hz_i का उपयोग आउटपुट सिग्नल को बफर करने के लिए किया जाता है। वीएचडीएल एक असाइनमेंट के अधिकार पर एक संकेत का उपयोग करना पसंद नहीं करता है जब यह एक आउटपुट भी होता है।


1
बुरा नहीं है, लेकिन आप पूर्णांक के साथ अहस्ताक्षरित को जोड़ / तुलना कर सकते हैं, इसलिए: if prescaler = 50_000_000/4 then ...और prescaler <= prescaler + 1;थोड़ा सरल होगा।
ब्रायन ड्रमंड बाद

@StaceyAnne यह कोशिश करते हुए, मुझे "out 'ऑब्जेक्ट clk_o से नहीं पढ़ा जा सकता है,' बफर 'या' inout 'का उपयोग करें" क्या मुझे कुछ याद आया?
चोरी

@ यार्डिंग, आउटपुट पर एक बफर की जरूरत है। वीएचडीएल इस तथ्य को पसंद नहीं करता है कि clk_2Hzयह एक आउटपुट है, लेकिन फिर भी इसका मूल्य इस पंक्ति में पढ़ा जा रहा है clk_2Hz <= not clk_2Hz;। मैंने फिक्स में एड किया है।
स्टेनरी

+1 महान उदाहरण। लेकिन यहाँ वह जगह है जहाँ मेरा अज्ञान (VHDL के लिए नया) दिखाता है। बीच क्या अंतर है prescaler <= (others => '0');और prescaler <= '0';?
cbmeeks

NVM! मुझे पूरी तरह से याद है कि othersमेरे पास एक वीएचडीएल पुस्तक पढ़ने के लिए क्या उपयोग किया गया था। यह सिर्फ "000000000000000000 ....", आदि जैसे कुछ का उपयोग करने के बजाय सभी "अन्य" बिट्स को एक सामान्य मूल्य घोषित करने का एक शॉर्टकट है
cbmeeks

9

एक घड़ी prescaler का उपयोग करें।

आपका प्रीस्कूलर मान आपका (घड़ी_स्पीड / वांछित_कॉक_स्पेड) / 2 होगा (50Mhz (50,000,000) / 2hz (2)) / 2 = 12,500,000 जो बाइनरी में 101111101011110000100000 होगा।

और अधिक: (50,000,000) / 2) / 2 = 12,500,000 बाइनरी में कनवर्ट करें -> 101111101011110000100000

यहाँ कुछ करने के लिए कोड है: आप के लिए 2hz की जरूरत है जो कुछ के लिए newClock का उपयोग करें ...

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ClockPrescaler is
    port(
        clock   : in STD_LOGIC; -- 50 Mhz
        Led     : out STD_LOGIC
    );
end ClockPrescaler;

architecture Behavioral of ClockPrescaler is
    -- prescaler should be (clock_speed/desired_clock_speed)/2 because you want a rising edge every period
    signal prescaler: STD_LOGIC_VECTOR(23 downto 0) := "101111101011110000100000"; -- 12,500,000 in binary
    signal prescaler_counter: STD_LOGIC_VECTOR(23 downto 0) := (others => '0');
    signal newClock : std_logic := '0';
begin

    Led <= newClock;

    countClock: process(clock, newClock)
    begin
        if rising_edge(clock) then
            prescaler_counter <= prescaler_counter + 1;
            if(prescaler_counter > prescaler) then
                -- Iterate
                newClock <= not newClock;

                prescaler_counter <= (others => '0');
            end if;
        end if;
    end process;


end Behavioral;

ऐसा लगता है कि आप दो घड़ियाँ, 0.5 हर्ट्ज और 1 हर्ट्ज में से एक पैदा कर रहे हैं? (चूंकि आपकी घड़ी की अवधि आपका प्रीस्कूलर * 2 है?)। इसके अलावा, "+" एक त्रुटि देगा, क्योंकि आप स्लेव जोड़ रहे हैं, और मैं किसी भी मामले में इस तरह से ऐड की अतिप्रवाह संपत्ति का उपयोग करने के बारे में निश्चित नहीं हूं। क्यों नहीं, बस newClock : std_logic := '0'prescaler / 2 तक गिनती और असाइन करें newClk <= not newClk?
stanri

धन्यवाद, मेरा तर्क थोड़ा हटकर था। मैंने अपनी प्रारंभिक पोस्ट को कुछ परीक्षण किए गए कोड और आपके कुछ सुझावों के साथ अद्यतन किया :)
MLM

ऊ - उन सभी लोगों और शून्य और यह कहने के लिए एक टिप्पणी कि यह वास्तव में क्या है! क्यों आप के लिए ऐसा करने के लिए संकलक का उपयोग नहीं करते ??? और क्यों न केवल पूर्णांक का उपयोग करें?
मार्टिन थॉम्पसन

मैं गलत हो सकता हूँ, लेकिन मुझे लगता है कि जब ": = (others => '0')" के रूप में arhitecture में संकेतों को परिभाषित करते हुए डिफ़ॉल्ट मानों का उपयोग करना संश्लेषित नहीं है।
आर्टर्स वैंकेन्स

यह संश्लेषित है, लेकिन मूल रूप से केवल SRAM- आधारित FPGAs पर काम करता है, जैसे कि Xilinx, Altera या Liceice से अधिकांश।
यान वर्नियर

8

आप आमतौर पर कुछ भी धीमा नहीं करना चाहते हैं, बस सही दर पर सक्षम बनाएं और तर्क में इसका उपयोग करें:

 if rising_edge(50MHz_clk) and enable = '1' then

आप इस प्रकार सक्षम बना सकते हैं:

process 
   variable count : natural;
begin
   if rising_edge(50MHz_clk) then
       enable <= '0';
       count := count + 1;
       if count = clock_freq/desired_freq then
          enable <= '1';
          count := 0;
       end if;
    end if;
end process;

अपनी घड़ी की आवृत्ति और वांछित सक्षम आवृत्ति के साथ कुछ जोड़े बनाएं और जब आप बूट करने के लिए स्व-दस्तावेज कोड के साथ जाएं।


3

मैं इसके बजाय Xilinx प्राइमिटिस डिजिटल घड़ी प्रबंधक आईपी का उपयोग करने का सुझाव दूंगा

इसमें ग्राफ़िकल सेटिंग्स इंटरफ़ेस है जहाँ आप निर्दिष्ट कर सकते हैं कि आपको क्या आवृत्ति चाहिए। यह आवृत्ति के रूप में आपके वांछित आउटपुट के साथ एक घटक उत्पन्न करेगा।

यह आईपी विज़ार्ड में पाया जा सकता है;

यहाँ छवि विवरण दर्ज करें

और तब आप यह निर्दिष्ट करने में सक्षम होंगे कि आप क्या आवृत्ति चाहते हैं: यहाँ छवि विवरण दर्ज करें


0

कारक = इनपुट-सिग्नल-फ्रीकेंसी / आउटपुट-प्रिस्क्लेर-फ्रीकेंसी।

सीई = घड़ी सक्षम। इसका उपयोग न होने पर यह एक घड़ी (clk) चौड़ी नाड़ी या ऊँची होनी चाहिए।

क्यू = वांछित फ्रीसी के साथ एक घड़ी चौड़ी पल्स का आउटपुट सिग्नल।

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

entity prescaler is

  generic (
    FACTOR : integer);

  port (
    clk : in  std_logic;
    rst : in  std_logic;
    CE  : in  std_logic;
    Q   : out std_logic);

end prescaler;

architecture for_prescaler of prescaler is
  signal counter_reg, counter_next : integer range 0 to FACTOR-1;
  signal Q_next: std_logic;
begin  -- for_prescaler

  process (clk, rst)
  begin  -- process
    if rst = '1' then                   -- asynchronous reset (active low)
      counter_reg <= 0;
    elsif clk'event and clk = '1' then  -- rising clock edge
      counter_reg <= counter_next;
    end if;
  end process;

  process (counter_reg, CE)
  begin  -- process
    Q_next <= '0';
     counter_next <= counter_reg;
     if CE = '1' then
        if counter_reg = FACTOR-1  then
          counter_next <= 0;
           Q_next <= '1';
         else
           counter_next <= counter_reg + 1;
        end if;
      end if;
  end process;

  process (clk, rst)
  begin  -- process
    if rst = '1' then                   -- asynchronous reset (active low)
      Q <= '0';
    elsif clk'event and clk = '1' then  -- rising clock edge
      Q <= Q_next;
    end if;
  end process; 

end for_prescaler;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.