----------------------------------------------------------------------------------
-- 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;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.spi_master_pkg.ALL;
use work.m25p32_pkg.ALL;
use work.spi_analyser_pkg.ALL;

entity  m25p32_top_tb is
   end  m25p32_top_tb;

architecture Behavioral of m25p32_top_tb is 


   signal s_rst           : 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 (3  downto 0);

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

   signal prom_mosi_o     : STD_LOGIC;
   signal prom_cclk_o     : STD_LOGIC;
   signal prom_cs0_b_n_o  : STD_LOGIC;

   signal prom_din_i      : STD_LOGIC;

   signal s_FMI           : r_FMI;
   signal s_FMI_slv       : STD_LOGIC_VECTOR (     r_FMI'a_length - 1 downto 0); 

   signal s_SR_m25p32     : r_SR_m25p32;
   signal s_SR_m25p32_slv : STD_LOGIC_VECTOR (r_SR_m25p32'a_length - 1 downto 0);

   --! 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_spi_mosi      : STD_LOGIC;
   signal s_spi_miso      : STD_LOGIC := '0';
   signal s_spi_clk       : STD_LOGIC;
   signal s_spi_cs_n      : STD_LOGIC;

   signal s_inst_check    : STD_LOGIC_VECTOR (7    downto 0) := (others => '0');
   signal s_addr_check    : STD_LOGIC_VECTOR (23   downto 0) := (others => '0');
   signal s_data_check    : STD_LOGIC_VECTOR (2047 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;

   signal s_wr_page       : r_page;
   signal s_rd_word       : r_word;

begin

   s_FMI_slv        <= f_STD_LOGIC_VECTOR(s_FMI); 
   s_SR_m25p32_slv  <= f_STD_LOGIC_VECTOR(s_SR_m25p32);

   --! Connections for the serializaer
   s_rst            <= wb_rst_i; 
   s_serial_data    <= prom_mosi_o;
   s_serial_clock   <= prom_cclk_o;
   s_clk            <= wb_clk;


   --! Connections for the m25p32 
   uut: m25p32_top port map(
      wb_rst_i       =>  wb_rst_i, 
      wb_clk         =>  wb_clk, 

      wb_we_i        =>  wb_we_i , 
      wb_stb_i       =>  wb_stb_i, 
      wb_cyc_i       =>  wb_cyc_i, 
      wb_sel_i       =>  wb_sel_i, 
      wb_data_i      =>  wb_data_i, 
      wb_data_o      =>  wb_data_o, 
      wb_addr_i      =>  wb_addr_i, 
      wb_ack_o       =>  wb_ack_o, 
      wb_rty_o       =>  wb_rty_o, 
      wb_err_o       =>  wb_err_o, 

      prom_mosi_o    =>  prom_mosi_o, 
      prom_cclk_o    =>  prom_cclk_o, 
      prom_cs0_b_n_o =>  prom_cs0_b_n_o,
      prom_din_i     =>  prom_din_i);

   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);


   --! @brief Process that generates the wb_clk
   clk_i_process : process
   begin
      wb_clk <= '0';
        wait for c_WISHBONE_PERIOD/2;
      wb_clk <= '1';
        wait for 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'); 
         --! And also the miso line
         prom_din_i    <= '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(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 send_operation (
             operation : t_operations;
             sector: STD_LOGIC_VECTOR(c_SECTOR_BITS - 1           downto 0);
             page  : STD_LOGIC_VECTOR(c_PAGES_PER_SECTOR_BITS -1  downto 0)) is
         variable v_FMI : r_FMI;
      begin
         v_FMI.OPR  <= '1'; 
         v_FMI.OP   <= operation; 
         v_FMI.PG   <= page; 
         v_FMI.SCT  <= sector; 
         v_FMI.x    <= (others => '0'); 
         wishbone_write(s_wb_we,
                        s_wb_stb, s_wb_cyc, s_wb_sel,
                        s_wb_data_i, s_wb_addr,         
                        X"00" & v_FMI, c_FMI_addr);
      end procedure;

      procedure write_word_SPI_send_data_pool(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  := to_unsigned(pos,c_WORDS_PER_PAGE_BITS + 1); 
         wishbone_write(s_wb_we,
                        s_wb_stb, s_wb_cyc, s_wb_sel,
                        s_wb_data_i, s_wb_addr,         
                        v_word, v_pos);
      end procedure;

      procedure read_SPI_rcved_data(signal read_data :
                                       out STD_LOGIC_VECTOR(31 downto 0)) is
      begin
         wishbone_read (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;

   begin

      --! 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 c_WISHBONE_PERIOD*10;
      wb_rst_i  <= '0';
        wait for c_WISHBONE_PERIOD*10;

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

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

         wait until rising_edge(wb_clk);
      wishbone_write_SR(s_SR_m25p32);

      set_FMOH(WRSR,
               0,
               0);
      send_instruction;


      --! Test schema WRSR:
      --!                                          [wishbone addr]
      --! 1.- 
      --! 2.- Place a WRP order through FMOH         c_FMOH_addr

      set_FMOH(WRP,
               1,
               1);

      wait for 10*c_WISHBONE_PERIOD;

         --! Overwrite test
         --! Why try to perform a write into FMOH when a operation is being
         --! performed.
         --! It should not rewrite the FMOH value.
         send_instruction;

      --! Know it should accept the instruction
      wait for 200*c_WISHBONE_PERIOD;
      send_instruction;

      wait;

   end process m25p32_access;

end;
