library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

use work.core_pkg.all;
use work.op_pkg.all;

entity ctrl is
	port (
		clk         : in std_logic;
		res_n       : in std_logic;
		stall       : in std_logic;

		stall_fetch : out std_logic;
		stall_dec   : out std_logic;
		stall_exec  : out std_logic;
		stall_mem   : out std_logic;
		stall_wb    : out std_logic;

		flush_fetch : out std_logic;
		flush_dec   : out std_logic;
		flush_exec  : out std_logic;
		flush_mem   : out std_logic;
		flush_wb    : out std_logic;

		-- from FWD
		wb_op_exec  : in  wb_op_type;
		exec_op_dec : in  exec_op_type;

		-- from MEM
		pcsrc_in    : in std_logic;
		pcsrc_out   : out std_logic
	);
end entity;

architecture rtl of ctrl is
	signal flush_branch_ctrl : std_logic;
	signal stall_fwd_ctrl : std_logic;
begin

	-- concurrent
	stall_fwd_ctrl <= '1' when wb_op_exec.src = WBS_MEM and (exec_op_dec.rs1 = wb_op_exec.rd or exec_op_dec.rs2 = wb_op_exec.rd) else '0';
	
	pcsrc_out <= '0';
	
	flush_branch_ctrl <= pcsrc_in;

	flush_fetch <= flush_branch_ctrl;
	flush_dec   <= flush_branch_ctrl;
	flush_exec  <= flush_branch_ctrl;
	flush_mem   <= '0';
	flush_wb    <= '0';
	
	-- sequential
	sync : process(clk, res_n, stall)
	begin
		if res_n = '0' then
			stall_fetch <= '0';
			stall_dec   <= '0';
			stall_exec  <= '0';
			stall_mem   <= '0';
			stall_wb    <= '0';
		elsif rising_edge(clk) and stall = '0' then
			stall_fetch <= stall_fwd_ctrl;
			stall_dec <= stall_fwd_ctrl;
			stall_exec <= stall_fwd_ctrl;
			stall_mem <= stall_fwd_ctrl;
			stall_wb <= stall_fwd_ctrl;
		end if;
	end process;
	
end architecture;
