मेरे पास एक Xilinx FPGA बोर्ड है, जिसमें 50MHz क्रिस्टल है। मुझे वीएचडीएल में इसे 2 हर्ट्ज तक विभाजित करने की आवश्यकता है। मैं यह कैसे करु?
मेरे पास एक Xilinx FPGA बोर्ड है, जिसमें 50MHz क्रिस्टल है। मुझे वीएचडीएल में इसे 2 हर्ट्ज तक विभाजित करने की आवश्यकता है। मैं यह कैसे करु?
जवाबों:
मूल रूप से, ऐसा करने के दो तरीके हैं। पहला 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;
ध्यान देने योग्य बातें:
EDIT: clk_2Hz_i का उपयोग आउटपुट सिग्नल को बफर करने के लिए किया जाता है। वीएचडीएल एक असाइनमेंट के अधिकार पर एक संकेत का उपयोग करना पसंद नहीं करता है जब यह एक आउटपुट भी होता है।
if prescaler = 50_000_000/4 then ...
और prescaler <= prescaler + 1;
थोड़ा सरल होगा।
clk_2Hz
यह एक आउटपुट है, लेकिन फिर भी इसका मूल्य इस पंक्ति में पढ़ा जा रहा है clk_2Hz <= not clk_2Hz;
। मैंने फिक्स में एड किया है।
prescaler <= (others => '0');
और prescaler <= '0';
?
others
मेरे पास एक वीएचडीएल पुस्तक पढ़ने के लिए क्या उपयोग किया गया था। यह सिर्फ "000000000000000000 ....", आदि जैसे कुछ का उपयोग करने के बजाय सभी "अन्य" बिट्स को एक सामान्य मूल्य घोषित करने का एक शॉर्टकट है
एक घड़ी 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;
newClock : std_logic := '0'
prescaler / 2 तक गिनती और असाइन करें newClk <= not newClk
?
आप आमतौर पर कुछ भी धीमा नहीं करना चाहते हैं, बस सही दर पर सक्षम बनाएं और तर्क में इसका उपयोग करें:
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;
अपनी घड़ी की आवृत्ति और वांछित सक्षम आवृत्ति के साथ कुछ जोड़े बनाएं और जब आप बूट करने के लिए स्व-दस्तावेज कोड के साथ जाएं।
मैं इसके बजाय Xilinx प्राइमिटिस डिजिटल घड़ी प्रबंधक आईपी का उपयोग करने का सुझाव दूंगा ।
इसमें ग्राफ़िकल सेटिंग्स इंटरफ़ेस है जहाँ आप निर्दिष्ट कर सकते हैं कि आपको क्या आवृत्ति चाहिए। यह आवृत्ति के रूप में आपके वांछित आउटपुट के साथ एक घटक उत्पन्न करेगा।
यह आईपी विज़ार्ड में पाया जा सकता है;
और तब आप यह निर्दिष्ट करने में सक्षम होंगे कि आप क्या आवृत्ति चाहते हैं:
कारक = इनपुट-सिग्नल-फ्रीकेंसी / आउटपुट-प्रिस्क्लेर-फ्रीकेंसी।
सीई = घड़ी सक्षम। इसका उपयोग न होने पर यह एक घड़ी (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;