----------------------------------------------------------------------------------
-- Company:        ETH Zurich, Institute for Particle Physics
-- Engineer:       Q. Weitzel
-- 
-- Create Date:    10/06/2010 
-- Design Name: 
-- Module Name:    FTU_dna_gen - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description:    entity to read out the FPGA DNA identifier
--
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;

entity dna_gen is
  Port (
    clk   : IN  STD_LOGIC;
    dna   : OUT STD_LOGIC_VECTOR(63 downto 0) := (others => '0');
    ready : OUT STD_LOGIC := '0'
  );
end dna_gen;

architecture Behavioral of dna_gen is
	constant DNA_FOR_SIM : bit_vector := X"01710000E000FAD2"; -- for simulation only
  signal dout_sig  : STD_LOGIC := '0';
  signal read_sig  : STD_LOGIC := '0';
  signal shift_sig : STD_LOGIC := '0';
  signal dna_sig   : STD_LOGIC_VECTOR(63 downto 0) := (others => '0');

  type FTU_dna_gen_StateType is (IDLE, READ_DNA, SHIFT_DNA, DNA_READY);
  signal FTU_dna_gen_State : FTU_dna_gen_StateType;

  signal shift_cntr : INTEGER range 0 to 64 := 0;
  signal start_sig : std_logic := '0';
  
begin
  
  DNA_PORT_inst : DNA_PORT
   generic map (
      SIM_DNA_VALUE => DNA_FOR_SIM)  -- Specifies the Pre-programmed factory ID value
   port map (
      DOUT => dout_sig,   -- 1-bit DNA output data
      CLK => clk,         -- 1-bit clock input
      DIN => '0',         -- 1-bit user data input pin
      READ => read_sig,   -- 1-bit input, active high load DNA, active low read
      SHIFT => shift_sig  -- 1-bit input, active high shift enable
   );

  FTU_dna_gen_FSM : process(clk)
  begin
    if Falling_edge(clk) then
		if (start_sig = '0') then	-- do it only once.
    		start_sig <= '1';
   		end if;
      case FTU_dna_gen_State is
        when IDLE =>
          ready <= '0';
          read_sig <= '0';
          shift_sig <= '0';
          if (start_sig = '1') then
            FTU_dna_gen_State <= READ_DNA;
          else
            FTU_dna_gen_State <= IDLE;
          end if;
        when READ_DNA =>
          ready <= '0';
          read_sig <= '1';
          shift_sig <= '0';
          FTU_dna_gen_State <= SHIFT_DNA;
        when SHIFT_DNA =>
          shift_cntr <= shift_cntr + 1;
          ready <= '0';
          read_sig <= '0';
          if (shift_cntr < 57) then
            dna_sig <= dna_sig(62 downto 0) & dout_sig;  -- put in from right
            shift_sig <= '1';
            FTU_dna_gen_State <= SHIFT_DNA;
          --elsif (shift_cntr = 56) then
            --dna_sig <= dna_sig(62 downto 0) & dout_sig;  -- put in from right
            --shift_sig <= '0';
            --FTU_dna_gen_State <= SHIFT_DNA;
          else
            shift_sig <= '1';
            FTU_dna_gen_State <= DNA_READY;
          end if;
        when DNA_READY =>
          ready <= '1';
          start_sig <= '0';
          read_sig <= '0';
          shift_sig <= '0';
      end case;
    end if;
  end process FTU_dna_gen_FSM;

  dna <= dna_sig;
    
end Behavioral;
