fpga - FSM 2 process VHDL -


i attempting write down vhdl code fsm of control unit of project. chose 2 process way 1 process state register , other process next state , output logic. anyway i'm having problems in setting solution signals give synthesis latch warning (i know why appear). solution found (without using 1 single process both state register , output logic , without adding 3 more states) add output logic in process manages state logic.

with surprise works conceptually correct? mean, correct dirty code of state register process output logic or breaking 2 process pattern?

this code of working , "latch-free warning" control unit. anyway latch involved signal sel_mode don't know how specify in else branch of state idle "keep previous value of "sel_mode"(without having latch warning).

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity control_unit port ( clock : in  std_logic;        reset_n_in : in  std_logic;        primo_operando : in  std_logic;        secondo_operando : in  std_logic;        add_sub : in  std_logic;           ov : in std_logic;           subtract_in : in std_logic;           led_ov : out std_logic;           reset_n_out : out std_logic;        subtract_out : out  std_logic;           en_w_primo_op : out std_logic;           en_w_secondo_op : out std_logic;           en_w_risultato : out std_logic;           sel_mode : out std_logic_vector(1 downto 0)           ); end control_unit;  architecture behavioral of control_unit  type state (idle, primo_op, secondo_op, risultato); signal curr, nxt : state := idle;  begin  change_state : process(clock, reset_n_in) begin     if reset_n_in = '0'         curr <= idle; -- in following lines mix state register logic output logic     elsif rising_edge(clock)         if curr = primo_op             sel_mode <= "10";         elsif curr = secondo_op             sel_mode <= "01";         elsif curr = risultato             sel_mode <= "00";         end if;         curr <= nxt;     end if; end process;  fsm: process(curr, reset_n_in, primo_operando, secondo_operando, add_sub) begin     if reset_n_in = '0'         reset_n_out <= '0';     else         reset_n_out <= '1';     end if;     en_w_primo_op <= '0';     en_w_secondo_op <= '0';     en_w_risultato <= '0';     case curr         when idle =>             if primo_operando = '1'              --   sel_mode <= "10";                 nxt <= primo_op;             elsif secondo_operando = '1'              -- sel_mode <= "01";                 nxt <= secondo_op;             elsif add_sub = '1'              -- sel_mode <= "00";                 nxt <= risultato;             else                 nxt <= idle;              -- how specify keep sel_mode previous value??             end if;         when primo_op =>          -- sel_mode <= "10";             en_w_primo_op <= '1';             nxt <= idle;         when secondo_op =>          -- sel_mode <= "01";             en_w_secondo_op <= '1';             nxt <= idle;         when risultato =>          -- sel_mode <= "00";             en_w_risultato <= '1';             nxt <= idle;     end case; end process;  led_ov <= ov; subtract_out <= subtract_in;  end behavioral; 

added:

with surprise works conceptually correct? mean, correct dirty code of state register process output logic or breaking 2 process pattern?

the state of design made of all registers in design, not register curr in design. can think of way:

  • the (partial) state of fsm defined curr. described using two-process form.

  • the register sel_mode in posted code data-path register, , thus, defines state of data-path part. have described using one-process form. alternate solution using two-process form, describe below.


anyway latch involved signal "sel_mode" don't know how specify in else branch of state idle "keep previous value of "sel_mode"(without having latch warning).

to prevent inference of latch, have save current value of sel_mode clock-edge triggered register , assign register value whenever want output previous value. register represents previous value, called sel_mode_prev. assignment of register takes place in clocked process reset logic:

change_state : process(clock, reset_n_in) begin     if reset_n_in = '0'         curr <= idle;         sel_mode_prev <= "00"; -- or other value     elsif rising_edge(clock)         curr <= nxt;         sel_mode_prev <= sel_mode_i; -- save current value     end if; end process; 

the output sel_mode assigned in combinational part. but, cannot read value of output in assignment of sel_mode_prev above, have assign desired value sel_mode intermediate value, called sel_mode_i. combinational process fsm assigns signal. assignment of output sel_mode <= sel_mode_i; done combinational below process other output assignments.

here, complete modified architecture comments:

architecture behavioral of control_unit  type state (idle, primo_op, secondo_op, risultato); signal curr, nxt : state := idle;  signal sel_mode_i    : std_logic_vector(1 downto 0); -- internal version of output signal sel_mode_prev : std_logic_vector(1 downto 0); -- previous version of sel_mode  begin  change_state : process(clock, reset_n_in) begin     if reset_n_in = '0'         curr <= idle;         sel_mode_prev <= "00"; -- or other value     elsif rising_edge(clock)         curr <= nxt;         sel_mode_prev <= sel_mode_i; -- save current value     end if; end process;  fsm: process(curr, reset_n_in, primo_operando, secondo_operando, add_sub,              sel_mode_prev) -- add sel_mode_prev here begin     if reset_n_in = '0'         reset_n_out <= '0';     else         reset_n_out <= '1';     end if;     en_w_primo_op <= '0';     en_w_secondo_op <= '0';     en_w_risultato <= '0';     case curr         when idle =>             if primo_operando = '1'                 sel_mode_i <= "10"; -- assign internal signal                 nxt <= primo_op;             elsif secondo_operando = '1'                 sel_mode_i <= "01"; -- assign internal signal                 nxt <= secondo_op;             elsif add_sub = '1'                 sel_mode_i <= "00"; -- assign internal signal                 nxt <= risultato;             else                 sel_mode_i <= sel_mode_prev; -- output old value @ default                 nxt <= idle;             end if;         when primo_op =>             sel_mode_i <= "10"; -- assign internal signal             en_w_primo_op <= '1';             nxt <= idle;         when secondo_op =>             sel_mode_i <= "01"; -- assign internal signal             en_w_secondo_op <= '1';             nxt <= idle;         when risultato =>             sel_mode_i <= "00"; -- assign internal signal             en_w_risultato <= '1';             nxt <= idle;     end case; end process;  sel_mode <= sel_mode_i; -- assign internal signal output led_ov <= ov; subtract_out <= subtract_in;  end behavioral; 

Comments

Popular posts from this blog

Delphi XE2 Indy10 udp client-server interchange using SendBuffer-ReceiveBuffer -

Qt ActiveX WMI QAxBase::dynamicCallHelper: ItemIndex(int): No such property in -

Enable autocomplete or intellisense in Atom editor for PHP -