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
Post a Comment