如何找到时钟分频器的频率?



假设我的板上有一个 100Mhz 时钟和以下时钟分频器:

entity div is
port(clk:in std_logic;
clk_out:out std_logic);

architecture ar of div is
begin
process(clk)
variable aux:integer := 0;
variable aux2:std_logic := '0';
begin
if clk = '1' and clk'event then
aux := aux + 1;
if aux = 1600500 and aux2='0' then
aux = 0;
aux2 = 1;
end if;


if aux = 1600500 and aux2 ='1' then
aux = 0;
aux2 = 1;
end if;
end if;
clk_out <= aux2;
end process;
end;

新时钟的频率是多少(clk_out( ?

时钟分频器有多种形式。 如果您正在寻找高速时钟,例如在使用双数据速率(DDR(存储器时,您实际上希望使用FPGA的时钟管理器。例如赛灵思数字时钟管理器 (DCM(。它们提供非常稳定的边沿同步时钟输出。

对于低速时钟,您可以使用建议的分频器。但是,这些也有多种口味。如果除法比是整数,则可以像使用简单计数器一样使用简单计数器。对于下一个示例,时钟分频器将始终将输入频率除以 2(例如 50 MHz-> 25 MHz(,然后进一步除以设置的比率(例如 25/3 = 8 1/3 MHz(

library ieee;
use ieee.std_logic_1164.all;
entity simp_clk_div is
generic(
half_clk_div_ratio  : positive);
port(
input_clk  : in  std_logic;
output_clk : out std_logic);
end entity;
architecture rtl of simp_clk_div is
constant clk_div_cnt : natural := half_clk_div_ratio - 1;
signal cnt : natural := clk_div_cnt;
signal output_clk_i :  std_logic := '0';
begin
divide : process(input_clk) begin
if rising_edge(input_clk) then
if cnt = 0 then
cnt <= clk_div_cnt;
output_clk_i <= not output_clk_i;
else
cnt <= cnt - 1;
end if;
end if;
end process;
output_clk <= output_clk_i;
end architecture;
entity simp_clk_div_tb is end entity;
library ieee;
architecture behavior of simp_clk_div_tb is
use ieee.std_logic_1164.all;
signal input_clk, output_clk : std_logic;
begin
DUT : entity work.simp_clk_div
generic map(
clk_div_ratio => 3) 
port map(
input_clk => input_clk,
output_clk => output_clk);
clk_stim : process begin
input_clk <= '0', '1' after 1 ns;
wait for 2 ns;
if (now > 200 ns) then wait; end if;
end process;
end architecture;

如果您想要更多的自由,例如将 50MHz 转换为 3 MHz,您可以使用小数时钟分频器。但是,此组件需要更多的资源。此外,时钟输出上有很多抖动,以不等长的时钟脉冲的形式出现。但对于低速时钟来说,这通常不是一个大问题。

library ieee;
use ieee.std_logic_1164.all;
entity frac_clk_div is
generic(
input_freq  : positive;
output_freq : positive);
port(
input_clk  : in  std_logic;
output_clk : out std_logic);
end entity;
architecture rtl of frac_clk_div is
constant cnt_sub : positive := output_freq*2;
signal cnt : natural := input_freq;
signal output_clk_i :  std_logic := '0';
begin
divide : process(input_clk) begin
if rising_edge(input_clk) then
if cnt < cnt_sub then
cnt <= input_freq - (cnt_sub - cnt);
output_clk_i <= not output_clk_i;
else
cnt <= cnt - cnt_sub;
end if;
end if;
end process;
output_clk <= output_clk_i;
end architecture;
entity frac_clk_div_tb is end entity;
library ieee;
architecture behavior of frac_clk_div_tb is
use ieee.std_logic_1164.all;
signal input_clk, output_clk : std_logic;
begin
DUT : entity work.frac_clk_div
generic map(
input_freq => 50_000_000,
output_freq => 3_000_000)
port map(
input_clk => input_clk,
output_clk => output_clk);
clk_stim : process begin
input_clk <= '0', '1' after 1 ns;
wait for 2 ns;
if (now > 200 ns) then wait; end if;
end process;
end architecture;

最新更新