VHDL - FSM не запускается (ТОЛЬКО при симуляции времени)

Я работаю над своей магистерской диссертацией, и я новичок в VHDL, но все же мне нужно реализовать некоторые сложные вещи. Это одна из самых простых структур, которую мне приходилось писать, но я все еще сталкиваюсь с некоторыми проблемами.

Это автомат, реализующий 24-битный регистр сдвига с активным низким синхронизирующим сигналом (для программирования ЦАП). Это просто конец сложной цепочки разработок, которую я создал для своего проекта. Я следовал модели конечного автомата, насколько мог.

Поведенческая симуляция работает нормально, на самом деле вся созданная мною цепочка проработок отлично работает в том, что касается поведенческой симуляции. Однако, как только я пробую имитацию Post-translate, все начинает идти не так: много выходных сигналов «X».

С этим простым регистром сдвига я НЕ получаю никакого «X», однако я не могу перейти к фазе load_and_prepare_data. Кажется, что current_state изменяется (проверяя некоторые сигналы), но разработка не продолжается.

Имейте в виду, что, поскольку я новичок в этом языке, я понятия не имею, какие временные ограничения мне следует установить для этого FSM (и я бы все равно не знал, как их записать в top.ucf)

Вы видите, что не так? заранее спасибо

ИЗМЕНИТЬ

Я последовал вашим советам и очистил конечный автомат, используя процесс с одним состоянием. Я все еще сомневаюсь, «куда что ставить», но мне очень нравится новая реализация. Как бы то ни было, теперь я получаю чистую поведенческую симуляцию, но на всех выходных данных в посттрансляционной симуляции отображается «Х». Чем это вызвано? Я отправлю и новый код, и тестовый стенд:

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    14:44:03 11/28/2014 
-- Design Name: 
-- Module Name:    dac_ad5764r_24bit_sr_programmer_v2 - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: This is a PISO shift register that gets a 24bit parallel input word.
--              It outputs the 24bit input word starting from the MSB and enables
--              an active low ChipSelect line for 24 clock periods.
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
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;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity dac_ad5764r_24bit_sr_programmer_v2 is
    Port ( clk : in  STD_LOGIC;
           start : in  STD_LOGIC;
           reset : in  STD_LOGIC; -- Note that this reset is for the FSM not for the DAC
           reset_all_dac : in STD_LOGIC;
           data_in : in  STD_LOGIC_VECTOR (23 downto 0);
           serial_data_out : out  STD_LOGIC;
           sync_out : out  STD_LOGIC; -- This is a chip select
           reset_out : out STD_LOGIC;
           busy : out STD_LOGIC
         );
end dac_ad5764r_24bit_sr_programmer_v2;

architecture Behavioral of dac_ad5764r_24bit_sr_programmer_v2 is

-- Stati
type state_type is (idle, load_and_prepare_data, transmission);
--ATTRIBUTE ENUM_ENCODING : STRING; 
--ATTRIBUTE ENUM_ENCODING OF state_type: TYPE IS "001 010 100";
signal state: state_type := idle;
--signal next_state: state_type := idle;

-- Clock counter
--signal clk_counter_enable : STD_LOGIC := '0';
signal clk_counter : unsigned(4 downto 0) := (others => '0');

-- Shift register
signal stored_data: STD_LOGIC_VECTOR (23 downto 0) := (others => '0');

begin

FSM_single_process: process(clk)
begin
    if rising_edge(clk) then
        if reset = '1' then
            serial_data_out <= '0';
            sync_out <= '1';
            reset_out <= '1';
            busy <= '0';
            state <= idle;
        else
            -- Default
            serial_data_out <= '0';
            sync_out <= '1';
            reset_out <= '1';
            busy <= '0';

            case (state) is
                when transmission =>
                    serial_data_out <= stored_data(23);
                    sync_out <= '0';
                    busy <= '1';
                    clk_counter <= clk_counter + 1;
                    stored_data <= stored_data(22 downto 0) & "0";
                    state <= transmission;
                    if (clk_counter = 23) then
                        state <= idle;
                    end if;
                when others => -- Idle
                    if start = '1' then
                        serial_data_out <= data_in(23);
                        sync_out <= '0';
                        reset_out <= '1';
                        busy <= '1';
                        stored_data <= data_in;
                        clk_counter <= "00001";
                        state <= transmission;
                    end if;
            end case;

--            if (reset_all_dac = '1') then
--              reset_out <= '0';
--          end if;
        end if;
    end if;
end process;


end;

И тестовый стенд:

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 dac_ad5764r_24bit_sr_programmer_tb IS
END dac_ad5764r_24bit_sr_programmer_tb;

ARCHITECTURE behavior OF dac_ad5764r_24bit_sr_programmer_tb IS 

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

    COMPONENT dac_ad5764r_24bit_sr_programmer_v2
    PORT(
         clk : IN  std_logic;
         start : IN  std_logic;
         reset : IN  std_logic;
         data_in : IN  std_logic_vector(23 downto 0);
         serial_data_out : OUT  std_logic;
         reset_all_dac : IN std_logic;
         sync_out : OUT  std_logic;
         reset_out : OUT  std_logic;
         --finish : OUT  std_logic;
         busy : OUT  std_logic
        );
    END COMPONENT;


   --Inputs
   signal clk : std_logic := '0';
   signal start : std_logic := '0';
   signal reset : std_logic := '0';
   signal data_in : std_logic_vector(23 downto 0) := (others => '0');
   signal reset_all_dac : std_logic := '0';

    --Outputs
   signal serial_data_out : std_logic;
   signal sync_out : std_logic;
   signal reset_out : std_logic;
   --signal finish : std_logic;
   signal busy : std_logic;

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

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: dac_ad5764r_24bit_sr_programmer_v2 PORT MAP (
          clk => clk,
          start => start,
          reset => reset,
          data_in => data_in,
          reset_all_dac => reset_all_dac,
          serial_data_out => serial_data_out,
          sync_out => sync_out,
          reset_out => reset_out,
          --finish => finish,
          busy => busy
        );

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


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
      wait for clk_period*10;
      reset <= '1' after 25 ns;
      wait for clk_period*1;
      reset <= '0' after 25 ns;
      wait for clk_period*3; 
      reset_all_dac <= '1' after 25 ns;
      wait for clk_period*1;
      reset_all_dac <= '0' after 25 ns;
      wait for clk_period*5; 
      data_in <= "111111111111111111111111" after 25 ns;
      wait for clk_period*3;
        start <= '1' after 25 ns;
      wait for clk_period*1;
        start <= '0' after 25 ns;


      wait;
   end process;

END;

ОБНОВЛЕНИЕ 1

Обновлено с учетом последнего дизайна: этот код не вызывает никакого «X» (не могу понять, почему, это не так, но предыдущий сделал). Однако он не запускается (в моделировании POST-TRANSLATE), как и первые три процесса, и сигнал sync_out застревает на 0, тогда как по умолчанию он должен быть равен «1».

имитация 1

ОБНОВЛЕНИЕ 2

Я изучал технологическую схему, начиная с проблемы sync_out = 0: она реализована с помощью FDS, S - это сигнал сброса FSM, D исходит от LUT3 с I = state & reset & start и INIT = 45 = "00101101. ". Я искал этот LUT3 при моделировании и заметил, что он имеет INIT = "00000000"!

Что-то мне не хватает в том, как запустить эту симуляцию? Кажется, что не все LUT в дизайне выставлены!

ОБНОВЛЕНИЕ 3. Кажется, что в моделировании Post-Translate есть какие-то ошибки, или я по какой-то причине неправильно его настраиваю: модели Post-Map и Post-PAR работают и отображают некоторые результаты . Однако есть странная ошибка: регистр stored_data не обновляется полным вектором data_in, после чего автомат работает правильно и выводит сохраненные данные. Я посмотрел на технологическую схему сразу после синтеза, и по какой-то причине биты 23,22,21,19,18 не связаны с соответствующим битом data_in. Вы можете увидеть эффект на этом скриншоте из моделирования Post-Map. То же самое происходит и в Post-PAR, но похоже, что эти проблемы возникают непосредственно из-за синтеза! Stored_Data = / = Data_in

Решено: странный результат возникает при оптимизации синтеза. Инструмент понял, что предыдущий блок в цепочке разработки никогда не будет выводить бит, отличный от 0 для этого конкретного бита. Моя ошибка заключалась в том, что я предполагал, что могу протестировать единственный блок: на самом деле я тестировал блок, синтезированный для ПЛИС с учетом всего остального в проекте!

Спасибо всем, кто мне помог, буду следовать вашим советам!


person FlyerDragon    schedule 12.01.2015    source источник
comment
попробуйте перевести автомат в следующее состояние в процесс синхронизации (т. е. синхронизированный), это упростит анализ.   -  person Sam Palmer    schedule 12.01.2015
comment
другое предложение, поскольку я не вижу ничего явно очевидного, что не так в VHDL. Удостоверились ли вы, что правильно управляете сигналами от испытательного стенда или модуля верхнего уровня, т.е. пуск не происходит на 1.   -  person Sam Palmer    schedule 12.01.2015
comment
также попробуйте синхронизировать FSM_output_reg_process.   -  person Sam Palmer    schedule 12.01.2015
comment
Вы аннотируете список соединений после синтеза значениями задержки SDF? Это может привести к неожиданным результатам, если задержки в дереве тактовых импульсов не учитываются как приводящие к недопустимым проскальзыванию цикла и другим ошибкам моделирования.   -  person Kevin Thibedeau    schedule 12.01.2015
comment
Спасибо за предложения! @SamPalmer, тестовый стенд должен быть в порядке, и он работает в поведенческом режиме. Зачем мне отслеживать эти процессы? AFAIK эти процессы должны быть асинхронными, чтобы они могли разрабатывать, как только у них есть входы, тогда их выходы используются в синхронизированных процессах.   -  person FlyerDragon    schedule 12.01.2015
comment
@KevinThibedeau Я новичок в программном обеспечении, вы можете быть более точными? Как я могу это проверить? Я должен сказать, что я работаю над Xilinx Spartan-6 и использую ISE Webpack с ISim для моделирования.   -  person FlyerDragon    schedule 12.01.2015
comment
по личному опыту, это значительно упрощает отладку и, как правило, является хорошей практикой для временного анализа и предотвращает синтез защелок. Также я думаю, что видел проблему, вам нужно добавить случай для данных load_and_prepare в конечный автомат, иначе он просто вернется в режим ожидания?   -  person Sam Palmer    schedule 13.01.2015
comment
Это не так, next_state в load_and_prepare_data - это передача. Имейте в виду, что ПОВЕДЕНЧЕСКАЯ симуляция хороша, поэтому с функциональной точки зрения все в порядке. Проблема возникает из-за того, как реализован код, и, я думаю, из-за присущих ему задержек портов.   -  person FlyerDragon    schedule 13.01.2015


Ответы (2)


Я предпочитаю однопроцессную форму конечного автомата, которая чище, проще и гораздо менее подвержена ошибкам, таким как ошибки списка чувствительности. Я бы также поддержал пункты отличного ответа Пеббельса. Однако я не думаю, что здесь проблема.

Одна вещь, о которой следует помнить при моделировании пост-синтезатора и пост-ФАР, - это то, что их модель времени отличается от поведенческой модели. Поведенческая модель следует простым правилам, описанным в этом ответе, и обеспечивает что в типичном потоке проектирования вы можете сразу перейти к аппаратному обеспечению - без постсинтезирующего моделирования, не беспокоясь.

На самом деле, я использую моделирование после синтеза или PAR только в том случае, если я преследую подозреваемую ошибку в инструменте. (То есть для схем FPGA, а не ASIC!)

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

В поведенческом моделировании таких неприятностей поможет небольшая дисциплина. Но то же самое нельзя сказать о моделировании после PAR.

Ваша тестовая среда, вероятно, настроена так же, как и поведенческая модель. А если так, то, скорее всего, проблема.

Вот что я делаю в этой ситуации: я не претендую на официальный авторитет, только на опыт. Он также хорошо работает при сопряжении ПЛИС с моделями внешней памяти с реалистичными временными интервалами.

1) Я предполагаю, что простая (поведенческая) временная модель работает правильно для всех ВНУТРЕННИХ сигналов проекта.

2) Я не предполагаю ничего подобного для входов и выходов из проекта.

3) Я принимаю к сведению расчетную настройку и время удержания на входах, (а) из таблицы данных FPGA или лучше, (б) из значений наихудшего случая, показанных в отчете после синтеза или после PAR, и структурирую < сильный> тестовый стенд вокруг них. Рабочий пример: время установки 1 нс, время удержания 2 нс, период тактирования 10 нс. Это означает, что любой ввод между 2 и 9 нс после фронта тактового сигнала гарантированно будет правильно считан. Выбираю (произвольно) 5 нс.

signal_to_fpga <= driving_value after 5 ns;

(Обратите внимание, что Xilinx делает это абсурдно противоречащим интуиции, выражая их как «смещение входа / выхода до / после», которое относится к времени к предыдущему или будущему фронту часов вместо того, на которое вы смотрите)

В качестве альтернативы, если в реальном мире ввод осуществляется от ЦП или памяти, я использую временные характеристики этого устройства из таблицы данных.

4) Я отмечаю время истечения времени ожидания для наихудшего случая, указанное в таблице данных или отчете, и структурирую дизайн вокруг них. (скажем, 7 нс)

fpga_output_pin <= driving_value after 7 ns;

Обратите внимание, что это предложение «после» явно игнорируется при синтезе; однако обратная аннотация после синтеза представит что-то очень похожее.
5) Если это окажется недостаточно хорошим, тогда (возможно, в компоненте оболочки, чтобы избежать загрязнения синтезируемого кода) повысить точность, например

fpga_output_pin <= 'X' after 1 ps, driving_value after 7 ns;

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

7) Я исправляю эти сбои. Это может включать добавление реалистичных задержек перед тестированием значений, выводимых из проекта. Это может быть итеративный процесс.

Теперь у меня есть разумные основания полагать, что имитационная модель после PAR попадет прямо в тестовый стенд и заработает.

person user_1818839    schedule 13.01.2015
comment
Большое спасибо за ваш ответ, я пробормотал об этом пару дней и как-то попробовал ваше решение, но у меня все еще есть проблемы. См. Правку в моем исходном сообщении, еще раз спасибо! - person FlyerDragon; 15.01.2015
comment
Кроме того, я понимаю, что лучше указать ВСЕ выходы в разделе сброса / запуска и непосредственно перед CASE с оператором по умолчанию. Затем переназначьте все переменные внутри корпуса. Верный? А как насчет ВНУТРЕННИХ сигналов? Как насчет блока операторов по умолчанию непосредственно перед if (reset = 1) then? - person FlyerDragon; 15.01.2015
comment
Я не вижу состояния load_and_prepare_data? - person user_1818839; 15.01.2015
comment
Я думаю, что в этой реализации нет необходимости иметь выделенное состояние для загрузки данных, я просто делаю это при обнаружении запуска. Я снова обновляю код своими недавними изменениями. - person FlyerDragon; 15.01.2015
comment
Сим отображает только сигналы верхнего уровня. В поведенческом симуляторе вы можете углубиться в сам модуль и посмотреть (например) Current_State в окне симуляции. Обычно это не работает для симуляторов после маршрута, но вы можете выделить несколько битов на портах, отражающих их. Да, это боль - постмаршрутная симуляция - это боль - см. Пункт 3 ответа! - person user_1818839; 15.01.2015
comment
Некоторые новые подробности смотрите в моем обновлении. Имейте в виду, что у меня включен Keep_Hierarchy для целей отладки (это уже базовый блок в моем огромном дизайне). - person FlyerDragon; 15.01.2015
comment
Моделирование Post-Map и Post-PAR работает, но я обнаружил странную ошибку в технологической схеме после просмотра моделирования: подробности см. В моем обновлении. Спасибо большое за вашу помощь! - person FlyerDragon; 15.01.2015

Вот несколько советов по улучшению вашего кода:

  1. Вы можете удалить зависимости Xilinx от UNISIM, потому что вы не используете какие-либо Xilinx Primitves.
  2. Применение атрибута ENUM_ENCODING не влияет на кодирование состояния, если вы также не определите атрибут FSM_ENCODING и не установите его значение для пользователя. Кодирование One-Hot можно принудительно установить, установив для параметра FSM_ENCODING значение one-hot. Обычно синтез достаточно умен, чтобы найти лучшую кодировку.
    подробнее ...
  3. Ни один из ваших регистров не имеет значения по умолчанию:
    signal current_state : state_type := idle;
  4. Your FSM is no FSM in the eyes of Xilinx synthesis tool (XST). I'm sure if you look into your synthesis report, you won't find that XST reports a FSM for current_state.
    So what's wrong with your FSM?
    • Your FSM has no initial state.
    • У вашего FSM есть несколько состояний сброса (простоя, load_and_prepare_data)
    • У вашего FSM нет перехода от простоя к load_and_prepare_data (сброс - это без перехода)
    • Запись переходов next_state для текущего состояния может заставить XST думать, что это не конечный автомат, и достаточно присвоения по умолчанию next_state <= current_state;.
  5. Если вы измените тип сигнала clk_counter на unsigned, вы сможете выполнять арифметические операции намного проще.
    increment: clk_counter <= clk_counter + 1;
    clear: clk_counter <= (others => '0');
    compare: if (clk_counter = 23) then
  6. Использование сигнала состояния конечного автомата вне процессов конечного автомата - плохой стиль.

    FSM_next_state_process: process(current_state, start,  clk_counter, reset_all_dac)
    begin
      next_state  <= current_state;
    
      OutReg_busy        <= '1';
      OutReg_reset_out   <= '1';
      OutReg_sync_out    <= '1';
      clk_counter_enable <= '0';
    
      case (current_state) is
        when idle =>
          OutReg_busy      <= '0';
          if (reset_all_dac = '1') then
            OutReg_reset_out <= '0';
          end if;
    
        when load_and_prepare_data =>
          next_state <= transmission;
    
        when transmission =>
          clk_counter_enable <= '1';
          OutReg_sync_out <= '0';
    
          if (clk_counter = 23) then
            next_state <= idle;
          end if;
    
        when others =>
          next_state <= idle;
    
      end case ;
    end process;
    
person Paebbels    schedule 12.01.2015
comment
Спасибо за ответ, я прокомментирую ваши подсказки: (1) Не знал, это было автоматически сгенерировано, спасибо! - person FlyerDragon; 13.01.2015
comment
(2) Еще раз спасибо, я этого не знал, в любом случае эти строки прокомментированы. Это была редакция, которую я пытался просто увидеть, поэтому ничего не происходило: синтез после этого повторно оптимизировал кодировку! - person FlyerDragon; 13.01.2015
comment
(3) Я добавил значение по умолчанию для всех внутренних регистров, незначительные вещи изменились при моделировании, но я думаю, что лучше их все равно включать :) - person FlyerDragon; 13.01.2015
comment
(4) Да. Обнаружен конечный автомат ‹FSM_3› для сигнала ‹current_state›. Состояния = 3 Перехода = 10 Входов = 3 Выхода = 3 Тактовый сигнал = clk (возрастающий_ край) Сброс = сброс (положительный) ResetType = синхронный ResetState = холостой ход PowerUpState = холостой ход Кодирование = авто Реализация = LUT. - person FlyerDragon; 13.01.2015
comment
(5) Реализация в любом случае должна быть такой же: найден 5-битный сумматор для сигнала ‹clk_counter [4] _GND_76_o_add_3_OUT›, созданного в строке 1241. - person FlyerDragon; 13.01.2015
comment
(6) clk_counter_process - это просто еще одна часть FSM_sync_process. Как я уверен, вы поняли, что мне нужно подсчитать тактовые циклы, чтобы определить, что передача закончилась. Это связано с тем, что микросхема ЦАП отклоняет любой последовательный ввод, который не связан с сигналом SYNC = 0, ровно в течение 24 тактовых циклов. - person FlyerDragon; 13.01.2015
comment
Спасибо за все эти советы, но симуляция времени по-прежнему не работает. Есть ли другие предложения? - person FlyerDragon; 13.01.2015
comment
@FlyerDragon Не могли бы вы обновить свой код в вопросе? Re (4): Ничего страшного :) XST ищет несколько шаблонов FSM, и если он найдет один, вы можете быть счастливы. - person Paebbels; 13.01.2015