----------------------------------------------
-- MSS copyright 2001-2002
-- Filename: POWER_MEASUREMENT.VHD
-- Author: Alain Zarembowitch / MSS
-- Inheritance: none
-- Edit date: 12-15-02
-- Revision: 0.001
-- Description: 
--		baseband signal power measurement
--		Averaged over 1024 samples
--		Assumption: input samples have a mean of zero
-- 	Input samples format: 5.11
---------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity POWER_MEASUREMENT is
  port (
	ASYNC_RESET: in std_logic;
		-- asynchronous reset, active high
	CLK: in  std_logic;   
		-- clock synchronous
	SAMPLE_CLK_IN: in std_logic;
		-- input samples
	DATA_I_ABS_IN: in std_logic_vector(14 downto 0);
	DATA_Q_ABS_IN: in std_logic_vector(14 downto 0);
		-- input samples absolute values. format 4.11 (no sign, always positive)
		-- read at rising edge of CLK, when SAMPLE_CLK_IN = '1'
	SYNC_RESET: in std_logic;
		-- synchronous reset.
		-- 1 CLK wide pulse aligned with SAMPLE_CLK_IN.

	SAMPLE_CLK_OUT: out std_logic;
	POWER_OUT: out std_logic_vector(23 downto 0)	
		-- power. format 8.16, unsigned
    );
end entity;

architecture behavior of POWER_MEASUREMENT is



-----------------------------------------------------------------
-- COMPONENT
-----------------------------------------------------------------
-----------------------------------------------------------------
-- SIGNALS
-----------------------------------------------------------------
-- Suffix _E is for precision extended
-- Suffix _D for delay
signal ZERO: std_logic;
signal ONE: std_logic;
signal DATA_I_ABS_IN_D: std_logic_vector(14 downto 0);
signal DATA_Q_ABS_IN_D: std_logic_vector(14 downto 0);
signal SAMPLE_CLK_IN_D: std_logic;
signal SAMPLE_CLK_IN_D2: std_logic;
signal SAMPLE_CLK_IN_D3: std_logic;
signal DATA_ABS: std_logic_vector(14 downto 0);
signal DATA_SQUARE: std_logic_vector(29 downto 0);
signal DATA_SQUARE_D: std_logic_vector(29 downto 0);
signal SAMPLE_COUNT: std_logic_vector(14 downto 0);
signal POWER_ACC: std_logic_vector(44 downto 0);

-----------------------------------------------------------------
-- IMPLEMENTATION
-----------------------------------------------------------------
begin
ZERO <= '0';
ONE <= '1';

-- Reclock input signals
-- Save I & Q as a undivisible group. 
RECLOCK_001: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		DATA_I_ABS_IN_D <= (others => '0');
		DATA_I_ABS_IN_D <= (others => '0');
	elsif rising_edge(CLK) then

		if(SAMPLE_CLK_IN = '1') and (SAMPLE_CLK_IN_D = '0') then
			DATA_I_ABS_IN_D <= DATA_I_ABS_IN;
			DATA_Q_ABS_IN_D <= DATA_Q_ABS_IN;
			SAMPLE_CLK_IN_D <= '1';
	  	else
			SAMPLE_CLK_IN_D <= '0';
	  	end if;
	end if;
end process;

-- Time share multiplier. Start with I.
DATA_ABS <= DATA_I_ABS_IN_D when (SAMPLE_CLK_IN_D = '1') else DATA_Q_ABS_IN_D;
DATA_SQUARE <= DATA_ABS * DATA_ABS;

-- reclock power sample.
-- Format is 8.22
RECLOCK_002: process(ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		DATA_SQUARE_D <= (others => '0');
		SAMPLE_CLK_IN_D2 <= '0';
	elsif rising_edge(CLK) then
		SAMPLE_CLK_IN_D2 <= SAMPLE_CLK_IN_D;

		if(SAMPLE_CLK_IN_D = '1') or (SAMPLE_CLK_IN_D2 = '1') then
			DATA_SQUARE_D <= DATA_SQUARE;
	  	end if;
	end if;
end process;

-- average over 32K (16K complex) samples
-- Sample counter. Aligned with SAMPLE_CLK_IN_D2
SAMPLE_COUNT_GEN: process (ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		SAMPLE_COUNT <= (others => '0');
	elsif rising_edge(CLK) then
		if(SYNC_RESET = '1') then
			-- first sample
			SAMPLE_COUNT <= (others => '0');
		elsif(SAMPLE_CLK_IN_D = '1') then
			SAMPLE_COUNT <= SAMPLE_COUNT + 1;
		end if;
	end if;
end process;

-- extend precision of the squaring to make room for 32K samples (15 bits)
-- DATA_SQUARE_D format is 8.22
-- POWER_ACC/32K format (averaged 32K samples) is 8.22
ACC_001: process (ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		POWER_ACC <= (others => '0');  
		SAMPLE_CLK_IN_D3 <= '0';
	elsif rising_edge(CLK) then
		SAMPLE_CLK_IN_D3 <= SAMPLE_CLK_IN_D2;

		if(SAMPLE_CLK_IN_D2 = '1') or (SAMPLE_CLK_IN_D3 = '1') then
-- test test test			if(SAMPLE_COUNT(9 downto 0) = "1111111111") then
			if(SAMPLE_COUNT = "011111111111111") then	-- 32K samples = 16K complex samples
				-- reset accumulator
				POWER_ACC <= (others => '0');  
			else
				-- accumulate
				POWER_ACC <= POWER_ACC + ("000000000000000" & DATA_SQUARE_D);  
		  	end if;
		end if;
	end if;
end process;
 
 
ACC_002: process (ASYNC_RESET, CLK)
begin
	if(ASYNC_RESET = '1') then
		POWER_OUT <= (others => '0');  
		SAMPLE_CLK_OUT <= '0';
	elsif rising_edge(CLK) then
-- test test test		if(SAMPLE_CLK_IN_D2 = '1') and (SAMPLE_COUNT(9 downto 0) = "1111111111") then
		if(SAMPLE_CLK_IN_D2 = '1') and (SAMPLE_COUNT = "011111111111111") then -- 32K samples = 16K complex samples
				-- save accumulated value = measured power
				POWER_OUT <= POWER_ACC(44 downto 21);
				SAMPLE_CLK_OUT <= '1';
		else
				SAMPLE_CLK_OUT <= '0';
		end if;
	end if;
end process;
 
end behavior;

