----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    17:06:55 10/21/2011 
-- Design Name: 
-- Module Name:    Driver - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------


-- ===================================================================================================
-- This module is responsible for generating the bitstring.
-- ===================================================================================================

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;

entity Driver is
   generic (
      CLFSR_LEN_NB: integer := 12
      );
   port ( 
      Clk: in  std_logic;
      RESET: in std_logic;
      start: in std_logic;
      ready: out std_logic;
      continue: in std_logic;
      RegionSizeMinus1: in std_logic_vector(CLFSR_LEN_NB-1 downto 0);
      GroupSizeExponent: in std_logic_vector(CLFSR_LEN_NB-1 downto 0);
      CLFSR_start: out std_logic;
      CLFSR_ready: in std_logic;
      CLFSR_init_seed: out std_logic;
      CLFSR_next_seq: out std_logic;
      CLFSR_set_n_ahead_val: out std_logic;
      CLFSR_inc_n_ahead: out std_logic;
      CLFSR_val_to_set: out std_logic_vector(CLFSR_LEN_NB-1 downto 0);
      CLFSR_n_ahead_setting: in std_logic_vector(CLFSR_LEN_NB-1 downto 0);
      Pairings_OverRunErr: out std_logic
      );
end Driver;

architecture beh of Driver is
   type state_type is (idle, run_lfsr, wait_continue);
   signal state_reg, state_next: state_type;

   signal CLFSR_num_bits_reg, CLFSR_num_bits_next: unsigned(CLFSR_LEN_NB-1 downto 0);

   signal Pairings_OverRunErr_reg, Pairings_OverRunErr_next: std_logic;

   signal tmp: unsigned(CLFSR_LEN_NB-1 downto 0);
   signal max_set_iterations: unsigned(CLFSR_LEN_NB-1 downto 0);

   begin

   tmp <= unsigned(RegionSizeMinus1) - unsigned(CLFSR_n_ahead_setting);
   max_set_iterations <= (tmp + 1) sll to_integer(unsigned(GroupSizeExponent));

-- =============================================================================================
-- State and register logic
-- =============================================================================================
   process(Clk, RESET)
      begin
      if ( RESET = '1' ) then
         state_reg <= idle;
         CLFSR_num_bits_reg <= (others => '0');
         Pairings_OverRunErr_reg <= '0';
      elsif ( Clk'event and Clk = '1' ) then
         state_reg <= state_next;
         CLFSR_num_bits_reg <= CLFSR_num_bits_next;
         Pairings_OverRunErr_reg <= Pairings_OverRunErr_next;
      end if; 
   end process;

-- =============================================================================================
-- Combo logic for state machine. 
-- =============================================================================================
   process (state_reg, start, continue, CLFSR_ready, CLFSR_num_bits_reg, max_set_iterations, CLFSR_n_ahead_setting, 
      RegionSizeMinus1, Pairings_OverRunErr_reg)
      begin
      state_next <= state_reg;
      CLFSR_num_bits_next <= CLFSR_num_bits_reg;
      Pairings_OverRunErr_next <= Pairings_OverRunErr_reg;

      ready <= '0';
      CLFSR_start <= '0';
      CLFSR_init_seed <= '0';
      CLFSR_next_seq <= '0';
      CLFSR_set_n_ahead_val <= '0';
      CLFSR_inc_n_ahead <= '0';
      CLFSR_val_to_set <= (others => '0');

      case state_reg is

-- =====================
         when idle =>
            ready <= '1';
            if ( start = '1' ) then
               ready <= '0';
               Pairings_OverRunErr_next <= '0';
               CLFSR_set_n_ahead_val <= '1';
               CLFSR_val_to_set <= std_logic_vector(to_unsigned(1, CLFSR_LEN_NB));
               CLFSR_num_bits_next <= (others => '0');
               CLFSR_init_seed <= '1';
               CLFSR_start <= '1';
               state_next <= run_lfsr;
            end if;

-- =====================
         when run_lfsr =>
            if ( CLFSR_ready = '1' ) then
               state_next <= wait_continue;
            end if;

-- =====================
         when wait_continue =>
            ready <= '1';
            if ( continue = '1' ) then
               if ( CLFSR_num_bits_reg = unsigned(max_set_iterations) - 1 ) then
                  if ( unsigned(CLFSR_n_ahead_setting) = unsigned(RegionSizeMinus1) ) then
                     Pairings_OverRunErr_next <= '1';
                     state_next <= idle;
                  else
                     CLFSR_start <= '1';
                     CLFSR_init_seed <= '1';
                     CLFSR_inc_n_ahead <= '1';
                     CLFSR_num_bits_next <= (others => '0');
                     state_next <= run_lfsr;
                  end if;
               else
                  CLFSR_start <= '1';
                  CLFSR_next_seq <= '1';
                  CLFSR_num_bits_next <= CLFSR_num_bits_reg + 1;
                  state_next <= run_lfsr;
               end if;
            end if;
      end case;
   end process;

   Pairings_OverRunErr <= Pairings_OverRunErr_reg;

end beh;
