假设我的主板上有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)的频率是多少?
答案 0 :(得分:0)
时钟分频器有很多种。 如果您正在寻找高速时钟,例如在使用双数据速率(DDR)存储器时,您实际上想要使用FPGA的时钟管理器。例如。 Xilinx Digital Clock Manager (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;