----------------------------------------------------------------------------------
--
-- Copyright CERN 2011.
-- 
-- This documentation describes Open Hardware and is licensed under the
-- CERN OHL v. 1.1.
--
-- You may redistribute and modify this documentation under the terms of the CERN
-- OHL v.1.1. (http://ohwr.org/cernohl).
--
-- This documentation is distributed WITHOUT
-- ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY
-- QUALITY AND FITNESS FOR A PARTICULAR PURPOSE. Please see the CERN OHL v.1.1 for
-- applicable conditions.
--
----------------------------------------------------------------------------------
--
-- Company:        CERN, BE-CO-HT 
-- Engineer:       Carlos Gil Soriano
-- 
-- Create Date:    15:23:39 15-06-2012        
-- Design Name:                                
-- Module Name:    m25p32_core_pkg                 
-- Project Name:   Level Conversion Circuits  
-- Target Devices: Spartan 6
-- Tool versions:  Xilinx ISE 13.4
-- Description:    m25p32_core_pkg.vhd contains the procedures that rule
--                 m25p32_core.vhd fsm
--
-- Dependencies:   m25p32_pkg.vhd
--
-- Revision: 0.1
--   0.01          + File Created
--                 
-- Additional Comments: 
--
----------------------------------------------------------------------------------

library IEEE;
library work;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.m25p32_pkg.ALL;
use work.spi_master_pkg.ALL;

package m25p32_core_pkg is


   type t_m25p32_fsm  is (S0_IDLE,
                          S1_WREN,
                          S2A_SPI_OP_LD_DBUF,
                          S2B_SPI_OP_LD_SPIBUF,
                          S3_DEL_PROG_CYCLE,
                          S4_WRDI,
                          Q0_ERROR);

   ------------------------------------------------------------------------------
   --  m25p32 m25p32 m25p32 m25p32 m25p32 SPI Instruction set
   ------------------------------------------------------------------------------
   --  INSTRUCTION        DESCRIPTION                ADDRESS         DATA
   --                                                 BYTES          BYTES
   --    WREN              WRite ENable                 0             0
   --    WRDI              WRite DIsable                0             0
   --    RDSR              ReaD Status Register         0             1
   --    WRSR              WRite Status Register        0             1
   --    READ              READ data bytes              3             4
   --    PP                Page Program                 3             256
   --    SE                Sector Erase                 3             0
   --    BE                Bulk Erase                   0             0
   -------------------------------------------------------------------------------
   constant c_WREN_inst      : STD_LOGIC_VECTOR(7  downto 0) := X"06";
   constant c_WRDI_inst      : STD_LOGIC_VECTOR(7  downto 0) := X"04";
   constant c_RDSR_inst      : STD_LOGIC_VECTOR(7  downto 0) := X"05";
   constant c_WRSR_inst      : STD_LOGIC_VECTOR(7  downto 0) := X"01";
   constant c_READ_inst      : STD_LOGIC_VECTOR(7  downto 0) := X"03";
   --   constant c_FAST_READ_inst : STD_LOGIC_VECTOR(7  downto 0) := X"0B";
   constant c_PP_inst        : STD_LOGIC_VECTOR(7  downto 0) := X"02";
   constant c_SE_inst        : STD_LOGIC_VECTOR(7  downto 0) := X"D8";
   constant c_BE_inst        : STD_LOGIC_VECTOR(7  downto 0) := X"C7";


      constant c_SPI1_IDLE : r_SPI1 := (PUSH_DATA => '0', PUSH_ADDR => '0',
                                        PUSH_INST => '0', x => (others  => '0'),
                                        SEND_DATA => '0',
                                        SEND_ADDR => '0',
                                        SEND_INST => '0',
                                        SEND_OP   => '0',
                                        y         => (others  => '0'),
                                        CLK_DIV   => c_CLK_DIV,
                                        z         => (others  => '0'));


   --! WREN instruction. Configuration for SPI0 and SPI1 registers.
   constant c_SPI0_WREN  : r_SPI0 := (CPOL  => c_CPOL,
                                      CPHA  => c_CPHA,
                                      x     => (others => '0'),
                                      BDATA => (others => '0'),
                                      BADDR => (others => '0'),
                                      BINST => to_unsigned( 1 , 9));

      constant c_SPI1_WREN : r_SPI1 := (PUSH_DATA => '0', PUSH_ADDR => '0',
                                        PUSH_INST => '1', x => (others  => '0'),
                                        SEND_DATA => '0',
                                        SEND_ADDR => '0',
                                        SEND_INST => '1',
                                        SEND_OP   => '1',
                                        y         => (others  => '0'),
                                        CLK_DIV   => c_CLK_DIV,
                                        z         => (others  => '0'));


   --! WRDI instruction. Configuration for SPI0 and SPI1 registers.
   constant c_SPI0_WRDI  : r_SPI0 := (CPOL  => c_CPOL,
                                      CPHA  => c_CPHA,
                                      x     => (others => '0'),
                                      BDATA => (others => '0'),
                                      BADDR => (others => '0'),
                                      BINST => to_unsigned( 1, 9));

      constant c_SPI1_WRDI : r_SPI1 := (PUSH_DATA => '0', PUSH_ADDR => '0',
                                        PUSH_INST => '1', x => (others  => '0'),
                                        SEND_DATA => '0',
                                        SEND_ADDR => '0',
                                        SEND_INST => '1',
                                        SEND_OP   => '1',
                                        y         => (others  => '0'),
                                        CLK_DIV   => c_CLK_DIV,
                                        z         => (others  => '0'));


   --! WRSR instruction. Configuration for SPI0 and SPI1 registers.
   constant c_SPI0_WRSR  : r_SPI0 := (CPOL  => c_CPOL,
                                      CPHA  => c_CPHA,
                                      x     => (others => '0'),
                                      BDATA => to_unsigned( 1 , 9),
                                      BADDR => (others => '0'),
                                      BINST => to_unsigned( 1 , 9));

      constant c_SPI1_WRSR : r_SPI1 := (PUSH_DATA => '1', PUSH_ADDR => '0',
                                        PUSH_INST => '1', x => (others  => '0'),
                                        SEND_DATA => '1',
                                        SEND_ADDR => '0',
                                        SEND_INST => '1',
                                        SEND_OP   => '1',
                                        y         => (others  => '0'),
                                        CLK_DIV   => c_CLK_DIV,
                                        z         => (others  => '0'));


   --! PP instruction. Configuration for SPI0 and SPI1 registers.
   constant c_SPI0_PP    : r_SPI0 := (CPOL  => c_CPOL,
                                      CPHA  => c_CPHA,
                                      x     => (others => '0'),
                                      BDATA => to_unsigned( 256 , 9),
                                      BADDR => to_unsigned(   3 , 9),
                                      BINST => to_unsigned(   1 , 9));

      constant c_SPI1_PP : r_SPI1 := (PUSH_DATA => '0', PUSH_ADDR => '0',
                                      PUSH_INST => '0', x => (others  => '0'),
                                      SEND_DATA => '1',
                                      SEND_ADDR => '1',
                                      SEND_INST => '1',
                                      SEND_OP   => '1',
                                      y         => (others  => '0'),
                                      CLK_DIV   => c_CLK_DIV,
                                      z         => (others  => '0'));


   --! SE instruction. Configuration for SPI0 and SPI1 registers.
   constant c_SPI0_SE    : r_SPI0 := (CPOL  => c_CPOL,
                                      CPHA  => c_CPHA,
                                      x     => (others => '0'),
                                      BDATA => (others => '0'),
                                      BADDR => to_unsigned( 3 , 9), 
                                      BINST => to_unsigned( 1 , 9));

      constant c_SPI1_SE : r_SPI1 := (PUSH_DATA => '0', PUSH_ADDR => '0',
                                      PUSH_INST => '0', x => (others  => '0'),
                                      SEND_DATA => '0',
                                      SEND_ADDR => '1',
                                      SEND_INST => '1',
                                      SEND_OP   => '1',
                                      y         => (others  => '0'),
                                      CLK_DIV   => c_CLK_DIV,
                                      z         => (others  => '0'));

   --! Included here to be less verbose in m25p32_core.vhd
   -- c_CLK_I_PERIOD can be found in spi_master_pkg.vhd
   component spi_master_core is
      generic(
        g_INST_LENGTH  : NATURAL := c_INST_LENGTH;
        g_ADDR_LENGTH  : NATURAL := c_ADDR_LENGTH;
        g_DATA_LENGTH  : NATURAL := c_DATA_LENGTH;
        g_CLK_I_PERIOD : NATURAL := c_CLK_I_PERIOD);
      port(
        rst_i        : in  STD_LOGIC;
        clk_i        : in  STD_LOGIC;

        inst_i       : in  STD_LOGIC_VECTOR (8*g_INST_LENGTH - 1 downto 0);
        addr_i       : in  STD_LOGIC_VECTOR (8*g_ADDR_LENGTH - 1 downto 0);
        data_i       : in  STD_LOGIC_VECTOR (8*g_DATA_LENGTH - 1 downto 0);

        SPI0_i       : in  STD_LOGIC_VECTOR (31 downto 0);
        SPI1_i       : in  STD_LOGIC_VECTOR (31 downto 0);
        SPI2_o       : out STD_LOGIC_VECTOR (15 downto 0);

        spi_mosi_o   : out STD_LOGIC;
        spi_miso_i   : in  STD_LOGIC;
        spi_clk_o    : out STD_LOGIC;
        spi_cs_n_o   : out STD_LOGIC);
   end component;

end m25p32_core_pkg;

package body m25p32_core_pkg is
end m25p32_core_pkg;
