2015-08-27 22 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