Простая задача конечного автомата - PullRequest
3 голосов
/ 13 октября 2010

У меня очень простой FSM, который должен управлять некоторыми выходными сигналами внешнего ОЗУ. Проблема, с которой я столкнулся, связана с обработкой шины данных. который может быть как вводом, так и выводом ... Я не слишком уверен, как я могу справиться Лучше всего это дело в моем ФСМ. Проблема исходит из следующей строки:

  v.sram_data   <= io_sram_data;

Очевидно, левая часть является переменной, а правая часть является сигналом. Есть ли "хороший" способ обработки входных сигналов в FSM, как у меня?

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 ]

2 голосов
/ 13 октября 2010

При 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.arch.fpga и comp.lang.vhdl придерживаются такого мнения

1 голос
/ 13 октября 2010

Кроме того, вы использовали символ присвоения сигнала <= несколько раз, когда вам действительно нужно присвоение переменной :=.

Итак, вы хотите написать

v.f := a;

для присвоения значения a полю переменной v и

s <= a;

для назначения a для сигнала или порта s.

0 голосов
/ 14 октября 2010

Я бы поддержал Мартина в этом.

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

Входная шина всегда совпадает с двунаправленной шиной данных.

Затем двунаправленной шине данных назначается выходная шина, когда выходной сигнал действителен, и Z, если он недопустим.*

Z будет переопределено фактическим состоянием ввода шины.

...