在 VHDL 中创建分频器

发布于 2024-11-14 01:12:11 字数 2144 浏览 2 评论 0原文

主要编辑:

阅读威尔·迪恩的评论后问题得到解决。原来的问题在修改后的代码下面:

-- 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的每个上升沿发生变化。

谢谢,威尔·迪恩:)

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

原问题如下:

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

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

不幸的是,合成的逻辑块似乎不起作用 - 我按顺序展示了逻辑块和代码(我确实认为应该起作用)。

逻辑块http://img808.imageshack.us/img808/3333/unledly.png< /a>

我真正想知道的是“tick”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;

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

MAJOR EDIT:

Problem was solved after reading Will Dean's comment. The original question is below the revised code:

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

The synthesized logic block of the revised code is a single asynchronous-reset DFF that takes half_clk as output and inverted half_clk as input, which means the value of half_clk changes on every rising edge of clk.

Thanks, Will Dean :)

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

Original question below:

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

I need a simple clock divider (just divide-by-two) and instead of usinga template, I thought I'd try to write one myself to keep in training.

Unfortunately, the synthesized logic block does not appear to work - I present the logic block and the code (which I really think ought to work), in that order.

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

What I'm really wondering is what the devil is up with the "tick" DFF - it apparently takes its input from the mux-selector which is... Yeah.

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;

I'm sure the error in the code is obvious but I've been staring myself blind trying to find it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

依 靠 2024-11-21 01:12:11

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

如果这是针对 FPGA 目标并且“half_clk”确实用作时钟(例如,将DFF 上的时钟引脚,而不是使能引脚)...不要这样做

使用通用 FPGA 逻辑/结构创建派生时钟将导致构建工具出现问题,并最终导致构建失败(无法满足时序要求),或者由于约束未正确传递到所有时钟网络而导致构建不按预期运行。

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

If halfclk is to be used as an enable and not a true clock, disregard this advice...

If this is for an FPGA target and "half_clk" is really being used as a clock (e.g. going to the clock pin on a DFF, and not the enable pin)... Don't do this.

Creating derived clocks using general FPGA logic/fabic will lead to problems with build tools, and can eventually lead to failed builds (won't meet timing), or builds that do not behave as expected because constraints not correctly passed through to all clock networks.

Instead use clock management blocks that are built into FPGA fabric especially for this purpose. In the world of Xilinx parts, these are called Digital Clock Managers (DCM) or Mixed Mode Clock Manager (MMCM). I am not sure what the equivalent Altera component is. Read up on the documentation to determine the best use for your application.

相权↑美人 2024-11-21 01:12:11

根据您修改后的代码,我对架构进行了修改:

-- 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 的两个边缘上计时的触发器。

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

Based on your revised code, I offer this modification to the architecture:

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

I've removed this process and replaced with a concurrent assignment:

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

as what this is asking for is a flipflop clocked on both edges of tick.

This will appear to achieve what you want in terms of the waveforms wiggling the way you want them to, but will not synthesise. It also adds an extra delta delay to the output which may or may not cause problems if you use it as a clock "down the road". As others have commented, this is not a good plan anyway in most architectures (but for some it is "the right way").

桃扇骨 2024-11-21 01:12:11

您确定要在启动时重置吗?按照您定义的刻度条件的方式,如果刻度不是零或一(即:它可能是 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;

Are you sure you're resetting at startup? The way you've got your conditional for tick defined, nothing will happen if tick isn't zero or one (ie: it could be U, Z, X, etc).

I generally suggest covering all cases with your conditional expressions, ie:

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

or

        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;
浪荡不羁 2024-11-21 01:12:11

一个简单的计数器就可以解决问题(正确的方法当然是 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;

A simple counter does the trick (proper way is DCM of course):

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文