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

entity IFStage is
port(
	
	pc : out std_logic_vector(15 downto 0);
	instr_a_bus: out std_logic_vector(15 downto 0);
	instr_rd: out std_logic;
	
	jmp_adr: in std_logic_vector(15 downto 0);
	clk, stall, jmp_cond, clr: in std_logic
);
end entity IFStage;

architecture struct of IFStage is

-- PC
	signal pc_out: std_logic_vector(15 downto 0);
	
-- MUX
	signal mux_out: std_logic_vector(15 downto 0);
	
-- MUX STALL
	signal new_pc: std_logic_vector(15 downto 0);
	
-- INCREMENTER
	signal incrementer_out: std_logic_vector(15 downto 0);

-- STALL	
	signal temp: std_logic;

begin
	

-- PC Registre ----------------------------------------------------------
	pc_reg: entity work.reg(arch)
             generic map(16)
			 port map(input => new_pc, output => pc_out, clk => clk, clr => clr );
			 
-- INCREMENTER ----------------------------------------------------------
	if_incrementer: entity work.incrementer(arch)
			 port map(input => pc_out, output => incrementer_out);
			 
-- PC saved for next stage ----------------------------------------------
	pc <= incrementer_out;
	
-- MUX next address ------------------------------------------------------------------------
	mux_new_pc: entity work.mux_2(arch)
			 port map(input1 => incrementer_out, input2 => jmp_adr, output => mux_out, sel => jmp_cond);
			 
-- MUX STALL address -----------------------------------------------------------------------
	mux_stall_new_pc: entity work.mux_2(arch)
			 port map(input1 => mux_out, input2 => pc_out, output => new_pc, sel => stall);
			 
-- RD signal for memory ---------------------------------------------------------------------
	temp <=  not stall;
	instr_rd <= temp;

-- INSTRUCTION address -----------------------------------------------------------------------
	instr_a_bus <= pc_out when temp = '1' else "ZZZZZZZZZZZZZZZZ";

end architecture struct;
	
