--------------------------------------------------------------------------------
-- Company: 
-- Engineer:
--
-- Create Date:   12:31:47 06/20/2012
-- Design Name:   
-- Module Name:   /media/BACKUP/CERN/contrib/ohwr/conv-ttl-blo/hdl/spi_master_multifield/test/spi_master_core_tb.vhd
-- Project Name:  spi_master_multifield
-- Target Device:  
-- Tool versions:  
-- Description:   
-- 
-- VHDL Test Bench Created by ISE for module: spi_master_core
-- 
-- Dependencies:
-- 
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
-- Notes: 
-- This testbench has been automatically generated using types std_logic and
-- std_logic_vector for the ports of the unit under test.  Xilinx recommends
-- that these types always be used for the top-level I/O of a design in order
-- to guarantee that the testbench will bind correctly to the post-implementation 
-- simulation model.
--------------------------------------------------------------------------------

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;

package m25p32_top_tb_pkg is

   --! Constant only used in simulation
   constant c_WISHBONE_PERIOD   : TIME      := 50 ns;  --! Working at 20MHz 

   component m25p32_top is
      generic(
              g_WB_ADDR_LENGTH : NATURAL  := c_WORDS_PER_PAGE_BITS + 1);
      port ( 
              wb_rst_i       : in  STD_LOGIC;
              wb_clk         : in  STD_LOGIC;

              wb_we_i        : in  STD_LOGIC;
              wb_stb_i       : in  STD_LOGIC;
              wb_cyc_i       : in  STD_LOGIC;
              wb_sel_i       : in  STD_LOGIC_VECTOR (3  downto 0);
              wb_data_i      : in  STD_LOGIC_VECTOR (31 downto 0); 
              wb_data_o      : out STD_LOGIC_VECTOR (31 downto 0); 
              wb_addr_i      : in  STD_LOGIC_VECTOR (g_WB_ADDR_LENGTH - 1 downto 0); 
              wb_ack_o       : out STD_LOGIC; 
              wb_rty_o       : out STD_LOGIC; 
              wb_err_o       : out STD_LOGIC;

              op_finished_o  : out STD_LOGIC;

              prom_mosi_o    : out STD_LOGIC;
              prom_cclk_o    : out STD_LOGIC;
              prom_cs0_b_n_o : out STD_LOGIC;
              prom_din_i     : in  STD_LOGIC
           );
   end component;

   procedure wishbone_write (
            signal wb_clk    : in  STD_LOGIC;
            signal wb_we     : out STD_LOGIC;
            signal wb_stb    : out STD_LOGIC;
            signal wb_cyc    : out STD_LOGIC;
            signal wb_sel    : out STD_LOGIC_VECTOR (3  downto 0);
            signal wb_data   : out STD_LOGIC_VECTOR (31 downto 0);
            signal wb_addr   : out STD_LOGIC_VECTOR (c_WORDS_PER_PAGE_BITS 
                                                                 downto 0);
                   reg_data  :     STD_LOGIC_VECTOR (31 downto 0);
                   reg_addr  :     STD_LOGIC_VECTOR (c_WORDS_PER_PAGE_BITS 
                                                                downto 0));

   procedure wishbone_read (
            signal wb_clk    : in  STD_LOGIC;
            signal wb_we     : out STD_LOGIC;
            signal wb_stb    : out STD_LOGIC;
            signal wb_cyc    : out STD_LOGIC;
            signal wb_sel    : out STD_LOGIC_VECTOR (3  downto 0);
            signal wb_data   : in  STD_LOGIC_VECTOR (31 downto 0);
            signal wb_addr   : out STD_LOGIC_VECTOR (c_WORDS_PER_PAGE_BITS 
                                                                 downto 0);
            signal read_data : out STD_LOGIC_VECTOR (31 downto 0);
                   reg_addr  :     STD_LOGIC_VECTOR (c_WORDS_PER_PAGE_BITS 
                                                                downto 0));

   function fill_page return r_page;
   function fill_read return STD_LOGIC_VECTOR;

end m25p32_top_tb_pkg;

package body m25p32_top_tb_pkg is

      --! @brief Procedure to place wishbone writes at a given address.
      --! @param wb_clk    Wishbone clock signal
      --!        wb_we     Write enable signal 
      --!        wb_stb    Strobe signal
      --!        wb_cyc    Cycle signal
      --!        wb_sel    Addres select signal
      --!        wb_data   Data signal to be read from
      --!        wb_addr   Address signal to read from
      --!        reg_data  Data to write into wishbone bus
      --!        reg_addr  Address to read from
      procedure wishbone_write (
            signal wb_clk    : in  STD_LOGIC;
            signal wb_we     : out STD_LOGIC;
            signal wb_stb    : out STD_LOGIC;
            signal wb_cyc    : out STD_LOGIC;
            signal wb_sel    : out STD_LOGIC_VECTOR (3  downto 0);
            signal wb_data   : out STD_LOGIC_VECTOR (31 downto 0);
            signal wb_addr   : out STD_LOGIC_VECTOR (c_WORDS_PER_PAGE_BITS 
                                                                 downto 0);
                   reg_data  :     STD_LOGIC_VECTOR (31 downto 0);
                   reg_addr  :     STD_LOGIC_VECTOR (c_WORDS_PER_PAGE_BITS 
                                                                 downto 0)) is
      begin
           wait until rising_edge(wb_clk);
         wb_we    <= '1';  
         wb_stb   <= '1';  
         wb_cyc   <= '1';  
         wb_sel   <= X"F";  
         wb_data  <= reg_data; 
         wb_addr  <= reg_addr;
           wait until rising_edge(wb_clk);
           --! Here we wait for the ack and keep till operation is finished
           wait until rising_edge(wb_clk);
         wb_we    <= '0';  
         wb_stb   <= '0';  
         wb_cyc   <= '0';  
         wb_sel   <= X"F";  
      end procedure;

      --! @brief Procedure to place wishbone reads at a given address.
      --! @param wb_clk    Wishbone clock signal
      --!        wb_we     Write enable signal 
      --!        wb_stb    Strobe signal
      --!        wb_cyc    Cycle signal
      --!        wb_sel    Addres select signal
      --!        wb_data   Data signal to be read from
      --!        wb_addr   Address signal to read from
      --!        read_data Signal where to place the read data from wb
      --!        reg_addr  Address to read from
      procedure wishbone_read (
            signal wb_clk    : in  STD_LOGIC;
            signal wb_we     : out STD_LOGIC;
            signal wb_stb    : out STD_LOGIC;
            signal wb_cyc    : out STD_LOGIC;
            signal wb_sel    : out STD_LOGIC_VECTOR (3  downto 0);
            signal wb_data   : in  STD_LOGIC_VECTOR (31 downto 0);
            signal wb_addr   : out STD_LOGIC_VECTOR (c_WORDS_PER_PAGE_BITS 
                                                                 downto 0);
            signal read_data : out STD_LOGIC_VECTOR (31 downto 0);
                   reg_addr  :     STD_LOGIC_VECTOR (c_WORDS_PER_PAGE_BITS 
                                                                 downto 0)) is
      begin
           wait until rising_edge(wb_clk);
         wb_we    <= '0';  
         wb_stb   <= '1';  
         wb_cyc   <= '1';  
         wb_sel   <= X"F";  
         wb_addr  <= reg_addr;
           wait until rising_edge(wb_clk);
           --! Here we wait for the ack and keep till operation is finished
         read_data  <= wb_data; 
           wait until rising_edge(wb_clk);
         wb_stb   <= '0';  
         wb_cyc   <= '0';  
         wb_sel   <= X"F";  
      end procedure;


      --! @brief Funtion to fill a page with predefined words.
      function fill_page return r_page is
         variable v_var0   : r_word := (word_slv => X"DEADBEEF"); 
         variable v_var1   : r_word := (word_slv => X"8BADF00D"); 
         variable v_var2   : r_word := (word_slv => X"C001F007"); 
         variable v_var3   : r_word := (word_slv => X"B16B00B5");
         variable v_return : r_page;
      begin
         for i in 0 to c_PAGE_SIZE/4 - 1 loop
            case (i mod 4) is
               when 0 =>
                  v_return(i) := v_var0;
               when 1 =>
                  v_return(i) := v_var1;
               when 2 =>
                  v_return(i) := v_var2;
               when others  =>
                  v_return(i) := v_var3;
            end case;
         end loop;
         return v_return;
      end function fill_page;

      function fill_read return STD_LOGIC_VECTOR is
         variable v_return  : STD_LOGIC_VECTOR(c_READ_LENGTH*8 - 1 downto 0);
      begin
         v_return := X"600D700D";
         return v_return;
      end function fill_read;

end m25p32_top_tb_pkg;
