2015-11-11 2 views
-1

Итак, в моем последнем школьном проекте мне пришлось реализовать в VHDL алгоритм, который вычислял комплексное среднее значений различных наборов значений.vhdl fsm counter conditions

Нам пришлось использовать FSM с внешними счетчиками для управления адресами памяти и управления изменениями состояния. Итак, когда я закончил набор, я хотел перейти из состояния 3 в состояние 4, состояние 4 в состояние 5 и состояние 5 в init. Это делается с использованием сигнала под названием Олин (для счетчика memIn) и OlOut (для счетчика memOut)

entity control is 
    Port (clk : in STD_LOGIC; 
      rst : in STD_LOGIC; 
      finish: out STD_LOGIC; 
      op1, op2 : out STD_LOGIC; 
      muxes : out STD_LOGIC_VECTOR (3 downto 0); 
      enables : out STD_LOGIC_VECTOR (2 downto 0); 
      cenO, cenI : out STD_LOGIC; 
      olIn, olOut : in STD_LOGIC; 
      we: out STD_LOGIC); 
end control; 

architecture Behavioral of control is 

type fsm_states is (s_init, load, cycle1, cycle2, cycle3, cycle4, cycle5, done); 
signal next_state, state: fsm_states; 
signal sfinish: STD_LOGIC; 

begin 
    state_reg : process(clk,rst) 
    begin 
     if (clk'event and clk='1') then 
      if(rst = '1') then 
       state <= s_init; 
      else 
       state <= next_state; 
      end if; 
     end if;    
    end process; 

    state_comb: process(state,sfinish, olIn, olOut) 
    begin 
     next_state <= state; 
     case state is 
      when s_init => 
       next_state <= load; 
      when load => 
       next_state <= cycle1; 
      when cycle1 => 
       next_state <= cycle2; 
      when cycle2 => 
       next_state <= cycle3; 
      when cycle3 => 
       next_state <= cycle4; 
      when cycle4 => 
       if(olIn='1') then 
        next_state <= cycle5; 
       else 
        next_state <= cycle1; 
       end if; 
      when cycle5 => 
       if(olOut='1') then 
        next_state <= done; 
       else 
        next_state <= s_init; 
       end if; 
      when done => 
       next_state <= done; 
     end case; 
    end process; 

    process (state,olIn) 
    begin 
     case state is 
      when s_init => 
       cenI <= '1';  
       cenO <= '0'; 
       muxes <= "XXXX"; 
       enables <= "X11";  
       op1 <= 'X'; 
       op2 <= 'X'; 
       sfinish <= '0'; 
       we <= '0'; 
      when load => 
       cenI <= '0'; 
       cenO <= '0'; 
       muxes <= "XXX0"; 
       enables <= "110"; 
       op1 <= 'X'; 
       op2 <= 'X'; 
       sfinish <= '0'; 
       we <= '0'; 
      when cycle1 => 
       cenI <= '0'; 
       cenO <= '0'; 
       muxes <= "0001"; 
       enables <= "110"; 
       op1 <= '0'; 
       op2 <= '0'; 
       sfinish <= '0'; 
       we <= '0'; 
      when cycle2 => 
       cenI <= '0'; 
       cenO <= '0'; 
       muxes <= "1011"; 
       enables <= "110"; 
       op1 <= '0'; 
       op2 <= '0'; 
       sfinish <= '0'; 
       we <= '0'; 
      when cycle3 => 
       cenI <= '1'; 
       cenO <= '0'; 
       muxes <= "X101"; 
       enables <= "010"; 
       op1 <= '1'; 
       op2 <= '0'; 
       sfinish <= '0'; 
       we <= '0'; 
      when cycle4 => 
       cenI <= '0'; 
       cenO <= '0'; 
       muxes <= "XXXX"; 
       enables <= "100"; 
       op1 <= 'X'; 
       op2 <= 'X'; 
       sfinish <= '0'; 
       we <= '0'; 
       if(olIn = '1') then 
        we <= '1'; 
        cenO <= '1'; 
       end if; 
      when cycle5 => 
       cenI <= '0'; 
       cenO <= '1'; 
       muxes <= "XXXX"; 
       enables <= "110"; 
       op1 <= 'X'; 
       op2 <= 'X'; 
       sfinish <= '0'; 
       we <= '0'; 
       if (olIn = '1') then 
        we <= '1'; 
        cenO<= '1'; 
        cenI <= '1'; 
       end if; 
      when done => 
       cenI <= '0'; 
       cenO <= '0'; 
       muxes <= "XXXX"; 
       enables <= "000"; 
       op1 <= 'X'; 
       op2 <= 'X'; 
       sfinish <= '1'; 
       we <= '0'; 
     end case; 
    end process; 

    finish <= sfinish; 
end Behavioral; 

так, как я реализованный счетчик memIn было так:

library IEEE; 

use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.STD_LOGIC_ARITH.ALL; 
use IEEE.STD_LOGIC_UNSIGNED.ALL; 
use ieee.numeric_std.all; 


entity counter is 
    generic (N : integer := 4; -- numero de bits do contador global 
      Ni : integer := 3; -- numero de bits do contador local 
      I : integer := 0 -- valor inicial dos contadores 
      ); 
    Port ( 
      clk : in STD_LOGIC; 
      rst: in STD_LOGIC; 
      cen : in STD_LOGIC; 
      ol : out STD_LOGIC; 
      counter : out STD_LOGIC_VECTOR (N-1 downto 0)); 
end counter; 

architecture Behavioral of counter is 
    signal counter2: std_logic_vector (Ni-1 downto 0); 
    signal tmp, i_aux: std_logic_vector (N-1 downto 0); 
begin 

    i_aux<=std_logic_vector(to_unsigned(I, i_aux'length)); 

    process (clk, rst, cen, i_aux, counter2) 
    begin 
     if (rst ='1') then 
      tmp <= i_aux; 
      counter2 <= i_aux(Ni-1 downto 0); 
     elsif (clk'event and clk = '1') and (cen = '1') then 
      ol <= '0'; 
      tmp <= tmp + 1; 
      counter2 <= counter2 + 1; 
     end if; 
     if (counter2 = "1010") then 
      ol <= '1'; 
     end if; 
     if (counter2 = "1011") then 
      ol <= '0'; 
      counter2 <= (0 => '1', others => '0'); 
     end if; 
    end process; 
    counter <= tmp; 

end Behavioral; 

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

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

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

Бит 0 счетчика: выход не входит в память (я должен оставаться в одном и том же адресе памяти для двух циклов), поэтому счетчик должен рассчитывать на восемь (4 адреса памяти (от 1 до 4) Адрес памяти ноль для подготовки данных.

Как я мог бы сделать это лучше? Должен ли я просто поставить обнаружение внутри процесса и пытался труднее получить детектор матча, который работал?

Благодаря

+0

Что такое «обнаружение шаблонов» и какой процесс? Я вижу четыре процесса и не могу сказать, о ком вы говорите. –

+0

@BrianDrummond Извините, добавили эту информацию на исходное сообщение. Обнаружение паттерна - это обнаружение числа 1010 в компоненте счетчика. Процесс - это процесс внутри компонента счетчика. –

+0

Почему вы синтезируете логику с присвоениями «X»? Это означает защелки с включенными комбинаторными значениями состояний. Используйте назначения по умолчанию перед оператором case и не считайте защелки. Вероятно, это улучшит время и позволит использовать комбинаторные «детекторы». Не является [минимальным, полным и проверяемым примером] (http://stackoverflow.com/help/mcve) - связь между «ol» и «olIn» и «olOut» не отображается, а также цель тактовой частоты , 'control' не анализируется без контекстного предложения. Не смешивайте std_logic_arith/unsigned и numeric_std. – user1155120

ответ

1

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

В качестве синхронного процесса его список чувствительности должен быть process (clk, rst) и ничего больше, и образец теста должен быть в пределах if rising_edge(clk).

ОДНАКО, это должно быть написано с пониманием how signal and variable assignments are scheduled. В частности, если вы этого не поняли, вы можете обнаружить, что события происходят по циклу позже, чем ожидалось. Два подхода может помочь:

  1. Если counter2 является переменным, то сравнения происходят на обновленном значении, и установите ol при counter2 = 10.
  2. или вы могли бы просто заранее Сравнение цикла, например, if (counter2 = "1001") then, так что флаг устанавливается в том же цикле, что counter2становится 10. Это фактически приведет к более быстрому оборудованию, поскольку сравнение и приращение происходят параллельно, работая с зарегистрированными входами, вместо того, чтобы выполнять сравнение на выходе комбинационного сумматора.

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

+0

Хорошо, я продолжу анализ вашего ответа и большое спасибо за ввод! –

+0

@Brian почему он непопулярен в некоторых кругах? Я широко использовал его в своих академических проектах, а также несколько профессиональных проектов. – wahab

+0

@wahab: Я сам задаю этот вопрос! Но все еще публикуются новые книги VHDL, которые, похоже, «не получают» и даже не рассматривают его преимущества как недостатки. Возможно, они все еще спорят о седой старой «Мили/Муре»? –

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