2013-04-27 45 views
0

我正在vhdl中實現一個Mealy類型的FSM。我目前正在使用雙重過程,雖然我剛剛讀過一個單一過程可能會更整潔。考慮你的答案的一個參數。VHDL FSM設置單元輸入和使用相同狀態的輸出

問題的簡短版本是:我可以有一個狀態,其中另一個組件的輸入被更改,並且在相同的狀態下,使用該組件的輸出?這將是安全的還是將會是一場老鼠賽跑,我應該用組件的輸出做出另一個狀態?

長版本:我有一個內存模塊。這是一個fifo內存,激活它的復位信號將一個名爲queue_pointer的變量放到它的第一個元素中。在寫入存儲器之後,指針增加,並且如果它超出範圍,則(然後也)重置爲第一個元素,並且輸出信號完成被激活。順便說一句,我把這個組件稱爲FIMEM。

我的FSM首先編寫整個FIMEM,然後轉移到其他問題上。最後一次寫入將從狀態完成:

  when SRAM_read => 
      READ_ACK    <= '1'; 
      FIMEM_enable   <= '1'; 
      FIMEM_write_readNEG <= '0'; 

      if(FIMEM_done = '1') then --is that too fast? if so, we're gonna have to add another state 
       FIMEM_reset <= '1'; --this is even faster, will need check 
       data_pipe_to_FOMEM := DELAYS_FIMEM_TO_FOMEM; 
       next_state <= processing_phase1; 
      else 
       SRAM_address := SRAM_address + 1; 
       next_state <= SRAM_wait_read; 
      end if; 

在此狀態下,啓用和寫入活動意味着數據將寫入FIMEM。如果這是內存上的最後一個數據空間,那麼FIMEM_done將會激活,並且if中的很好的代碼將處理未來。但是,會有足夠的時間嗎?如果沒有,並且下一個狀態轉到SRAM_wait_read,並且FIMEM_done被激活,那麼會出現問題。 FIMEM是完全同步的(而我的代碼的這一部分是在異步過程中)的事實更多地混淆了?

這裏是我記憶的代碼,以防萬一:

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.NUMERIC_STD.ALL; 

entity memory is 
    generic (size: positive := 20); 
    Port ( clk, 
       reset, 
       enable, 
       write_readNEG: in std_logic; 
       done: out std_logic; 
      data_in: in STD_LOGIC_VECTOR(7 downto 0); 
      data_out: out STD_LOGIC_VECTOR(7 downto 0)); 
end memory; 

architecture Behavioral of memory is 

    subtype word is STD_LOGIC_VECTOR(7 downto 0); 
    type fifo_memory_t is array (0 to size-1) of word; 
    signal fifo_memory : fifo_memory_t :=((others=> (others=>'0'))); 

    --Functionality instructions: 
    --Resetting sets the queue pointer to the first element, and done to 0 
    --Each cycle with enable active, a datum from the pointer position is 
    --written/read according to write_readNEG, and the pointer is incremented. 
    --If the operation was at the last element, the pointer returns to the first place 
    --and done is set to 1. When done is 1, enable is ignored. 

    Begin 
    process(clk,reset) 
      variable done_buf : std_logic; 
      variable queue_pointer: natural range 0 to size-1; 
    begin 
     if(reset = '1') then 
       queue_pointer := 0; 
       done_buf := '0'; 
     elsif(rising_edge(clk)) then 
       if(done_buf = '0' and enable = '1') then 
         case write_readNEG is 
           when '0' => 
             data_out <= fifo_memory(queue_pointer); 
           when '1' => 
             fifo_memory(queue_pointer) <= data_in; 
           when others  => null; 
         end case; 
         if(queue_pointer = size-1) then 
           done_buf := '1'; 
           queue_pointer := 0;--check 
         else 
           queue_pointer := queue_pointer + 1; 
         end if; 
       end if; --enable x not done if 
     end if; --reset/rising edge end if 
     done <= done_buf; 
    end process; 
End Behavioral; 

更多細節由第一評論的啓發:

可以出同一週期的數據存儲器使能激活,如下所示: Post-Place and Route Simulation 請注意,啓用時的值「1」實際上是寫入內存中的。

不幸的是,這段代碼處於異步過程!儘管我非常強烈地想到轉向單流程描述。

與我之前設計的所有電路相比,我很難通過仿真對其進行測試。這是我大學的一個項目,我們將vhdl程序下載到xilinx spartan 3 FPGA。這一次,我們得到了一個在Matlab和FPGA的SRAM之間傳輸數據的單元(其功能我不知道)。因此,我必須使用本機在SRAM和我的存儲器模塊之間傳輸數據。這意味着,爲了模擬,我的測試平臺文件將不得不模擬給定的單位!這是很難的..假設我必須嘗試,雖然...

回答

2

首先,無論是使用單進程還是雙進程類型的FSM表示法都是一個偏好問題(或公司編碼風格規則) 。我發現單一過程符號更易於編寫/讀取/管理。

您的啓用只有在下一個上升時鐘沿之後,信號纔會對您的存儲器代碼產生影響。 完成因此與實際存儲器狀態相關的信號因此將在更新使能後的一個時鐘週期可用。我猜(並希望!但在您的發佈代碼中不可見),您的current_state < = next_state部分FSM是同步的!因此當完成更新時,狀態機將處於SRAM_wait_read狀態!

btw:使用模擬器!這將有助於檢查功能!


感謝您添加模擬視圖!奇怪你的完成信號更新neg。時鐘邊緣......在我的模擬中,它在pos上更新。邊緣;順便說一句,它應該! enter image description here

爲了使情況更加清晰我建議你移動done < = done_buf;行內的「rising_edge-if」(當使用同步過程時,應該以任何方式完成!)。