mirror of
https://github.com/Nuand/bladeRF-wiphy.git
synced 2024-12-19 05:38:09 +00:00
257 lines
8.6 KiB
VHDL
257 lines
8.6 KiB
VHDL
-- This file is part of bladeRF-wiphy.
|
|
--
|
|
-- Copyright (C) 2020 Nuand, LLC.
|
|
--
|
|
-- This program is free software; you can redistribute it and/or modify
|
|
-- it under the terms of the GNU General Public License as published by
|
|
-- the Free Software Foundation; either version 2 of the License, or
|
|
-- (at your option) any later version.
|
|
--
|
|
-- This program is distributed in the hope that it will be useful,
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
-- GNU General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU General Public License along
|
|
-- with this program; if not, write to the Free Software Foundation, Inc.,
|
|
-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
library ieee ;
|
|
use ieee.std_logic_1164.all ;
|
|
use ieee.numeric_std.all ;
|
|
|
|
library wlan ;
|
|
use wlan.wlan_p.all ;
|
|
use wlan.wlan_rx_p.all ;
|
|
|
|
entity wlan_acquisition is
|
|
port (
|
|
clock : in std_logic ;
|
|
reset : in std_logic ;
|
|
|
|
in_sample : in wlan_sample_t ;
|
|
quiet : in std_logic ;
|
|
burst : in std_logic ;
|
|
|
|
acquired : out std_logic ;
|
|
p_mag : buffer signed( 23 downto 0 ) ;
|
|
|
|
out_sample : out wlan_sample_t
|
|
) ;
|
|
end entity;
|
|
|
|
architecture arch of wlan_acquisition is
|
|
|
|
type sample_history_t is array (natural range 31 downto 0 ) of wlan_sample_t ;
|
|
signal sample_history : sample_history_t ;
|
|
signal sample_counter : unsigned( 9 downto 0 );
|
|
|
|
signal power_accum : unsigned( 31 downto 0 ) ;
|
|
signal ptemp : unsigned( 31 downto 0 ) ;
|
|
signal itemp : signed( 31 downto 0 ) ;
|
|
signal qtemp : signed( 31 downto 0 ) ;
|
|
signal i_accum : signed( 31 downto 0 ) ;
|
|
signal q_accum : signed( 31 downto 0 ) ;
|
|
signal accum_valid : std_logic ;
|
|
|
|
signal i_sum : signed( 31 downto 0 ) ;
|
|
signal q_sum : signed( 31 downto 0 ) ;
|
|
|
|
signal div_i_power : signed( 31 downto 0 ) ;
|
|
signal div_q_power : signed( 31 downto 0 ) ;
|
|
signal div_power_valid : std_logic ;
|
|
|
|
signal div_i_power_r : signed( 31 downto 0 ) ;
|
|
signal div_q_power_r : signed( 31 downto 0 ) ;
|
|
signal div_power_valid_r : std_logic ;
|
|
|
|
signal div_i_squared : unsigned( 31 downto 0 ) ;
|
|
signal div_q_squared : unsigned( 31 downto 0 ) ;
|
|
signal div_squared_valid : std_logic ;
|
|
|
|
signal div : unsigned( 31 downto 0 ) ;
|
|
signal burst_counter : unsigned( 31 downto 0 ) ;
|
|
signal div_valid : std_logic ;
|
|
|
|
signal p_valid : std_logic ;
|
|
signal iq_valid : std_logic ;
|
|
|
|
signal max : unsigned( 31 downto 0 ) ;
|
|
signal max_counter : unsigned( 7 downto 0 ) ;
|
|
signal min : unsigned( 31 downto 0 ) ;
|
|
signal min_found : std_logic ;
|
|
signal peak_found : std_logic ;
|
|
|
|
signal p_sample : wlan_sample_t ;
|
|
|
|
signal peak_match : std_logic ;
|
|
signal first_peak : std_logic ;
|
|
begin
|
|
process( clock )
|
|
begin
|
|
if( reset = '1' ) then
|
|
burst_counter <= ( others => '0' );
|
|
elsif( rising_edge( clock ) ) then
|
|
if( in_sample.valid = '1' ) then
|
|
if( burst = '1' ) then
|
|
burst_counter <= burst_counter + 1 ;
|
|
else
|
|
burst_counter <= ( others => '0' ) ;
|
|
end if;
|
|
end if;
|
|
end if ;
|
|
end process ;
|
|
|
|
process( clock )
|
|
begin
|
|
if( reset = '1' ) then
|
|
sample_counter <= ( others => '0' ) ;
|
|
power_accum <= ( others => '0' ) ;
|
|
i_accum <= ( others => '0' ) ;
|
|
q_accum <= ( others => '0' ) ;
|
|
elsif( rising_edge( clock ) ) then
|
|
accum_valid <= '0' ;
|
|
if( burst = '0' or quiet = '1' ) then
|
|
sample_counter <= ( others => '0' ) ;
|
|
power_accum <= ( others => '0' ) ;
|
|
i_accum <= ( others => '0' ) ;
|
|
q_accum <= ( others => '0' ) ;
|
|
iq_valid <= '0';
|
|
p_valid <= '0';
|
|
elsif( in_sample.valid = '1' and sample_counter < 650 ) then
|
|
sample_counter <= sample_counter + 1 ;
|
|
|
|
for i in 0 to sample_history'high - 1 loop
|
|
sample_history( i + 1 ) <= sample_history( i ) ;
|
|
end loop ;
|
|
sample_history(0).i <= in_sample.i ;
|
|
sample_history(0).q <= - in_sample.q ;
|
|
|
|
ptemp <= unsigned((resize(in_sample.i * in_sample.i + in_sample.q * in_sample.q, 32))) ;
|
|
p_valid <= '1';
|
|
if( p_valid = '1') then
|
|
power_accum <= power_accum + ptemp ;-- unsigned((resize(in_sample.i * in_sample.i + in_sample.q * in_sample.q, 32))) ;
|
|
end if;
|
|
|
|
|
|
if( sample_counter > 30 ) then
|
|
i_sum <= resize(sample_history(14).i + sample_history(30).i, 32);
|
|
q_sum <= resize(sample_history(14).q + sample_history(30).q, 32);
|
|
end if ;
|
|
|
|
if( sample_counter > 31 ) then
|
|
iq_valid <= '1';
|
|
itemp <= signed(resize(shift_right(i_sum * in_sample.i - q_sum * in_sample.q, 6), 32));
|
|
qtemp <= signed(resize(shift_right(i_sum * in_sample.q + q_sum * in_sample.i, 6), 32));
|
|
if( iq_valid = '1' ) then
|
|
i_accum <= i_accum + itemp;
|
|
q_accum <= q_accum + qtemp;
|
|
accum_valid <= '1' ;
|
|
end if;
|
|
end if ;
|
|
end if ;
|
|
end if ;
|
|
end process ;
|
|
|
|
process( clock )
|
|
begin
|
|
if( reset = '1' ) then
|
|
div_power_valid_r <= '0' ;
|
|
div_i_power_r <= ( others => '0' ) ;
|
|
div_q_power_r <= ( others => '0' ) ;
|
|
elsif( rising_edge( clock ) ) then
|
|
div_power_valid_r <= div_power_valid ;
|
|
div_i_power_r <= div_i_power ;
|
|
div_q_power_r <= div_q_power ;
|
|
end if ;
|
|
end process ;
|
|
|
|
process( clock )
|
|
begin
|
|
if( reset = '1' ) then
|
|
max <= ( others => '0' ) ;
|
|
max_counter <= ( others => '0' ) ;
|
|
peak_found <= '0' ;
|
|
elsif( rising_edge( clock ) ) then
|
|
div_squared_valid <= '0' ;
|
|
div_valid <= '0' ;
|
|
if( quiet = '1' ) then
|
|
max <= ( others => '0' ) ;
|
|
max_counter <= ( others => '0' ) ;
|
|
peak_found <= '0' ;
|
|
else
|
|
if( div_power_valid_r = '1' ) then
|
|
div_i_squared <= unsigned(resize(div_i_power_r * div_i_power_r, 32)) ;
|
|
div_q_squared <= unsigned(resize(div_q_power_r * div_q_power_r, 32)) ;
|
|
div_squared_valid <= '1' ;
|
|
end if ;
|
|
|
|
if( div_squared_valid = '1' ) then
|
|
div <= unsigned(resize(div_i_squared + div_q_squared, 32)) ;
|
|
div_valid <= '1';
|
|
end if ;
|
|
|
|
if( div_valid = '1' ) then
|
|
if( div > max ) then
|
|
max <= div ;
|
|
max_counter <= to_unsigned(31, max_counter'length) ;
|
|
else
|
|
if( max_counter = 0 ) then
|
|
peak_found <= '1' ;
|
|
min <= div ;
|
|
else
|
|
max_counter <= max_counter - 1 ;
|
|
end if ;
|
|
end if ;
|
|
end if ;
|
|
end if ;
|
|
end if ;
|
|
end process ;
|
|
|
|
|
|
U_power_div : entity work.wlan_divide
|
|
generic map (
|
|
SAMPLE_WIDTH => 32,
|
|
DENOM_WIDTH => 32,
|
|
NUM_PIPELINE => 32
|
|
) port map (
|
|
clock => clock,
|
|
reset => reset,
|
|
|
|
in_i => resize(shift_left(i_accum, 8), 32),
|
|
in_q => resize(shift_left(q_accum, 8), 32),
|
|
in_denom => resize(shift_right(power_accum, 12), 32),
|
|
|
|
in_valid => accum_valid,
|
|
in_done => '0',
|
|
|
|
out_i => div_i_power,
|
|
out_q => div_q_power,
|
|
out_valid => div_power_valid,
|
|
out_done => open
|
|
) ;
|
|
|
|
process(all)
|
|
begin
|
|
if( burst_counter > 192 and burst_counter < 254 ) then
|
|
acquired <= peak_found ; --and peak_match and first_peak;
|
|
else
|
|
acquired <= '0';
|
|
end if;
|
|
end process ;
|
|
|
|
U_p_norm : entity wlan.wlan_p_norm
|
|
port map (
|
|
clock => clock,
|
|
reset => reset,
|
|
quiet => quiet,
|
|
|
|
sample => in_sample,
|
|
p_normed => p_sample,
|
|
|
|
p_mag => p_mag
|
|
);
|
|
|
|
out_sample <= in_sample;
|
|
end architecture ;
|