2017-02-11 45 views
-1

Я пытаюсь реализовать FIFO (в VHDL), но в тот момент, когда я запускаю testbench, симуляция показывает только 165 нс, когда я устанавливаю время на 800ns. Я получаю его, чтобы запустить 800ns, когда я прокомментирую строку, которая присваивает push_valid_i 1 в тестовом банке (в «Цикл 2»). Это, похоже, проблема с реализацией, верно? На всякий случай, я запускаю Xilinx ISE 14.7 на ubuntu 64. Вот реализация на тестовом стенде.ISim не работает полное время моделирования [VHDL - Xilinx ISE]

Реализация:

library IEEE; 
USE ieee.std_logic_1164.ALL; 
USE ieee.numeric_std.ALL; 
use WORK.my_pkg.ALL; 

entity Fifo is  
    Port(
     clk    : in STD_LOGIC; 
     rst_n    : in STD_LOGIC; 
     -- DATA 
     push_data_i : in STD_LOGIC_VECTOR (FIFO_WIDTH-1 downto 0);  -- Data IN. 
     pop_data_o  : out STD_LOGIC_VECTOR (FIFO_WIDTH-1 downto 0);  -- Data out. 
     -- CONTROL 
     push_valid_i : in STD_LOGIC;            -- 1 to write push_data_i into the FIFO. 
     pop_grant_i : in STD_LOGIC;            -- 1 to read from the FIFO. 
     -- STATUS 
     push_grant_o : out STD_LOGIC;            -- 0 when full. To write push_grant_o=1 and push_valid_i=1. 
     pop_valid_o  : out STD_LOGIC;            -- 1 where there is data available in the FIFO. 

     -- TEST/DEBUG Purpose only 
     PORT_write_ptr_reg : out STD_LOGIC_VECTOR (FIFO_DEPTH-1 downto 0); 
     PORT_write_ptr_next : out STD_LOGIC_VECTOR (FIFO_DEPTH-1 downto 0); 
     PORT_write_ptr_succ : out STD_LOGIC_VECTOR (FIFO_DEPTH-1 downto 0); 

     PORT_read_ptr_reg : out STD_LOGIC_VECTOR (FIFO_DEPTH-1 downto 0); 
     PORT_read_ptr_next : out STD_LOGIC_VECTOR (FIFO_DEPTH-1 downto 0); 
     PORT_read_ptr_succ : out STD_LOGIC_VECTOR (FIFO_DEPTH-1 downto 0); 

     PORT_full_reg, PORT_empty_reg, PORT_full_next, PORT_empty_next, PORT_wr_en : out STD_LOGIC; 
     PORT_operation : out STD_LOGIC_VECTOR (1 downto 0) 
     ); 
end Fifo; 

architecture Behavioral of Fifo is 
    type reg_type is array (FIFO_DEPTH-1 downto 0) of STD_LOGIC_VECTOR (FIFO_WIDTH-1 downto 0);    -- FIFO_WIDTH x FIFO_DEPTH 2D-array. 
    signal array_reg : reg_type;                         -- FIFO itself. Data is stored here. 
    signal write_ptr_reg, write_ptr_next, write_ptr_succ : STD_LOGIC_VECTOR (FIFO_DEPTH-1 downto 0);  -- Write control registers. 
    signal read_ptr_reg, read_ptr_next, read_ptr_succ : STD_LOGIC_VECTOR (FIFO_DEPTH-1 downto 0);   -- Read control registers. 
    signal full_reg, full_next : STD_LOGIC := '0';                   -- Status registers 
    signal empty_reg, empty_next : STD_LOGIC := '1';                  -- Status registers 
    signal operation : STD_LOGIC_VECTOR (1 downto 0) := "00";               -- Operation 2 bit array 
    signal wr_en: STD_LOGIC;                          -- Write possible register. 

    begin 
     -- ** PUSH & POP PORTS (data) ** -- 
     process(clk, rst_n) 
     begin 
      if(rst_n='0') then 
       array_reg <= (others=>(others=>'0'));          -- Sets the entire array_reg (2D-array) to 0. 
       write_ptr_reg <= (others=>'0'); -- Resets all write registers (to 0). 
       read_ptr_reg <= (others=>'0'); -- Resets all read registers (to 0). 
       full_reg <= '0';      -- Full register is set to 0 as FIFO is not FULL. 
       empty_reg <= '1';      -- Empty register is set to 1 as FIFO is empty. 
      elsif (clk'event and clk='1') then            -- Rising edge of the clock. 
       if (wr_en='1') then 
        array_reg(to_integer(unsigned(write_ptr_reg))) <= push_data_i; -- It writes the incoming data (push_data_i) to the corresponding position in the FIFO. 
                             -- It expects an intiger as the position in the array. Therefore the 'to_intiger' function. 
       write_ptr_reg <= write_ptr_next; -- Current write position becomes the next one on clock event. 
       read_ptr_reg <= read_ptr_next; -- Current read position becomes the next one on clock event. 
       full_reg <= full_next;    -- Current full position becomes the next one on clock event. 
       empty_reg <= empty_next;   -- Current empty position becomes the next one on clock event. 
       end if; 
      end if; 
     end process; 
     -- Input port: 
     wr_en <= push_valid_i and (not full_reg); -- If FIFO is NOT full it is possible to write. 
     push_grant_o <= (not full_reg);     -- Outputs if the FIFO is FULL (push_grant_o=0) 
     -- Output port: 
     -- It is done differently from the input port as the output data ('first-in', pointed by read_ptr_reg)has to be available all the time. 
     pop_data_o <= array_reg(to_integer(unsigned(read_ptr_reg))); 

     -- Successive values to read and write when requested. 
     write_ptr_succ <= STD_LOGIC_VECTOR(unsigned(write_ptr_reg)+1); 
     read_ptr_succ <= STD_LOGIC_VECTOR(unsigned(read_ptr_reg)+1); 

     -- ** Events and register control ** -- 
     operation <= (push_valid_i & pop_grant_i); -- Concatenates the two control inputs for the 'case, when' statement. 
     process(write_ptr_reg, write_ptr_succ, read_ptr_reg, read_ptr_succ, 
        operation, full_reg, empty_reg) 
     begin 
      write_ptr_next <= write_ptr_reg;  -- This for lines are to assure that the current state does not 
      read_ptr_next <= read_ptr_reg;  -- change in case none of the case-when statements happen. 
      full_next <= full_reg; 
      empty_next <= empty_reg; 
      case operation is 
       when "00" =>           -- Not write (push) or read (pop). 
       when "01" =>           -- Read. 
        if(empty_reg /= '1') then      -- If FIFO is NOT empty, it can be read. 
         read_ptr_next <= read_ptr_succ;   -- It points to the successive position to read. 
         full_next <= '0';        -- As one position is read, FIFO will NOT be full. 
         if(read_ptr_succ=write_ptr_reg) then -- Read 'reached' write. So the FIFO will be EMPTY. 
          empty_next <= '1'; 
         end if; 
        end if; 
       when "10" =>           -- Write. 
        if(full_reg /='1') then       -- If FIFO is NOT full, it can be written. 
         write_ptr_next <= write_ptr_succ; 
         empty_next <= '0';       -- The FIFO is written, so it will NOT be empty. 
         if(write_ptr_succ=read_ptr_reg) then -- Write 'reached' read, so the FIFO will be full. 
          full_next <= '1'; 
         end if; 
        end if; 
       when others =>          -- Write and Read at the same time. 
        write_ptr_next <= write_ptr_succ; 
        read_ptr_next <= read_ptr_succ; 
       end case; 
     end process; 

     -- Output STATUS 
     push_grant_o <= not full_reg; 
     pop_valid_o <= not empty_reg; 

     -- TEST/DEBUG ONLY 
     PORT_write_ptr_reg <= write_ptr_reg; 
     PORT_write_ptr_next <= write_ptr_next; 
     PORT_write_ptr_succ <= write_ptr_succ; 
     PORT_read_ptr_reg <= read_ptr_reg; 
     PORT_read_ptr_next <= read_ptr_next; 
     PORT_read_ptr_succ <= read_ptr_succ; 
     PORT_full_reg <= full_reg; 
     PORT_empty_reg <= empty_reg; 
     PORT_full_next <= full_next; 
     PORT_empty_next <= empty_next; 
     PORT_wr_en <= wr_en; 
     PORT_operation <= (push_valid_i & pop_grant_i); 
end Behavioral; 

Пользовательская библиотека 'my_pkg':

library IEEE; 
use IEEE.STD_LOGIC_1164.all; 

package my_pkg is 
     constant FIFO_DEPTH : positive := 4; 
     constant DATA_WIDTH : positive := 3; 
     constant FIFO_WIDTH : positive := DATA_WIDTH+1; --DATAWIDTH=WIDTH+1bitParity 
     constant PARITY  : bit   := '0'; -- EVEN or ODD. 
     constant PARITY_BIT : bit   := '0'; -- LSB or MSB. 
end my_pkg; 

Я использовал постоянный тип, как это должно быть синтезируемого, и я читал, что переменная не является.

Испытательный стенд:

LIBRARY ieee; 
USE ieee.std_logic_1164.ALL; 

-- Uncomment the following library declaration if using 
-- arithmetic functions with Signed or Unsigned values 
--USE ieee.numeric_std.ALL; 

ENTITY Fifo_testbench IS 
END Fifo_testbench; 

ARCHITECTURE behavior OF Fifo_testbench IS 

    -- Component Declaration for the Unit Under Test (UUT) 

    COMPONENT Fifo 
    PORT(
     clk : IN std_logic; 
     rst_n : IN std_logic; 
     push_data_i : IN std_logic_vector(3 downto 0); 
     pop_data_o : OUT std_logic_vector(3 downto 0); 
     push_valid_i : IN std_logic; 
     pop_grant_i : IN std_logic; 
     push_grant_o : OUT std_logic; 
     pop_valid_o : OUT std_logic; 
     PORT_write_ptr_reg : OUT std_logic_vector(3 downto 0); 
     PORT_write_ptr_next : OUT std_logic_vector(3 downto 0); 
     PORT_write_ptr_succ : OUT std_logic_vector(3 downto 0); 
     PORT_read_ptr_reg : OUT std_logic_vector(3 downto 0); 
     PORT_read_ptr_next : OUT std_logic_vector(3 downto 0); 
     PORT_read_ptr_succ : OUT std_logic_vector(3 downto 0); 
     PORT_full_reg : OUT std_logic; 
     PORT_empty_reg : OUT std_logic; 
     PORT_full_next : OUT std_logic; 
     PORT_empty_next : OUT std_logic; 
     PORT_wr_en : OUT std_logic; 
     PORT_operation : OUT std_logic_vector(1 downto 0) 
     ); 
    END COMPONENT; 


    --Inputs 
    signal clk : std_logic := '0'; 
    signal rst_n : std_logic := '0'; 
    signal push_data_i : std_logic_vector(3 downto 0) := (others => '0'); 
    signal push_valid_i : std_logic := '0'; 
    signal pop_grant_i : std_logic := '0'; 

    --Outputs 
    signal pop_data_o : std_logic_vector(3 downto 0); 
    signal push_grant_o : std_logic; 
    signal pop_valid_o : std_logic; 
    signal PORT_write_ptr_reg : std_logic_vector(3 downto 0); 
    signal PORT_write_ptr_next : std_logic_vector(3 downto 0); 
    signal PORT_write_ptr_succ : std_logic_vector(3 downto 0); 
    signal PORT_read_ptr_reg : std_logic_vector(3 downto 0); 
    signal PORT_read_ptr_next : std_logic_vector(3 downto 0); 
    signal PORT_read_ptr_succ : std_logic_vector(3 downto 0); 
    signal PORT_full_reg : std_logic; 
    signal PORT_empty_reg : std_logic; 
    signal PORT_full_next : std_logic; 
    signal PORT_empty_next : std_logic; 
    signal PORT_wr_en : std_logic; 
    signal PORT_operation : std_logic_vector(1 downto 0); 

    -- Clock period definitions 
    constant clk_period : time := 10 ns; 

BEGIN 

    -- Instantiate the Unit Under Test (UUT) 
    uut: Fifo PORT MAP (
      clk => clk, 
      rst_n => rst_n, 
      push_data_i => push_data_i, 
      pop_data_o => pop_data_o, 
      push_valid_i => push_valid_i, 
      pop_grant_i => pop_grant_i, 
      push_grant_o => push_grant_o, 
      pop_valid_o => pop_valid_o, 
      PORT_write_ptr_reg => PORT_write_ptr_reg, 
      PORT_write_ptr_next => PORT_write_ptr_next, 
      PORT_write_ptr_succ => PORT_write_ptr_succ, 
      PORT_read_ptr_reg => PORT_read_ptr_reg, 
      PORT_read_ptr_next => PORT_read_ptr_next, 
      PORT_read_ptr_succ => PORT_read_ptr_succ, 
      PORT_full_reg => PORT_full_reg, 
      PORT_empty_reg => PORT_empty_reg, 
      PORT_full_next => PORT_full_next, 
      PORT_empty_next => PORT_empty_next, 
      PORT_wr_en => PORT_wr_en, 
      PORT_operation => PORT_operation 
     ); 

    -- Clock process definitions 
    clk_process :process 
    begin 
     clk <= '1'; 
     wait for clk_period/2; 
     clk <= '0'; 
     wait for clk_period/2; 
    end process; 


    -- Stimulus process 
    stim_proc: process 
    begin   
     -- hold reset state for 100 ns. 
     wait for 20 ns; 

     rst_n <= '1'; 
     wait for clk_period; 
     -- Cycle 2 
     push_valid_i <= '1'; 
     push_data_i <= "0001"; 
     wait for clk_period; 

     wait; 
    end process; 

END; 

Вот снимок экрана, когда push_valid_i < = '1' комментирует: https://ibb.co/koy0dv

Вот снимок экрана, когда push_valid_i < = '1' не прокомментировал : https://ibb.co/mxiSQa

Спасибо за помощь.

+0

Источник для пакета my_package не включен. FIFO_DEPTH нельзя использовать как ширину двоичного адреса ('signal write_ptr_reg, write_ptr_next, write_ptr_succ: STD_LOGIC_VECTOR (FIFO_DEPTH-1 до 0); read_ptr_reg, read_ptr_next, read_ptr_succ: STD_LOGIC_VECTOR (FIFO_DEPTH-1 downto 0);') и массив size ('type reg_type - это массив (FIFO_DEPTH - 1 до 0) STD_LOGIC_VECTOR (FIFO_WIDTH-1 до 0);'). 2, увеличенный до ширины ptr в битах, является размером массива. Поверните привязку к проверке. Исправьте размер массива или ширину ptr, и ваш тестовый тест будет работать до остановки (часы бесплатны). – user1155120

+0

FIFO можно увеличить по глубине, чтобы соответствовать адресу: 'type reg_type - это массив (2 ** FIFO_DEPTH - 1 до 0) STD_LOGIC_VECTOR (FIFO_WIDTH - 1 downto 0);'. – user1155120

+0

Вы можете объяснить, как симуляция останавливается при 165ns: есть ли в окне консоли какие-либо ASSERT или REPORTS, рассказывающие вам, что пошло не так? –

ответ

0

факты, как мы можем увидеть их:

Я пытаюсь реализовать FIFO (в VHDL), но в тот момент я бегу испытательный стенд, моделирование показывает только 165ns, когда я установил время, чтобы быть 800ns.

Я получаю его, чтобы запустить 800ns, когда я прокомментирую строку, которая присваивает push_valid_i 1 в testbench (в «Цикл 2»).

Это, кажется, проблема с реализацией, не так ли? На всякий случай, я бегу Xilinx ISE 14.7 на убунту 64.

взглянуть на глубину FIFO и устанавливается FIFO_DEPTH:

type reg_type is array (FIFO_DEPTH-1 downto 0) of STD_LOGIC_VECTOR (FIFO_WIDTH-1 downto 0); 
    -- FIFO_WIDTH x FIFO_DEPTH 2D-array. 
    signal array_reg : reg_type; 

FIFO адрес указатели определены (в битах) по FIFO_DEPTH:

signal write_ptr_reg, write_ptr_next, write_ptr_succ : STD_LOGIC_VECTOR (FIFO_DEPTH-1 downto 0); 
    -- Write control registers. 

FIFO указатели к памяти FIFO выводятся как целые индексы из этих указателей:

  if (wr_en='1') then 
       array_reg(to_integer(unsigned(write_ptr_reg))) <= push_data_i; 
      -- It writes the incoming data (push_data_i) to the corresponding position in the FIFO. 

      -- It expects an intiger as the position in the array. Therefore the 'to_intiger' function. 

Вызов to_integer в пакете numeric_std преобразует двоичное значение без знака в целое число с диапазоном от 0 до максимального целочисленного значения, выраженного длиной бита двоичного значения. Для FIFO_DEPTH 4 с диапазоном от указателя FIFO_DEPTH - 1 DOWNTO 0, что будет представлять натуральные числа от 0 до 15.

Это контрастирует с размером массива FIFO (количество слов, равным 4.

Взгляните на Xilinx ISim User Guide (UG660) на ISIM, найденный в ISE 14.7 показывает, что диапазон индекса связан проверка должна происходить всегда:

rangcheck option.png

анализа, разработка и моделирования вашего дизайна, и это испытательный стенд в другом инструменте VHDL (ghdl) показывает проверку границ погрешности для индексируемой записи (код VHDL показано выше).

IEEE Std 1076-2008 8.3 индексированные имена, пункт 3 последнее предложение:

Это ошибка, если значение индекса не принадлежит диапазону соответствующего индекса диапазона массива.

Проверка диапазона индексов требуется по стандарту VHDL, а когда это выполняется, указывается ошибка модели, захваченная симулятором. Для 4-битового двоичного адреса указатель диапазон индекса типа массива должен быть объявлены

type reg_type is array (2 ** FIFO_DEPTH - 1 downto 0) of STD_LOGIC_VECTOR (FIFO_WIDTH-1 downto 0); 

, в котором не было бы тогда соответствующим расположение FIFO-массив для каждого значения индекса указателя.

внесении этого изменения в результатах reg_type декларации в модели, которая будет работать до 800 нс:

fifo_testbench.png

Вы можете видеть из информационной панели сигнала, что маркер показан на ваших 165 нс, которая только совпадающий с падающим фронтом clk и что события предвидения в модели получены из нарастающего фронта clk, представляющего запись в индекс 14 (E).

Это не совпадает с первой операцией для адреса вне диапазона индекса типа массива.

Я считаю, что ISIM не выполняет проверку диапазона индекса здесь (и должен быть). Помимо того, что модель написали объекты фантомного элемента вне диапазона индекса типа массива, в конечном итоге развращение имитационной модели до точки отказа на заднем фронте clk.

Этот вопрос может быть подтвержден путем внесения вышеуказанного изменения в объявление типа reg_type.

В то время как ваши собственные формы волны спутать вы можете увидеть, что комментирование push_valid_i <= '1'; в цикле 2 в результатах TestBench ни в коем приращению указателя:

fifo_testbench_valid_commented.png

И моделирования работает весь 800 нс, потому что есть нет индексированных операций вне диапазона исходного диапазона регистров reg_type.

Таким образом, у вас есть ошибка проверки диапазона, которая должна быть обнаружена во время моделирования, а ее нет, и ее можно вылечить, изменив размер массива для типа reg_type.

Из комментария цепи на ваш вопрос:

Тип reg_type был неправильный размер, чтобы использовать в качестве адреса для указателей правого? Я проанализирую его подробно, поскольку я не совсем понял его и вернусь к вам

Да, размер массива, указанный в объявлении типа reg_type, неверен.

Мы становимся анекдотически осведомленными о проблемах с инструментами с течением времени. Независимо от того, может ли быть включена проверка диапазона индексов в ISIM, несмотря на то, что она всегда включена, вероятно, будет проблемой версии ISIM, и в противном случае это может быть подтверждено экспериментами.

Существует также несколько альтернатив при сохранении полезности ISIM для моделирования. Вы можете синтезировать дизайн, сообщить об ошибке. Вы могли бы использовать другой симулятор, который, как известно, выполнял проверку диапазона индексов, это не помешало бы вам использовать ISIM после того, как все проверки границ будут выполнены и, как известно, будут действительными (и повторно подтверждены после любых изменений, влияющих на границы).

Проблема в ISIM также может отображаться в подмножестве возможных случаев, требующих проверки диапазона индекса. (VHDL сложна для реализации).

Если есть недостаток, и Xilinx будет уведомлен, они (в конечном итоге) исправит проблему в более поздней версии ISIM.

Сообщите нам, если изменяется размер массива reg_type.

+0

С изменением размера массива reg_type. Но я до сих пор не понимаю. Если FIFO_DEPTH равно 4, почему это 15 - 0 для адреса? – aripod

+0

С этим также я получаю массив 16x4. Таким образом, полное условие (там, где есть 4 элемента, введенные в FIFO), никогда не поднимает флаг full_reg, когда write_ptr_succ = read_ptr_reg. – aripod

+0

Четыре бита: «000» = 0, «0001» = 1, «0010» = 2, «0011» = 3, «0100» = 4, «0101» = 5, «0110 = 6,« 0111 »= 7 , "1000" = 8, "1001" = 9, "1010" = 10, "1011" = 11, "1100 = 12," 1101 "= 13," 1110 "= 14 и" 1111 "= 15. для 'to_integer (без знака (write_ptr_reg))'. Ваш testbench нажимает столько элементов, сколько может. Полное является результатом сопоставления указателей записи и чтения ('write_ptr_succ = read_ptr_reg'). Увеличение размера массива создает больший размер адреса соответствия FIFO. Существует зависимость log2 между шириной адреса и глубиной FIFO. Для 4-х глубинных FIFO требуется преобразование и сравнение двух бит ptr. – user1155120