2015-05-24 59 views
2

我收到了一份描述我大學RAM的任務。在我看來,我已經編寫了一個代碼來模擬上述設備的行爲。但它似乎並不奏效。VHDL。新值賦值後信號值不會改變

我在下面的方式描述的設備的實體:

LIBRARY ieee; 
USE ieee.std_logic_1164.all; 
USE ieee.std_logic_arith.all; 
LIBRARY RAM_lib; 
USE RAM_lib.RAM_pkg.all; 

ENTITY RAM IS 
    GENERIC(
     WORD_LENGTH: INTEGER := 8; 
     ADDRESS_LENGTH: integer := 8 
    ); 
    PORT( 
     Enable : IN  std_logic; 
     DATA_IN : IN  std_logic_vector(WORD_LENGTH - 1 downto 0); 
     DATA_OUT : OUT std_logic_vector(WORD_LENGTH - 1 downto 0); 
     ADDR  : IN  std_logic_vector(ADDRESS_LENGTH - 1 downto 0); 
     RESET : IN  std_logic; 
     CLK  : IN  std_logic; 
     WR  : IN  std_logic; 
     RD  : IN  std_logic 
    ); 

-- Declarations 

END RAM ; 

和行爲的部分看起來像:

use work.RAM_pkg.all; 

architecture behavior of ram is 

    ---- DATA TYPES DECLARATIONS 
    -- used type declarations 
    subtype DATA is std_logic_vector(WORD_LENGTH - 1 downto 0); 
    subtype ADDRESS is std_logic_vector(ADDRESS_LENGTH - 1 downto 0); 
    type MEMORY is array (0 to 2**ADDRESS_LENGTH - 1) of DATA; 

    ---- SIGNAL DECLARATION 
    signal RAM : MEMORY; 
begin use work.RAM_pkg.all; 

architecture behavior of ram is 

    ---- DATA TYPES DECLARATIONS 
    -- used type declarations 
    subtype DATA is std_logic_vector(WORD_LENGTH - 1 downto 0); 
    subtype ADDRESS is std_logic_vector(ADDRESS_LENGTH - 1 downto 0); 
    type MEMORY is array (0 to 2**ADDRESS_LENGTH - 1) of DATA; 

    ---- SIGNAL DECLARATION 
    signal RAM : MEMORY; 
begin 

-- plug in or plug out ram 
plug_in_out: process (enable) is 
    variable first_load : boolean := true; 
    begin 
    if ((enable = '0' and enable'event) or first_load = true) then 
     data_out <= (others => 'Z'); 

     if (first_load = true) then 
     first_load := false; 
     end if; 
    end if; 
    end process; 

reset_ram: process (reset) is 
    variable initialized: boolean := false; 
    begin 
    if ((reset = '1' and reset'event) or (initialized = false)) then 
     ram <= (OTHERS => (OTHERS => '0')); 

     if (initialized = false) then 
     initialized := true; 
     end if; 
    end if; 
    end process; 

-- it serves both "read" and "write" operation for the RAM 
    read_write: process (clk) is 
    variable index : integer range 0 to 2**address_length - 1; 
    begin 
     if (enable = '1' and clk = '1' and clk'event) then 
     index := toInt(addr); 

     if (wr = '1') then 
      ram(index) <= data_in; 
     end if; 

     if (rd = '1') then 
      data_out <= ram(index); 
     end if; 
     end if; 
    end process; 
end architecture behavior; 



-- plug in or plug out ram 
plug_in_out: process (enable) is 
    variable first_load : boolean := true; 
    begin 
    if ((enable = '0' and enable'event) or first_load = true) then 
     data_out <= (others => 'Z'); 

     if (first_load = true) then 
     first_load := false; 
     end if; 
    end if; 
    end process; 

reset_ram: process (reset) is 
    variable initialized: boolean := false; 
    begin 
    if ((reset = '1' and reset'event) or (initialized = false)) then 
     ram <= (OTHERS => (OTHERS => '0')); 

     if (initialized = false) then 
     initialized := true; 
     end if; 
    end if; 
    end process; 

-- it serves both "read" and "write" operation for the RAM 
    read_write: process (clk) is 
    variable index : integer range 0 to 2**address_length - 1; 
    begin 
     if (enable = '1' and clk = '1' and clk'event) then 
     index := toInt(addr); 

     if (wr = '1') then 
      ram(index) <= data_in; 
     end if; 

     if (rd = '1') then 
      data_out <= ram(index); 
     end if; 
     end if; 
    end process; 
end architecture behavior; 

The timing diagram The timing diagram

因此,主問題是爲什麼初始化沒有執行,因爲它已在的第5行中指出0進程。代碼的調試表明上述行被執行,但RAM信號的值保持不變。

+0

如果內容在寫入之前無效,爲什麼要初始化RAM?沒有奇偶校驗或ECC存在,'U'或'結果'X會告訴你是否讀取之前未寫入的內存位置,與波形轉儲不同,整個內容不能同時用於封裝設計。 – user1155120

+0

你能詳細解釋一下,你的意思是「如果內容在寫入之前無效,你爲什麼要初始化RAM」。但我不確定我是否清楚地瞭解你。你是否意味着一個寫入操作可能出現在RAM初始化之前? –

回答

1

在VHDL中,應該在單個進程中分配一個信號。否則,你會得到多個驅動程序,這通常是不可綜合的。如果驅動值不兼容(例如同時驅動'0'和'1',這將產生'X'),則在仿真中將相同信號分配多個值將導致衝突。

掃描您的代碼,我可以看到至少有data_outram在多個進程中具有分配。合併您的流程應該可以解決您的問題。

此外,RAM不能被重置。這與模擬無關,但會影響合成。您可以復位輸出寄存器(data_out),但RAM本身不能復位。如果這樣做,合成器將使用寄存器而不是嵌入式RAM。但是,通過將其定義爲signal ram: MEMORY := (others => (others => '0'));,您可以擁有RAM的初始內容。這由綜合支持。

+0

非常感謝您的回答! –

+0

謝謝大衛,做出了改變 –

0

這裏有幾個問題。首先,如前所述,您不應使用多個進程寫入相同的信號,或者您有多個驅動程序問題。

如果您確實需要異步啓用(與您在plug_in_out中描述的最接近),那麼您需要一個單獨的信號用於實際輸出。例如:

data_out_real <= (others => 'Z') when enable = '0' else data_out; 

這是一個組合的VHDL單線(不在一個進程內)。儘管如此,我並不推薦異步啓用,但如果在主進程中運行同步啓用,您會完美無瑕。

您用於獲取初始狀態的變量操作可能不會合成,但您不需要一個操作。 data_out_real將始終具有明確的值("ZZZZ...")或data_out的副本。你可以給DATA_OUT當你與申報信號給出一個初始值:

signal data_out : std_logic_vector(word_length-1 downto 0) := (others => '0'); 

假設你要創建一個內存模塊針對一個FPGA,你不能一次復位的一切(你能在寄存器文件,但是RAM是不同的),當你嘗試在reset_ram進程中(它將模擬,也許合成,但不進入FPGA的Block RAM)進行。執行此操作的正常方法是在復位變爲高電平時觸發復位狀態,該狀態包含一個計數器,該計數器遍歷每個時鐘的一個位置爲0的每個地址。請注意,該狀態機佔用與正常讀/寫行爲相同的過程(處於非復位狀態)。還請注意,這不會像您所排序的異步復位 - 在reset_ram中描述。

實際的read_write進程看起來可以讀取/寫入你的內存狀態,雖然你不需要索引變量/賦值,但是在你的2個ram索引操作中使用更少的行。

要在此實現啓用,您可能需要將enable='1'clk='1' and clk'event分隔爲單獨的圖層。這允許你爲你的數據輸出一個默認值0或甚至Z(必須在你的clk上升沿檢查之內,在你的啓用檢查的else部分之外)。如果你真的想要一個同步啓用,那麼最好是做這樣的事情,而不是我上面演示的組合位。此外,如果想要啓用異步,則需要處理跨時鐘路徑,以便在此處的同步過程中使用它。

最後,想想你真正想要你的啓用。在我描述的大多數RAM中,當啓用變低時,我不想失去最後一次讀取的值,我只是不希望它改變。這更容易完成,因爲當啓用功能較弱時,您可以不提及該做什麼,並且該信號將保持其最後的值。