VHDL «генерирует» состояния FSM

У меня есть переменное количество модулей, связанных с другим модулем через signal bus : std_logic_vector(NUM-1 downto 0), причем каждый компонент использует 8 бит, так что:

bus(7 downto 0) = first module
bus(15 downto 8) = second module

Что касается создания экземпляров и сопоставления портов, это легко сделать с помощью

INST: for i in 0 to NUM-1 generate
         Inst_module port map ( bus => bus(i*8+7 downto i*8) );
       end generate INST;

Мой вопрос: я хотел бы иметь возможность взаимодействовать с каждым модулем через FSM (поскольку ему также нужно делать некоторые другие вещи), поэтому я хотел бы иметь возможность «сгенерировать» следующий код, вместо того, чтобы записывать каждое состояние вручную (где signal empty : std_logic_vector(NUM-1 downto 0) — это флаг состояния для каждого модуля)

 type state_type is (st0_idle, st1_work0, st1_work1 --,etc.)
 signal state : state_type;
 begin
 process(empty)
   begin
     if RESET = '1' then
        --reset FSM
        state <= st0_idle;
     else
       if CLK'event and CLK='1' then
         case state is
           when st0_idle =>
             if empty(0) = '0' then
               state <= st1_work0;
             elsif empty(1) = '1' then
               state <= st1_work1;
             --etc.
             end if;             
           when st1_work0 =>
             bus(7 downto 0) <= SOMETHING;
             state <= st0_idle;
           when st1_work1 =>
              bus(15 downto 8) <= SOMETHINGELSE;
              state <= st0_idle;
            --etc..
       end if;
     end if;
end process;

Как видите, повторов много. Но я не могу просто положить for-generate в корпус, так что мне делать?


person Ali Lown    schedule 08.11.2011    source источник


Ответы (1)


Хороший способ сделать процессы с конечными автоматами более читабельными — объединить общий код с процедурами, определенными внутри процесса. Например:

process (empty) is

  procedure assign_something (
    index      : natural;
    something  : std_logic_vector(7 downto 0)
    next_state : state_type
  ) is
  begin
    bus(index*8+7 downto index*8) <= something;
    state <= next_state;
  end procedure;

begin
  wait until rising_edge(clk);
  case state is
    when st0_idle  => ...
    when st1_work0 => assign_something(0, something,      st0_idle);
    when st1_work1 => assign_something(1, something_else, st0_idle);
    -- ... etc ...
  end case;
  if reset = '1' then
    state <= st0_idle;
  end if;
end procedure;

Надеюсь, вы уловили идею. В зависимости от того, насколько регулярной является структура конечного автомата, вы также можете заменить перечисленные переменные состояния, соответствующие каждому индексу, простой переменной счетчика или индекса, которую вы отслеживаете вместе с именованным состоянием.

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

Применение этого изменения сделало бы код примерно таким:

architecture ...

type state_type is (st_idle, st_work);
signal state : state_type;
signal index : integer range 0 to NUM-1;

...
begin
...

process (empty) is

  procedure assign_something (
    index      : natural;
    something  : std_logic_vector(7 downto 0)
    next_state : state_type
  ) is
  begin
    bus(index*8+7 downto index*8) <= something;
    state <= next_state;
  end procedure;

begin
  wait until rising_edge(clk);
  case state is
    when st_idle  => 
      for i in 0 to NUM-1 loop
         if empty(i) = '1' then
           index := i;
           exit;
         end if;
      end loop;
    when st_work => assign_something(index, something, st_idle);
  end case;
  if reset = '1' then
    state <= st_idle;
  end if;
end procedure;

Очевидно, это нужно изменить, чтобы точно соответствовать тому, что вы хотите сделать... =)

person wjl    schedule 08.11.2011
comment
Но нет способа автоматически сгенерировать NUM количество предложений when? - person Ali Lown; 09.11.2011
comment
Невозможно сгенерировать предложения when, но обходной путь, который я подразумевал, заключается в том, что у вас фактически не будет переменной состояния для каждого состояния присваивания NUM, а будет использоваться отдельная переменная состояния индекса вместе с вашими перечисляемыми состояниями. Затем вместо оператора when, отправляющего assign_something, вы просто напрямую вызываете assign_something(index,...) в соответствующем состоянии. Таким образом, у вас будет просто state_type is (st_idle, st_work) и еще signal index : integer range 0 to NUM-1 или что-то подобное. - person wjl; 09.11.2011
comment
Ах хорошо. извините, я пропустил это значение. Спасибо. - person Ali Lown; 09.11.2011
comment
Я добавил еще несколько примеров кода на случай, если это поможет, но я думаю, что вы поняли идею. знак равно - person wjl; 09.11.2011