2015-05-18 2 views
0

У меня есть небольшая проблема с моим конечным автоматом, который у меня есть , написанный в VHDL в последнее время. Я попытался создать «интеллектуальный» счетчик , запускаемый часами с частотой 2 Гц. Этот счетчик встроен в одно состояние FSM и запускается нажатием кнопки на плате DE2.Счетчик внутри FSM в VHDL

Во-первых, вся система находится в состоянии ожидания, и если я нажимаю эту кнопку, состояние изменилось к подсчету и счетчик начнет увеличиваться и его текущее значение отображается на дисплее. После достижения значения по модулю состояние СЧЕТЧИК возвращается к IDLE, а счетчик устанавливается на ноль.

Моя проблема в том, что счетчик не работает правильно - значение счетчика было слишком велико. Поэтому я попытался решить эту проблему с помощью этой конструкции: если (clk_tick'event и clk_tick = 1), то ..., есть ошибки в синтез: Ошибка (10822): ошибка HDL в Citac_FSM.vhd (57) : не могли бы реализовать регистров для заданий по этому фронту тактового импульса

ошибка (10821): HDL ошибки при Citac_FSM.vhd (62): не может вывести зарегистрировать «AUTOMAT: FLG», потому что его поведение не соответствует любой поддерживаемый регистр модель

У кого-нибудь есть идея решить эту проблему? И что это правильный способ для записи синхронизируемых часов FSM с двумя (или более) синхронизирующими источниками?

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 
use ieee.std_logic_unsigned.all; 

ENTITY Counter_FSM IS 
GENERIC (
     REGSIZE : integer := 8; -- range of counter 
     MODULO : natural := 50 -- modulo value 
     ); 
PORT (
     CLK  : IN STD_LOGIC; -- puls 50 MHz 
     CLK_tick : IN STD_LOGIC; -- puls 2 Hz 
     RESET : IN STD_LOGIC; -- reset 
     READY : OUT STD_LOGIC; -- counter is ready to start 
     START_C : IN STD_LOGIC; -- start of counting 
     DOUT   : OUT STD_LOGIC_VECTOR(REGSIZE - 1 downto 0) --out 
    ); 
END Counter_FSM; 


ARCHITECTURE Behavior OF Counter_FSM is 

    type counterState is (IDLE, COUNTING); -- states of FSM 
    signal currCounterState : counterState;  -- current state 
    signal nextCounterState : counterState; -- next state 
    signal cnt : std_logic_vector(REGSIZE - 1 downto 0); -- counter 

    begin 

    UPDATE: process(RESET, CLK) 
     begin 
      if (RESET = '0') then 
       currCounterState <= IDLE; 
      elsif (CLK'event and CLK = '1') then 
       currCounterState <= nextCounterState; 
      end if; 
    end process; 


    COMBI: process (clk_tick, start_c, currCounterState) 
     variable flg : std_logic := '0'; 
     begin 
      if (clk_tick'event and clk_tick = '1') then 
       flg := '1'; 
      end if; 

      case currCounterState is 
       when IDLE => 
        cnt <= (others => '0'); -- counter value = zero 
        READY <= '1';    -- we can start 
        if (start_c = '1') then -- if button is pushed 
        nextCounterState <= COUNTING; -- go to COUNTING 
        end if; 

       when COUNTING => 
        READY <= '0'; 
        if (flg = '1') then -- Was there impuls of 2 Hz? 
         cnt <= cnt + 1;   -- yes -> incrementing 
         flg := '0'; 
         if (cnt = MODULO) then -- if cnt = MODULO 
          cnt <= (others => '0'); -- then cnt = zero 
          nextCounterState <= IDLE; 
         end if; 
        end if; 

       when others => 
        nextCounterState <= IDLE; 
      end case; 
     -- OUTPUT 
      douT <= cnt;  
     end process; 

end Behavior; 

Большое спасибо.

Мирек

P.S .: Я сожалею, что мой английский не так хорошо.

+0

Второй процесс представляет собой сочетание тактовой и разблокированной логики, которая, вероятно, запутывает инструмент синтеза. Отделите их. И убедитесь, что счетчик синхронизирован: в настоящее время он разблокирован.Или лучше, напишите всю партию как более простой, более мелкий однопроцессорный конечный автомат. –

+0

Как генерируется 'clk_tick'? Является ли это симметричным тактовым импульсом или импульсом 1 из 1/50 МГц, возникающим один раз каждые 500 мс? –

ответ

0

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

Вы могли бы написать что-то вроде этого:

when COUNTING => 
    nextCounterState <= COUNTING; 
    READY <= '0'; 
    if (prev_clk_tick = '0' and clk_tick = '1') then 
     next_cnt <= cnt + 1;   -- yes -> incrementing 
     if (cnt = MODULO) then 
      next_cnt <= (others => '0'); 
      nextCounterState <= IDLE; 
     end if; 
    end if; 

Я оставлю вас, чтобы добавить дополнительные регистры.

0

Я уже решил свою проблему :-). Я переместил счетчик в отдельный процесс, а затем привязал сигналы ведьм к FSM. Таким образом, он работает очень хорошо.

При чтении кнопки я использую два D-триггера для синхронизации в данный момент.

я должен сделать замечание по стилю программирования VHDL - это слишком отличается от «нормального» программирования как язык C :-D

Хорошего дня!

Смежные вопросы