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

时间:2018-05-08 21:57:42

标签: vhdl clock active-hdl

假设我的主板上有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)的频率是多少?

1 个答案:

答案 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;