library ieee;
use ieee.std_logic_1164.all;

use ieee.numeric_std.all;
use ieee.std_logic_misc.all;

use work.core_pkg.all;

entity regfile is
	port (
		clk              : in  std_logic;
		res_n            : in  std_logic;
		stall            : in  std_logic;
		rdaddr1, rdaddr2 : in  reg_adr_type;
		rddata1, rddata2 : out data_type;
		wraddr           : in  reg_adr_type;
		wrdata           : in  data_type;
		regwrite         : in  std_logic
	);
end entity;

architecture rtl of regfile is
	
	type data_arr is array(0 to 2**REG_BITS-1) of data_type;
	
	signal reg : data_arr := (others => (others => '0'));
	signal rdaddr1_cur : reg_adr_type := (others => '0');
	signal rdaddr2_cur : reg_adr_type := (others => '0');

begin

	sync : process(all)
	begin
		if res_n = '0' then
			reg <= (others => (others => '0'));
			rdaddr1_cur <= (others => '0');
			rdaddr2_cur <= (others => '0');
		elsif rising_edge(clk) then
			if stall = '0' then
				rdaddr1_cur <= rdaddr1;
				rdaddr2_cur <= rdaddr2;
				if regwrite = '1' and or_reduce(wraddr) = '1'then
					reg(to_integer(unsigned(wraddr))) <= wrdata;
				end if;
			end if;
		end if;	
	end process;
	
	read_control : process(all)
	begin
		rddata1 <= reg(to_integer(unsigned(rdaddr1_cur)));
		rddata2 <= reg(to_integer(unsigned(rdaddr2_cur)));
		if regwrite = '1' and unsigned(wraddr) >= unsigned(ZERO_REG) and stall = '0' then -- >= comparison saves some fmax (quartus is witchcraft)
			if rdaddr1_cur = wraddr then
				rddata1 <= wrdata;
			end if;
			if rdaddr2_cur = wraddr then	
				rddata2 <= wrdata;
			end if;
		end if;
	end process;
	
end architecture;
