-- ------------------------------------------------------------------------
-- 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       : Testcase architecture for verification of decoder
-- ------------------------------------------------------------------------
-- Revision history  :
--
--   $Log$
-- ------------------------------------------------------------------------

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

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

use     work.bfm_hamm_rom_pkg.all;


-- ------------------------------------------------------------------------ --
--                                                             ARCHITECTURE --
-- ------------------------------------------------------------------------ --
architecture tc_decoder of tc is

  -- ---------------------------------------------------------------------------
  --  General constants
  -- ---------------------------------------------------------------------------
  -- number of random inputs tested 
  constant c_RND_TEST_NUM     : integer   := 10000;
  -- test case ID
  constant c_MID              : string    := "TX_DECODER";
  
  -- ---------------------------------------------------------------------------
  --  Signals
  -- ---------------------------------------------------------------------------
  
  -- error signal, 'Z' no error, '1' - error
  signal tc_err               : std_logic := 'Z';
  -- simulation control signal
  signal stimuli_done         : std_logic := '0';
  -- read error from bus funtional model package rom_master_pkg 
  signal read_bfm_err         : std_logic := '0';
  
  

  -----------------------------------------------------------------------------
  --procedure declaration
  ----------------------------------------------------------------------------

  -- procedure to write all possible input data to one random memory address
  -- -------------------------------------------------------------------------
  procedure proc_all_data_write_check (
    addr                : in  integer;
	signal read_bfm_err : out std_logic;
	signal slow_req     : inout std_logic;
	signal fast_req     : inout std_logic
  );
  
  -- procedure to ckeck decoding of all possibilities of single error words 
  -- inserted on one random adress of memory with random input data
  -- -------------------------------------------------------------------------
  procedure proc_all_SE_dec_check (
    addr                : in integer;
	signal read_bfm_err : out std_logic;
	signal slow_req     : inout std_logic;
	signal fast_req     : inout std_logic
  );
  
  -- procedure to ckeck decoding of all possibilities of double error words 
  -- inserted on one random adress of memory with random input data
  -- -------------------------------------------------------------------------
  procedure proc_all_DE_dec_check (
    addr                : in integer;
	signal read_bfm_err : out std_logic;
	signal slow_req     : inout std_logic;
	signal fast_req     : inout std_logic
  );
  

  
  -----------------------------------------------------------------------------
  --procedure definition
  ----------------------------------------------------------------------------
  
    -- procedure to write all possible input data to one random memory address
  -- -------------------------------------------------------------------------
  procedure proc_all_data_write_check (
    addr                : in  integer;
	signal read_bfm_err : out std_logic;
	signal slow_req     : inout std_logic;
	signal fast_req     : inout std_logic
  ) is
    variable seed1 :positive ;
    variable seed2 :positive ;
    variable re1 : integer;
    variable re2 : real ;
  begin
    msg(c_MID, "Start writing " & integer'image(c_RND_TEST_NUM) & " random data to one address of memory ");
	
	for i in 0 to c_RND_TEST_NUM loop
           uniform (seed1,seed2,re2);
           re1 := integer (re2 * real(2**c_INF_DATA_WIDTH -1));
           proc_write_data (addr => addr, data => std_logic_vector(to_unsigned(re1,c_INF_DATA_WIDTH)), fast => true, req => fast_req);
	   proc_read_rom (addr => addr, fast => false, read_bfm_err => read_bfm_err, req => slow_req);
	   proc_read_rom (addr => addr, fast => true, read_bfm_err => read_bfm_err, req => fast_req);
	end loop;
	
    msg(c_MID, "Finished writing " & integer'image(c_RND_TEST_NUM) & " random data to one address of memory ");
  end procedure;
  
  
  -- procedure to ckeck decoding of all possibilities of single error words 
  -- inserted on one random adress of memory with random input data
  -- -------------------------------------------------------------------------
  procedure proc_all_SE_dec_check (
    addr                : in  integer;
	signal read_bfm_err : out std_logic;
	signal slow_req     : inout std_logic;
	signal fast_req     : inout std_logic
  ) is
    variable seed1 :positive ;
    variable seed2 :positive ;
    variable re1 : integer;
    variable re2 : real ;
    variable err_word : std_logic_vector(c_ENCODED_DATA_WIDTH-1 downto 0) := (
	  c_ENCODED_DATA_WIDTH-1 downto 1 => '0', 
	  0 => '1'
	 );
  begin
    msg(c_MID, "Start writing random data with all possible single error word to one address of memory ");
		
	for i in 0 to c_ENCODED_DATA_WIDTH - 1 loop
          uniform (seed1,seed2,re2);
          re1 := integer (re2 * real(2**c_INF_DATA_WIDTH -1));
	  proc_write_data (addr => addr, data => std_logic_vector(to_unsigned(re1,c_INF_DATA_WIDTH)), fast => true, req => fast_req);
	  proc_insert_err_val (err_addr => addr, err_word => err_word, req => fast_req);
	  proc_read_rom (addr => addr, fast => true, read_bfm_err => read_bfm_err, req => fast_req);
	  proc_read_rom (addr => addr, fast => false, read_bfm_err => read_bfm_err, req => slow_req);
	  err_word := err_word(c_ENCODED_DATA_WIDTH-2 downto 0) & '0';
	end loop;
	
    msg(c_MID, "Finished writing random data with all possible single error word to one address of memory ");
  end procedure;
  
  -- procedure to ckeck decoding of all possibilities of double error words 
  -- inserted on one random adress of memory with random input data
  -- -------------------------------------------------------------------------
  procedure proc_all_DE_dec_check (
    addr                : in  integer;
	signal read_bfm_err : out std_logic;
	signal slow_req     : inout std_logic;
	signal fast_req     : inout std_logic
  ) is
    variable seed1 :positive ;
    variable seed2 :positive ;
    variable re1 : integer;
    variable re2 : real ;
    variable err_word : std_logic_vector(c_ENCODED_DATA_WIDTH-1 downto 0) := (others => '0');
  begin
    msg(c_MID, "Start writing random data with all possible double error word to one address of memory ");

	
	for i in 0 to c_ENCODED_DATA_WIDTH - 2 loop
	  err_word(i) := '1';
	  for j in i+1 to c_ENCODED_DATA_WIDTH - 1 loop
	    err_word(j) := '1';
            uniform (seed1,seed2,re2);
            re1 := integer (re2 * real(2**c_INF_DATA_WIDTH -1));
	    proc_write_data (addr => addr, data => std_logic_vector(to_unsigned(re1,c_INF_DATA_WIDTH)), fast => true, req => fast_req);
	    proc_insert_err_val (err_addr => addr, err_word => err_word, req => fast_req);
	    proc_read_rom (addr => addr, fast => true, read_bfm_err => read_bfm_err, req => fast_req);
	    proc_read_rom (addr => addr, fast => false, read_bfm_err => read_bfm_err, req => slow_req);
		err_word(j) := '0';
	  end loop;
	  err_word(i) := '0';
	end loop;
	
    msg(c_MID, "Finished writing random data with all possible double error word to one address of memory ");
  end procedure;
  
  
  
begin


  tc_err <= read_bfm_err;
  
  
  -- ---------------------------------------------------------------------- --
  --  stimuli process
  -- ---------------------------------------------------------------------- --
  stim_proc: process
  begin

  --!!! if interface action (fast='0') -> req=>rw_req !!!
  --!!! if instant rom_module action (fast='1') -> req=>rom_set_req !!!

   -- check simulation run from start
      wait for 2*c_CLK_PERIOD;

   -- Write all possible input data to one random memory address
      proc_all_data_write_check(addr => 1, read_bfm_err => read_bfm_err, slow_req => rw_req, fast_req => rom_set_req);
	  wait for c_CLK_PERIOD;
	  
   -- Check decoding of all possibilities of single error words
      proc_all_SE_dec_check(addr => 1, read_bfm_err => read_bfm_err,
                            slow_req => rw_req, fast_req => rom_set_req);
	  wait for c_CLK_PERIOD;
	  
   -- Check decoding of all possibilities of double error words
      proc_all_DE_dec_check(addr => 1, read_bfm_err => read_bfm_err,
                            slow_req => rw_req, fast_req => rom_set_req);
      wait for c_CLK_PERIOD;
	  
  
      -- trigger end of stimuli generation
      stimuli_done <= '1';

      wait;
  end process;


  -- ---------------------------------------------------------------------- --
  --  simulation control process
  -- ---------------------------------------------------------------------- --
  p_sim_control : process
  begin
    wait on stimuli_done, BFM_ERR, tc_err;

    if (stimuli_done = '1') then
      msg(c_MID, "==========================================================");
      msg(c_MID, " !!! SIMULATION PASSED !!!");
      msg(c_MID, "==========================================================");

      -- stop oscillator
      proc_stop_osc(trig_osc => trig_osc);
      wait;
    end if;

    if (BFM_ERR = '1' or tc_err = '1') then
      msg(c_MID, "==========================================================");
      msg(c_MID, " !!! SIMULATION FAILED !!!");
      msg(c_MID, "==========================================================");

      -- stop oscillator
      proc_stop_osc(trig_osc => trig_osc);
      wait;
    end if;
  end process p_sim_control;



end architecture tc_decoder;

-- ------------------------------------------------------------------------ --
--                                                   Testcase configuration --
-- ------------------------------------------------------------------------ --
configuration tc_decoder_config of tb is
  for beh
    for tc_1 : tc
      use entity work.tc(tc_decoder);
    end for;
  end for;
end tc_decoder_config; 