带计数器的无符号加法不起作用

Unsigned Addition with Counter Doesn't Work

我正在构建一个计数器,用于计算输入通道的上升沿。我简化了我的设计以包括两个状态,onetwo,其中完成计数。出于某种原因,每当我尝试将 1 添加到 counter_reg,或尝试为其分配任何数字时,信号在 ModelSim 中变为红色并带有 X。下面提供了信号发生情况的代码和图片。

我已经包含了 IEEE.NUMERIC_STD.ALL,所以我应该可以进行无符号加法。我不确定 counter_reg 有什么问题。我的柜台有什么问题吗?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity photon_counter is
    Port ( clk,reset : in STD_LOGIC;
           arm,shifter,channel : in STD_LOGIC;
           start : in STD_LOGIC);
end photon_counter;

architecture fsm_arch of photon_counter is
type state_type is (idle,zero,one);
type array_type is array (1 downto 0) of UNSIGNED (15 downto 0);
signal state_reg,state_next : state_type;
signal arm_prev,shifter_prev,channel_prev : STD_LOGIC;
signal counter : array_type;
signal counter_reg,counter_next : UNSIGNED (15 downto 0);
begin
--------------------------------------
--State Register
--------------------------------------
process(clk,reset)
begin
if reset='1' then
    state_reg <= zero;
    counter_reg <= (others => '0');
    counter <= (others => (others => '0'));
elsif rising_edge(clk) then
    state_reg <= state_next;
    counter_reg <= counter_next;
    arm_prev <= arm;
    shifter_prev <= shifter;
    channel_prev <= channel;
end if;
end process;
--------------------------------------
--Next-State Logic/Output Logic
--------------------------------------
process(clk,reset,state_reg,start,counter_reg,shifter_prev,shifter,arm,channel_prev,channel)
begin
--default actions
    state_next <= state_reg;
    counter_next <= counter_reg;
    counter_reg <= counter_reg;
    case state_reg is
        when idle =>
            counter_reg <= (others => '0');
            counter <= (others => (others => '0'));
            if start = '1' then
                state_next <= zero;
            end if;
        when zero =>
            if (shifter = '1') and (shifter_prev = '0') then
                state_next <= one;
                counter(0) <= counter_reg;
            end if;
            if (channel = '1') and (channel_prev = '0') then
                counter_next <= counter_reg + 1;
            end if;
        when one =>
            if arm = '1' then
                state_next <= zero;
                counter(1) <= counter_reg;
            end if;
            if (channel = '1') and (channel_prev = '0') then
                counter_reg <= counter_reg + 1;
            end if;
    end case;
end process;
end fsm_arch;

如下所示,counter_regcounter_next 从值 0 开始,直到我尝试将 1 添加到 counter_next。 channel_prev上升的瞬间,counter_regcounter_next都变成X(错误),变成红色。

您的 counter_reg 信号在两个不同的进程中分配。这就是我们所说的 "multiple drive" 情况。这通常是不可取的,就像任何短路一样,因为当两个进程不同意分配的值时,事情就会变得非常糟糕。

解决方案:从一个进程驱动您的计数器。

关于此的更多信息:如果这很糟糕,为什么在编译或启动模拟时没有出现错误?因为大多数人不了解也不关心VHDL中的unresolved/resolved类型。默认情况下,VHDL 类型是 unresolved。这意味着,如果您尝试从多个进程驱动这种类型的信号,您将在编译或细化时收到一个错误,基本上是 "I cannot decide what value to assign if your processes disagree, this is forbidden"。这是一个非常好的功能,因为这种意外短路会造成严重后果。您可以尝试此操作并通过将 unsigned(已解决)计数器替换为 natural(未解决)计数器来查看错误:

signal counter_reg,counter_next : natural 0 to 2**16 - 1;

调整其余代码,看看编译时会发生什么。

有时,从多个进程(高阻抗共享总线,bi-directional RAM 数据总线...)驱动信号很有用,因此 VHDL 允许定义一个分辨率函数来计算几个驱动程序的结果值。此函数可用于定义未解析 parent 类型的已解析子类型。如果您能找到 ieee.std_logic_1164 的源代码,您将看到未解析的 9 值 std_ulogic 类型(u 表示未解析)的声明、解析函数和已解决的子类型 std_logic(看到了吗?没有 u)。

但是在使用解析类型时,您必须自己注意不要创建short-circuits。不再有编译器错误,没有安全带。当您的一个驱动过程驱动一个强值(“0”或“1”)时,所有其他驱动过程必须驱动一个弱值('Z' 表示高阻抗)。否则,您将得到未知的结果值,如您所见,由 Modelsim 以红色表示。

不幸的是,大多数人并不真正知道 Ustd_Ulogic 中代表什么。因此,为了简化,他们总是使用 std_logic 而不是 应该 使用的 std_ulogic。此外,逻辑综合器的供应商也朝着相同的方向努力,因为他们经常偏爱 std_logic(当他们不只是强迫您使用它时)。标准化 ieee.numeric_std 包的人也做了同样的事情:他们将 unsignedsigned 类型声明为已解析类型(事实上,它们与 std_logic_vector 具有相同的声明) .这就像全速行驶,晚上戴着墨镜,没有灯光,没有系好安全带一样不幸。

最后,有人意识到这是多么不幸,ieee.numeric_std 的当前版本现在还声明了 UNRESOLVED_UNSIGNED(别名 U_UNSIGNED)和 UNRESOLVED_SIGNED(别名 U_SIGNED).唉,这有点太晚了,大多数设计师永远不会改变他们现有的代码或习惯,我想知道如果第一选择不同的话,可以避免多少错误。

我的建议:

  • 如果您真的不打算拥有多个物理驱动程序,请不要从多个进程驱动一个信号,手动避免短路等,
  • 如果不需要,请不要使用已解析的类型,这样,如果您不小心创建了多个驱动器情况,工具将引发错误,
  • 在您的情况下,从一个进程驱动 counter_reg,将其声明为 U_UNSIGNEDNATURAL,并将所有其他信号声明为 STD_ULOGIC,而不是 STD_LOGIC.