3

我正在尝试将 50MHz 时钟降低到 25.175MHz,以便在 VGA 控制器中使用。我已经有一个时钟分频器,但是当当前时钟速度和所需时钟速度的结果分频不是整数时,我很难减慢时钟速度。即 50000000/25175000 ~ 1.98。时钟分频器编译并运行,但如果分频是十进制数,则不输出任何内容。这是我的代码:

    LIBRARY IEEE;
    USE  IEEE.STD_LOGIC_1164.ALL;

    ENTITY Clockdiv IS PORT (
        Clkin: IN STD_LOGIC;
        Clk: OUT STD_LOGIC);
    END Clockdiv;

    ARCHITECTURE Behavior OF Clockdiv IS
        CONSTANT max: INTEGER := 50000000/25175000;
        CONSTANT half: INTEGER := max/2;
        SIGNAL count: INTEGER RANGE 0 TO max;
    BEGIN
        PROCESS
        BEGIN
            WAIT UNTIL Clkin'EVENT and Clkin = '1';

            IF count < max THEN
                count <= count + 1;
            ELSE
                count <= 0;
            END IF;

            IF count < half THEN
                Clk <= '0';
            ELSE
                Clk <= '1';
            END IF;
        END PROCESS;
    END Behavior;

我在 google 上搜索,发现使用 REAL 数据类型将允许您使用小数,但是当我将我使用的变量更改为 REAL 时,Quartus 给了我错误:Error (10414): VHDL Unsupported Feature error at Clockdiv.vhd(12): cannot synthesize non-constant real objects or values.

然后,如果我将“计数”更改为一种CONSTANT类型,我会收到错误:Error (10477): VHDL error at Clockdiv.vhd(18): name "count" must represent signal.

有谁知道我怎样才能把时钟减慢到 25.175MHz?另外,有没有人知道如何减慢时钟,以便编译器对得到的除法是十进制值感到满意?

谢谢

4

2 回答 2

4

一般来说,实数是不可综合的,因此您需要提出一个基于整数的解决方案。

这个比例相当棘手,因为它几乎是 2:1,但并不完全。大多数基于边沿的时钟分频器电路仅在原始时钟的一个边沿上工作,因此您可以分频的最低比率是 2。在这种情况下,您必须在时钟的两个边沿上工作。

一旦你得到了,你需要有一个计数器,它以你的比率的分母递增,它是否超过了分子,然后输出一个时钟边沿。

PROCESS
    BEGIN
        WAIT UNTIL Clkin'EVENT;

        IF count < max THEN
            count <= count + DENOMINATOR;
        ELSE
            count <= 0;
        END IF;

        IF count > NOMINATOR THEN
            Clk <= ~Clk;
        END IF;
    END PROCESS;

对于这个比率,我认为您可以表示它的最小方式是 2000/1007。

这样做的问题是你会得到一个基本上是 25MHz 的时钟,但偶尔(每 2000 / 7 次迭代)你会得到一个额外的优势。它不会是 25.175MHz 时钟。如果没有 PLL,就不可能从 50MHz 获得 25.175MHz。

于 2012-06-18T14:43:11.677 回答
2

我写了很多 VGA 控制器,只使用 25 MHz 时钟从来都不是什么大问题。但是,如果您绝对想靠近,您的 FPGA 可能有某种时钟管理器(我只熟悉 Xilinx 设备),它允许您通过乘法和除法输入时钟来合成输出时钟。

此外,虽然在这种情况下使用派生/门控时钟(您直接在进程中设置值的时钟)可能对您有用,但它可能会导致许多难以调试的问题。更好的解决方案是生成时钟使能,然后在同一(快速)时钟上运行所有内容。

最后一件事,虽然这可能是首选风格的问题,但我通常使用时钟进程语句而不是WAIT语句(如下所示,上升沿触发、同步复位和时钟启用)。我发现它更易于阅读和理解,并且不太容易编写不可综合的构造,例如, 或带有多个s 的wait for 10ns;语句。WAIT

process(clk)
begin
    if(rising_edge(clk)) then
        if(sync_reset = '1') then
            --Reset logic
        elsif(clk_enable = '1') then
            --Actual functionality
        end if;
    end if;
end process;
于 2012-06-18T19:27:21.837 回答