简单的状态机问题[英] Simple State Machine Problem

本文是小编为大家收集整理的关于简单的状态机问题的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我有一个非常简单的FSM,该FSM应该驱动外部RAM的一些输出信号.我处理数据总线的问题 哪个可以输入和输出...我不太确定如何处理 我的FSM中最好的情况.问题来自以下行:

  v.sram_data   <= io_sram_data;

显然,左侧是一个变量,而右侧是信号.是否有一种"不错的"方式如何处理FSM中的Inot信号?

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!

推荐答案

使用inout s,最好将其直接在顶层将其拆分为两个信号data_from_outside和data_to_outside.然后,您的下层需要在实体,一个输入向量,一个输出向量和一个信号上说何时驱动外部数据的信号.双向信号也不适合记录.

顶级需要做:

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

从样式的角度来看:将所有内容都放在一个过程中.关于此事有一些争论,但是comp.ark.fpga和comp.lang.vhdl上的许多受人尊敬的海报是这种观点.

其他推荐答案

另外,当您真正需要变量分配:=.

时,您使用了信号分配符号<=

所以,你想写

v.f := a;

用于分配值a为变量v和

的字段
s <= a;

分配a向信号或端口s.

其他推荐答案

我会在这方面与Martin一起.

将双向方向留在顶层,然后在下面的所有逻辑上看到两个总线,一个输入总线和一个输出总线.

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

然后,双向数据总线在输出有效时分配了输出总线,而z则在无效时将其分配.

z将被总线的实际输入状态覆盖.

本文地址:https://www.itbaoku.cn/post/2090992.html

问题描述

I have a very simple FSM which should drive some output signals of an external RAM. The problem that I have comes with handling the data bus which can be input as well as output... I am not too sure how I can handle best this case in my FSM. The problem comes from the following line:

  v.sram_data   <= io_sram_data;

Obviously, the left hand side is a variable while the right hand side is a signal. Is there a "nice" way how to handle inout signals in a FSM as the one I have?

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;

Many thanks for comments that code improve this simple FSM!

推荐答案

With inouts its better to split it up right at the top level into two signals data_from_outside and data_to_outside. Then your lower level needs three elements on the entity, one input vector, one output vector and a signal to say when to drive the outside data. Bidirectional signals don't sit well with records either.

The top level then needs to do:

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

From the point of view of style: put everything in one process. There's some debate about this, but many respected posters on comp.arch.fpga and comp.lang.vhdl are of this opinion.

其他推荐答案

Also, you used a signal assignment symbol <= a few times when you really need a variable assignment :=.

So, you want to write

v.f := a;

for assigning value a to field of variable v, and

s <= a;

to assign a to signal or port s.

其他推荐答案

I would side with Martin on this.

Leave the bi-directionality at the top level, and then all the logic below that see two buses, an input bus and an output bus.

The input bus is always the same as the bi-directional data bus.

The bi-directional data bus then gets assigned the output bus when output is valid, and Z when it is not valid.

The Z will be overridden by the actual input state of the bus.