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

entity test_bench is
end entity test_bench;

architecture tb of test_bench is
  
   
    signal clk, reset: std_logic;
	
	--ROM outputs and inputs
    signal ROM_rd: std_logic;
    signal A_ROM_BUS: std_logic_vector(15 downto 0);
    signal D_ROM_BUS: std_logic_vector(15 downto 0);
    
    -- RAM outputs and inputs bb                               
    signal RAM_rd, RAM_wr: std_logic;
    signal A_RAM_BUS: std_logic_vector(15 downto 0);
    signal D_RAM_BUS: std_logic_vector(15 downto 0); 


	--------- testing ------------
-- IFStage
	-- signal  CPU_pc_IF : std_logic_vector(15 downto 0);
	
--IDStage
	-- signal  CPU_pc_ID : std_logic_vector(15 downto 0);	
    -- signal  CPU_displ_ID: std_logic_vector(15 downto 0);
	-- signal  CPU_s1_ID, CPU_s2_ID, CPU_ds_ID: std_logic_vector(3 downto 0);
	-- signal  CPU_reg_s1_rd_ID, CPU_reg_s2_rd_ID, CPU_reg_ds_rd_ID, CPU_reg_ds_wr_ID: std_logic;
			
--OFStage
	-- signal  CPU_pc_OF : std_logic_vector(15 downto 0);
	-- signal  CPU_instructions_OF: std_logic_vector(20 downto 0);
	-- signal  CPU_s2_OF, CPU_ds_OF: std_logic_vector(3 downto 0);
	-- signal  CPU_displ_OF: std_logic_vector(15 downto 0);
	-- signal  CPU_A_OF, CPU_B_OF, CPU_C_OF: std_logic_vector(15 downto 0);
		
--EXStage

	-- signal  CPU_RES_EX: std_logic_vector(15 downto 0);
	-- signal  CPU_C_EX: std_logic_vector(15 downto 0);
	-- signal  CPU_ds_EX: std_logic_vector(3 downto 0);
	-- signal  CPU_STACK_data_EX, CPU_displ_EX: std_logic_vector(15 downto 0);
    -- signal  CPU_jmp_cond_EX, CPU_reg_wr_EX, CPU_ret_EX, CPU_load_EX, CPU_store_EX: std_logic;
    -- signal  CPU_jsr_EX, CPU_push_EX, CPU_loadn_EX, CPU_str_EX, CPU_rts_EX, CPU_pop_EX, CPU_hlt_EX: std_logic;
      
--WBStage 

    -- signal  CPU_sp_WB: std_logic_vector(15 downto 0);
    -- signal  CPU_SPreset_WB: std_logic;
    -- signal  CPU_reg_data_WB: std_logic_vector(15 downto 0);
    -- signal  CPU_ds_WB: std_logic_vector(3 downto 0); 
    -- signal  CPU_jmp_cond_WB, CPU_reg_wr_WB: std_logic;
    -- signal  CPU_jmp_adr_WB: std_logic_vector(15 downto 0);
    -- signal  CPU_hlt_WB: std_logic; 
    
--STALL unit

    -- signal CPU_stall_if: std_logic;
    -- signal CPU_stall_id: std_logic;
    -- signal CPU_stall_of: std_logic;
    -- signal CPU_stall_ex: std_logic;
    -- signal CPU_stall_wb: std_logic;
        
    -- signal CPU_reset_if: std_logic;
    -- signal CPU_reset_id: std_logic;
    -- signal CPU_reset_of: std_logic;
    -- signal CPU_reset_reg_of: std_logic;
    -- signal CPU_reset_ex: std_logic;
    -- signal CPU_reset_wb: std_logic;    
    
   
begin

          
  the_cpu : entity work.PipelineCPU
    port map (  
	clk, reset,
	--ROM outputs and inputs
    ROM_rd,
    A_ROM_BUS,
    D_ROM_BUS,
    -- RAM outputs and inputs
    RAM_rd, RAM_wr,
    A_RAM_BUS,
    D_RAM_BUS
	--------- testing ------------
-- IFStage
	  -- CPU_pc_IF,
--IDStage
	  -- CPU_pc_ID,
      -- CPU_displ_ID,
	  -- CPU_s1_ID, CPU_s2_ID, CPU_ds_ID,
	  -- CPU_reg_s1_rd_ID, CPU_reg_s2_rd_ID, CPU_reg_ds_rd_ID, CPU_reg_ds_wr_ID,		
--OFStage
	  -- CPU_pc_OF,
	  -- CPU_instructions_OF,
	  -- CPU_s2_OF, CPU_ds_OF,
	  -- CPU_displ_OF,
	  -- CPU_A_OF, CPU_B_OF, CPU_C_OF,		
--EXStage
	  -- CPU_RES_EX,
	  -- CPU_C_EX,
	  -- CPU_ds_EX,
	  -- CPU_STACK_data_EX, CPU_displ_EX,
      -- CPU_jmp_cond_EX, CPU_reg_wr_EX, CPU_ret_EX, CPU_load_EX, CPU_store_EX, CPU_jsr_EX,
      -- CPU_push_EX, CPU_loadn_EX, CPU_str_EX, CPU_rts_EX, CPU_pop_EX, CPU_hlt_EX,     
--WBStage 
      -- CPU_sp_WB,
      -- CPU_SPreset_WB,
      -- CPU_reg_data_WB,
      -- CPU_ds_WB, 
      -- CPU_jmp_cond_WB, CPU_reg_wr_WB,
      -- CPU_jmp_adr_WB,
      -- CPU_hlt_WB,

--STALL unit
      -- CPU_stall_if,
      -- CPU_stall_id,
      -- CPU_stall_of,
      -- CPU_stall_ex,
      -- CPU_stall_wb,
        
      -- CPU_reset_if,
      -- CPU_reset_id,
      -- CPU_reset_of,
      -- CPU_reset_reg_of,
      -- CPU_reset_ex,
      -- CPU_reset_wb 
);

  reset_driver : reset <= '1', '0' after 52 ns;

  clock_driver : process is -- generator takta
  begin

    loop
      clk <= '1';
      wait for 1 ns;
      clk <= '0';
      wait for 50 ns;
    end loop;
  end process clock_driver;
  
  
      --- ROM memorija ---
   ROM_mem_behav : process (clk) is
    
    type rom_type is array (0 to 2**16 - 1) of 
	std_logic_vector(15 downto 0);

    variable rom : rom_type
      := ( X"f105",	 -- 00 load r1, r0
           X"3211",  -- 01 add r2, r1, r1
           X"f315",  -- 02 load r3, r1
           X"f425",  -- 03 load r4, r2
           X"3221",  -- 04 add r2, r2, r1
           X"f525",  -- 05 load r5, r2
           X"b403",  -- 06 beq r4, r0, r3 
           X"3221",  -- 07 add r2, r2, r1
           X"f625",	 -- 08 load r6, r2
           X"f602",  -- 09 push r6
           X"4331",  -- 0a sub r3, r3, r1
           X"9530",  -- 0b bgt r5, r3, r0
           X"d5fe",	 -- 0c str r5, #-2
           X"f403",  -- 0d pop r4
           X"f303",  -- 0e pop r3
           X"f600",  -- 0f jsr r6 
           X"211f",	 -- 10 movr r1, r1, #1
           X"c201",	 -- 11 rts r2 #1
           X"8350",	 -- 12 not r3, r5       
           X"f106",  -- 13 store r1, r0
           X"f206",  -- 14 store r2, r0
           X"f306",  -- 15 store r3, r0
           X"d480",  -- 16 str r4, #-128                     
           X"3243",  -- 17 add r2, r4, r3
           X"3125",  -- 18 add r1, r2, r5
           X"f001",  -- 19 ret
           X"0000",  -- 1a  
           X"0000",  -- 1b 
	   others => X"0000" );
  
  begin
    if (reset = '1') then D_ROM_BUS <= "ZZZZZZZZZZZZZZZZ"; 
    elsif ( clk'event and clk = '1' ) then
        if (ROM_rd = '1') then
            D_ROM_BUS <= rom(conv_integer(A_ROM_BUS)) after 10 ns; 
        else
            D_ROM_BUS <= "ZZZZZZZZZZZZZZZZ" after 10 ns;
        end if;
    end if;
 end process ROM_mem_behav; 
 
 
 
      --- RAM memorija ---
   RAM_mem_behav : process (clk) is
    
    type ram_type is array (0 to 2**16 - 1) of 
	std_logic_vector(15 downto 0);

    variable ram : ram_type
      := ( X"0001",	 -- 00 
           X"0003",  -- 01 
           X"000C",  -- 02 
           X"0006",  -- 03 
           X"0010",  -- 04 
           X"0100",  -- 05 
           X"0017",  -- 06 
           X"0000",  -- 07
           X"0000",	 -- 08 
           X"0000",  -- 09 
           X"0100",  -- 0A
           X"0000",  -- 0B
           X"000F",	 -- 0C
           X"ac02",  -- 0D
           X"2042",  -- 0E
           X"6441",  -- 0F
           X"4000",	 -- 10 
           X"000A",  -- 11 
           X"C910",  -- 12 
           X"0001",  -- 13 
           X"6100",  -- 14 
           X"000A",  -- 15  
           X"BF00",  -- 16 
	   others => X"0000" );
  
  begin
    if (reset = '1') then D_RAM_BUS <= "ZZZZZZZZZZZZZZZZ"; 
    elsif ( clk'event and clk = '1' ) then

        if (RAM_rd = '1') then
            D_RAM_BUS <= ram(conv_integer(A_RAM_BUS)) after 10 ns; 
        elsif (RAM_wr = '1') then
            ram(conv_integer(A_RAM_BUS)) := D_RAM_BUS;
        else
            D_RAM_BUS <= "ZZZZZZZZZZZZZZZZ" after 10 ns;
        end if;

    end if;
 end process RAM_mem_behav;   
end architecture tb;