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

package spi_analyser_pkg is 

   component spi_analyser
      port(  rst_i            : in  STD_LOGIC;
             SPI0_i           : in  r_SPI0;
             SPI1_i           : in  r_SPI1;

             spi_mosi_o       : in  STD_LOGIC;
             spi_miso_i       : in  STD_LOGIC;
             spi_clk_o        : in  STD_LOGIC;
             spi_cs_n_o       : in  STD_LOGIC;

             inst_check_o     : out STD_LOGIC_VECTOR (7    downto 0);
             addr_check_o     : out STD_LOGIC_VECTOR (23   downto 0);
             data_check_o     : out STD_LOGIC_VECTOR (2047 downto 0);

             end_inst_flag_o  : out STD_LOGIC;
             end_addr_flag_o  : out STD_LOGIC;
             end_data_flag_o  : out STD_LOGIC
   );
   end component;

   component spi_slave_writer
      generic(
         g_READ_LENGTH         : NATURAL := c_READ_LENGTH);
      port(  rst_i           : in  STD_LOGIC;
             SPI0_i          : in  r_SPI0;
             SPI1_i          : in  r_SPI1;
             STATUS_i        : in  r_STATUS;

             bytes_to_wr_i   : in  NATURAL;
             read_i          : in STD_LOGIC_VECTOR(g_READ_LENGTH*8 - 1 downto 0);

             end_read_flag_o : out STD_LOGIC;

             spi_miso_o      : out STD_LOGIC;
             spi_clk_i       : in  STD_LOGIC
          );
   end component;



   -- Clock period definitions
   constant c_WISHBONE_PERIOD : TIME := 10 ns;

   procedure set_SPI_mode (signal SPI0: out r_SPI0;
                                  cpol:     STD_LOGIC;
                                  cpha:     STD_LOGIC);

   procedure set_spi_lengths (signal SPI0        : out r_SPI0;
                                     inst_length : in  NATURAL;
                                     addr_length : in  NATURAL;
                                     data_length : in  NATURAL;
                                     read_length : in  NATURAL);

   procedure set_SPI0 (signal SPI0          : out r_SPI0;
                              cpol          :     STD_LOGIC;
                              cpha          :     STD_LOGIC;
                              inst_length   : in  NATURAL;
                              addr_length   : in  NATURAL;
                              data_length   : in  NATURAL;
                              read_length   : in  NATURAL);

   procedure set_FIFO_contents(
         signal clk_i  : in STD_LOGIC;
         signal inst_i : out STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
         signal addr_i : out STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
         signal data_i : out STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0);
                inst   : in  STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
                addr   : in  STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
                data   : in  STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0)); 

   procedure send_SPI_and_wait (signal clk_i    : in  STD_LOGIC;
                                signal SPI1     : out r_SPI1;
                                signal SPI2     : in  r_SPI2;
                                       send_inst: in  STD_LOGIC;
                                       send_addr: in  STD_LOGIC;
                                       send_data: in  STD_LOGIC;
                                       read_miso: in  STD_LOGIC;
                                       clk_div  : in  UNSIGNED(3 downto 0)); 

   procedure set_SPI1 (
         signal clk_i     : in  STD_LOGIC;
         signal SPI1      : out r_SPI1; 
         signal SPI2      : in  r_SPI2; 
                send_inst : in  STD_LOGIC;
                send_addr : in  STD_LOGIC;
                send_data : in  STD_LOGIC;
                read_mosi : in  STD_LOGIC;
                clk_div   : in  NATURAL;
         signal inst_i    : out STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
         signal addr_i    : out STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
         signal data_i    : out STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0);
                inst      : in  STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
                addr      : in  STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
                data      : in  STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0));

   procedure spi_command(
        signal clk_i              : in  STD_LOGIC;
        signal s_rst_spi_analyser : out STD_LOGIC;
        signal SPI0          : out r_SPI0;
        signal SPI1          : out r_SPI1;
        signal SPI2          : in  r_SPI2;
               cpol          : in  STD_LOGIC;
               cpha          : in  STD_LOGIC;
               clk_div       : in  NATURAL;
               inst_length   : in  NATURAL;
               addr_length   : in  NATURAL;
               data_length   : in  NATURAL;
               read_length   : in  NATURAL;
               send_inst     : in  STD_LOGIC;
               send_addr     : in  STD_LOGIC;
               send_data     : in  STD_LOGIC;
               read_mosi     : in  STD_LOGIC;
        signal inst_i    : out STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
        signal addr_i    : out STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
        signal data_i    : out STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0);
               inst      : in  STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
               addr      : in  STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
               data      : in  STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0)); 

end spi_analyser_pkg;

package body spi_analyser_pkg is

   procedure set_SPI_mode (signal SPI0: out r_SPI0;
                                  cpol:     STD_LOGIC;
                                  cpha:     STD_LOGIC ) is
   begin
      SPI0.CPOL   <= cpol;
      SPI0.CPHA   <= cpha;
   end procedure set_SPI_mode;

   procedure set_spi_lengths (signal SPI0        : out r_SPI0;
                                     inst_length : in  NATURAL;
                                     addr_length : in  NATURAL;
                                     data_length : in  NATURAL;
                                     read_length : in  NATURAL) is
   begin
      SPI0.BREAD  <= to_unsigned(read_length, SPI0.BREAD'length);
      SPI0.BDATA  <= to_unsigned(data_length, SPI0.BDATA'length);
      SPI0.BADDR  <= to_unsigned(addr_length, SPI0.BADDR'length);
      SPI0.BINST  <= to_unsigned(inst_length, SPI0.BINST'length);
   end procedure set_spi_lengths;

   procedure set_SPI0(
         signal SPI0          : out r_SPI0;
                cpol          :     STD_LOGIC;
                cpha          :     STD_LOGIC;
                inst_length   : in  NATURAL;
                addr_length   : in  NATURAL;
                data_length   : in  NATURAL;
                read_length   : in  NATURAL) is
   begin
      set_SPI_mode(SPI0, cpol, cpha);
      set_spi_lengths(SPI0, inst_length, addr_length, data_length, read_length);
   end procedure;

   procedure set_FIFO_contents(
         signal clk_i  : in STD_LOGIC;
         signal inst_i : out STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
         signal addr_i : out STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
         signal data_i : out STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0);
                inst   : in  STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
                addr   : in  STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
                data   : in  STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0)) is
   begin
      inst_i <= inst;
      addr_i <= addr;
      data_i <= data;
         wait until rising_edge(clk_i);
   end procedure;

   procedure send_SPI_and_wait (signal clk_i    : in  STD_LOGIC;
                                signal SPI1     : out r_SPI1;
                                signal SPI2     : in  r_SPI2;
                                       send_inst: in  STD_LOGIC;
                                       send_addr: in  STD_LOGIC;
                                       send_data: in  STD_LOGIC;
                                       read_miso: in  STD_LOGIC;
                                       clk_div  : in  UNSIGNED(3 downto 0)) is
   begin
      SPI1.SEND_INST <= '0';
      SPI1.SEND_ADDR <= '0';
      SPI1.SEND_DATA <= '0';
      SPI1.READ_MISO <= '0';
      SPI1.PUSH_INST <= '0';
      SPI1.PUSH_ADDR <= '0';
      SPI1.PUSH_DATA <= '0';
      SPI1.CLK_DIV   <= to_unsigned(0,4);
      wait until rising_edge(clk_i);
      if send_inst = '1' then
         SPI1.SEND_INST <= '1';
         SPI1.PUSH_INST <= '1';
      end if;
      if send_addr = '1' then
         SPI1.SEND_ADDR <= '1';
         SPI1.PUSH_ADDR <= '1';
      end if;
      if send_data = '1' then
         SPI1.SEND_DATA <= '1';
         SPI1.PUSH_DATA <= '1';
      end if;
      if read_miso = '1' then
         SPI1.READ_MISO <= '1';
      end if;
      SPI1.SEND_OP   <= '1';
      SPI1.CLK_DIV   <= clk_div;
         wait until SPI2.SENT_OP = '1';
      SPI1.SEND_OP   <= '0';
      SPI1.SEND_INST <= '0';
      SPI1.SEND_ADDR <= '0';
      SPI1.SEND_DATA <= '0';
      SPI1.READ_MISO <= '0';
      SPI1.PUSH_INST <= '0';
      SPI1.PUSH_ADDR <= '0';
      SPI1.PUSH_DATA <= '0';
   end procedure;


   procedure set_SPI1 (
          signal clk_i     : in  STD_LOGIC;
          signal SPI1      : out r_SPI1; 
          signal SPI2      : in  r_SPI2; 
                 send_inst : in  STD_LOGIC;
                 send_addr : in  STD_LOGIC;
                 send_data : in  STD_LOGIC;
                 read_mosi : in  STD_LOGIC;
                 clk_div   : in  NATURAL;
          signal inst_i    : out STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
          signal addr_i    : out STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
          signal data_i    : out STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0);
                 inst      : in  STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
                 addr      : in  STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
                 data      : in  STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0))is
      variable v_clk_div : UNSIGNED(3 downto 0);
   begin
      v_clk_div :=    to_unsigned(clk_div,4);
      set_FIFO_contents(clk_i, inst_i, addr_i, data_i,
                               inst,   addr,   data);
      send_SPI_and_wait(clk_i, SPI1, SPI2,
                        send_inst, send_addr, send_data, read_mosi,
                        v_clk_div); 
   end procedure;


   procedure spi_command(
        signal clk_i              : in  STD_LOGIC;
        signal s_rst_spi_analyser : out STD_LOGIC;
        signal SPI0          : out r_SPI0;
        signal SPI1          : out r_SPI1;
        signal SPI2          : in  r_SPI2;
               cpol          : in  STD_LOGIC;
               cpha          : in  STD_LOGIC;
               clk_div       : in  NATURAL;
               inst_length   : in  NATURAL;
               addr_length   : in  NATURAL;
               data_length   : in  NATURAL;
               read_length   : in  NATURAL;
               send_inst     : in  STD_LOGIC;
               send_addr     : in  STD_LOGIC;
               send_data     : in  STD_LOGIC;
               read_mosi     : in  STD_LOGIC;
        signal inst_i    : out STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
        signal addr_i    : out STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
        signal data_i    : out STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0);
               inst      : in  STD_LOGIC_VECTOR(8*c_INST_LENGTH - 1 downto 0);
               addr      : in  STD_LOGIC_VECTOR(8*c_ADDR_LENGTH - 1 downto 0);
               data      : in  STD_LOGIC_VECTOR(8*c_DATA_LENGTH - 1 downto 0)) is
   begin
      s_rst_spi_analyser <= '1';
         wait until rising_edge(clk_i);
         wait for c_WISHBONE_PERIOD*3/2;
      s_rst_spi_analyser <= '0';
         wait until rising_edge(clk_i);
      set_SPI0(SPI0, cpol, cpha,
               inst_length, addr_length, data_length, read_length);
      set_SPI1(clk_i, SPI1, SPI2,
               send_inst, send_addr, send_data, read_mosi, clk_div,
               inst_i, addr_i, data_i, inst, addr, data);
   end procedure;

      --      procedure assert_to_file(data      : STD_LOGIC_VECTOR(31 downto 0);
      --                               reference : STD_LOGIC_VECTOR(31 downto 0);
      --                               test_id   : STRING;
      --                               msg       : STRING) is
      --         variable line_buffer : LINE;
      --      begin
      --         if data = reference then
      --            write(line_buffer, string'(test_id&sep&"OK"&sep&msg));
      --         else
      --            write(line_buffer, string'(test_id&sep&"Fail"&sep&msg));
      --         end if;
      --         writeline(file_handler, line_buffer);
      --         assert data = reference  report "Bad"&msg;
      --      end procedure;

end spi_analyser_pkg;
