2017-07-29 61 views
2

我是一名軟件工程師(JAVA/C++),而不是電氣工程師,所以你可以想象VHDL對我來說是徹底的困惑,因爲我不知道什麼是合成器正試圖在幕後做。它告訴我,它無法綜合我認爲是一個非常簡單的架構。 (實際上它是爲我的幾個實體做的,所以我懷疑我誤解了一些基本概念,並在多個地方重複了架構錯誤。)這是爲什麼不能合成? (在NOT(時鐘邊沿)不保留它的值)

爲什麼不能合成... (ERROR - controller.vhd( 63):語句不是合成的,因爲它不 NOT(時鐘邊緣)的條件下保持其價值VHDL-1242 完成:錯誤代碼2)

LIBRARY ieee; 
USE ieee.std_logic_1164.all; 

ENTITY controller IS 
    PORT (
     ack: out STD_LOGIC := '0'; 
     data_request: in STD_LOGIC 
    ); 
END controller; 

ARCHITECTURE logic OF controller IS 
BEGIN 
    PROCESS (data_request) 
    BEGIN 
     if (rising_edge(data_request)) then 
      -- other logic will be added here 
      ack <= '1'; 
     elsif (falling_edge(data_request)) then 
      -- other logic will be added here too 
      ack<='0'; 
     end if; 
    END PROCESS; 
END logic; 

(是的,我完全知道,該過程的「邏輯」可以由 ack < = data_request替代;但是我的vhdl源實際上比t更復雜他的 ,但我已經將其歸結爲引發錯誤的最簡單的子集。請不要建議用不同的結構/併發語句替換進程。)

基本上,當data_request行轉換爲高電平時,ack輸出應該被驅動爲高電平;在下降的時候應該改變爲低點。 (並且在每種情況下,我都希望其他一些東西也會發生變化,因此我需要該過程而不是併發語句,但更改它只是爲了向頂層實體發出請求已完成的信號。)

什麼是「不持有其價值」?什麼「時鐘」是指什麼時候它說「不(時鐘邊緣)」?

我很想解釋如何解決這個問題(不改變結構)以及我想要問合成器做什麼以及爲什麼合成器無法完成目標的解釋。

+0

我可能已經找出了一些原因,爲什麼...讀取後,我認爲在靈敏度過程中的「X <= Y」分配中的X輸出由合成器實現,其中觸發器附加到靈敏度事件上作爲時鐘我試圖用兩個觸發器不支持的不同時鐘源來驅動觸發器。它是否正確?那麼,如何根據兩個不同的事件來改變輸出,比如兩種不同的方式? – user3059763

+1

您的綜合工具將具有用於順序邏輯的HDL指南,其中顯示了從IEEE Std 1076.6-2004(撤回)派生的可接受形式。這裏的問題是你試圖使用data_request的兩個邊作爲雙數據速率時鐘,而DDR如果支持,只能用於iO單元並需要特殊調用(並使用兩個觸發器)。通常每個進程只能支持一個時鐘邊沿。認爲硬件描述語言。 – user1155120

回答

0

與軟件的編譯器相反,綜合硬件通常不是逐字地完成的。相反,對整個代碼塊進行分析以找到常見的結構,例如有限狀態機。在你的情況下,大多數綜合工具會認識的過程,如

process (...) 
begin 
    if rising_edge(clk) then 
     -- code here 
    end if; 
end process; 

也就是說,只有一個檢查上升沿。您的代碼可能會出現問題,因爲您使用相同的if語句來檢查上升沿和下降沿。

使您的代碼工作可以像使用兩個if語句一樣簡單。然而,正如user1155120指出的那樣,兩邊的觸發可能不適用於所有目標(FPGA)。模擬沒有這個限制。

你也可以嘗試添加一個單獨的時鐘信號,它會在上升沿觸發某段代碼。該代碼然後檢查data_request信號。

或者(但這取決於你有什麼其他代碼),你可以檢查data_request的級別而不是邊緣,例如,

if data_request = '1' then 
    -- rising edge code 
else 
    -- falling edge code 
end if; 
+0

這種修復方法是否會導致類似A = A + 1的「上升沿代碼」的問題,其中增量會失去控制? – user3059763

+0

如果你確實有這樣的語句,級別觸發的代碼不適合你。嘗試另外兩個仍然是邊緣觸發的建議。 – Mattenii

1

VHDL只是一種編程語言,實際上很多結構都是可能的。但是,您想要爲器件編程VHDL(FPGA?)。這意味着你必須按照特定的規則進行編程。

爲了能夠檢測到邊緣,您必須在兩個時間點觀察一個值:a前後。因此你必須在你的代碼中引入時間的概念。 「信號x在t-1時爲'0',在t時爲'1'。」

在大多數可編程器件中,時鐘的時間概念並不爲人所知。你作爲程序員必須介​​紹它。在大多數數字電路中,你會使用一個特定頻率的振盪器,大部分都被稱爲'時鐘'。

數字邏輯還有其他問題,那就是延遲。電力不會以無限的速度穿過邏輯。因此,你必須考慮到不同行駛路徑上的延遲。這使得設計異步邏輯非常困難。或者,您可以將值存儲在特定位置的存儲器元素中,以解決定時問題,稱爲同步邏輯。這些元素通常是寄存器。

爲什麼我解釋這一點,是爲了激發爲你的設計引入時鐘的理由,以滿足你特定的要求。您需要記住data_request的前一個狀態,以便觀察更改。

signal data_request_old : std_logic; 
begin 
    data_request_old <= data_request when rising_edge(clk); 
    if data_request = '1' and data_request_old = '0' then 
     -- rising edge 
    end if; 
    if data_request = '0' and data_request_old = '1' then 
     -- falling edge 
    end if; 

x_old <= x when rising_edge(clk)將推斷寄存器,延遲輸入一個時鐘週期。

p.s.我假設data_request已經與clk同步。否則你首先需要同步它。

p.s.2我正在編寫when rising_edge(clk);作爲最小的結構,大多數FPGA綜合工具都可以接受。如果你的沒有,你需要寫一個完整的過程。

+0

你什麼時候更新data_request_old?你在一個異步系統上。 –

+0

@kingsjester我不明白你的問題。你可以重新說明嗎?我不在任何系統上。 – JHBonarius

+0

組件是異步的,所以什麼時候更新'data_request_old'?我想這是'data_request'的前一個值,但是在異步系統上,您無法在時鐘邊緣更新它。所以我想你會在'data_request'值發生變化時更新它,這意味着'data_request'的下降沿或者上升沿就是你正在實現的目標... –

1

問題是您的信號ack僅在上升沿和下降沿設置。綜合將嘗試使您的組件在現實世界中運行,並且會受到物理限制。換句話說,你必須管理沒有事件的情況。 你的情況,你只需要添加一個else語句進行if,像下面這樣:

architecture logic of controller is 

signal ack_s : std_logic := '0'; 

begin 
    process(data_request) 
    begin 
     if (rising_edge(data_request)) then 
      -- other logic will be added here 
      ack_s <= '1'; 
     elsif (falling_edge(data_request)) then 
      -- other logic will be added here too 
      ack_s <= '0'; 
     else then 
      ack_s <= ack_s; 
     end if; 
    end process; 

    ack <= ack_s; -- You map the output on the internal signal 

end architecture logic; 

這樣,你的信號總是被映射到一個值。如果您嘗試繪製原理圖,您會明白這一點。此外,您必須使用signal,因爲當ack是輸出時,您不能到ack <= ack;。 作爲提示,我建議您每次做if塊時總是有一個else聲明,因爲在現實世界的電路中,您總是需要默認行爲。

相關問題