VHDL中具有比较匹配和负载的同步计数器

时间:2018-09-24 11:39:54

标签: logic vhdl counter fpga

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

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_value 信号分配负载值。每当负载信号为高并且检测到上升沿时,计数器值都会更新为 load_value

另一个功能是比较单元,它在 compare_match 输出上输出高电平。仿真工作符合预期,但在spartan 3 fpga上合成此设计时,我有几个问题。

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

1 个答案:

答案 0 :(得分:1)

在我看来,一般而言,这是一个很好的描述。 但是,我想指出一些小问题(可能会让我对您的第一个问题有一些答案)。

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

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

关于比较本身,您描述它的方式绝对是正确的,并且您将不会发现状态。基本上,您已经指定了所有可能的条件,所以在那里没有任何惊喜。

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

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