2017-04-08 31 views
0

大家好,我最近開始使用VHDL編寫代碼(這裏的代碼是T觸發器),而且我有一個錯誤提示「進程時鐘過於複雜」,這是第一個代碼附在下面,令人驚訝的是我的解決方案太。但我不知道它是如何工作的,代碼沒有錯誤是第二個代碼。我搜索了半個小時的錯誤,但找不到滿意的原因。請幫忙。VHDL錯誤「過程時鐘過於複雜。」

首先代碼:

LIBRARY ieee; 
USE ieee.std_logic_1164.all; 

ENTITY t_ff IS 
    PORT(t,clk,rst:IN STD_LOGIC; 
     q,q_bar:OUT STD_LOGIC); 
END t_ff; 

ARCHITECTURE t_ff OF t_ff IS 
SIGNAL temp: STD_LOGIC; 
BEGIN 
    PROCESS(clk,rst) 
    BEGIN 
     IF(clk='1' AND clk'event)THEN 
      IF(t='1')THEN temp<= NOT temp; 
      END IF; 
     ELSIF(rst='1')THEN temp<='0'; 
     END IF; 
     q<= temp; 
     q_bar<= NOT temp; 
    END PROCESS; 
END t_ff; 

二碼:

LIBRARY ieee; 
USE ieee.std_logic_1164.all; 

ENTITY t_ff IS 
    PORT(t,clk,rst:IN STD_LOGIC; 
     q,q_bar:OUT STD_LOGIC); 
END t_ff; 

ARCHITECTURE t_ff OF t_ff IS 
SIGNAL temp: STD_LOGIC; 
BEGIN 
    PROCESS(clk,rst) 
    BEGIN 
     IF(rst='1')THEN temp<='0'; 
     ELSIF(clk='1' AND clk'event)THEN 
      IF(t='1')THEN temp<= NOT temp; 
      END IF; 
     END IF; 
     q<= temp; 
     q_bar<= NOT temp; 
    END PROCESS; 
END t_ff; 

回答

1

的原因很簡單。但首先我們需要更改代碼:

這兩個版本都沒有描述T觸發器的行爲;都描述了至少2個,即使不是3個觸發器的行爲。這是因爲

在時鐘過程中的每個信號分配推斷觸發器

有每個進程3個信號分配 - 對tempqq_bar - 所以你會得到3倒裝觸發器(儘管1是多餘的,所以可以通過合成器進行優化)。所以,首先,如果你想保證你只有一個觸發器,你需要重寫每個進程,以便其中只包含一個信號分配。

重寫第一個過程沒有意義,因爲其他原因是錯誤的 - 稍後會看到。第二個過程應該重寫這樣的事:

PROCESS(clk,rst) 
BEGIN 
    IF (rst='1') THEN temp<='0'; 
    ELSIF (clk='1' AND clk'event) THEN 
     IF (t='1') THEN temp <= NOT temp; 
     END IF; 
    END IF; 
END PROCESS; 

q <= temp; 
q_bar <= NOT temp; 

換句話說,你需要將任務移動到qq_bar過程之外。第二版本的這個新版本描述了具有異步復位的T型觸發器的行爲:

如果復位被置位然後復位觸發器;否則,如果T 輸入是在時鐘的上升沿有效,則反轉 觸發器

如果我重寫你的第一個版本,它會描述並不一些電子元件的行爲存在,所以它不能被合成。不存在這樣的觸發器與此行爲:

如果T 輸入在時鐘的上升沿置位,則反轉 觸發器;否則,如果復位被斷言然後復位觸發器

你可以已經描述爲T型觸發器與同步復位:

在時鐘的上升沿:如果復位被斷言然後復位 觸發器,否則,如果T輸入在時鐘的上升邊緣 斷言,則反轉觸發器

這樣

PROCESS(clk) 
BEGIN 
    IF (clk='1' AND clk'event) THEN 
     IF (rst='1') THEN temp<='0'; 
     ELSIF (t='1') THEN temp <= NOT temp; 
     END IF; 
    END IF; 
END PROCESS; 

q <= temp; 
q_bar <= NOT temp; 

最後,你正在使用一種相當老式的編碼風格。我會建議使用rising_edge函數。你的括號也是多餘的。一個經驗豐富的VHDL代碼會寫這樣的第二個版本:

PROCESS(clk,rst) 
BEGIN 
    IF rst='1' THEN temp<='0'; 
    ELSIF rising_edge(clk) THEN 
     IF t='1' THEN temp<= NOT temp; 
     END IF; 
    END IF; 
END PROCESS;  

q <= temp; 
q_bar <= NOT temp; 
+0

我有4點,我不清楚。 1在第一個代碼中,你寫了'q <= q',所以我需要將它定義爲INOUT。 2爲什麼我不能寫'clk ='1'和clk'event'是因爲硬件(FPGA)缺乏這種能力。 3我怎麼知道我在設計中使用了多少觸發器?我正在使用Altera Max + plus II。 4爲什麼我不能寫異步。檢查t輸入後復位。 – rockingsharma

+0

@rockingsharma 1)使用vhdl2008設置,因爲這支持輸出讀數,否則你應該使用臨時中間信號。 2)'rising_edge(clk)'更好。 3)你的綜合工具應該報告這一點。你應該切換到quartus II。 4)你不能在'如果rising_edge(clk)''後面使用'elsif',那只是糟糕的代碼結構。 – JHBonarius

+0

@rockingsharma 1)你是對的(除非你用J.H.Bonarius說的VHDL 2008)。假設你不是,我已經重寫了我的答案。您需要將分配移至過程中的'q'和'q_bar'。 2&3)見上面4)我回答了上面的問題。如果你寫的是在時鐘上升沿測試後異步復位,那麼你正在模擬一個不存在的觸發器的行爲。真正的觸發器的異步復位輸入具有優先權:如果您在復位時持有一個實際的觸發器,則其輸出在復位時保持不變。結束。如果你沒有重置它,你只能計時。 –