首页 > 解决方案 > 具有比较匹配和加载的 VHDL 中的同步计数器

问题描述

我创建了以下具有比较匹配功能的计数器:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity Counter is
    generic (
        N : natural := 24
    );

    port (
        -- Input counter clock
        clk                 : in std_logic := '0';
        -- Enable the counter
        enable              : in std_logic := '0';
        -- Preload value loaded when clk is rising and load is 1
        load_value          : in std_logic_vector((N-1) downto 0) := (others => '0');
        -- Set to 1 to load a value
        load                : in std_logic := '0';
        -- Compare match input is compared with the counter value
        compare_match_value : in std_logic_vector((N-1) downto 0) := (others => '0');
        -- Is 1 when compare_match_value = counter_value
        compare_match       : out std_logic := '0';
        output_value        : out std_logic_vector((N-1) downto 0) := (others => '0') 
    );
end Counter;

architecture Behavioral of Counter is
    signal counter_value      : unsigned((N - 1) downto 0) := to_unsigned(0, N);
begin
    output_value <= std_logic_vector(counter_value);

    process (clk) is 
    begin 
        if rising_edge(clk) then
            if enable = '1' then
                if load = '1' then
                    counter_value <= unsigned(load_value);
                else 
                    counter_value <= counter_value + 1;
                end if;
            else 
                if load = '1' then 
                    counter_value <= unsigned(load_value);
                end if;
            end if;
        end if;
    end process;

    process (counter_value) is
    begin 
        if unsigned(compare_match_value) = counter_value then 
            compare_match <= '1';
        else
            compare_match <= '0';
        end if;
    end process;
end Behavioral;

我的计数器的行为是与输入clk信号完全同步。始终可以禁用计数器,并且该值保持在当前计数值。可以使用 load 和load_value信号分配负载值。每当负载信号为高且检测到上升沿时,计数器值都会更新为load_value

另一个特性是比较单元,它在compare_match输出上输出高电平。模拟按预期工作,但在 spartan 3 fpga 上综合此设计时我有几个问题。

  1. 这是否被认为是我的计数器的好设计,因为我在 VHDL 方面仍然没有太多经验。
  2. 在我的设计中在进一步的逻辑中使用比较单元时是否有任何未定义的状态?正如我所看到的,每当更新counter_value时都会计算 compare_match 。
  3. 当对 N 使用较大的数字时,我需要考虑的延迟有什么特别之处吗?

标签: logicvhdlcounterfpga

解决方案


总的来说,在我看来这是一个很好的描述。但是,我想指出一些小事(这可能是我对您的第一个问题的一些答案)。

1)因为,我现在看到您的计数器不包含任何重置(既不异步也不同步)。一般来说,您无法预测计数的起点(即使在启动时可能全为 0)。在我看来,如果你能有一个复位信号,那将是一个更简洁的设计。我还注意到,无论计数器是否启用,加载都会被激活。我对此没有评论,因为它可能是您设计的规范。也许您可以通过将“if load”部分移到“if enable”之外(即更改比较的顺序)来压缩代码。为了提高可读性(特别是当设计更复杂时),我建议您标记该过程。这将帮助您识别设计的不同部分。如果您使用 emacs 的 VHDL 模式,您可以跳过很多额外的输入。它内置了模板,可以处理与编码相关的“无聊”部分。我还看到您的输入端口具有默认值。在我看来,这不是一个很好的做法。它们会被合成器忽略,导致 IP 的行为可能与您的预期不同。一般来说,不要对外部信号做出假设(部分是指定的)。最后,我对比较部分发表评论。这适用于问题 1) 和 2) 它们会被合成器忽略,导致 IP 的行为可能与您的预期不同。一般来说,不要对外部信号做出假设(部分是指定的)。最后,我对比较部分发表评论。这适用于问题 1) 和 2) 它们会被合成器忽略,导致 IP 的行为可能与您的预期不同。一般来说,不要对外部信号做出假设(部分是指定的)。最后,我对比较部分发表评论。这适用于问题 1) 和 2)

1-2) 在比较过程中,您刚刚在敏感度列表中列出了 counter_value。这意味着当 counter_value 更改时才会激活该进程。由于您将它与作为块输入的信号 (compare_match_value) 进行比较(因此它可以更改值),因此最好将它也包含在灵敏度列表中。否则,当您更改 compare_match_value 时,比较将不适用(即进程不会被激活)。Linting 工具和合成器可能会抱怨它(声明警告,如不完整的敏感度列表)。事实上,在组合过程的列表中列出所有可能发生变化的信号是一种很好的做法。

关于比较本身,您描述它的方式绝对没问题,您不会发现状态。基本上你已经指定了所有可能的条件,所以没有惊喜。

3)关于你的第三个问题,因为你的目标是FPGA,你可以“放松”它。FPGA 具有用于快速算术运算的专用结构,并且(只要您不使用所有它们)合成器将使用它们来关闭时间。同样在 ASIC 中,合成器可能会选择适当的算术结构来关闭时间。如果您想安全起见,可以在比较块的输出处添加一个寄存器。这将防止创建一个长的组合路径,特别是如果您的 IP 必须与其他块集成。当然,这个额外的寄存器会增加 1 个时钟周期的延迟,但它会改善你的整体时序。

我希望这些建议对您有用,并(至少部分)覆盖您的疑虑。继续编码:)


推荐阅读