VHDL'生成'FSM状态

时间:2011-11-08 21:20:17

标签: 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,所以我该怎么办?

1 个答案:

答案 0 :(得分:4)

使状态机的进程更具可读性的一种好方法是将公共代码合并到进程中定义的过程中。例如:

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;

显然必须更改以完全匹配您想要做的事情... =)