2016-03-22 56 views
4

我有我的代碼的以下簡化示例,其中可以模擬DeltasTest實體來顯示問題。真正設計中的時鐘是基於通用的反轉或非反轉的,並且在此之下提供幾個其他實體。我該如何解決這個增量週期時鐘延遲問題

問題在於,行爲模擬中簡單的邊緣檢測器不起作用(data_out只是一個小故障),這是由於反轉階段在時鐘上引入的Δ週期延遲。有沒有一個標準或其他優雅的方式來解決這個問題?

到目前爲止,我的最佳解決方案是將data_in信號分配給另一個信號,使其具有與clk相同的增量循環延遲。我想使用一個函數來根據需要反轉時鐘作爲函數的第二個參數,但這個時鐘在很多地方都有使用,這看起來不是很優雅,而且我很確定它甚至可以解決這個問題。問題。抓着吸管,我也試着把時鐘反轉賦值給transport賦值,但是,正如所料,這沒有任何區別。

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 

entity Deltas is 
    Generic (
     CLK_INVERT : boolean := false 
    ); 
    Port (
     clk : in std_logic; 
     data_in : in std_logic 
    ); 
end Deltas; 

architecture Behavioral of Deltas is 

    -- Signals 
    signal data_reg : std_logic := '0'; 
    signal clk_inverted : std_logic := '0'; 
    signal data_out : std_logic := '0'; 

begin 

    ClkInvert : if (CLK_INVERT) generate 
     clk_inverted <= not clk; 
    else generate 
     clk_inverted <= clk; 
    end generate; 

    process (clk_inverted) 
    begin 
     if (rising_edge(clk_inverted)) then 
      data_reg <= data_in; 
     end if; 
    end process; 

    process (data_reg, data_in) 
    begin 
     if (data_reg /= data_in) then 
      data_out <= '1'; 
     else 
      data_out <= '0'; 
     end if; 
    end process; 

    -- Other entities use `clk_inverted`. Commented out so that this example compiles 
    --LowerEntity : entity work.Counter 
    --port map (
    -- clk => clk_inverted 
    --); 

end Behavioral; 

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 

entity DeltasTest is 
end DeltasTest; 

architecture Behavioral of DeltasTest is 

    signal clk : std_logic := '0'; 
    signal data_in : std_logic := '0'; 

begin 

    clk <= not clk after 10 ns; 

    process (clk) 
     variable count : integer := 0; 
    begin 
     if (rising_edge(clk)) then 
      count := count + 1; 
      if (count = 4) then 
       count := 0; 
       data_in <= not data_in; 
      end if; 
     end if; 
    end process; 

    uut : entity work.Deltas 
    Port map (
     clk => clk, 
     data_in => data_in 
    ); 

end Behavioral; 
+0

有兩個問題:1)爲什麼在'Deltas'中不使用'falling_edge()',而是用delta延遲生成'clk_inverted',然後在這個上使用'rising_edge()'? 2)爲什麼在實際設計中不是基於'clk'生成的'data_in'上的刺激,而是僅僅基於時間?改變這將使邊緣檢測器工作。如果需要反轉時鐘,則除了clk之外,還要在頂層進行分配,並通過層次結構進行分配。 –

+2

@MortenZilmer感謝您的評論。 1)我沒有使用'falling_edge()',因爲時鐘的極性取決於一個通用的。 2)數據信號實際上是由'clk'生成的,但這最終沒有任何區別,因爲我的例子與我的真實代碼不完全相同。我會更新示例以包含您的更改。 –

+0

您可能會在http://electronics.stackexchange.com/ – Tansir1

回答

3

我想,你對data_in額外的增量週期的「解決方案」可能是最乾淨簡單的解決方案。

語義上,對clk_inverted的賦值可能會轉化爲硬件,作爲時鐘信號中的反相器,因此模擬中的增量循環延遲表示真實硬件中引入的(可能(*)真實)競態條件。

因此,仿真行爲不僅僅是一個煩惱,而是一個有用的屬性,警告您必須注意與良好的同步設計實踐存在潛在偏差。 (*)只有「可能是真實的」,因爲根據技術的不同,合成可能會通過檢測相反的邊緣將反演「推」到下游的FF--根據Morten的評論自動轉換您的設計。

當額外的增量循環被埋在別人的IP中,或許是外部組件(如內存)的模型時,它變得更加棘手。然後,IP就不再受控制,板級仿真可能會在錯誤的時鐘週期內讀取或寫入數據。在FPGA的I/O分配(來自FPGA數據表或合成報告)中的慣性延遲或PCB上的傳輸延遲,我的答案是添加近似的I/O延遲。這確保了我的模擬能夠逼近電路板的行爲 - 並不完美,但足以讓我在正常的同步實踐之後設計內部邏輯。


一個更乾淨的解決方案將是生成兩個不同的基於通用的時鐘進程。這完全消除了煩人的三角洲週期。

最後!對於SM,在保持時鐘過程儘可能簡單,有效益的2-過程形式的使用...

不會這麼快......

要重構的行爲是時鐘邊沿檢測,它已經被重構爲一個來自過時和複雜(級別和事件)表達式的簡單函數。

爲什麼不進一步重構時鐘邊沿檢測,例如...

function clock_edge(signal clk : in std_logic) return boolean is 
begin 
    if CLK_INVERT then 
     return falling_edge(clk); 
    else 
     return rising_edge(clk); 
    end if; 
end clock_edge; 
... 

process (my_clock) is 
begin 
    if clock_edge(my_clk) then ... 

我還沒有測試過,看看綜合工具是否可以根據需要實現這一點。有些人可能會,有些人可能不會(如果他們只是特別包含系統提供的功能而不是正確地完成工作)

在分層設計中,此函數將位於包中,供需要它的任何實體使用。這帶來了泛型可見性的問題:一個建議是在包中使用常量,另一個是將泛型作爲第二個參數傳遞給函數。正確的做法可能取決於合成工具施加的限制。

+0

找到更廣泛的受衆。感謝您的答案。所涉及的數據信號實際上是在FPGA內部以與我在上述特定設計中更新的測試平臺中所示的方式相同的方式創建的,但所討論的實體可用於兩種信號都是外部輸入的情況。有趣的一點是,如果插入實際的逆變器,這可能是現實世界的問題。 –

+0

另一種解決方案是基於泛型生成兩個不同的時鐘進程。最後!用於SM的2進程形式,其中保持時鐘進程儘可能簡單是有好處的! –

+0

感謝您的補充想法,我沒有想過將時鐘邊緣函數作爲一個「本地」函數,而這個函數不需要每次都傳遞布爾值,這使得它更乾淨,我在想什麼。儘管在這種情況下使用函數的主要問題是該實體在其下面還有其他實體,它們也使用反轉(或不反轉)時鐘。 –

0

我認爲你有一個亞穩態發生的情況。你輸入的數據,如果它來自外界可能不會同步。

通過兩個級聯寄存器對data_in進行時鐘處理,並將兩個寄存器進行比較,而不是將data_reg與輸入信號進行比較。

我敢肯定我之前

1

犯這個錯誤如何使用時鐘上了年紀的風格和CLK_POLARITY更換CLK_INVERT。我自己並沒有這樣做,但我很確定我在某個地方見過它。

entity Deltas is 
    Generic (
     CLK_POLARITY : std_logic := '1' 
    ); 
    Port (
     clk : in std_logic; 
     data_in : in std_logic 
    ); 
end Deltas; 
architecture Behavioral of Deltas is 
    signal data_reg : std_logic; 
    signal data_out : std_logic; 

begin 

    process (clk) 
    begin 
     if clk = CLK_POLARITY and clk'event then 
      data_reg <= data_in; 
     end if; 
    end process; 

這就提出了一個更大的問題,如何做一個寫IP可能會進行不同的設計需要不同的時鐘極性(爲這裏所做的),不同的復位極性,以及不同的復位樣式(異步復位VS同步復位)。我認爲我們需要一套實現觸發器的程序。除了具有異步復位功能的DFF以外,我認爲我們也可以擁有像DFFR(帶有復位功能的DFF)的東西,它的實現由所使用的封裝體確定。

-- In package body asynchronous resets 
procedure DFFR (
    signal Clk : std_logic ; 
    signal Reset : std_logic ; 
    signal DataIn : std_logic ; 
    signal DataOut : std_logic ; 
    constant ResetValue : std_logic 
) is 
begin 
    if Reset = RESET_POLARITY then 
    DataOut <= ResetValue ; 
    elsif Clk = CLOCK_POLARITY and Clk'event then 
    DataOut <= DataIn ; 
    end if ; 
end procedure DFFR ; 

-- In package body synchronous resets 
procedure DFFR (
    signal Clk : std_logic ; 
    signal Reset : std_logic ; 
    signal DataIn : std_logic ; 
    signal DataOut : std_logic ; 
    constant ResetValue : std_logic 
) is 
begin 
    if Clk = CLOCK_POLARITY and Clk'event then 
    if Reset = RESET_POLARITY then 
     DataOut <= ResetValue ; 
    else 
     DataOut <= DataIn ; 
    end if ; 
    end if ; 
end procedure DFFR ; 

-- In package body power on reset by initialization 
procedure DFFR (
    signal Clk : std_logic ; 
    signal Reset : std_logic ; 
    signal DataIn : std_logic ; 
    signal DataOut : std_logic ; 
    constant ResetValue : std_logic 
) is 
begin 
    if Clk = CLOCK_POLARITY and Clk'event then 
    DataOut <= DataIn ; 
    end if ; 
end procedure DFFR ; 

針對不同時鐘域做出不同決策的設計需要爲每個時鐘域分別設置一個庫。

即將到來的IEEE 1076-2018正在爲IEEE開放源代碼試點開放當前的VHDL軟件包。也許我們可以在下一次修訂中得到這個結果 - 但是,目前我比我有更多的想法,所以我們需要更多的參與者。

+0

中體現這個,哇,開源的VHDL包?!希望我們不會像Linux內核那樣發生擴散。需要一些適當的審查機制。其他VHDL工具供應商將只能非常有選擇性地支持新標準(甚至更糟的是他們現在支持VHDL-2008) – JHBonarius

+0

順便說一下,也許,關於第二個代碼,您不需要兩個軟件包。只需添加一個'SYNCHR_RESET'布爾泛型,然後使用'if not SYNCHR_RESET and reset = RESET_POLARITY then [...] elsif clk = CLOCK_POLARITY and clk'event then then SYNCHR_RESET and reset = RESET_POLARITY then [... etc.]'。我認爲合成工具會接受這一點。 – JHBonarius

+0

@JHBonarius開源的重要性在於分發,特別是使用GHDL等開源工具進行分發。更進一步的說,WRT供應商,我只希望他們注意從IEEE開源組織發佈的版本。進程仍然是待定,但我希望它將IEEE和開源方法的優點混合在一起。 –