----------------------------------------------
-- MSS copyright 2001-2012
-- Filename: AWGN.VHD
-- Author: Alain Zarembowitch / MSS
-- Inheritance: none
-- Edit date: 5/13/15
-- Revision: 4
-- Description: 
--		Dual AWGN generation
--		Muller-Box method.
-- 	Uses 5 block RAMs.
-- 	Maximum speed: 1 output sample per CLK
	-- Two independent white gaussian noise sample. signed 2's complement. Read at rising edge of CLK
	-- when SAMPLE_CLK_OUT = '1'. 
	-- Floating point format 5.11
	-- Mean is 0. Std = 1.0 
-- Latency is 6 CLK from SAMPLE_CLK_REQ to output ready
--
-- Rev 3 8/17/12 AZ
-- Port to Spartan-6 + variables initialization for simulation + simulation output to file
--
-- Rev 4 5/13/15 AZ
-- Added pipeline for higher speed
---------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library UNISIM;
use UNISIM.VComponents.all;

entity AWGN is
  port (
	CLK: in  std_logic;   
		-- clock synchronous
	SYNC_RESET: in std_logic;
		-- synchronous reset.
	SAMPLE_CLK_REQ: in std_logic;
		-- request for output bit, 

	SAMPLE_CLK_OUT: out std_logic;
	NOISE_SAMPLE1_OUT: out std_logic_vector(15 downto 0);	
	NOISE_SAMPLE2_OUT: out std_logic_vector(15 downto 0)	
		-- Two independent white gaussian noise sample. signed 2's complement. Read at rising edge of CLK
		-- when SAMPLE_CLK_OUT = '1'. Latency is 6 CLKs after request.
		-- Mean is 0. Std = 1.0
		-- Floating point format: 5.11
    );
end entity;

architecture behavior of AWGN is



-----------------------------------------------------------------
-- COMPONENT
-----------------------------------------------------------------
	COMPONENT CODEGEN
	PORT(
		CLK : IN std_logic;
		BIT_CLK_REQ : IN std_logic;
		SYNC_RESET : IN std_logic;
		CODE_PERIOD : IN std_logic_vector(23 downto 0);
		CODE_SEL : IN std_logic_vector(2 downto 0);
		G1 : IN std_logic_vector(23 downto 0);
		G2 : IN std_logic_vector(23 downto 0);          
		BIT_CLK_OUT : OUT std_logic;
		CODE_START : OUT std_logic;
		CODE_BIT : OUT std_logic
		);
	END COMPONENT;

component SIGNED_SIN_COS_TBL is
	port (
		ADDR: in std_logic_vector(7 downto 0);
			-- angle. 0 to 360 degree. No 0 representation.
			-- 0x00 -> 0.703 deg, 0xff -> 359.296 deg.
		DATA_OUT: out std_logic_vector(8 downto 0);
			-- sine or cosine value. range -1 to +1. 
			-- 9-bit signed (2's complement)
			-- Note: the output is asymmetrical due to 2's complement 
			-- representation(+127 positive, -128 negative)
		CLK: in std_logic;
		ASYNC_RESET: in std_logic;

		SIN_COSN: in std_logic
			-- sine or cosine# selection flag
			-- reason: the same table is used for both cosine and sine
			-- generation
	);
end component;

	component SIM2OUTFILE is
		 Generic (
			FILENAME: string
		 );
		 Port ( 
			--// CLK, RESET
			CLK: in std_logic;
				-- Reference clock
			DATA1: in std_logic_vector(11 downto 0);
			DATA2: in std_logic_vector(11 downto 0);
			DATA3: in std_logic_vector(11 downto 0);
			SAMPLE_CLK_IN: in std_logic
				-- DATA_IN is read at the rising edge of CLK when SAMPLE_CLK_IN = '1'

	);
	END COMPONENT;

-----------------------------------------------------------------
-- SIGNALS
-----------------------------------------------------------------
-- Suffix _E is for precision extended
-- Suffix _D for delay

--// random sequence generation
constant CODE_SEL: std_logic_vector(2 downto 0) := "010";	-- maximal length sequence
constant G2: std_logic_vector(23 downto 0) := (others => '0');  -- no G2
constant CODE_PERIOD_0: std_logic_vector(23 downto 0) := x"000FFF";
constant CODE_PERIOD_1: std_logic_vector(23 downto 0) := x"001FFF";
constant CODE_PERIOD_2: std_logic_vector(23 downto 0) := x"003FFF";
constant CODE_PERIOD_3: std_logic_vector(23 downto 0) := x"007FFF";
constant CODE_PERIOD_4: std_logic_vector(23 downto 0) := x"00FFFF";
constant CODE_PERIOD_5: std_logic_vector(23 downto 0) := x"01FFFF";
constant CODE_PERIOD_6: std_logic_vector(23 downto 0) := x"000FFF";
constant CODE_PERIOD_7: std_logic_vector(23 downto 0) := x"001FFF";
constant CODE_PERIOD_8: std_logic_vector(23 downto 0) := x"003FFF";
constant CODE_PERIOD_9: std_logic_vector(23 downto 0) := x"007FFF";
constant CODE_PERIOD_10: std_logic_vector(23 downto 0) := x"00FFFF";
constant CODE_PERIOD_11: std_logic_vector(23 downto 0) := x"01FFFF";
constant CODE_PERIOD_12: std_logic_vector(23 downto 0) := x"000FFF";
constant CODE_PERIOD_13: std_logic_vector(23 downto 0) := x"001FFF";
constant CODE_PERIOD_14: std_logic_vector(23 downto 0) := x"003FFF";
constant CODE_PERIOD_15: std_logic_vector(23 downto 0) := x"007FFF";
constant CODE_PERIOD_16: std_logic_vector(23 downto 0) := x"00FFFF";
constant CODE_PERIOD_17: std_logic_vector(23 downto 0) := x"01FFFF";
constant CODE_PERIOD_18: std_logic_vector(23 downto 0) := x"000FFF";
constant CODE_PERIOD_19: std_logic_vector(23 downto 0) := x"001FFF";
constant CODE_PERIOD_20: std_logic_vector(23 downto 0) := x"003FFF";
constant CODE_PERIOD_21: std_logic_vector(23 downto 0) := x"007FFF";
constant CODE_PERIOD_22: std_logic_vector(23 downto 0) := x"00FFFF";
constant CODE_PERIOD_23: std_logic_vector(23 downto 0) := x"01FFFF";
constant CODE_PERIOD_24: std_logic_vector(23 downto 0) := x"000FFF";
constant CODE_PERIOD_25: std_logic_vector(23 downto 0) := x"001FFF";
constant CODE_PERIOD_26: std_logic_vector(23 downto 0) := x"003FFF";
constant CODE_PERIOD_27: std_logic_vector(23 downto 0) := x"007FFF";
constant CODE_PERIOD_28: std_logic_vector(23 downto 0) := x"00FFFF";
constant CODE_PERIOD_29: std_logic_vector(23 downto 0) := x"01FFFF";
constant CODE_PERIOD_30: std_logic_vector(23 downto 0) := x"00FFFF";
constant CODE_PERIOD_31: std_logic_vector(23 downto 0) := x"01FFFF";
constant CODE_PERIOD_32: std_logic_vector(23 downto 0) := x"000FFF";
constant CODE_PERIOD_33: std_logic_vector(23 downto 0) := x"001FFF";
constant CODE_PERIOD_34: std_logic_vector(23 downto 0) := x"003FFF";
constant CODE_PERIOD_35: std_logic_vector(23 downto 0) := x"007FFF";
constant CODE_PERIOD_36: std_logic_vector(23 downto 0) := x"00FFFF";
constant CODE_PERIOD_37: std_logic_vector(23 downto 0) := x"01FFFF";
constant G1_0: std_logic_vector(23 downto 0) := x"000E08";
constant G1_1: std_logic_vector(23 downto 0) := x"001C80";
constant G1_2: std_logic_vector(23 downto 0) := x"003802"; 
constant G1_3: std_logic_vector(23 downto 0) := x"006000"; --
constant G1_4: std_logic_vector(23 downto 0) := x"00D008"; --
constant G1_5: std_logic_vector(23 downto 0) := x"012000"; --
constant G1_6: std_logic_vector(23 downto 0) := x"0008B0"; --
constant G1_7: std_logic_vector(23 downto 0) := x"001260"; --
constant G1_8: std_logic_vector(23 downto 0) := x"002604"; --
constant G1_9: std_logic_vector(23 downto 0) := x"004830"; --
constant G1_10: std_logic_vector(23 downto 0) := x"008580"; --
constant G1_11: std_logic_vector(23 downto 0) := x"01E000"; --
constant G1_12: std_logic_vector(23 downto 0) := x"000C9A"; --
constant G1_13: std_logic_vector(23 downto 0) := x"001C58"; --
constant G1_14: std_logic_vector(23 downto 0) := x"00348C"; --
constant G1_15: std_logic_vector(23 downto 0) := x"0078A0"; --
constant G1_16: std_logic_vector(23 downto 0) := x"00D019"; --
constant G1_17: std_logic_vector(23 downto 0) := x"014120"; --
constant G1_18: std_logic_vector(23 downto 0) := x"000FE4"; --
constant G1_19: std_logic_vector(23 downto 0) := x"0018E2"; --
constant G1_20: std_logic_vector(23 downto 0) := x"003CB8"; --
constant G1_21: std_logic_vector(23 downto 0) := x"007E41"; --
constant G1_22: std_logic_vector(23 downto 0) := x"00F816"; --
constant G1_23: std_logic_vector(23 downto 0) := x"01D509"; --
constant G1_24: std_logic_vector(23 downto 0) := x"000D7A"; --
constant G1_25: std_logic_vector(23 downto 0) := x"001FA8"; --
constant G1_26: std_logic_vector(23 downto 0) := x"002CDA"; --
constant G1_27: std_logic_vector(23 downto 0) := x"0071AC"; --
constant G1_28: std_logic_vector(23 downto 0) := x"00C1BC"; --
constant G1_29: std_logic_vector(23 downto 0) := x"01B9A0"; --
constant G1_30: std_logic_vector(23 downto 0) := x"00FDC2"; -- 
constant G1_31: std_logic_vector(23 downto 0) := x"01F178"; --
constant G1_32: std_logic_vector(23 downto 0) := x"000FDD"; --
constant G1_33: std_logic_vector(23 downto 0) := x"0019EA"; --
constant G1_34: std_logic_vector(23 downto 0) := x"003BE9"; --
constant G1_35: std_logic_vector(23 downto 0) := x"007E69"; --
constant G1_36: std_logic_vector(23 downto 0) := x"00F39A"; --
constant G1_37: std_logic_vector(23 downto 0) := x"01F3FB"; --
signal SAMPLE_CLK_REQ_D: std_logic := '0';
signal SAMPLE_CLK_REQ_D2: std_logic := '0';
signal SAMPLE_CLK_REQ_D3: std_logic := '0';
signal SAMPLE_CLK_REQ_D4: std_logic := '0';
signal SAMPLE_CLK_REQ_D5: std_logic := '0';
signal SAMPLE_CLK_REQ_D6: std_logic := '0';
signal SAMPLE_CLK_REQ_D7: std_logic := '0';


--// Box-Muller method
signal F: std_logic_vector(15 downto 0) := (others => '0');
signal F_D: std_logic_vector(10 downto 0) := (others => '0');
signal F_D2: std_logic_vector(10 downto 0) := (others => '0');
signal X1: std_logic_vector(29 downto 0) := (others => '0');
signal X1_ADDR: std_logic_vector(9 downto 0) := (others => '0');
signal X2: std_logic_vector(7 downto 0) := (others => '0');
signal G: std_logic_vector(8 downto 0) := (others => '0');
signal G_ABS: std_logic_vector(7 downto 0) := (others => '0');
signal G_SIGN: std_logic := '0';
signal N1: std_logic_vector(18 downto 0) := (others => '0');	-- unsigned signed noise sample. 
signal N2: std_logic_vector(19 downto 0) := (others => '0');	-- signed noise sample. Representation 1 sign, 3 integer bits, 6 fractional
signal N3: std_logic_vector(15 downto 0) := (others => '0');	-- signed noise sample
signal N3_E: std_logic_vector(17 downto 0) := (others => '0');

-- Block RAM 2 (used to create a virtually independent random variable)
signal WPTR: std_logic_vector(9 downto 0) := (others => '0');
signal RPTRA: std_logic_vector(9 downto 0) := (others => '0');
signal RPTRB: std_logic_vector(9 downto 0) := (others => '0');
signal RPTRC: std_logic_vector(9 downto 0) := (others => '0');
signal DATA1: std_logic_vector(15 downto 0) := (others => '0');
signal DATA2A: std_logic_vector(15 downto 0) := (others => '0');
signal DATA2A_E: std_logic_vector(17 downto 0) := (others => '0');
signal DATA2B: std_logic_vector(15 downto 0) := (others => '0');
signal DATA2B_E: std_logic_vector(17 downto 0) := (others => '0');
signal DATA2C: std_logic_vector(15 downto 0) := (others => '0');
signal DATA2C_E: std_logic_vector(17 downto 0) := (others => '0');
signal DATA3: std_logic_vector(15 downto 0) := (others => '0');
signal DATA3_PART1: std_logic_vector(17 downto 0) := (others => '0');
signal DATA3_PART2: std_logic_vector(17 downto 0) := (others => '0');
signal DATA3_E: std_logic_vector(17 downto 0) := (others => '0');
signal RPTR2: std_logic_vector(9 downto 0) := (others => '0');
signal DATA4: std_logic_vector(15 downto 0) := (others => '0');

constant SIMULATION: std_logic := '0';	-- enable/disable file log
-----------------------------------------------------------------
-- IMPLEMENTATION
-----------------------------------------------------------------
begin

-- generate 38 independent random variables

-- latency 1 CLK
CODEGEN_00: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_0,
	CODE_SEL => CODE_SEL,
	G1 => G1_0,
	G2 => G2,
	BIT_CLK_OUT => SAMPLE_CLK_REQ_D,
	CODE_START => open,
	CODE_BIT => X1(0)
	);

CODEGEN_01: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_1,
	CODE_SEL => CODE_SEL,
	G1 => G1_1,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(1)
	);

CODEGEN_02: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_2,
	CODE_SEL => CODE_SEL,
	G1 => G1_2,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(2)
	);

CODEGEN_03: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_3,
	CODE_SEL => CODE_SEL,
	G1 => G1_3,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(3)
	);

CODEGEN_04: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_4,
	CODE_SEL => CODE_SEL,
	G1 => G1_4,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(4)
	);

CODEGEN_05: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_5,
	CODE_SEL => CODE_SEL,
	G1 => G1_5,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(5)
	);

CODEGEN_06: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_6,
	CODE_SEL => CODE_SEL,
	G1 => G1_6,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(6)
	);

CODEGEN_07: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_7,
	CODE_SEL => CODE_SEL,
	G1 => G1_7,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(7)
	);

CODEGEN_08: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_8,
	CODE_SEL => CODE_SEL,
	G1 => G1_8,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(8)
	);

CODEGEN_09: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_9,
	CODE_SEL => CODE_SEL,
	G1 => G1_9,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(9)
	);

CODEGEN_010: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_10,
	CODE_SEL => CODE_SEL,
	G1 => G1_10,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(10)
	);

CODEGEN_011: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_11,
	CODE_SEL => CODE_SEL,
	G1 => G1_11,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(11)
	);

CODEGEN_012: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_12,
	CODE_SEL => CODE_SEL,
	G1 => G1_12,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(12)
	);

CODEGEN_013: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_13,
	CODE_SEL => CODE_SEL,
	G1 => G1_13,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(13)
	);

CODEGEN_014: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_14,
	CODE_SEL => CODE_SEL,
	G1 => G1_14,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(14)
	);

CODEGEN_015: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_15,
	CODE_SEL => CODE_SEL,
	G1 => G1_15,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(15)
	);

CODEGEN_016: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_16,
	CODE_SEL => CODE_SEL,
	G1 => G1_16,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(16)
	);

CODEGEN_017: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_17,
	CODE_SEL => CODE_SEL,
	G1 => G1_17,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(17)
	);

CODEGEN_018: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_18,
	CODE_SEL => CODE_SEL,
	G1 => G1_18,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(18)
	);

CODEGEN_019: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_19,
	CODE_SEL => CODE_SEL,
	G1 => G1_19,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(19)
	);

CODEGEN_020: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_20,
	CODE_SEL => CODE_SEL,
	G1 => G1_20,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(20)
	);

CODEGEN_021: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_21,
	CODE_SEL => CODE_SEL,
	G1 => G1_21,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(21)
	);

CODEGEN_022: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_22,
	CODE_SEL => CODE_SEL,
	G1 => G1_22,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(22)
	);

CODEGEN_023: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_23,
	CODE_SEL => CODE_SEL,
	G1 => G1_23,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(23)
	);

CODEGEN_024: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_24,
	CODE_SEL => CODE_SEL,
	G1 => G1_24,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(24)
	);

CODEGEN_025: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_25,
	CODE_SEL => CODE_SEL,
	G1 => G1_25,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(25)
	);

CODEGEN_026: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_26,
	CODE_SEL => CODE_SEL,
	G1 => G1_26,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(26)
	);

CODEGEN_027: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_27,
	CODE_SEL => CODE_SEL,
	G1 => G1_27,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(27)
	);

CODEGEN_028: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_28,
	CODE_SEL => CODE_SEL,
	G1 => G1_28,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(28)
	);

CODEGEN_029: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_29,
	CODE_SEL => CODE_SEL,
	G1 => G1_29,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X1(29)
	);

CODEGEN_030: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_30,
	CODE_SEL => CODE_SEL,
	G1 => G1_30,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X2(0)
	);

CODEGEN_031: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_31,
	CODE_SEL => CODE_SEL,
	G1 => G1_31,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X2(1)
	);


CODEGEN_032: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_32,
	CODE_SEL => CODE_SEL,
	G1 => G1_32,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X2(2)
	);


CODEGEN_033: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_33,
	CODE_SEL => CODE_SEL,
	G1 => G1_33,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X2(3)
	);


CODEGEN_034: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_34,
	CODE_SEL => CODE_SEL,
	G1 => G1_34,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X2(4)
	);


CODEGEN_035: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_35,
	CODE_SEL => CODE_SEL,
	G1 => G1_35,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X2(5)
	);


CODEGEN_036: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_36,
	CODE_SEL => CODE_SEL,
	G1 => G1_36,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X2(6)
	);


CODEGEN_037: CODEGEN port map(
	CLK => CLK,
	BIT_CLK_REQ => SAMPLE_CLK_REQ,
	SYNC_RESET => SYNC_RESET,
	CODE_PERIOD => CODE_PERIOD_37,
	CODE_SEL => CODE_SEL,
	G1 => G1_37,
	G2 => G2,
	BIT_CLK_OUT => open,
	CODE_START => open,
	CODE_BIT => X2(7)
	);

-- Box Muller method
-- 5 * 32 * 16-bit wide LUT are used to generate f(x1) = sqrt(2)*sqrt(-ln(x1)),
-- where x1 is a uniformly random variable.
-- Look up table. 6 * 32*16-bit wide tables in one physical table. 
-- Output format: 16-bit unsigned. (always positive). Bits 15-11 are unused. Bits 10-8 are integer,
-- bits 7-0 are fractional
-- Block RAM is used as ROM
-- Latency is one CLK after address is stable
   -- RAMB16_S18: 1k x 16 + 2 Parity bits Single-Port RAM
   --             Spartan-3
   -- Xilinx HDL Language Template, version 13.1

   RAMB16_S18_001 : RAMB16_S18
   generic map (
      INIT => X"00000", --  Value of output RAM registers at startup
      SRVAL => X"00000", --  Ouput value upon SSR assertion
      WRITE_MODE => "WRITE_FIRST", --  WRITE_FIRST, READ_FIRST or NO_CHANGE
      -- The following INIT_xx declarations specify the intial contents of the RAM
      -- Address 0 to 255

-- word order 
--		31 .... 16
--		15 .... 0
-- word 0 is never read
-- Design trick: to ease the cut and paste transition from Matlab to vhdl, 
-- the word order is wrong. Because of the uniform distribution of addresses, the 
-- order does not matter EXCEPT that the word 0 should never be read.
		
-- k1 (see awgn1.m matlab). input index ranges from 1/32 to 32/32
      INIT_00 => X"01200113010500F800EB00DE00D000C200B400A5009500840072005C00410000",
      INIT_01 => X"02A2025B022D020A01ED01D401BE01AA019801860176016701580149013B012D",
-- k2 (see awgn1.m matlab). input index ranges from 1/32^2 to 32/32^2
      INIT_02 => X"02DD02D802D302CE02CA02C502C102BD02BA02B602B202AF02AB02A802A50000",
      INIT_03 => X"03B90388036A0355034303350328031D0314030B030302FB02F502EE02E802E2",
-- k3 (see awgn1.m matlab) input index ranges from 1/32^3 to 32/32^3
      INIT_04 => X"03E403E003DC03D903D603D303D003CD03CA03C703C503C203C003BE03BB0000",
      INIT_05 => X"048F04680450043F04310426041C0414040D0406040003FA03F503F003EC03E8",
-- k4 (see awgn1.m matlab) input index ranges from 1/32^4 to 32/32^4
      INIT_06 => X"04B204AF04AC04A904A704A404A2049F049D049B049904970495049304910000",
      INIT_07 => X"05440522050D04FF04F304EA04E204DB04D504CF04CA04C504C104BD04B904B6",
-- k5 (see awgn1.m matlab) input index ranges from 1/32^5 to 32/32^5
      INIT_08 => X"05620560055D055B05580556055405520550054E054C054A0549054705460000",
      INIT_09 => X"05E305C505B305A6059B0593058C05860580057B05770573056F056C05680565",
-- k6 (see awgn1.m matlab) input index ranges from 1/32^6 to 32/32^6
      INIT_0A => X"05FE05FC05FA05F705F505F305F105F005EE05EC05EA05E905E705E605E40000",
      INIT_0B => X"067306570647063B0632062A0624061E061906150611060D060A060706040601",
-- other rows unused.
      INIT_0C => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_0D => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_0E => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_0F => X"0000000000000000000000000000000000000000000000000000000000000000",
      -- Address 256 to 511
      INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
      -- Address 512 to 767
      INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
      -- Address 768 to 1023
      INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
      INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000",
      -- The next set of INITP_xx are for the parity bits
      -- Address 0 to 255
      INITP_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INITP_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
      -- Address 256 to 511
      INITP_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INITP_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
      -- Address 512 to 767
      INITP_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INITP_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
      -- Address 768 to 1023
      INITP_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
      INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000")
   port map (
      DO => F,      -- 16-bit Data Output
      DOP => open,    -- 2-bit parity Output
      ADDR => X1_ADDR,  -- 10-bit Address Input
      CLK => CLK,    -- Clock
      DI => x"0000",      -- 16-bit Data Input
      DIP => "00",    -- 2-bit parity Input
      EN => '1',      -- RAM Enable Input
      SSR => '0',    -- Synchronous Set/Reset Input
      WE => '0'       -- Write Enable Input
   );

-- Input to f function is a 6*5-bit uniformly random variable. 
-- Because of the segmented nature of the table lookup, some processing must be done on the 30-bit
-- random variable.
-- If > 1/32, use address 0 - 31 (INIT_00 and INIT_01) 
-- elseif > 1/32^2, use address 32 - 63  (INIT_02 and INIT_03)
-- elseif > 1/32^3, use address 64 - 95 (INIT_02 and INIT_03)
-- elseif > 1/32^4, use address 96 - 127 (INIT_04 and INIT_05)
-- elseif > 1/32^5, use address 128 - 139 (INIT_06 and INIT_07)
-- else use address 139 - 191 (INIT_08 and INIT_09)
X1_ADDR_GEN: process(X1)
begin
	if(X1(29 downto 25) /= "00000") then
		-- 2/32 (represented as "00001") to 32/32 (represented as "11111")
		-- 1/32 not used
		X1_ADDR(4 downto 0) <= X1(29 downto 25);
		X1_ADDR(9 downto 5) <= "00000";
	elsif(X1(24 downto 20) /= "00000") then
		-- 2/32^2 to 32/32^2
		-- 1/32^2 not used
		X1_ADDR(4 downto 0) <= X1(24 downto 20);
		X1_ADDR(9 downto 5) <= "00001";
	elsif(X1(19 downto 15) /= "00000") then
		-- 2/32^3 to 32/32^3
		-- 1/32^3 not used
		X1_ADDR(4 downto 0) <= X1(19 downto 15);
		X1_ADDR(9 downto 5) <= "00010";
	elsif(X1(14 downto 10) /= "00000") then
		-- 2/32^4 to 32/32^4
		-- 1/32^4 not used
		X1_ADDR(4 downto 0) <= X1(14 downto 10);
		X1_ADDR(9 downto 5) <= "00011";
	elsif(X1(9 downto 5) /= "00000") then
		-- 2/32^5 to 32/32^5
		-- 2/32^5 not used
		X1_ADDR(4 downto 0) <= X1(9 downto 5);
		X1_ADDR(9 downto 5) <= "00100";
	else
		-- 2/32^6 to 32/32^6
		-- 1/32^6 not used
	--elsif(X1(4 downto 0) /= "00000") then
		X1_ADDR(4 downto 0) <= X1(4 downto 0);
		X1_ADDR(9 downto 5) <= "00101";
  	end if;
end process;

-- Latency is 2 CLKs. Therefore, F must be delayed by one extra CLK.
SIGNED_SIN_COS_TBL_001: SIGNED_SIN_COS_TBL port map(
	ASYNC_RESET => '0',
	CLK => CLK,
	SIN_COSN => '0',

	ADDR => X2,
	DATA_OUT => G
	);
	
-- Realign F and G timing (1 clock). Compute G absolute value for unsigned multiplication
RECLOCK_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			G_ABS <= (others => '0');
			G_SIGN <= '0';
			F_D <= (others => '0');
			F_D2 <= (others => '0');
			SAMPLE_CLK_REQ_D2 <= '0';
			SAMPLE_CLK_REQ_D3 <= '0';
			SAMPLE_CLK_REQ_D4 <= '0';
		else
			F_D <= F(10 downto 0);
			F_D2 <= F_D;
			SAMPLE_CLK_REQ_D2 <= SAMPLE_CLK_REQ_D;
			SAMPLE_CLK_REQ_D3 <= SAMPLE_CLK_REQ_D2;
			SAMPLE_CLK_REQ_D4 <= SAMPLE_CLK_REQ_D3;

			if(G(8) = '0') then
				-- positive
				G_ABS <= G(7 downto 0);
				G_SIGN <= '0';
			elsif(G = "100000000") then
				-- special case
				G_ABS <= "11111111";
				G_SIGN <= '1';
			else
				-- negative
				G_ABS <= not(G(7 downto 0)) + 1;
				G_SIGN <= '1';
			end if;
		end if;
	end if;
end process;

-- f*g  = 11 bits + 8 bits
N1 <= G_ABS * F_D2;	

-- Reclock unsigned noise sample. Restore sign
RECLOCK_002: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			SAMPLE_CLK_REQ_D5 <= '0';
			N2 <= (others => '0');
		else
			SAMPLE_CLK_REQ_D5 <= SAMPLE_CLK_REQ_D4;
			if(SAMPLE_CLK_REQ_D4 = '1') then
				if(G_SIGN = '0') then
					-- no sign change
					N2(18 downto 0) <= N1;
					N2(19) <= '0';
				else
					-- negative
					N2 <= ("1" & (not(N1))) + 1;
				end if;
			end if;
		end if;
	end if;
end process;

-- Keep only 16 bits
N3 <= N2(19 downto 4);

-- Delay noise samples to create independent variables
-- Write samples to a 256*16 buffer
WPTR_GEN_001: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			WPTR <= (others => '0');
		else
			if(SAMPLE_CLK_REQ_D5 = '1') then
				WPTR <= WPTR + 1;
			end if;
		end if;
	end if;
end process;

-- Generate a totally independent random read pointer
RPTRA <= X1(9 downto 0);
RPTRB <= X1(19 downto 10);
RPTRC <= X1(29 downto 20);

   RAMB16_S18_S18_002 : RAMB16_S18_S18
   port map (
      DOA => open,      -- Port A 16-bit Data Output
      DOB => DATA2A,      -- Port B 16-bit Data Output
      DOPA => open,    -- Port A 2-bit Parity Output
      DOPB => open,    -- Port B 2-bit Parity Output
      ADDRA => WPTR,  -- Port A 10-bit Address Input
      ADDRB => RPTRA,  -- Port B 10-bit Address Input
      CLKA => CLK,    -- Port A Clock
      CLKB => CLK,    -- Port B Clock
      DIA => N3,      -- Port A 16-bit Data Input
      DIB => x"0000",      -- Port B 16-bit Data Input
      DIPA => "00",    -- Port A 2-bit parity Input
      DIPB => "00",    -- Port-B 2-bit parity Input
      ENA => '1',      -- Port A RAM Enable Input
      ENB => '1',      -- PortB RAM Enable Input
      SSRA => SYNC_RESET,    -- Port A Synchronous Set/Reset Input
      SSRB => SYNC_RESET,    -- Port B Synchronous Set/Reset Input
      WEA => SAMPLE_CLK_REQ_D5,      -- Port A Write Enable Input
      WEB => '0'       -- Port B Write Enable Input
   );

   RAMB16_S18_S18_003 : RAMB16_S18_S18
   port map (
      DOA => open,      -- Port A 16-bit Data Output
      DOB => DATA2B,      -- Port B 16-bit Data Output
      DOPA => open,    -- Port A 2-bit Parity Output
      DOPB => open,    -- Port B 2-bit Parity Output
      ADDRA => WPTR,  -- Port A 10-bit Address Input
      ADDRB => RPTRB,  -- Port B 10-bit Address Input
      CLKA => CLK,    -- Port A Clock
      CLKB => CLK,    -- Port B Clock
      DIA => N3,      -- Port A 16-bit Data Input
      DIB => x"0000",      -- Port B 16-bit Data Input
      DIPA => "00",    -- Port A 2-bit parity Input
      DIPB => "00",    -- Port-B 2-bit parity Input
      ENA => '1',      -- Port A RAM Enable Input
      ENB => '1',      -- PortB RAM Enable Input
      SSRA => SYNC_RESET,    -- Port A Synchronous Set/Reset Input
      SSRB => SYNC_RESET,    -- Port B Synchronous Set/Reset Input
      WEA => SAMPLE_CLK_REQ_D5,      -- Port A Write Enable Input
      WEB => '0'       -- Port B Write Enable Input
   );

   RAMB16_S18_S18_004 : RAMB16_S18_S18
   port map (
      DOA => open,      -- Port A 16-bit Data Output
      DOB => DATA2C,      -- Port B 16-bit Data Output
      DOPA => open,    -- Port A 2-bit Parity Output
      DOPB => open,    -- Port B 2-bit Parity Output
      ADDRA => WPTR,  -- Port A 10-bit Address Input
      ADDRB => RPTRC,  -- Port B 10-bit Address Input
      CLKA => CLK,    -- Port A Clock
      CLKB => CLK,    -- Port B Clock
      DIA => N3,      -- Port A 16-bit Data Input
      DIB => x"0000",      -- Port B 16-bit Data Input
      DIPA => "00",    -- Port A 2-bit parity Input
      DIPB => "00",    -- Port-B 2-bit parity Input
      ENA => '1',      -- Port A RAM Enable Input
      ENB => '1',      -- PortB RAM Enable Input
      SSRA => SYNC_RESET,    -- Port A Synchronous Set/Reset Input
      SSRB => SYNC_RESET,    -- Port B Synchronous Set/Reset Input
      WEA => SAMPLE_CLK_REQ_D5,      -- Port A Write Enable Input
      WEB => '0'       -- Port B Write Enable Input
   );

-- sum four independent variables
-- Extend 2 bits to prevent overflow
DATA2A_E(15 downto 0) <= DATA2A;
DATA2A_E(17 downto 16) <= (others => DATA2A(15));
DATA2B_E(15 downto 0) <= DATA2B;
DATA2B_E(17 downto 16) <= (others => DATA2B(15));
DATA2C_E(15 downto 0) <= DATA2C;
DATA2C_E(17 downto 16) <= (others => DATA2C(15));
N3_E(15 downto 0) <= N3;
N3_E(17 downto 16) <= (others => N3(15));

-- added pipeline for speed 5/13/15 AZ
RECLOCK_003: process(CLK)
begin
	if rising_edge(CLK) then
		if (SYNC_RESET = '1') then
			DATA3_PART1 <= (others => '0');
			DATA3_PART2 <= (others => '0');
		elsif(SAMPLE_CLK_REQ_D5 = '1') then
			DATA3_PART1 <= DATA2A_E + DATA2B_E;
			DATA3_PART2 <= DATA2C_E + N3_E;
		end if;
	end if;
end process;

DATA3_E <= DATA3_PART1 + DATA3_PART2;
DATA3 <= DATA3_E(17 downto 2);

-- store DATA3 to create another random variation
-- Generate a totally independent random read pointer
RPTR2 <= X1(17 downto 8);

  RAMB16_S18_S18_005 : RAMB16_S18_S18
   port map (
      DOA => open,      -- Port A 16-bit Data Output
      DOB => DATA4,      -- Port B 16-bit Data Output
      DOPA => open,    -- Port A 2-bit Parity Output
      DOPB => open,    -- Port B 2-bit Parity Output
      ADDRA => WPTR,  -- Port A 10-bit Address Input
      ADDRB => RPTR2,  -- Port B 10-bit Address Input
      CLKA => CLK,    -- Port A Clock
      CLKB => CLK,    -- Port B Clock
      DIA => DATA3,      -- Port A 16-bit Data Input
      DIB => x"0000",      -- Port B 16-bit Data Input
      DIPA => "00",    -- Port A 2-bit parity Input
      DIPB => "00",    -- Port-B 2-bit parity Input
      ENA => '1',      -- Port A RAM Enable Input
      ENB => '1',      -- PortB RAM Enable Input
      SSRA => SYNC_RESET,    -- Port A Synchronous Set/Reset Input
      SSRB => SYNC_RESET,    -- Port B Synchronous Set/Reset Input
      WEA => SAMPLE_CLK_REQ_D5,      -- Port A Write Enable Input
      WEB => '0'       -- Port B Write Enable Input
   );

OUTPUT: process(CLK)
begin
	if rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			NOISE_SAMPLE1_OUT <= (others => '0');
			NOISE_SAMPLE2_OUT <= (others => '0');
			SAMPLE_CLK_OUT <= '0';
		else
			SAMPLE_CLK_OUT <= SAMPLE_CLK_REQ_D5;
			if(SAMPLE_CLK_REQ_D5 = '1') then
				NOISE_SAMPLE1_OUT <= DATA3;
				NOISE_SAMPLE2_OUT <= DATA4;
			end if;
		end if;
	end if;
end process;

--// simulation. send to a tab-delimited text file for subsequent (Matlab) plot.
SIM2OUTFILE_X: if(SIMULATION = '1') generate
	Inst_SIM2OUTFILE1: SIM2OUTFILE 
	generic map(
		FILENAME => "awgn1.txt"
	)
	PORT MAP(
		CLK => CLK,
		DATA1 => DATA3(15 downto 4),
		DATA2 => DATA4(15 downto 4),
		DATA3 => x"000",	
		SAMPLE_CLK_IN => SAMPLE_CLK_REQ_D5
	);
end generate;




end behavior;

