----------------------------------------------------------------------------------
--
-- 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:    17:34:08 06/14/2012 
-- Design Name:     
-- Module Name:    spi_master_core - Behavioral 
-- Project Name:   CTDAH/SVEC
-- Target Devices: Spartan 6
-- Tool versions:  Xilinx ISE 13.4
-- Description:    Wishbone access for SPI core. 
--
-- Dependencies: 
--
-- Revision: 0.1
--   0.01          + File Created
--   0.1           - Alpha version. Able to write and output data correctly at
--                   different configurations.
-- Additional Comments: 
--
----------------------------------------------------------------------------------

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


entity spi_master_regs is
   port(
              wb_rst_i   : in  STD_LOGIC; 
              wb_clk_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_we_i    : in  STD_LOGIC;
              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 (3  downto 0); 
              wb_ack_o   : out STD_LOGIC; 
              wb_rty_o   : out STD_LOGIC; 
              wb_err_o   : out STD_LOGIC; 

              SPI0_o     : out STD_LOGIC_VECTOR (31 downto 0); 
              SPI1_o     : out STD_LOGIC_VECTOR (31 downto 0); 
              SPI2_i     : in STD_LOGIC_VECTOR  (15 downto 0) 
           );
end spi_master_regs;

architecture Behavioral of spi_master_regs is

   signal s_SPI0   : STD_LOGIC_VECTOR (31  downto 0);
   signal s_SPI1   : STD_LOGIC_VECTOR (31  downto 0);
   signal s_SPI2   : STD_LOGIC_VECTOR (15  downto 0);

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

begin

   wb_ack_o <= s_wb_ack; 
   wb_rty_o <= s_wb_rty; 
   wb_err_o <= s_wb_err; 

   SPI0_o   <= s_SPI0; 
   SPI1_o   <= s_SPI1;
   s_SPI2   <= SPI2_i;

   p_wb: process (wb_clk_i)
   begin
      if rising_edge(wb_clk_i) then
         if wb_rst_i = '1' then
            s_SPI0 <= f_STD_LOGIC_VECTOR(c_SPI0_default);
            s_SPI1 <= f_STD_LOGIC_VECTOR(c_SPI1_default);
         elsif (wb_stb_i = '1' and wb_cyc_i = '1') then
            if (s_wb_ack or s_wb_rty or s_wb_err) = '1' then
               s_wb_ack   <= '0';
               s_wb_rty   <= '0';
               s_wb_err   <= '0';
            else
               s_wb_ack   <= '0'; 
               s_wb_rty   <= '0'; 
               s_wb_err   <= '0'; 
               case wb_we_i is
                  when '1' =>
                     case wb_addr_i is
                        when c_SPI0_addr =>
                           s_SPI0      <= wb_data_i;
                           s_wb_ack    <= '1'; 
                        when c_SPI1_addr =>
                           s_SPI1      <= wb_data_i;
                           s_wb_ack    <= '1'; 
                        when others      =>
                           s_wb_err    <= '1'; 
                     end case;
                  when others =>
                     case wb_addr_i is
                        when c_SPI0_addr =>
                           wb_data_o   <= s_SPI0;
                           s_wb_ack    <= '1'; 
                        when c_SPI1_addr =>
                           wb_data_o   <= s_SPI1;
                           s_wb_ack    <= '1'; 
                        when c_SPI2_addr =>
                           wb_data_o(15 downto  0)   <= s_SPI2;
                           wb_data_o(31 downto 16)   <= (others => '0');
                           s_wb_ack                  <= '1'; 
                       when others      =>
                     end case;
               end case;
            end if;
         else
         end if;
      else
      end if;
   end process;

end Behavioral;
