-- ------------------------------------------------------------------------
-- ON Semiconductor Proprietary and Confidential Information.
-- ------------------------------------------------------------------------

-- ------------------------------------------------------------------------
-- Company           : ON Semiconductor
-- ------------------------------------------------------------------------
-- File              : $RCSfile$
-- ------------------------------------------------------------------------
-- Last Modified     : $Date: 2016/06/01$
-- Last Modified By  : $Author: Jan Bares $
-- Revision          : $Revision$
-- ------------------------------------------------------------------------
-- Description       : Model of ROM master. It stimulates signals for
--                     writing or reading memory
-- ------------------------------------------------------------------------
-- Revision history  :
--
--   $Log$
-- ------------------------------------------------------------------------

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


library work;
use     work.messages_pkg.all;
use     work.timing_pkg.all;
use     work.rom_master_pkg.all;
use     work.rom_pkg.all;

use     work.bfm_hamm_rom_pkg.all;

-- ------------------------------------------------------------------------ --
--                                                                   Entity --
-- ------------------------------------------------------------------------ --
entity rom_master is
  generic (
    -- checkers control
    g_MSG_ON                  : boolean := true;
	-- enable/disable checking of unknown input values
    g_X_CHECKS_ON             : boolean := true;
    -- unique identification
    g_MID                     : string
  );
  port (
    -- Inputs
    -- Main OSC clock to drive communication with ROM
    CLK         : in   std_logic;
    -- decoded data, read from memory
    READ_DATA   : in   std_logic_vector (c_INF_DATA_WIDTH-1 downto 0);
    -- flag, that on current adress of memory are corrupted data, that can not be corrected
    ERR_DET     : in   std_logic;
    -- flag, that on current adress of memory are corrupted data, that were corrected
    ERR_COR     : in   std_logic;

    -- Outputs
    -- original data, sended to be written in ROM memory
    WRITE_DATA  : out  std_logic_vector(c_INF_DATA_WIDTH-1 downto 0); 
    -- currently operated address to read/write data
    ADDR        : out  std_logic_vector(c_ROM_ADDR_WIDTH-1 downto 0);
    -- write enable signal for choosing write option
    WE          : out  std_logic;
    -- Bus funtional model error
    BFM_ERR     : out std_logic
  );
end rom_master;

-- ------------------------------------------------------------------------ --
--                                                             Architecture --
-- ------------------------------------------------------------------------ --
architecture beh of rom_master is

  -- ---------------------------------------------------------------------------
  -- Signals
  -- ---------------------------------------------------------------------------
  -- generated clock
  signal clk_int           : std_logic := '0';
  -- signal to stop oscillator at the end of simulation
  signal stop_osc          : std_logic := '0';
  -- number of errors in error memory on currectly operated address converted to std_logic_vector
  signal err_mem_slv       : std_logic_vector (1 downto 0) := (others => '0');
  
  -- flag, that unknown value has was on input signal from decoder
  signal x_check_err : std_logic := '0';
  -- flag, that simulation has too short clock period
  signal clk_period_err : std_logic := '0';
  -- flag, that wrong value of decoder signal was detected
  signal wrong_dec_sig : std_logic := '0';
  

begin

  -- Signal for testcase, that rom bus funcional model error was detected
  BFM_ERR <= x_check_err or clk_period_err or wrong_dec_sig;


  -- process for checking unknown values on input signals from decoder
  p_x_check: process
  begin
    if g_X_CHECKS_ON = true then
      -- x checker is not checking x values at the start of simulation
      if now < c_START_SIMULATION_DELAY then
        wait for c_START_SIMULATION_DELAY;
      end if;
      -- check for unknown values on input signals from decoder
      wait on READ_DATA, ERR_DET, ERR_COR;
      wait for 0 ns;
      if is_x(READ_DATA) then
        msg(g_MID, "X value on READ_DATA");
		x_check_err <= '1';
      end if;

      if is_x(ERR_DET) then
        msg(g_MID, "X value on ERR_DET");
		x_check_err <= '1';
      end if;

      if is_x(ERR_COR) then
        msg(g_MID, "X value on ERR_COR");
		x_check_err <= '1';
      end if;
	end if;
  end process p_x_check;

  -- process to start read/write operations
  p_rw_op: process
  begin

    --initalization values of output signals
    ADDR <= std_logic_vector(to_unsigned(0,c_ROM_ADDR_WIDTH));
    WRITE_DATA <= std_logic_vector(to_unsigned(0,c_INF_DATA_WIDTH));
    WE <= '0';
	
    loop
      wait on rw_req;
	  
	  if (g_MSG_ON) then
	    if (rom_timing.we_hold + rom_timing.we_setup > c_CLK_PERIOD) then
          msg(g_MID, "-- Too short clock period --");
          clk_period_err <= '1';
        end if;
	  end if;

      if (CLK = '1') and (CLK'last_event < rom_timing.we_hold) then
        wait for rom_timing.we_hold - CLK'last_event;

      elsif (CLK = '0') and (CLK'last_event > (c_CLK_PERIOD/2) - rom_timing.we_setup) then
        wait on CLK;
        wait for rom_timing.we_hold;
      end if;
 
      ADDR <= std_logic_vector(to_unsigned(rw_data_var.addr,c_ROM_ADDR_WIDTH));

      if rw_data_var.rw_op = c_WRITE then
        WRITE_DATA <= rw_data_var.data;
        WE <= '1';
      end if;

      wait until rising_edge(CLK);
	  
	  if rw_data_var.rw_op = c_WRITE then
	    --save original data to control memory on currently operated address
        ctrl_mem(rw_data_var.addr) := rw_data_var.encoded_data;
        --reset error memory currently operated address
        err_mem(rw_data_var.addr) := 0;
	  end if;
	  
	  wait for rom_timing.we_hold;

      if rw_data_var.rw_op = c_WRITE then
        WE <= '0';
      end if;
	  
      --handshake signal for rom_master_pkg
      rw_req_help <= not rw_req_help; 

    end loop;

    wait;
  end process p_rw_op;


  --simulation control process
  p_sim_control : process
  begin
	
	loop
      wait until rising_edge(CLK);
    
	  -- find out the actual value of error memory
      err_mem_slv <= std_logic_vector(to_unsigned(err_mem(rw_data_var.addr),2));
	  
      -- wait for decoder combinational logic delay
      wait for c_DECODER_COMB_DELAY; -- wait until decoder output signals are stable


      -- report wrong data
      if ((err_mem(rw_data_var.addr) < 2) and (ctrl_mem(rw_data_var.addr)(c_ENCODED_DATA_WIDTH-1 downto c_CHECK_DATA_WIDTH) /= READ_DATA)) then
        if (g_MSG_ON) then
          msg(g_MID, "-- Wrong data on output  while reading address --" & integer'image(rw_data_var.addr));
          wrong_dec_sig <= '1';
        end if;      
      end if;

      if ((err_mem(rw_data_var.addr) < 3) and err_mem_slv(0) /= ERR_COR) then
        if (g_MSG_ON) then
          msg(g_MID, "-- Wrong error correction flag while reading address --" & integer'image(rw_data_var.addr));
          wrong_dec_sig <= '1';
        end if;
      end if;

      if ((err_mem(rw_data_var.addr) < 3) and err_mem_slv(1) /= ERR_DET) then
        if (g_MSG_ON) then
          msg(g_MID, "-- Wrong error detection flag while reading address --" & integer'image(rw_data_var.addr));
          wrong_dec_sig <= '1';
        end if;
      end if;
    end loop;
  end process p_sim_control;

end beh;