2010-10-13 28 views
3

J'ai un FSM très simple qui devrait conduire quelques signaux de sortie d'une RAM externe. Le problème que j'ai vient avec la manipulation du bus de données qui peut être entrée ainsi que la sortie ... Je ne sais pas trop comment je peux gérer mieux ce cas dans mon FSM. Le problème provient de la ligne suivante:Problème simple de machine d'état

v.sram_data <= io_sram_data; 

De toute évidence, le côté gauche est une variable tandis que le côté droit est un signal. Existe-t-il une façon "agréable" de gérer les signaux inout dans un FSM comme celui que j'ai?

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; 

Merci beaucoup pour les commentaires qui améliorent ce code FSM simple!

Répondre

2

Avec inout s il est préférable de le séparer au niveau supérieur en deux signaux data_from_outside et data_to_outside. Ensuite, votre niveau inférieur a besoin de trois éléments sur l'entité, d'un vecteur d'entrée, d'un vecteur de sortie et d'un signal indiquant quand il faut piloter les données externes. Les signaux bidirectionnels ne s'accordent pas bien avec les enregistrements.

Le niveau supérieur doit alors faire:

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

Du point de vue du style: tout mis dans un processus. Il y a un débat à ce sujet, mais de nombreuses affiches respectées sur comp.arch.fpga et comp.lang.vhdl sont de cet avis.

1

Vous avez également utilisé un symbole d'affectation de signal <= plusieurs fois lorsque vous avez réellement besoin d'une affectation de variable :=.

Ainsi, vous voulez écrire

v.f := a; 

pour attribuer une valeur a au champ de la variable v et

s <= a; 

pour assigner a pour signaler ou port s.

0

Je serais du côté de Martin à ce sujet. Laissez la bidirectionnalité au niveau supérieur, puis toute la logique ci-dessous qui voit deux bus, un bus d'entrée et un bus de sortie.

Le bus d'entrée est toujours le même que le bus de données bidirectionnel.

Le bus de données bidirectionnel reçoit alors le bus de sortie lorsque la sortie est valide, et Z lorsqu'il n'est pas valide.

Le Z sera remplacé par l'état d'entrée réel du bus.