2016-04-19 33 views
0

我正在苦於VHDL難題。下面是一些代碼,應該解釋什麼,我試圖做的:如何確定是否所有for循環都結束,VHDL,Quartus-II

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.std_logic_arith.all; 
use work.all; 

entity forLoopTest is 
-- Number of bits known only at compilation 
generic(
    bits : integer range 1 to 1024;    := 256; 
); 
port(
    clk: in std_logic       := '0'; 
    -- Single bit inputs from foo 
    foo: in std_logic_vector(bits-1 downto 0) := (others => '0'); 
    -- Output should be high when all inputs have gone to '1' at some point 
    bar: out std_logic 
); 
end forLoopTest; 

------------------------------------------------------------------------------------------------------------ 

architecture implementation of forLoopTest is 
    -- Create states for finite state machine, where finish implies a '1' has been received 
    type FSM_states_single is (waitForHigh, finish); 
    -- Make an array of the states, one for each input bit 
    type FSM_states_multi is array (bits-1 downto 0) of FSM_states_single; 
    -- Create signal of states initialised to the waiting condition 
    signal state : FSM_states_multi     := (others => waitForHigh); 

begin 

    process(clk, foo) 
     -- For each input bit: 
     for bitNumber in 0 to bits-1 loop 
      case state(bitNumber) is 
       -- Whilst waiting, poll the input bit 
       when waitForHigh => 
        -- If it goes high, then switch states 
        if (foo(bitNumber) = '1') then 
         state(bitNumber) <= finish; 
        end if; 
       -- If input bit has gone high: 
       when finish => 
        -- What is simplest method of setting "bar"? 
         -- "bar" should be high if and only if all bits have equalled '1' at some point 
         -- Otherwise it should be '0' 
         -- Though of dominant setting '0', and submissive setting 'H', but multiple things setting output fails 
          -- Either explicitly, or only one of them is used, others ignored 
      end case; 
     end loop; 

    end process;   

end implementation; 

基本上,我試圖找到當所有for循環的「線程」已完成推導的最佳方法。以上是一個假設的例子來說明這一點。使用上述代碼的一種方法是簡單地「與」所有狀態。但是,我不知道如何和一個未知數量的變量(預編譯)。另外我很想知道解決這個問題的其他方法是什麼。

在此先感謝!

回答

1

爲您的過程添加了時鐘和重置。重置允許您清除狀態。

沒有酒吧的觸發器,它很容易做,移動一個if語句。

的情況下發言,因爲酒吧是如何得出去除,評估這兩個州是沒有必要的:

library ieee; 
use ieee.std_logic_1164.all; 
-- use ieee.std_logic_arith.all; -- not used 
use work.all; 

entity forlooptest is 
    generic (
     bits : integer range 1 to 1024 := 256 -- removed ';' 2 places 
    ); 
    port (
     clk: in std_logic; 
     reset: in std_logic; -- added 
     foo: in std_logic_vector(bits-1 downto 0) := (others => '0'); 
     bar: out std_logic 
    ); 
end entity forlooptest; 

architecture foo of forlooptest is 

    type FSM_states_single is (waitForHigh, finish); 
    type FSM_states_multi is array (bits-1 downto 0) of FSM_states_single; 
    signal state : FSM_states_multi := (others => waitForHigh); 

begin 

FOO_BAR: 
    process (clk, reset) 
     variable state_v: FSM_states_multi; -- added 
    begin -- original missing begin 

     state_v := state; -- variable can be evaluated after assignment 
     if reset = '1' then 
      state_v := (others => WaitForHigh); 
     elsif rising_edge(clk) then 
      for bitNumber in 0 to bits-1 loop 
       if state_v(bitNumber) = waitForHigh and 
           foo(BitNumber) = '1'  then 
        state_v(bitNumber) := finish; 
       end if; 
      end loop; 
      state <= state_v; 
     end if; 
     if state_v = (state_v'range => finish) then 
      bar <= '1'; -- bar not a FlipFlop move if statement above 
     else    -- preceding end if and add to reset condition for FF 
      bar <= '0'; -- no latch 
     end if; 
    end process;  

end architecture; 

製作吧觸發器可以通過移動它來完成,如果,如果前一結束上述說法,刪除else並賦值爲'0',並將< ='0'添加到復位。

還有一個狀態的變量副本,所以任何更新位立即可用於評估。 (信號分配不會在變量分配時立即生效)。

注意事項的核心,如何使用每個位置設置爲完成的聚合值來評估狀態(state_v)。這裏不能使用others。元素的數量及其類型必須從聚合表達式中作爲等於運算符的輸入來辨別。

添加小測試臺具有有限範圍的比特:

library ieee; 
use ieee.std_logic_1164.all; 

entity for_loop_test_tb is 
end entity; 

architecture fum of for_loop_test_tb is 
    constant bits: integer range 1 to 1024 := 16; 
    signal clk: std_logic := '0'; 
    signal reset: std_logic; -- added 
    signal foo: std_logic_vector(bits-1 downto 0) := (others => '0'); 
    signal bar: std_logic; 
begin 
DUT: 
    entity work.forlooptest 
     generic map (bits => bits) 
     port map (
      clk => clk, 
      reset => reset, 
      foo => foo, 
      bar => bar 
     ); 
CLOCK: 
    process 
    begin 
     wait for 5 ns; 
     clk <= not clk; 
     if now > 150 ns then 
      wait; 
     end if; 
    end process; 

STIMULI: 
    process 
    begin 
     wait for 10 ns; 
     reset <= '1'; 
     wait for 10 ns; 
     reset <= '0'; 
     wait for 10 ns; 
     foo <= x"0FF0"; 
     wait for 10 ns; 
     foo <= x"0001"; 
     wait for 10 ns; 
     foo <= x"F002"; 
     wait for 10 ns; 
     foo <= x"0F00"; 
     wait for 10 ns; 
     foo <= x"FF00"; 
     wait for 10 ns; 
     foo <= x"0001"; 
     wait for 10 ns; 
     foo <= x"00F0"; 
     wait for 10 ns; 
     foo <= x"F0F0"; 
     wait for 10 ns; 
     foo <= x"0004"; 
     wait for 10 ns; 
     foo <= x"CCCC"; 
     wait; 
    end process; 

end architecture; 

這給出:

for_loop_test_tb.png

(對位和值不同的輸入值的foo的數量分別限制提供容易解釋的波形。)

+0

傳下來我收到的最佳答案!徹底的,簡單的,很好的解釋。非常感謝你的幫助!對於編碼錯誤抱歉,由於我火車遲到,所以我很急。 – user3303504

0

(有許多事情錯與給定的過程:它可能應該主頻,使之運行在每個rising_edge(clk)那麼就沒有必要在敏感列表foo但是....)

一種方法是在輸入for循環之前設置爲TRUE的布爾變量finished

尚未完成(例如進入waitforHigh狀態或比其他finish任何狀態)將清除finished可變任何迭代...(任選地,除非它被轉換到finish狀態)。

然後,在end loop之後,下一條語句if finished then ...會告訴你你想知道什麼。