2017-08-26 109 views
2

我有VHDL實現可以在板上工作,它檢測到序列01110,並且會產生一個2個時鐘計數的標誌。它還檢測重疊序列,以及011101110將兩次提升標誌。VHDL狀態機測試臺 - 在機器上工作,但不能在模擬機上工作

我檢查了我的實施與板上的邏輯分析儀,我相當有信心,它的工作原理。我在電路板上以10 kHz的頻率重複序列0111,它有一個100 MHz的時鐘,我用預分頻器將它的頻率調整到10 kHz。

我的問題是,嘗試使用模擬重新建立一個類似的情景時,我沒有得到任何輸出,從邏輯分析儀預計

圖片由董事會從試驗檯enter image description here

圖片 enter image description here

試驗檯代號

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.STD_LOGIC_ARITH.ALL; 
use IEEE.STD_LOGIC_UNSIGNED.ALL; 

entity test_FSM_prac4 is 
-- Port (); 
end test_FSM_prac4; 

architecture Behavioral of test_FSM_prac4 is 

component FSM_prac4 is 
    port ( 
     inputSignal : in STD_LOGIC; 
     pushButton : in STD_LOGIC; 
     clk100mhz : in STD_LOGIC; 
     logic_analyzer : out STD_LOGIC_VECTOR (7 downto 0); 
     LEDs: out STD_LOGIC 
); end component; 

signal inputSignal : std_logic := '0'; 
signal pushButton: std_logic := '0'; 
signal clk100mhz: std_logic := '0'; 
signal logic_analyzer: std_logic_vector(7 downto 0); 
signal LEDs : std_logic; 

begin 

uut : FSM_prac4 port map(
    inputSignal => inputSignal, 
    pushButton => pushButton, 
    clk100mhz => clk100mhz, 
    logic_analyzer => logic_analyzer, 
    LEDs => LEDs 
    ); 

--generate clock 100mhz 
clock_tic: process begin 
    loop 
    clk100mhz <= '0'; 
    wait for 5ns; 
    clk100mhz <= '1'; 
    wait for 5ns; 
    end loop; 
end process; 

input_changes: process begin 
    loop 
    inputSignal <= '0'; 
    wait for 100us; 
    inputSignal <= '1'; 
    wait for 100us; 
    inputSignal <= '1'; 
    wait for 100us; 
    inputSignal <= '1'; 
    wait for 100us; 
    end loop; 
end process; 

end Behavioral; 

要顯示地圖平邏輯分析儀

logic_analyzer(0) <= masterReset; 
logic_analyzer(1) <= newClock -- 10Khz Clock; 
logic_analyzer(2) <= outputZ; 
--FSM States 
logic_analyzer(3) <= '1' when y = A ELSE '0'; 
logic_analyzer(4) <= '1' when y = B ELSE '0'; 
logic_analyzer(5) <= '1' when y = C ELSE '0'; 
logic_analyzer(6) <= '1' when y = D ELSE '0'; 
logic_analyzer(7) <= '1' when y = E ELSE '0'; 

如果有人可以直接向我在做什麼錯在測試平臺上,以及如何複製得到類似的結果作爲第一個圖像,因爲它表明,在模擬中,它始終保持在國家一併且新時鐘不翻轉意味着clk100mhz在某種程度上沒有連接,但我無法弄清楚原因。

任何幫助是極大的讚賞,感謝你們

編輯:

我寫了一個簡單的程序來測試我的標時鐘

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.STD_LOGIC_ARITH.ALL; 
use IEEE.STD_LOGIC_UNSIGNED.ALL; 

entity scaler_clk is 
Port ( 
      pushButton : in std_logic; 
      indicator : out std_logic; 
      clk100mhz : in STD_LOGIC; 
      clk10khz: out STD_LOGIC 
      ); 
end scaler_clk; 

architecture Behavioral of scaler_clk is 
    signal clockScalers : std_logic_vector (12 downto 0):= (others => '0') ; 
    signal prescaler: std_logic_vector(12 downto 0) := "1001110001000"; 
    signal newClock: std_logic := '0'; 
    signal masterReset : std_logic;  

begin 

    clk10khz <= newClock; 
    masterReset <= pushButton; 

    process (clk100mhz,masterReset) begin 
     if(masterReset <= '1') then <--- error occurs here 
      clockScalers <= "0000000000000"; 
      newClock <= '0'; 
      indicator <= '1'; 
     elsif (clk100mhz'event and clk100mhz = '1')then 
      indicator <= '0'; 
      clockScalers <= clockScalers + 1; 
      if(clockScalers > prescaler) then 
       newClock <= not newClock; 
       clockScalers <= (others => '0'); 
      end if; 
     end if; 
    end process; 

end Behavioral; 

測試臺代碼

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 

entity test_scaler_clk is 
-- Port (); 
end test_scaler_clk; 

architecture Behavioral of test_scaler_clk is 

    component scaler_clk Port ( 
      pushButton : in std_logic; 
      indicator : out std_logic; 
      --input clock 
      clk100mhz : in STD_LOGIC; 
      clk10khz: out STD_LOGIC 
      );end component; 

    signal clk100mhz: std_logic := '0'; 
    signal clk10khz : std_logic; 
    signal pushButton: std_logic; 
    signal indicator : std_logic; 

begin 

uut: scaler_clk port map(
    pushButton => pushButton, 
    indicator => indicator, 
    clk100mhz => clk100mhz, 
    clk10khz => clk10khz 
    );  

    pushButton <= '0'; 
    clock_tic: process begin 
     loop 
     clk100mhz <= '0'; 
     wait for 5ns; 
     clk100mhz <= '1'; 
     wait for 5ns; 
     end loop; 
    end process; 


end Behavioral; 

即使雖然我將pushButton設置爲'0',但它仍然觸發masterReset,任何人都知道爲什麼,這就是爲什麼10 kHz時鐘不工​​作

enter image description here

+0

明顯的不同:日誌顯示時鐘和刺激的速度相同,但在結核病中它們的速率不同。現在我們不知道組件的內部,因此我們無法進一步追蹤這種差異。 –

+0

是的,在板上我有一個100MHz的輸入時鐘,我把它縮小到10khz的輸出,然後反映在邏輯分析儀(1)上,我使用10khz時鐘作爲我的fsm –

+0

我試圖模擬相同的事情在測試臺上通過產生100mhz時鐘。它應該顯示在TB上的邏輯分析儀(1)上一個10khz時鐘,但它沒有顯示。我想知道是因爲我的synthex還是我錯過了一些東西 –

回答

2

有幾件事情,你可以(應該)在你的代碼提高。正如布萊恩已經解釋過,在你Behavioral建築scaler_clk,你應該有:

if(masterReset = '1') then 

代替:

if(masterReset <= '1') then 

現在,讓我們開始與您最初的問題的最可能的原因:未結合的成分。您的測試臺將實例化設計以驗證組件。 VHDL組件是實際實體的原型。原型足以編譯,因爲編譯器可以執行所有必要的語法和類型檢查。但是它們不足以模擬,因爲模擬器在原型後面還需要執行的。有些工具對未綁定的組件具有默認的綁定策略:如果他們發現具有相同名稱的實體並且只有一個體繫結構,則它們使用該策略。你的模擬器顯然不使用這種策略(至少在默認情況下,可能有一個選項,但它被禁用)。請注意,我知道的大多數模擬器在發現未綁定組件時都會發出警告。你可能錯過了這些警告。

無論如何,您的組件實例都是未綁定的(它們沒有關聯的實體/體系結構),並且模擬器將它們視爲黑盒子。除了你聲明的初始值(1)外,它們的輸出不被驅動。

如何解決這個問題?兩種選擇:

  1. 使用配置來指定哪些實體/架構對應被用於每個組件實例:

    for all: scaler_clk use entity work.scaler_clk(Behavioral); 
    
  2. 使用實體實例化,而不是組件:

    uut: entity work.scaler_clk(Behavioral) port map... 
    

現在,我們來看看代碼中可以改進的一些其他方面:

  1. 您正在使用非標準封裝,是經常不兼容甚至:IEEE.STD_LOGIC_ARITHIEEE.STD_LOGIC_UNSIGNED。由於它們不是標準的,它們甚至不應該在標準的IEEE庫中。您應該使用IEEE.NUMERIC_STD代替,並且只使用那一個。它聲明瞭SIGNEDUNSIGNED類型(聲明與STD_LOGIC_VECTOR相同)並重載算術運算符。

  2. 你的測試平臺生成具有100MHz的時鐘:

    clock_tic: process begin 
        loop 
        clk100mhz <= '0'; 
        wait for 5ns; 
        clk100mhz <= '1'; 
        wait for 5ns; 
        end loop; 
    end process; 
    

    的無限循環是無用的:一個進程已經是一個無限循環:

    clock_tic: process 
    begin 
        clk100mhz <= '0'; 
        wait for 5ns; 
        clk100mhz <= '1'; 
        wait for 5ns; 
    end process clock_tic; 
    

    會做同樣的。 input_changes過程的相同說明。

  3. 您的input_changes程序使用wait for <duration>陳述。這不是一個好主意,因爲與時鐘相比,您不知道信號何時觸發。是否在clk100mhz的上升沿之前,之後或恰好與此同時?如果它恰好在同一時間,會發生什麼?當然,您可以仔細選擇<durations>以避免這種歧義,但容易出錯。您只能在時鐘生成過程中使用wait for <duration>。在其他地方,它是更好地與時鐘同步:

    input_changes: process 
    begin 
        inputSignal <= '0'; 
        for i in 1 to 10000 loop 
         wait until rising_edge(clk100mhz); 
        end loop; 
        inputSignal <= '1'; 
        for i in 1 to 10000 loop 
         wait until rising_edge(clk100mhz); 
        end loop; 
        inputSignal <= '1'; 
        for i in 1 to 10000 loop 
         wait until rising_edge(clk100mhz); 
        end loop; 
        inputSignal <= '1'; 
        for i in 1 to 10000 loop 
         wait until rising_edge(clk100mhz); 
        end loop; 
    end process input_changes; 
    

    這可以保證只在時鐘的上升沿後inputSignal變化。你可以重寫它有點更優雅的方式(可能有點更容易維護):

    input_changes: process 
        constant values: std_logic_vector(0 to 3) := "0111"; 
    begin 
        for i in values'range loop 
         inputSignal <= values(i); 
         for i in 1 to 10000 loop 
          wait until rising_edge(clk100mhz); 
         end loop; 
        end loop; 
    end process input_changes; 
    
  4. 您使用解決類型(STD_LOGICSTD_LOGIC_VECTOR)。這些類型允許多個驅動器,即具有由多個設備(VHDL進程)驅動的硬件線(VHDL信號)。通常你不想要這個。通常你甚至希望避免這種瘟疫,因爲它可能導致短路。在大多數情況下,使用未分辨類型(STD_ULOGICSTD_ULOGIC_VECTOR)更明智一些,因爲如果在設計中意外造成短路,編譯器和/或模擬器將引發錯誤。最後一件事:如果顧名思義,你打算使用clk10khz信號作爲真正的時鐘,你應該重新考慮這個決定。這是您用自定義邏輯生成的信號。時鐘具有非常特定的電氣和時序約束,這些約束無法通過常規信號來實現。在使用clk10khz作爲時鐘之前,您必須處理時鐘偏移,時鐘緩衝...不是不可能,而是棘手。如果你確實使用它作爲時鐘,你的合成器可能會發出你也錯過了的重要警告(可能會在時間報告中看到)。而且,這在你的情況下可能沒有用處:從clk100mhz生成的使能信號可能可以用來代替,避免所有這些問題。相反的:

    process (clk100mhz,masterReset) begin 
        if(masterReset = '1') then 
         clockScalers <= "0000000000000"; 
         newClock <= '0'; 
         indicator <= '1'; 
        elsif (clk100mhz'event and clk100mhz = '1')then 
         indicator <= '0'; 
         clockScalers <= clockScalers + 1; 
         if(clockScalers > prescaler) then 
          newClock <= not newClock; 
          clockScalers <= (others => '0'); 
         end if; 
        end if; 
    end process; 
    

    使用:

    signal tick10khz: std_ulogic; 
    ... 
    process(clk100mhz, masterReset) begin 
        if masterReset = '1') then 
         clockScalers <= "0000000000000";  
         tick10khz <= '0'; 
        elsif rising_edge(clk100mhz) then 
         clockScalers <= clockScalers + 1; 
         tick10khz <= '0' 
         if(clockScalers > prescaler) then 
          tick10khz <= '1'; 
          clockScalers <= (others => '0'); 
         end if; 
        end if; 
    end process; 
    

    然後,而不是:

    process(clk10khz) 
    begin 
        if rising_edge(clk10khz) then 
         register <= register_input; 
        end if; 
    end process; 
    

    使用:

    process(clk100mhz) 
    begin 
        if rising_edge(clk100mhz) then 
         if tick10khz = '1' then 
          register <= register_input; 
         end if; 
        end if; 
    end process; 
    

    結果將是相同的,但只有一個100MHz時鐘,避免時鐘偏移,時鐘緩衝ng和時鐘域交叉問題。

(1)這說明了爲什麼使用初始值聲明變量和信號通常不是一個好主意:它隱藏了潛在的問題。如果沒有這個,你的信號會被卡在'U'(未初始化),這可能有助於理解問題的來源。

相關問題