简单的状态机问题

时间:2010-10-13 14:38:59

标签: vhdl fpga state-machine

我有一个非常简单的FSM,它应该驱动一些外部RAM的输出信号。我遇到的问题是处理数据总线 这可以输入也可以输出...我不太清楚如何处理 在我的FSM中最好这种情况。问题来自以下几行:

  v.sram_data   <= io_sram_data;

显然,左手侧是变量,而右手侧是信号。有一种“好的”方法如何处理FSM中的inout信号,就像我拥有的​​那样?

entity sram_fsm is
  port (
     clk              : in std_logic;
     reset            : in std_logic;
     out_sram_rd      : out std_logic;
     out_sram_wr      : out std_logic;
     out_sram_addr    : out std_logic_vector(3 downto 0);
     io_sram_data     : inout std_logic_vector(7 downto 0)

);  
end;

architecture Behavioral of sram_fsm is

  type state_type is (wr_init, wr_data, rd_init, rd_data);

  type reg_type is record
     state       : state_type;
     sram_data   : std_logic_vector(7 downto 0);
     sram_addr   : std_logic_vector(3 downto 0);   
     sram_rd     : std_logic;  
     sram_wr     : std_logic;     
  end record;   

  signal r, rin : reg_type;

  begin

  comb : process (r)
     variable v : reg_type;
begin
v := r;

case r.state is
  when wr_init =>
        v.sram_data    := "00000000";
        v.sram_addr    := "0000";   
  v.sram_rd      := '0';  
  v.sram_wr      := '0';     
  v.state        := wr_data;
  when wr_data =>
  io_sram_data  <= "00001000";
       v.sram_wr     := '1'; 
  v.state       := rd_init;
  when rd_init =>
  v.sram_addr   := "0000";   
  v.sram_rd     := '1';  
  v.sram_wr     := '0';     
  v.state       := wr_data;
  when rd_data =>
  v.sram_data   <= io_sram_data;
        v.state       := wr_init;     
 end case;

     out_sram_addr  <= v.sram_addr;
     out_sram_rd    <= v.sram_rd;    
     out_sram_wr    <= v.sram_wr;    

   rin <= v;

     end process;

regs : process (reset, clk)
begin
  if reset = '0' then
         r.state <= wr_init; 
     elsif rising_edge(clk) then
        r <= rin;
     end if;   
end process;   

 end Behavioral;

非常感谢代码改进这个简单的FSM的评论!

3 个答案:

答案 0 :(得分:2)

使用inout s最好将其从顶层拆分为两个信号data_from_outsidedata_to_outside。然后你的下层需要实体上的三个元素,一个输入向量,一个输出向量和一个信号来说明何时驱动外部数据。双向信号也不适合记录。

最高级别需要做:

data_pins <= data_to_outside when data_to_outside_enable = '1' else (others => 'Z');
data_from_outside <= data_pins;

从风格的角度来看:把所有东西都放在一个过程中。关于这一点有一些争论,但comp.arch.fpga和comp.lang.vhdl上的许多受人尊敬的海报都是这种观点。

答案 1 :(得分:1)

此外,当您确实需要变量赋值<=时,您曾多次使用信号分配符号:=

所以,你想写

v.f := a;

用于将值a分配给变量v的字段,以及

s <= a;

a分配给信号或端口s

答案 2 :(得分:0)

我会支持马丁。

将双向性保留在顶层,然后将下面的所有逻辑看作两条总线,一条输入总线和一条输出总线。

输入总线始终与双向数据总线相同。

双向数据总线在输出有效时分配输出总线,在无效时分配给Z.

Z将被总线的实际输入状态覆盖。