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

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

entity wb is
	port (
		clk        : in  std_logic;
		res_n      : in  std_logic;
		stall      : in  std_logic;
		flush      : in  std_logic;

		-- from MEM
		op         : in  wb_op_type;
		aluresult  : in  data_type;
		memresult  : in  data_type;
		pc_old_in  : in  pc_type;

		-- to FWD and DEC
		reg_write  : out reg_write_type
	);
end entity;

architecture rtl of wb is
	
	type internal_t is record 
		op : wb_op_type;
		aluresult : data_type;
		memresult : data_type;
		pc_old : pc_type;
	end record;
	
	signal internal : internal_t;
	constant INITIAL_INTERNAL : internal_t := (
		WB_NOP,
		(others => '0'),
		(others => '0'),
		(others => '0')
	);
begin
	
	--syncronous
	sync : process(clk, res_n, flush, stall)
	begin
		if res_n = '0' then
			internal <= INITIAL_INTERNAL;
		elsif stall = '0' and rising_edge(clk) then
			internal.op <= op;
			internal.aluresult <= aluresult;
			internal.memresult <= memresult;
			internal.pc_old	 <= pc_old_in;
		end if;
	end process;
	
	--concurrent
	reg_write.reg <= internal.op.rd;
	reg_write.write <= internal.op.write when flush = '0' else '0';
	
	with internal.op.src select reg_write.data <=
		internal.aluresult when WBS_ALU,
		internal.memresult when WBS_MEM,
		std_logic_vector(x"00000000" + unsigned(internal.pc_old) + x"4") when WBS_OPC;

end architecture;
