2013-11-09 36 views
3

我對VHDL(以及一般的數字電路)相當陌生,我試圖用BCD樣式塊實現兩位數的計數器。在這個電路外部會出現一些按鈕,當按下按鈕時,會將感興趣的數字加1(就像鬧鐘一樣)。這是一個異步操作,並且會在某種形式的編輯模式(外部強制執行)下發生。我寫的代碼工作正常,沒有「elsif rising_edge(digitUp1)然後」和「elsif rising_edge(digitUp1)然後」塊,但是失敗並且包含它們。我真的不知道爲什麼它不起作用或我如何解決它。請繼續收到錯誤,如「無法在此時鐘邊沿實現寄存器分配」,「無法爲count2 [3]推斷寄存器,因爲它的行爲取決於多個不同時鐘的邊沿」和「無法推斷寄存器」在MinuteCounter.vhd(21)處計數[count2 [3]「,因爲它不在時鐘邊緣外保持其值。任何幫助將不勝感激。VHDL:一個進程塊內的多個rising_edge檢測

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.std_logic_signed.all; 

-- ToDo: ENFORCE ON ALL COUNTERS (externally) LOGIC TO PAUSE AT MAX/MIN 

entity MinuteCounter is 
port(clockIn, digitUp1, digitUp2, reset, counting, countUp : in std_logic; 
     clockOut : out std_logic; 
     BCD1, BCD2 : out std_logic_vector(3 downto 0)); 
end MinuteCounter; 

architecture structure of MinuteCounter is 
signal count1, count2 : std_logic_vector(3 downto 0); 
signal carryOut : std_logic; 
begin 

process(clockIn, digitUp1, digitUp2, countUp, reset, counting) 
begin 

    -- Asynchronous reset 
    if reset = '1' then 
     count1 <= "0000"; 
     count2 <= "0000"; 

    -- What to run when there's an active edge of the clock 
    elsif rising_edge(clockIn) then 

     -- Code to run when timer is running 
     if counting = '1' then 

      -- What to do when counting up 
      if countUp = '1' then 
       if ((count1 = "1001") and (count2 = "0101")) then 
        count1 <= "0000"; 
        count2 <= "0000"; 
        if carryOut = '0' then 
         carryOut <= '1'; 
        else 
         carryOut <= '0'; 
        end if; 
       elsif count1 = "1001" then 
        count1 <= "0000"; 
        count2 <= count2 + 1; 
       else 
        count1 <= count1 + 1; 
       end if; 

      -- What to do when counting down (This logic is hard to understand) 
      else 
       if ((count1 = "0000") and (count2 = "0000")) then 
        count1 <= "1001"; 
        count2 <= "0101"; 
        if carryOut = '0' then 
         carryOut <= '1'; 
        else 
         carryOut <= '0'; 
        end if; 
       elsif count1 = "0000" then 
        count1 <= "1001"; 
        count2 <= count2 - 1; 
       else 
        count1 <= count1 - 1; 
       end if; 
      end if; 

     -- When counting is disabled, but there is an active edge (do nothing) 
     else 
      count1 <= count1; 
      count2 <= count2; 
     end if; 

    -- Code to run when entering values (will not be run if counting = '1') << Externally enforced 
    elsif rising_edge(digitUp1) then 
     if count1 = "1001" then 
      count1 <= "0000"; 
      count1 <= count1 + 1; 
     else 
      count1 <= count1 + 1; 
     end if; 

    -- Code to run when entering values (will not be run if counting = '1') << Externally enforced 
    elsif rising_edge(digitUp2) then 
     if count2 = "0101" then 
      count2 <= "0000"; 
      count2 <= count2 + 1; 
     else 
      count2 <= count2 + 1; 
     end if; 

    -- What to do when there is no active edge or other events (nothing) 
    else 
     count1 <= count1; 
     count2 <= count2; 
    end if; 

end process; 

-- Assign outputs 
BCD1 <= count1; 
BCD2 <= count2; 
clockOut <= carryOut; 

end structure; 

回答

8

的「爲什麼它不工作」是在問題的標題解釋:程序塊內多rising_edge檢測。

VHDL旨在描述硬件,並且沒有響應多個時鐘信號的基本電路元件。所以你不能用這種方式來描述電路。

那麼你如何解決它?

您可以將電路轉換爲任意一個進程只有一個時鐘信號(並且可以選擇正確使用一個異步復位信號)的電路。這可以使用真實寄存器和觸發器來實現。

兩種方式是:

  1. 幾個過程,使用信號A單一過程他們
  2. 之間進行通信,與單個時鐘,採樣在主時鐘邊緣的其它信號。

這些之間的正確決定需要一些設計的整體知識。

這裏聽起來好像所有三個時鐘信號實際上是按鈕按下,而不是一個快速時鐘。因此,您不能保證在按下另一個按鈕時會有時鐘邊沿。

所以這裏有很多方法之一:使一個時鐘信號(過程之外),它將涵蓋所有三個輸入事件。現在

my_clock <= clockIn or digitUp1 or digitUp2; 

您可以使用該時鐘重寫過程:

process(my_clock, reset) is 
begin 
    if reset = '1' then 
     -- reset actions 
    elsif rising_edge(my_clock) then 
     -- what caused this event? 
     if digitUp1 = '1' then  -- bump digit 1 
     elsif digitup2 = '1' then -- bump digit 2 
     else      -- count normally 
     endif; 
    end if; 
end process; 

注:

  1. 由於這是一個正確的同步過程,只有時鐘和復位屬於在敏感列表。
  2. 儘管這可以起作用,但它可能不是客戶想要的:例如,如果他按住全部三個按鈕,會發生什麼情況?您可能想要探索其他設計方法。
+0

從開關製造時鐘充滿了潛在的災難,當多個邊緣切換時彈跳:) –

+0

@Martin:的確如此,但那是另一回事!當然值得警惕。 –