在VHDL中创建分频器

时间:2011-06-07 07:12:31

标签: vhdl intel-fpga

主要编辑:

阅读Will Dean的评论后,问题得以解决。原始问题低于修订后的代码:

-- REVISED CODE (NOW WORKS)
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

entity CLOCK_DIVIDER is
    port(
        reset   :   in std_logic;
        clk :   in std_logic;
        half_clk    :   out std_logic
        );
end CLOCK_DIVIDER;


architecture CLOCK_DIVIDER of CLOCK_DIVIDER is
signal tick : std_logic;

begin

    process(clk, reset)
    begin
        if reset = '1' then
            tick <= '0';
        elsif clk = '1' and clk'EVENT then
            if tick = '0' then
                tick <= '1';
            elsif tick = '1' then
                tick <= '0';
            end if;
        end if;
    end process;

    process(tick)
    begin
        half_clk <= tick;
    end process

end CLOCK_DIVIDER;

修改后的代码的合成逻辑块是单个异步复位DFF,它将half_clk作为输出,并将half_clk反转为输入,这意味着half_clk的值在clk的每个上升沿都会发生变化。

谢谢,Will Dean:)

==== ==== ==== ==== ====

以下原始问题:

==== ==== ==== ==== ====

我需要一个简单的时钟分频器(只是除以2)而不是使用模板,我想我会尝试自己编写一个以继续训练。

不幸的是,合成的逻辑块似乎不起作用 - 我按顺序呈现逻辑块和代码(我认为应该工作)。

logic block http://img808.imageshack.us/img808/3333/unledly.png

我真正想知道的是魔鬼是如何使用“滴答”DFF - 它显然是从多路复用选择器输入的......是的。是的。

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

entity CLOCK_DIVIDER is
    port(
        reset   :   in std_logic;
        clk :   in std_logic;
        half_clk    :   out std_logic
        );
end CLOCK_DIVIDER;


architecture CLOCK_DIVIDER of CLOCK_DIVIDER is
signal tick : std_logic;

begin
    process(clk, reset)
    begin
        if reset = '1' then
            half_clk <= '0';
            tick <= '0';
        elsif clk = '1' and clk'EVENT then
            if tick = '0' then
                half_clk <= '0';
                tick <= '1';
            elsif tick = '1' then
                half_clk <= '1';
                tick <= '0';
            end if;
        end if;
    end process;
end CLOCK_DIVIDER;

我确信代码中的错误是显而易见的,但我一直盯着自己试图找到它。

4 个答案:

答案 0 :(得分:3)

如果halfclk用作启用而不是真正的时钟,请忽略此建议......

如果这是针对FPGA目标而且“half_clk”实际上被用作时钟(例如,转到DFF上的时钟引脚,而不是使能引脚)...... 不要这样做< / em>的

使用通用FPGA逻辑/ fabic创建派生时钟将导致构建工具出现问题,最终可能导致构建失败(无法满足时序),或构建因行为不正确而无法正常传递的构建所有时钟网络。

而是使用内置于FPGA架构中的时钟管理块,尤其是为此目的。在Xilinx器件领域,这些器件称为数字时钟管理器(DCM)或混合模式时钟管理器(MMCM)。我不确定等效的Altera组件是什么。阅读文档以确定最适合您的应用程序。

答案 1 :(得分:1)

根据您修改后的代码,我对架构提供了以下修改:

-- REVISED CODE (NOW WORKS) and simplified and synthesisable
architecture CLOCK_DIVIDER of CLOCK_DIVIDER is
    signal tick : std_logic;
begin
    process(clk, reset)
    begin
        if reset = '1' then
            tick <= '0';
        elsif rising_edge(clk) then -- use of rising_edge() is the correct idiom these days
            tick <= not tick;
        end if;
    end process;

    half_clk <= tick;
end CLOCK_DIVIDER;

我删除了此过程并替换为并发分配:

    process(tick)
    begin
        half_clk <= tick;
    end process

正如所要求的那样是在tick的两个边缘都有一个触发器。

这似乎可以实现您想要的波形摆动,但不会合成。它还会为输出增加额外的增量延迟,如果您将其用作“即时”时钟,则可能会或可能不会导致问题。正如其他人所评论的那样,在大多数架构中,这不是一个好的计划(但有些人认为这是“正确的方式”)。

答案 2 :(得分:0)

你确定你在启动时重置了吗?你定义了tick的条件的方式,如果tick不是零或一个(即:它可能是U,Z,X等),任何事情都不会发生。

我通常建议用条件表达式覆盖所有案例,即:

        if tick = '0' then
            half_clk <= '0';
            tick <= '1';
        else 
            half_clk <= '1';
            tick <= '0';
        end if;

        if tick = '0' then
            half_clk <= '0';
            tick <= '1';
        elsif tick = '1' then
            half_clk <= '1';
            tick <= '0';
        else
            -- Throw error or something here
        end if;

答案 3 :(得分:0)

一个简单的计数器可以解决问题(当然是正确的DCM):

signal cnt : std_logic_vector(3 downto 0);

...

clk_div_2  <= cnt(0);
clk_div_4  <= cnt(1);
clk_div_8  <= cnt(2);
clk_div_16 <= cnt(3);

...

process(clk)
 if clk'event and clk = '1' then
  cnt <= cnt + 1;
 end if;
end process;