2015-08-27 18 views
0

我正在构建一个计数器,用于统计输入通道的上升沿。我简化了我的设计,以包括两个状态,onetwo,其中计数完成。出于某种原因,无论何时我尝试将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_regcounter_next开始为0的值,直到我尝试加1 counter_next。当channel_prev上升时,counter_regcounter_next都变为X(错误)并变为红色。

ModelSim Waveform

+2

检查您在哪里分配问题的寄存器。如果您在多个流程中分配它,请不要!相反,在一个过程中保留所有的分配。 –

+1

'X'表示错误,不是未知('U')。你的信号'计数器'有2个驱动过程。第一个重置'counter',第二个过程为'counter'生成一个锁存器。 – Paebbels

+0

啊......愚蠢的错误。谢谢;修复它! –

回答

1

counter_reg信号被分配在两个不同的过程。这就是我们所说的“多驱动”情况。与任何短路一样,它通常是不受欢迎的,因为当两个过程对分配事物的价值意见不一致时变得非常糟糕。

解决方案:从一个单一过程驱动您的柜台。

更多关于此的信息:如果这样做不好,为什么编译时或启动模拟时没有出现错误?因为大多数人不知道或关心VHDL中的未解决/已解决的类型。默认情况下,VHDL类型为未解决。这意味着,如果您尝试从多个流程中驱动这种类型的信号,则在编译或阐述时会出现错误,基本上显示“如果您的流程不同意,我无法决定分配哪个值,这是被禁止的”。这是一个非常好的功能,因为这样的意外短路会产生严重的后果。你可以试试这个并通过一个natural(未解决)更换您unsigned(解决)专柜看到错误之一:

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

适应你的代码的其余部分,看看编译时会发生什么。

有时,很少有人会从多个进程中驱动一个信号(高阻抗共享总线,双向RAM数据总线...)。因此,VHDL允许定义一个分辨函数来计算结果值几个司机。该函数可用于定义未解析父类型的已解析子类型。如果您能找到​​的源代码,您将看到未解决的9值std_ulogic类型(未解决的u),解析函数以及已解析子类型std_logic的声明(请参阅?no u)的声明。

但是,当使用已解决的类型时,您自己必须注意不要造成短路。没有编译器错误,没有安全带。当你的一个驱动过程驱动一个强大的值('0'或'1')时,所有其他驱动过程必须驱动一个弱值('Z'为高阻抗)。否则,您将看到未知的结果值,由Modelsim以红色表示,如您所见。

不幸的是,大多数人并不真正知道U代表std_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