回答:
基本的に、これを行うには2つの方法があります。1つは、ザイリンクスネイティブクロックシンセサイザーコアを使用することです。この利点の1つは、Xlinxツールがクロックをそのように認識し、必要な経路を介してクロックをルーティングすることです。ツールはタイミング制約も処理します(2Hzクロックであるため、この場合は実際には適用されません)
2番目の方法は、カウンターを使用して、低速クロック周期の半分が経過するまで高速クロックパルスの数をカウントすることです。たとえば、あなたの場合、遅いクロックサイクルの1クロック周期を構成する高速クロックパルスの数は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;
注意事項:
編集:clk_2Hz_iは、出力信号をバッファリングするために使用されます。VHDLは、出力でもある割り当ての右側の信号を使用することを好みません。
if prescaler = 50_000_000/4 then ...
し、prescaler <= prescaler + 1;
少し単純になります。
clk_2Hz
出力であるという事実を嫌いますが、その値はこの行で読み取られていますclk_2Hz <= not clk_2Hz;
。修正で編集しました。
prescaler <= (others => '0');
とはprescaler <= '0';
?
others
が持っているVHDLの本を読んだときに何が使われていたのか、まったく見逃していました。それは、「... 000000000000000000」などを共通の値にすべての「その他」のビットを宣言する代わりのようなものを使用するためだけのショートカットだ
クロックプリスケーラを使用します。
プリスケーラーの値は(clock_speed / desired_clock_speed)/ 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;
起動する自己文書化コードを使用して、クロック周波数と必要なイネーブル周波数を使用していくつかの定数を作成します。
ザイリンクスprimiticeデジタルクロックマネージャーIPを使用することをお勧めします。
必要な周波数を指定できるグラフィカル設定インターフェイスがあります。希望する出力を周波数としてコンポーネントを生成します。
IPウィザードにあります。
そして、あなたはあなたが欲しい周波数を指定することができます:
係数=入力信号周波数/出力プリスケーラ周波数。
CE =クロックイネーブル。使用しない場合は、1クロック(clk)幅のパルスまたはハイにする必要があります。
Q =必要な周波数の1クロック幅パルスの出力信号。
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;