----------------------------------------------------------------------------------
-- Company:        CERN, BE-CO 
-- Engineer:       Carlos Gil Soriano
-- 
-- Create Date:    01:22:27 07/26/2012 
-- Design Name:    m25p32 top_tp level
-- Module Name:    m25p32_top_tp - RTL 
-- Project Name:   Level Conversion Circuits
-- Target Devices: Spartan 6
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------

library IEEE;
library work;

library modelsim_lib;
use modelsim_lib.util.ALL;

use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.m25p32_pkg.ALL;
use work.spi_master_pkg.ALL;
use work.m25p32_top_tb_pkg.ALL;
use work.spi_analyser_pkg.ALL;
use std.textio.ALL;

entity  m25p32_top_tb is
   end  m25p32_top_tb;

architecture Behavioral of m25p32_top_tb is 

   file     s_file_handler : TEXT;
   constant c_log_path     : STRING    := "../test/log/m25p32_top_tb.log";
   constant sep            : CHARACTER := ht;

   signal wb_rst_i                   : STD_LOGIC;
   signal s_rst_spi_analyser         : STD_LOGIC;
   signal wb_clk                     : STD_LOGIC;

   signal s_wb_we         : STD_LOGIC;
   signal s_wb_stb        : STD_LOGIC;
   signal s_wb_cyc        : STD_LOGIC;
   signal s_wb_sel        : STD_LOGIC_VECTOR (3  downto 0);
   signal s_wb_data_i     : STD_LOGIC_VECTOR (31 downto 0); 
   signal s_wb_data_o     : STD_LOGIC_VECTOR (31 downto 0); 
   signal s_wb_addr       : STD_LOGIC_VECTOR (c_WORDS_PER_PAGE_BITS downto 0);

   signal s_wb_ack        : STD_LOGIC; 
   signal s_wb_rty        : STD_LOGIC; 
   signal s_wb_err        : STD_LOGIC;

   signal s_spi_mosi      : STD_LOGIC;
   signal s_spi_clk       : STD_LOGIC;
   signal s_spi_cs_n      : STD_LOGIC;

   signal s_FMI           : r_FMI;
   signal s_SR_m25p32     : r_SR_m25p32;
   signal s_SR_m25p32_rd  : r_SR_m25p32;
   signal s_STATUS        : r_STATUS;


   --! Signals for the spi_analyser
   signal s_SPI0          : r_SPI0; 
   signal s_SPI0_slv      : STD_LOGIC_VECTOR (31 downto 0);
   signal s_SPI1          : r_SPI1; 
   signal s_SPI1_slv      : STD_LOGIC_VECTOR (31 downto 0);
   signal s_SPI2          : r_SPI2; 
   signal s_SPI2_slv      : STD_LOGIC_VECTOR (15 downto 0);
   signal s_SPI3          : r_SPI3;
   signal s_SPI3_slv      : STD_LOGIC_VECTOR (31 downto 0);

   signal s_inst_check    : STD_LOGIC_VECTOR (c_INST_LENGTH*8 - 1 downto 0)
                                                          := (others => '0');
   signal s_addr_check    : STD_LOGIC_VECTOR (c_ADDR_LENGTH*8 - 1 downto 0)
                                                          := (others => '0');
   signal s_data_check    : STD_LOGIC_VECTOR (c_DATA_LENGTH*8 - 1 downto 0)
                                                          := (others => '0');


   signal s_end_inst_flag : STD_LOGIC; 
   signal s_end_addr_flag : STD_LOGIC; 
   signal s_end_data_flag : STD_LOGIC;

   --! Signals for the spi_slave_writer
   signal s_rst_spi_slave_writer  : STD_LOGIC;
   signal s_bytes_to_wr   : NATURAL := 0;
   signal s_read          : STD_LOGIC_VECTOR (c_READ_LENGTH*8 - 1 downto 0)
                                                          := (others => '0');
   signal s_end_read_flag : STD_LOGIC;
   signal s_spi_miso      : STD_LOGIC;

   signal s_page          : r_page;

   signal s_op_finished  : STD_LOGIC;
   
   signal s_spi_addr     : STD_LOGIC_VECTOR(c_M25P32_ADDR_SIZE*8 - 1
                                                            downto 0);
   signal test_id        : NATURAL := 0;
   signal s_miso_word_rcv  : STD_LOGIC;
begin

   s_SPI0 <= f_SPI0(s_SPI0_slv);
   s_SPI1 <= f_SPI1(s_SPI1_slv);
   s_SPI2 <= f_SPI2(s_SPI2_slv);
   s_SPI3 <= f_SPI3(s_SPI3_slv);

   --! @brief Process to bypass internal signals requiered for correct
   --!        use of spi_analyser
   p_sig_spy : process is
   begin
      init_signal_spy("/uut/inst_m25p32_core/inst_spi_master_core/SPI0_i",
                      "s_SPI0_slv", 1);
      init_signal_spy("/uut/inst_m25p32_core/inst_spi_master_core/SPI1_i",
                      "s_SPI1_slv", 1);
      init_signal_spy("/uut/inst_m25p32_core/inst_spi_master_core/SPI2_o",
                      "s_SPI2_slv", 1);
      init_signal_spy("/uut/inst_m25p32_core/inst_spi_master_core/SPI3_o",
                      "s_SPI3_slv", 1);
      init_signal_spy("/uut/inst_m25p32_core/inst_spi_master_core/s_STATUS",
                      "s_STATUS", 1);
      wait;
   end process p_sig_spy;
 
   --! Connections for the m25p32 
   uut: m25p32_top port map(
      wb_rst_i       =>  wb_rst_i, 
      wb_clk         =>  wb_clk, 

      wb_we_i        =>  s_wb_we, 
      wb_stb_i       =>  s_wb_stb, 
      wb_cyc_i       =>  s_wb_cyc, 
      wb_sel_i       =>  s_wb_sel, 
      wb_data_i      =>  s_wb_data_i, 
      wb_data_o      =>  s_wb_data_o, 
      wb_addr_i      =>  s_wb_addr,

      wb_ack_o       =>  s_wb_ack, 
      wb_rty_o       =>  s_wb_rty, 
      wb_err_o       =>  s_wb_err, 

      miso_word_rcv  =>  s_miso_word_rcv,
      op_finished_o  =>  s_op_finished, 

      prom_mosi_o    =>  s_spi_mosi, 
      prom_cclk_o    =>  s_spi_clk, 
      prom_cs0_b_n_o =>  s_spi_cs_n,
      prom_din_i     =>  s_spi_miso);


   s_rst_spi_analyser <=     wb_rst_i
                          or s_op_finished
                          or s_SPI1.SEND_OP
                          or s_SPI2.SENT_OP;


   mosi_tester : spi_analyser port map(
          rst_i            => s_rst_spi_analyser, 
          SPI0_i           => s_SPI0, 
          SPI1_i           => s_SPI1, 

          spi_mosi_o       => s_spi_mosi, 
          spi_miso_i       => s_spi_miso, 
          spi_clk_o        => s_spi_clk, 
          spi_cs_n_o       => s_spi_cs_n, 
                                             
          inst_check_o     => s_inst_check, 
          addr_check_o     => s_addr_check, 
          data_check_o     => s_data_check,
                                             
          end_inst_flag_o  => s_end_inst_flag, 
          end_addr_flag_o  => s_end_addr_flag, 
          end_data_flag_o  => s_end_data_flag);

   s_rst_spi_slave_writer <=   wb_rst_i
                            or s_op_finished
                            or s_SPI1.SEND_OP
                            or s_SPI2.SENT_OP;

   miso_tester : spi_slave_writer port map(
          rst_i            => s_rst_spi_slave_writer, 
          SPI0_i           => s_SPI0, 
          SPI1_i           => s_SPI1, 
          STATUS_i         => s_STATUS, 

          bytes_to_wr_i    => s_bytes_to_wr, 
          read_i           => s_read, 

          end_read_flag_o  => s_end_read_flag, 

          spi_miso_o       => s_spi_miso, 
          spi_clk_i        => s_spi_clk);

   --! @brief Process that generates the wb_clk
   clk_i_process : process
   begin
      wb_clk <= '0';
        wait for work.m25p32_top_tb_pkg.c_WISHBONE_PERIOD/2;
      wb_clk <= '1';
        wait for work.m25p32_top_tb_pkg.c_WISHBONE_PERIOD/2;
   end process;


   --! @brief Testbench
   p_simulation : process

      --! @brief Init procedure for the test
      procedure init_cond is
      begin
         --! We reset the wishbone bus
            wait until rising_edge(wb_clk);
         s_wb_we       <= '0'; 
         s_wb_stb      <= '0'; 
         s_wb_cyc      <= '0'; 
         s_wb_sel      <= (others => '0'); 
         s_wb_data_i   <= (others => '0'); 
         s_wb_addr     <= (others => '0'); 
      end procedure;

      procedure wishbone_write_SR (reg_data : r_SR_m25p32) is
         variable v_reg_data  : STD_LOGIC_VECTOR(31 downto 0); 
      begin
         v_reg_data( 7 downto 0) :=  f_STD_LOGIC_VECTOR(reg_data);
         v_reg_data(31 downto 8) :=  (others => '0');
         wishbone_write(wb_clk, s_wb_we,
                        s_wb_stb, s_wb_cyc, s_wb_sel,
                        s_wb_data_i, s_wb_addr,         
                        v_reg_data, c_SR_m25p32_addr);
      end procedure;


      procedure wishbone_write_word_in_page(word : r_word;
                                         pos  : NATURAL) is
         variable v_word: STD_LOGIC_VECTOR(31 downto 0);
         variable v_pos : UNSIGNED (c_WORDS_PER_PAGE_BITS downto 0);
      begin
         v_word := f_STD_LOGIC_VECTOR(word); 
         v_pos  := '1' & to_unsigned(pos,c_WORDS_PER_PAGE_BITS); 
         wishbone_write(wb_clk, s_wb_we,
                        s_wb_stb, s_wb_cyc, s_wb_sel,
                        s_wb_data_i, s_wb_addr,         
                        v_word, STD_LOGIC_VECTOR(v_pos));
      end procedure;

      procedure read_SPI_rcved_data(signal read_data :
                                       out STD_LOGIC_VECTOR(31 downto 0)) is
      begin
         wishbone_read (wb_clk, s_wb_we,
                        s_wb_stb, s_wb_cyc, s_wb_sel,
                        s_wb_data_o, s_wb_addr, read_data, 
                        c_DATA_READ_addr);
      end procedure;

      procedure send_operation (
             operation : t_operations;
             sector: NATURAL;
             page  : NATURAL) is
         variable v_FMI : r_FMI;
      begin
         v_FMI.OPR  := '1'; 
         v_FMI.x    := (others => '0'); 
         v_FMI.OP   := operation; 
         v_FMI.PG   := to_unsigned(page,   c_PAGES_PER_SECTOR_BITS); 
         v_FMI.SCT  := to_unsigned(sector, c_SECTOR_BITS); 
         v_FMI.y    := (others => '0');
         s_spi_addr <=   c_ADDR_HEADER_PAD
                       & STD_LOGIC_VECTOR(v_FMI.SCT)
                       & STD_LOGIC_VECTOR(v_FMI.PG)
                       & c_ADDR_FOOTER_PAD;
         wishbone_write(wb_clk, s_wb_we,
                        s_wb_stb, s_wb_cyc, s_wb_sel,
                        s_wb_data_i, s_wb_addr,         
                        X"00" & f_STD_LOGIC_VECTOR(v_FMI), c_FMI_addr);
      end procedure;


      procedure check_inst(signal test_id   : NATURAL;
                                  operation : t_operations) is
         variable v_line_buffer  : LINE;
         variable v_field        : STRING ( 4 downto 1) := (others => ' ');
         variable v_operation    : STRING ( 4 downto 1) := (others => ' ');
         variable v_fail         : BOOLEAN := false;
         variable v_check        : STRING ( 4 downto 1) := "Fail";
         variable v_msg          : STRING (64 downto 1) := (others => ' ');
      begin
         v_field := "INST";
         if s_inst_check = c_WREN_inst then
            v_check := " -- ";
            v_field := "WREN";
            v_msg(26 downto 1) := "Start of TX: WREN received";
            write(v_line_buffer,string'(integer'image(test_id)&sep&v_check&sep
                                & v_operation&sep&v_field&sep&v_msg));
         elsif s_inst_check = c_WRDI_inst then
            v_check := " -- ";
            v_field := "WRDI";
            v_msg(24 downto 1) := "End of TX: WRDI received";
            write(v_line_buffer,string'(integer'image(test_id)&sep&v_check&sep
                                & v_operation&sep&v_field&sep&v_msg));
         else
            case operation is
               when x       =>
                  null;
               when RDID    =>
                  v_operation(4 downto 1) := "RDID";
                 if s_inst_check /= c_RDID_inst then
                     v_fail  := true;
                     v_msg(42 downto 1)   := "Bad instruction code for RDID instruction."; 
                  else
                     v_check := "  OK";
                     v_msg(47 downto 1)   := "RDID instruction received matches with expected"; 

                  end if;
               when RDSR    =>
                  v_operation(4 downto 1) := "RDSR";
                  if s_inst_check /= c_RDSR_inst then
                     v_fail  := true;
                     v_msg(42 downto 1)   := "Bad instruction code for RDSR instruction."; 
                  else
                     v_check := "  OK";
                     v_msg(47 downto 1)   := "RDSR instruction received matches with expected"; 
                 end if;
               when WRSR    =>
                  v_operation(4 downto 1) := "WRSR";
                  if s_inst_check /= c_WRSR_inst then
                     v_msg(42 downto 1)   := "Bad instruction code for WRSR instruction."; 
                  else
                     v_check := "  OK";
                     v_msg(47 downto 1)   := "WRSR instruction received matches with expected"; 
                 end if;
               when READ    =>
                  v_operation(4 downto 1) := "READ";
                  if s_inst_check /= c_READ_inst then
                     v_msg(42 downto 1)   := "Bad instruction code for READ instruction."; 
                  else
                     v_check := "  OK";
                     v_msg(47 downto 1)   := "READ instruction received matches with expected"; 
                 end if;
               when PP      =>
                  v_operation(2 downto 1) := "PP";
                  if s_inst_check /= c_PP_inst then
                     v_msg(40 downto 1)   := "Bad instruction code for PP instruction."; 
                  else
                     v_check := "  OK";
                     v_msg(45 downto 1)   := "PP instruction received matches with expected"; 
                 end if;
               when SE      =>
                  v_operation(2 downto 1) := "SE";
                  if s_inst_check /= c_SE_inst then
                     v_msg(40 downto 1)   := "Bad instruction code for SE instruction."; 
                  else
                     v_check := "  OK";
                     v_msg(45 downto 1)   := "SE instruction received matches with expected"; 
                 end if;
               when BE      =>
                  v_operation(2 downto 1) := "BE";
                  if s_inst_check /= c_BE_inst then
                     v_msg(40 downto 1)   := "Bad instruction code for BE instruction."; 
                  else
                     v_check := "  OK";
                     v_msg(45 downto 1)   := "BE instruction received matches with expected"; 
                 end if;
               when others  =>
                  null;
            end case;
         write(v_line_buffer,string'(integer'image(test_id)&sep&v_check&sep
                                   & v_operation&sep&v_field&sep&v_msg));

         end if;
         if v_fail = true then
            assert false report string'("Test"&sep&integer'image(test_id)&sep&v_msg)
                         severity error;
         end if;
         writeline(s_file_handler, v_line_buffer);
      end procedure;

      procedure check_addr(signal test_id   : NATURAL;
                                  operation : t_operations) is
         variable v_line_buffer  : LINE;
         variable v_field        : STRING ( 4 downto 1) := (others => ' ');
         variable v_operation    : STRING ( 4 downto 1) := (others => ' ');
         variable v_fail         : BOOLEAN := false;
         variable v_check        : STRING ( 4 downto 1) := "Fail";
         variable v_msg          : STRING (64 downto 1) := (others => ' ');
     begin
         v_field(4 downto 1) := "ADDR";
         case operation is
            when READ   =>
               v_operation(4 downto 1) := "READ";
               if s_spi_addr /= s_addr_check then
                  v_fail      := true;
                  v_msg(43 downto 1)       := "Address value mismatch in READ instruction.";
               else
                  v_fail   := false;
               end if;
            when PP     =>
               v_operation(2 downto 1) := "PP";
               if s_spi_addr /= s_addr_check then
                  v_fail      := true;
                  v_msg(41 downto 1)       := "Address value mismatch in PP instruction.";
               else
                  v_fail   := false;
               end if;
           when SE     =>
               v_operation(2 downto 1) := "SE";
               if s_spi_addr /= s_addr_check then
                  v_fail      := true;
                  v_msg(41 downto 1)       := "Address value mismatch in SE instruction.";
               else
                  v_fail   := false;
               end if;
          when others =>
               null;
         end case;
         if v_fail = false then
            v_check := "  OK";
            v_msg(38 downto 1)       := "Address received matches with expected";

         else
            assert false report string'("Test"&sep&integer'image(test_id)&sep&v_msg)
                         severity error;
         end if;
         write(v_line_buffer,string'( integer'image(test_id)      & sep
                                   & v_check     & sep
                                   & v_operation & sep
                                   & v_field     & sep
                                   & v_msg));
         writeline(s_file_handler, v_line_buffer);
      end procedure;

      procedure check_data(signal test_id   : NATURAL;
                                  operation : t_operations) is
         variable v_line_buffer  : LINE;
         variable v_field        : STRING ( 4 downto 1) := (others => ' ');
         variable v_operation    : STRING ( 4 downto 1) := (others => ' ');
         variable v_fail         : BOOLEAN := false;
         variable v_check        : STRING ( 4 downto 1) := "Fail";
         variable v_msg          : STRING (64 downto 1) := (others => ' ');
         variable v_page         : r_page;
         variable v_ocurreance   : BOOLEAN;
      begin
         v_field(4 downto 1) := "DATA";
         case operation is
            when WRSR   =>
               v_page := f_page(s_data_check);
               v_operation(4 downto 1) := "WRSR";
               if f_STD_LOGIC_VECTOR(s_SR_m25p32) /=
                  s_data_check (7 downto 0) then
                  v_msg(46 downto 1)     := "SR register value mismatch in WRSR instruction";
               else
                  v_fail   := false;
                  v_check  := "  OK";
                  v_msg(42 downto 1)     := "SR register received matches with expected";
               end if;
               write(v_line_buffer,string'( integer'image(test_id)    & sep
                                         & v_check     & sep
                                         & v_operation & sep
                                         & v_field     & sep
                                         & v_msg));
               writeline(s_file_handler, v_line_buffer);
            when PP     =>
               v_page      := f_page(s_data_check);
               v_operation(2 downto 1) := "PP";
               for i in 0 to c_PAGE_SIZE/4 - 1 loop
                  v_msg := (others => ' ');
                  if v_page /= s_page then
                     v_fail    := true;
                     v_ocurreance := true;
                     v_msg(31 downto 1)     := string'("Data value mismatch in PP instruction at word " & integer'image(i));
                     if v_fail = false then
                        v_check := "  OK";
                     else
                        assert false report string'("Test"&sep&integer'image(test_id)&sep&v_msg)
                                     severity error;
                     end if;
                     write(v_line_buffer,string'( integer'image(test_id)  & sep
                                               & v_check     & sep
                                               & v_operation & sep
                                               & v_field     & sep
                                               & v_msg));
                     writeline(s_file_handler, v_line_buffer);    
                  end if;
                  if v_ocurreance = false then
                     v_fail   := false;
                  end if;
               end loop;
            when others =>
               null;
         end case;
      end procedure;

      procedure check_read(signal test_id   : NATURAL;
                                  operation : t_operations) is
         variable v_line_buffer  : LINE;
         variable v_field        : STRING ( 4 downto 1) := (others => ' ');
         variable v_operation    : STRING ( 4 downto 1) := (others => ' ');
         variable v_fail         : BOOLEAN := false;
         variable v_check        : STRING ( 4 downto 1) := "Fail";
         variable v_msg          : STRING (64 downto 1) := (others => ' ');
         variable v_ocurreance   : BOOLEAN := false;
         variable v_page  : r_page;
      begin
         v_field(4 downto 1) := "READ";
         case operation is
            when RDSR =>
               v_page       := f_page(s_data_check);
               v_operation(4 downto 1)  := "RDSR";
               if s_SR_m25p32_rd /= s_SR_m25p32 then
                  v_fail    := true;
                  v_msg(31 downto 1)     := "Mismatched SR_m25p32 read value";
                  assert false report
                  string'("Test"&sep&integer'image(test_id)&sep&v_msg)
                               severity error;
               else
                  v_fail   := false;
               end if;
               if v_fail = false then
                  v_check := "  OK";
               end if;

               write(v_line_buffer,string'(
                              integer'image(test_id)      & sep
                             & v_check     & sep
                             & v_operation & sep
                             & v_field     & sep
                             & v_msg));
               writeline(s_file_handler, v_line_buffer);
            when READ =>
               v_page       := f_page(s_data_check);
               v_operation(4 downto 1)  := "READ";
               for i in 0 to c_PAGE_SIZE/4 - 1 loop
                  v_msg := (others => ' ');
                  if v_page(i) /= s_page(i) then
                     v_ocurreance := true;
                     v_fail       := true;
                     v_msg   := string'("Mismatched data read at word "
                                         &integer'image(i));
                     if v_fail = false then
                        v_check(2 downto 1) := "OK";
                     end if;
                     write(v_line_buffer,string'(
                                    integer'image(test_id)      & sep
                                   & v_check     & sep
                                   & v_operation & sep
                                   & v_field     & sep
                                   & v_msg));
                     writeline(s_file_handler, v_line_buffer);
                  assert false report string'("Test"&sep&integer'image(test_id)&sep&v_msg)
                               severity error;
                  end if; 
               end loop;
               if v_ocurreance = false then
                  v_fail   := false;
                  if v_fail = false then
                     v_check := "  OK";
                  end if;
                  write(v_line_buffer,string'(
                                  integer'image(test_id)     & sep
                                & v_check     & sep
                                & v_operation & sep
                                & v_field     & sep
                                & v_msg));
                  writeline(s_file_handler, v_line_buffer);
               end if;
            when others =>
               null;
         end case;
      end procedure;

      procedure write_file_header is
         variable v_line_buffer  : LINE;
         variable v_field        : STRING ( 6 downto 1);
         variable v_check        : STRING ( 7 downto 1);
         variable v_operation    : STRING ( 4 downto 1);
         variable v_msg          : STRING ( 9 downto 1);
     begin
        v_field        := "[Stat]"; 
        v_check        := "[Check]"; 
        v_operation    := "[OP]"; 
        v_msg          := "[Message]"; 
        write(v_line_buffer,string'( "[Test]"   & sep
                                  & v_check     & sep
                                  & v_operation & sep
                                  & v_field     & sep
                                  & sep  & sep  & sep
                                  & sep  & sep  & sep
                                  & sep  & v_msg));
        writeline(s_file_handler, v_line_buffer);
      end procedure;

      procedure check_received_SPI(       operation : t_operations;
                                          sector    : NATURAL;
                                          page      : NATURAL;
                                   signal test_id   : NATURAL) is
      begin
         -- We check WREN
         wait until rising_edge(s_end_inst_flag);
         check_inst(test_id, operation);
         -- We check operation
         wait until rising_edge(s_end_inst_flag);
         check_inst(test_id, operation);
         if    (operation = READ)
            or (operation = PP)
            or (operation = SE) then
            wait until rising_edge(s_end_addr_flag);
            check_addr(test_id, operation);
         end if;

         if    (operation = WRSR)
            or (operation = PP) then
            wait until rising_edge(s_end_data_flag);
            check_data(test_id, operation);
         end if;
         --TODO 2/10/2012 work on RDSR check
         if    (operation = RDSR) then
            wait until rising_edge(s_miso_word_rcv);
         end if;
         -- We check WRDI
         wait until rising_edge(s_end_inst_flag);
         check_inst(test_id, operation);
     end procedure;

       procedure wait_until_completion(signal trigger : in STD_LOGIC) is
       begin
          wait until rising_edge (trigger);
          wait for 1*work.m25p32_top_tb_pkg.c_WISHBONE_PERIOD;
          wait until rising_edge(wb_clk);
      end procedure;

      procedure check_and_wait(       operation : t_operations;
                                      sector    : NATURAL;
                                      page      : NATURAL;
                               signal trigger   : STD_LOGIC) is
      begin
         send_operation(operation, sector, page);
         check_received_SPI(operation, sector, page, test_id);
         test_id <= test_id + 1;
         wait_until_completion(trigger);
      end procedure;

   begin

      file_open(s_file_handler, c_log_path, WRITE_MODE);
      --! This line is cosmetic because this register is not loaded in the
      --! core until a call to send_instruction procedure is issued.
      s_FMI    <= c_FMI_default;
      --! First we perform the reset to the module
      init_cond;
      wb_rst_i  <= '1';
        wait for work.m25p32_top_tb_pkg.c_WISHBONE_PERIOD*10;
      wb_rst_i  <= '0';
        wait for work.m25p32_top_tb_pkg.c_WISHBONE_PERIOD*10;

      -------------------------------------------------------------------------------
      --! Test  Target
      --!    0    WRSR
      --!    1      PP   
      --!    2      SE   
      --!    3      BE   
      --!    4    RDSR 
      --!    5    RDID 
      --!    6    READ 
      -------------------------------------------------------------------------------

      s_SR_m25p32 <= (WIP  => '0', 
                      WEL  => '0',
                      BP0  => '1', 
                      BP1  => '1', 
                      BP2  => '1', 
                      x    => (others => '0'), 
                      SRWD => '0');

         wait until rising_edge(wb_clk);

      write_file_header;
      --! Some quick tests
      --! [0] Testing WRSR
      wishbone_write_SR(s_SR_m25p32);
      check_and_wait(WRSR, 0, 0, s_op_finished);

      --! [1] Testing PP
      s_page <= fill_page;
         wait until rising_edge(wb_clk);

      for i in 0 to c_PAGE_SIZE/4 - 1 loop
         wishbone_write_word_in_page(s_page(i), i);
      end loop;
         wait until rising_edge(wb_clk);
      check_and_wait(PP, 0, 0, s_op_finished);

      --! [2] Testing SE
      check_and_wait(SE, 7, 0, s_op_finished);

      --! [3] Testing BE
      check_and_wait(BE, 0, 0, s_op_finished);

      --! [4] Testing RDRSR
      s_read <= fill_read;
      check_and_wait(RDSR, 0, 0, s_op_finished);

      assert false report "No error. Simulation ends." severity failure;
   end process p_simulation;

end;
