----------------------------------------------------------------------------------
--
-- 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:09:09 08/08/2012
-- Design Name:    Serializer
-- Module Name:    serializer_sim.vhd 
-- Project Name:   Serializer
-- Target Devices: Spartan 6
-- Tool versions:  Xilinx ISE 13.4
-- Description:    Serializer to be gentlely used in simulation. No RTL model! 
--                 This is a parametrizable serializer that improves the
--                 readability of the test vectors in simulation and
--                 verification.
--
-- Dependencies: 
--
-- Revision: 0.1
--   0.01          + File Created
--                 
-- Additional Comments: 
--
----------------------------------------------------------------------------------

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

entity serializer_sim is
   generic(
       g_SERIAL_LENGTH         : NATURAL := c_SERIAL_LENGTH
   ); port(
       rst_i                : in  STD_LOGIC;
       enable_i             : in  STD_LOGIC;
       serial_data_i        : in  STD_LOGIC; 
       serial_clock_i       : in  STD_LOGIC;
       FMOH_i               : in  STD_LOGIC_VECTOR (r_FMOH'a_length - 1 downto 0);

       clk_i                : in  STD_LOGIC;
       serial_frame_rcved_o : out STD_LOGIC;
       parallel_frame_o     : out STD_LOGIC_VECTOR (c_SERIAL_LENGTH - 1 downto 0)
   );
end serializer_sim;

architecture Behavioral of serializer_sim is

   signal s_inst    :  inst_parallel;
   signal s_addr    :  addr_parallel;
   signal s_data    :  data_parallel;

   signal s_counter :  INTEGER;
   signal reset_cnt :  STD_LOGIC;

begin

   parallel_frame_o(c_SERIAL_LENGTH - 1
                                 downto   c_SERIAL_LENGTH - 1 
                                       - (inst_parallel'a_length - 1))
                    <= f_STD_LOGIC_VECTOR(s_inst);
   parallel_frame_o(  c_SERIAL_LENGTH
                    - inst_parallel'a_length - 1
                                 downto  c_SERIAL_LENGTH - 1
                                       - inst_parallel'a_length
                                       - (addr_parallel'a_length - 1)) 
                    <= f_STD_LOGIC_VECTOR(s_addr);
   parallel_frame_o(data_parallel'a_length - 1
                                 downto 0)            
                    <= f_STD_LOGIC_VECTOR(s_data);


   p_serial_clock :process(serial_clock_i, reset_cnt)
   begin
      --! We attended the reset strobe from the fast clk domain and reset the
      --! counter.
      if reset_cnt = '1' then
         s_inst        <= c_inst_paralell_default;
         s_addr        <= c_addr_paralell_default;
         s_data        <= c_data_paralell_default;
         s_counter     <= 0;
      end if;

      if rising_edge(serial_clock_i) then
         s_counter <= s_counter + 1;
         --! We capture the signal at the sampling time
         if s_counter < 8*c_SIZE_BLOCKS(0) then
            s_inst.inst(s_counter)                          <= serial_data_i;
         elsif   (s_counter <  8*(c_SIZE_BLOCKS(1)+c_SIZE_BLOCKS(0)))
            and  (s_counter >= 8* c_SIZE_BLOCKS(0))                  then
            s_addr.addr(s_counter - 8* c_SIZE_BLOCKS(0))    <= serial_data_i;
         else
            s_data.data(s_counter - 8*(c_SIZE_BLOCKS(1) + c_SIZE_BLOCKS(0)))
                                                            <= serial_data_i;
         end if;
      else
      end if;
   end process;


   --! This process only targets for placing a reset in the other domain.
   --! It was thought in the synthesizable way (which means this is the
   --! registered process and the combinatorial part is placed in the process
   --! above).
   p_clk :process(clk_i)
   begin
      if rising_edge(clk_i) then
         reset_cnt  <= '0';
         if rst_i = '1' then
            reset_cnt <= '1';
         --! Add all the logic here to generate serial_frame_rcved_o
         end if;
      end if;
   end process;
end Behavioral;
