我正在构建一个计数器来计算输入通道的上升沿。我已将设计简化为包括两个状态one
和two
,其中计数已完成。出于某种原因,每当我尝试向counter_reg
添加1,或者尝试为其分配任何数字时,信号在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_reg
和counter_next
以值0开始,直到我尝试向counter_next添加1。当channel_prev
上升时,counter_reg
和counter_next
都会变为X(错误)并变为红色。
答案 0 :(得分:1)
您的counter_reg
信号分配在两个不同的进程中。这就是我们所谓的“多驱动”情况。它通常是不受欢迎的,就像任何短路一样,因为当两个过程不同意分配事物的价值时会变得非常糟糕。
解决方案:从单一过程中驱动您的计数器。
更多关于这一点:如果这很糟糕,为什么在编译或启动模拟时没有出错?因为大多数人不了解或不关心VHDL中的未解析/已解决类型。默认情况下,VHDL类型为未解析。这意味着,如果您尝试从多个进程中驱动此类型的信号,您将在编译或精化时出现错误,基本上说“如果您的进程不同意,我无法决定分配什么值,这是禁止的”。这是一个非常好的功能,因为这种意外短路会产生严重后果。您可以尝试使用unsigned
(已解决的)计数器替换natural
(已解决)的计数器来查看错误:
signal counter_reg,counter_next : natural 0 to 2**16 - 1;
调整其余代码,看看编译时会发生什么。
有时,很少,从多个进程(高阻抗共享总线,双向RAM数据总线......)驱动信号非常有用。因此VHDL允许定义一个分辨率函数来计算几个结果值驱动程序。此函数可用于定义未解析父类型的已解析子类型。如果您能找到ieee.std_logic_1164
的源代码,您将看到未解析的9值std_ulogic
类型(未解析的u
)的声明,解析函数和声明已解决的子类型std_logic
(请参阅?no u
)。
但是当使用已解决的类型时,必须自己负责不要创建短路。没有编译器错误,没有安全带。当您的一个驱动过程驱动一个强值('0'或'1')时,所有其他驱动过程必须驱动一个弱值('Z'表示高阻抗)。否则,您将得到未知的结果值,如您所见,由Modelsim以红色表示。
不幸的是,大多数人并不真正知道U
代表的std_Ulogic
代表什么。因此,为了简化起见,他们始终使用std_logic
而不是应使用的内容:std_ulogic
。此外,逻辑合成器的供应商也在朝着同一个方向努力,因为他们经常支持std_logic
(当他们不仅仅强迫你使用它时)。标准化ieee.numeric_std
包的人也这样做:他们将unsigned
和signed
类型声明为已解析类型(如果事实,它们与std_logic_vector
具有相同的声明) 。这与夜间驾驶全速,佩戴太阳镜,没有灯光以及没有系安全带的情况一样令人遗憾。
最后,有人意识到这是多么不幸,当前版本的ieee.numeric_std
现在也声明了UNRESOLVED_UNSIGNED(别名为U_UNSIGNED)和UNRESOLVED_SIGNED(别名为U_SIGNED)。唉,这有点太晚了,大多数设计师永远不会改变他们现有的代码或习惯,我想知道如果第一选择有所不同,可以避免多少错误。
我的建议:
counter_reg
,将其声明为U_UNSIGNED
或NATURAL
,并将所有其他信号声明为STD_ULOGIC
,而不是{{1 }}。