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


-- ===================================================================================================
-- ===================================================================================================

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

entity Main is
   generic (
      CLFSR_LEN_NB: integer := 12;
      NUM_ROWS_NB: integer := 6;
      NUM_COLS_NB: integer := 6
      );
   port ( 
      Clk : in  std_logic;
      RESET: in std_logic;

-- Starts the process (TOP_gen_bstr)
      TOP_start: in std_logic; 

-- Is asserted when new row/col values are available.
      TOP_ready: out std_logic;

-- You assert once you've read the pairing_row/pairing_col from the slv registers (VDC_finished)
      TOP_continue: in std_logic;

-- Determines the pattern and how many pairing_rowx and pairing_colx values are generated. When 0,
-- 4096*4095/2, when 1, (15*14/2)*256
      TOP_exhaustive_or_subset: in std_logic;

      pairing_row1: out std_logic_vector(NUM_ROWS_NB-1 downto 0);
      pairing_col1: out std_logic_vector(NUM_COLS_NB-1 downto 0);
      pairing_row2: out std_logic_vector(NUM_ROWS_NB-1 downto 0);
      pairing_col2: out std_logic_vector(NUM_COLS_NB-1 downto 0);

      TOP_Pairings_OverRunErr: out std_logic
      );
end Main;

architecture beh of Main is

   constant TOP_NUM_ELES: integer := 4096;
   constant CLFSR_REG_LEN_NB: integer := 4;
   constant TOP_REGION_SIZE: integer := 2**CLFSR_REG_LEN_NB;
   constant CLFSR_GRP_LEN_NB: integer := CLFSR_LEN_NB - CLFSR_REG_LEN_NB;

   constant TOP_NO_NORM_REGION_SIZE_MINUS1: integer := TOP_NUM_ELES - 1;
   constant TOP_NO_NORM_GROUP_SIZE_EXPONENT: integer := 0;

   constant TOP_NORM_REGION_SIZE_MINUS1: integer := TOP_REGION_SIZE - 1;
   constant TOP_NORM_GROUP_SIZE_EXPONENT: integer := CLFSR_GRP_LEN_NB;

   constant TOP_NORM_GROUP_SIZE_MINUS1: integer := 2**CLFSR_GRP_LEN_NB - 1;

   signal TOP_seed_in_actual: std_logic_vector(CLFSR_LEN_NB-1 downto 0);

   signal TOP_RegionSizeMinus1: std_logic_vector(CLFSR_LEN_NB-1 downto 0);
   signal TOP_GroupSizeExponent: std_logic_vector(CLFSR_LEN_NB-1 downto 0);
   signal TOP_GroupSizeMinus1: std_logic_vector(CLFSR_LEN_NB-1 downto 0);
   signal TOP_advance_grp: std_logic;

-- Challenge LFSR
   signal CLFSR_start: std_logic;
   signal CLFSR_start_Norm: std_logic;
   signal CLFSR_start_NoNorm: std_logic;
   signal CLFSR_ready: std_logic;
   signal CLFSR_init_seed: std_logic;
   signal CLFSR_next_seq: std_logic;
   signal CLFSR_PRN_A: std_logic_vector(CLFSR_LEN_NB-1 downto 0);
   signal CLFSR_PRN_B: std_logic_vector(CLFSR_LEN_NB-1 downto 0);

   signal CLFSR_ready1: std_logic;
   signal CLFSR_ready2: std_logic;
   signal CLFSR_ready3: std_logic;
   signal CLFSR_ready4: std_logic;
   signal CLFSR_ready5: std_logic;
   signal CLFSR_set_n_ahead_val: std_logic;
   signal CLFSR_inc_n_ahead: std_logic;
   signal CLFSR_val_to_set: std_logic_vector(CLFSR_LEN_NB-1 downto 0);
   signal CLFSR_n_ahead_setting: std_logic_vector(CLFSR_LEN_NB-1 downto 0);
   signal CLFSR_n_ahead_setting_NoNorm: std_logic_vector(CLFSR_LEN_NB-1 downto 0);
   signal CLFSR_n_ahead_setting_Norm: std_logic_vector(CLFSR_REG_LEN_NB-1 downto 0);
   signal CLFSR_PRN1: std_logic_vector(CLFSR_LEN_NB-1 downto 0);
   signal CLFSR_PRN2: std_logic_vector(CLFSR_LEN_NB-1 downto 0);
   signal CLFSR_PRN3: std_logic_vector(CLFSR_REG_LEN_NB-1 downto 0);
   signal CLFSR_PRN4: std_logic_vector(CLFSR_GRP_LEN_NB-1 downto 0);
   signal CLFSR_PRN5: std_logic_vector(CLFSR_REG_LEN_NB-1 downto 0);

   begin


-- ====================================================================================================
-- BITGEN DRIVER
-- ====================================================================================================
-- This module is the driver for bit generation. 
   with TOP_exhaustive_or_subset select
      TOP_RegionSizeMinus1 <= std_logic_vector(to_unsigned(TOP_NO_NORM_REGION_SIZE_MINUS1, CLFSR_LEN_NB)) when '0',
                              std_logic_vector(to_unsigned(TOP_NORM_REGION_SIZE_MINUS1, CLFSR_LEN_NB)) when others;

   with TOP_exhaustive_or_subset select
      TOP_GroupSizeExponent <= std_logic_vector(to_unsigned(TOP_NO_NORM_GROUP_SIZE_EXPONENT, CLFSR_LEN_NB)) when '0',
                               std_logic_vector(to_unsigned(TOP_NORM_GROUP_SIZE_EXPONENT, CLFSR_LEN_NB)) when others;

   TOP_GroupSizeMinus1 <= std_logic_vector(to_unsigned(TOP_NORM_GROUP_SIZE_MINUS1, CLFSR_LEN_NB)); 

   DriverMod: entity work.Driver(beh)
      generic map (CLFSR_LEN_NB=>CLFSR_LEN_NB)
      port map (Clk=>Clk, RESET=>RESET, start=>TOP_start, ready=>TOP_ready, continue=>TOP_continue,
         RegionSizeMinus1=>TOP_RegionSizeMinus1, GroupSizeExponent=>TOP_GroupSizeExponent,
         CLFSR_start=>CLFSR_start, CLFSR_ready=>CLFSR_ready, CLFSR_init_seed=>CLFSR_init_seed, 
         CLFSR_next_seq=>CLFSR_next_seq, CLFSR_set_n_ahead_val=>CLFSR_set_n_ahead_val, 
         CLFSR_inc_n_ahead=>CLFSR_inc_n_ahead, CLFSR_val_to_set=>CLFSR_val_to_set, 
         CLFSR_n_ahead_setting=>CLFSR_n_ahead_setting, Pairings_OverRunErr=>TOP_Pairings_OverRunErr);


-- ====================================================================================================
-- CHALLENGE LFSRs
-- ====================================================================================================
   TOP_seed_in_actual <= std_logic_vector(to_unsigned(1, CLFSR_LEN_NB));

   with TOP_exhaustive_or_subset select
      CLFSR_start_NoNorm <= CLFSR_start when '0',
                            '0' when others;

   with TOP_exhaustive_or_subset select
      CLFSR_start_Norm <= CLFSR_start when '1',
                          '0' when others;

-- Exhaustive LFSRs
   ChlngLFSR_NoNormMod: entity work.ChlngLFSR_NoNorm(beh) 
      generic map (CLFSR_LEN_NB=>CLFSR_LEN_NB)
      port map (Clk=>Clk, RESET=>RESET, start=>CLFSR_start_NoNorm, init_seed=>CLFSR_init_seed, next_seq=>CLFSR_next_seq, 
         seed_in=>TOP_seed_in_actual, RegionSizeMinus1=>TOP_RegionSizeMinus1, ready=>CLFSR_ready1, PRN=>CLFSR_PRN1);

   ChlngLFSR_nAheadMod_NoNormMod: entity work.ChlngLFSR_nAhead_NoNorm(beh) 
      generic map (CLFSR_LEN_NB=>CLFSR_LEN_NB)
      port map (Clk=>Clk, RESET=>RESET, start=>CLFSR_start_NoNorm, init_seed=>CLFSR_init_seed, next_seq=>CLFSR_next_seq, 
         seed_in=>TOP_seed_in_actual, RegionSizeMinus1=>TOP_RegionSizeMinus1, set_n_ahead_val=>CLFSR_set_n_ahead_val, 
         inc_n_ahead=>CLFSR_inc_n_ahead, val_to_set=>CLFSR_val_to_set, n_ahead_setting=>CLFSR_n_ahead_setting_NoNorm,
         ready=>CLFSR_ready2, PRN=>CLFSR_PRN2);

-- Subset LFSRs
   ChlngLFSR_NormRegMod: entity work.ChlngLFSR_NormReg(beh) 
      generic map (CLFSR_LEN_NB=>CLFSR_REG_LEN_NB)
      port map (Clk=>Clk, RESET=>RESET, start=>CLFSR_start_Norm, init_seed=>CLFSR_init_seed, next_seq=>CLFSR_next_seq, 
         seed_in=>TOP_seed_in_actual(CLFSR_REG_LEN_NB-1 downto 0), RegionSizeMinus1=>TOP_RegionSizeMinus1(CLFSR_REG_LEN_NB-1 downto 0), 
         n_ahead_setting=>CLFSR_n_ahead_setting_Norm, advance_grp_out=>TOP_advance_grp, ready=>CLFSR_ready3, PRN=>CLFSR_PRN3);

   ChlngLFSR_NormGrpMod: entity work.ChlngLFSR_NormGrp(beh) 
      generic map (CLFSR_LEN_NB=>CLFSR_GRP_LEN_NB)
      port map (Clk=>Clk, RESET=>RESET, start=>CLFSR_start_Norm, init_seed=>CLFSR_init_seed, next_seq=>CLFSR_next_seq, 
         seed_in=>TOP_seed_in_actual(CLFSR_LEN_NB-1 downto CLFSR_REG_LEN_NB), RegionSizeMinus1=>TOP_GroupSizeMinus1(CLFSR_GRP_LEN_NB-1 downto 0),
         advance_grp=>TOP_advance_grp, ready=>CLFSR_ready4, PRN=>CLFSR_PRN4);

   ChlngLFSR_nAheadMod_NormMod: entity work.ChlngLFSR_nAhead_Norm(beh) 
      generic map (CLFSR_LEN_NB=>CLFSR_REG_LEN_NB)
      port map (Clk=>Clk, RESET=>RESET, start=>CLFSR_start_Norm, init_seed=>CLFSR_init_seed, next_seq=>CLFSR_next_seq, 
         seed_in=>TOP_seed_in_actual(CLFSR_REG_LEN_NB-1 downto 0), RegionSizeMinus1=>TOP_RegionSizeMinus1(CLFSR_REG_LEN_NB-1 downto 0), 
         set_n_ahead_val=>CLFSR_set_n_ahead_val, inc_n_ahead=>CLFSR_inc_n_ahead, 
         val_to_set=>CLFSR_val_to_set(CLFSR_REG_LEN_NB-1 downto 0), n_ahead_setting=>CLFSR_n_ahead_setting_Norm,
         advance_grp=>TOP_advance_grp, ready=>CLFSR_ready5, PRN=>CLFSR_PRN5);

   CLFSR_ready <= CLFSR_ready1 and CLFSR_ready2 and CLFSR_ready3 and CLFSR_ready4 and CLFSR_ready5;

   with TOP_exhaustive_or_subset select
      CLFSR_PRN_A <= CLFSR_PRN1 when '0',
                     CLFSR_PRN4 & CLFSR_PRN3 when others;

   with TOP_exhaustive_or_subset select
      CLFSR_PRN_B <= CLFSR_PRN2 when '0',
                     CLFSR_PRN4 & CLFSR_PRN5 when others;

   with TOP_exhaustive_or_subset select
      CLFSR_n_ahead_setting <= CLFSR_n_ahead_setting_NoNorm when '0',
                               (CLFSR_LEN_NB-1 downto CLFSR_REG_LEN_NB =>'0') & CLFSR_n_ahead_setting_Norm when others;

-- ====================================================================================================
-- ====================================================================================================
   pairing_row1 <= CLFSR_PRN_A(NUM_ROWS_NB+NUM_COLS_NB-1 downto NUM_COLS_NB);
   pairing_col1 <= CLFSR_PRN_A(NUM_COLS_NB-1 downto 0);
   pairing_row2 <= CLFSR_PRN_B(NUM_ROWS_NB+NUM_COLS_NB-1 downto NUM_COLS_NB);
   pairing_col2 <= CLFSR_PRN_B(NUM_COLS_NB-1 downto 0);


end beh;
