mirror of
https://github.com/Nuand/bladeRF-wiphy.git
synced 2024-12-30 10:39:08 +00:00
134 lines
4.8 KiB
VHDL
134 lines
4.8 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.math_real.all ;
|
||
|
|
||
|
library work ;
|
||
|
use work.wlan_p.all ;
|
||
|
|
||
|
package wlan_interleaver_p is
|
||
|
|
||
|
-- Deferred initialization in package body after function definition
|
||
|
constant WLAN_INTERLEAVER_BPSK : integer_array_t ;
|
||
|
constant WLAN_INTERLEAVER_QPSK : integer_array_t ;
|
||
|
constant WLAN_INTERLEAVER_16QAM : integer_array_t ;
|
||
|
constant WLAN_INTERLEAVER_64QAM : integer_array_t ;
|
||
|
|
||
|
-- Interleaving occurs on bits
|
||
|
function interleave( modulation : wlan_modulation_t ; x : std_logic_vector(287 downto 0) ) return std_logic_vector ;
|
||
|
|
||
|
-- Deinterleaving occurs on bit soft decisions
|
||
|
function deinterleave( modulation : wlan_modulation_t ; x : bsd_array_t(287 downto 0) ) return bsd_array_t ;
|
||
|
|
||
|
end package ;
|
||
|
|
||
|
package body wlan_interleaver_p is
|
||
|
|
||
|
function get_table( modulation : wlan_modulation_t ) return integer_array_t is
|
||
|
begin
|
||
|
case modulation is
|
||
|
when WLAN_BPSK => return WLAN_INTERLEAVER_BPSK ;
|
||
|
when WLAN_QPSK => return WLAN_INTERLEAVER_QPSK ;
|
||
|
when WLAN_16QAM => return WLAN_INTERLEAVER_16QAM ;
|
||
|
when WLAN_64QAM => return WLAN_INTERLEAVER_64QAM ;
|
||
|
when others => return WLAN_INTERLEAVER_BPSK ;
|
||
|
end case ;
|
||
|
report "get_table: Could not figure out modulation" severity failure ;
|
||
|
end function ;
|
||
|
|
||
|
function interleave( modulation : wlan_modulation_t ; x : std_logic_vector(287 downto 0) ) return std_logic_vector is
|
||
|
variable t : integer_array_t(0 to 287) ;
|
||
|
variable y : std_logic_vector(287 downto 0) := (others =>'-') ;
|
||
|
begin
|
||
|
t := get_table( modulation ) ;
|
||
|
for i in t'range loop
|
||
|
-- 0 only happens for the 0 entry, so stop there
|
||
|
if( i > 0 and t(i) = 0 ) then
|
||
|
exit ;
|
||
|
else
|
||
|
y(t(i)) := x(i) ;
|
||
|
end if ;
|
||
|
end loop ;
|
||
|
return y ;
|
||
|
end function ;
|
||
|
|
||
|
function deinterleave( modulation : wlan_modulation_t ; x : bsd_array_t(287 downto 0) ) return bsd_array_t is
|
||
|
variable t : integer_array_t(0 to 287) ;
|
||
|
variable y : bsd_array_t(287 downto 0) ;
|
||
|
begin
|
||
|
y := (others => (others => '0' )) ;
|
||
|
t := get_table( modulation ) ;
|
||
|
for i in t'range loop
|
||
|
-- Stop at the next 0 entry
|
||
|
if( i > 0 and t(i) = 0 ) then
|
||
|
exit ;
|
||
|
else
|
||
|
y(i) := x(t(i)) ;
|
||
|
end if ;
|
||
|
end loop ;
|
||
|
return y ;
|
||
|
end function ;
|
||
|
|
||
|
function calculate_interleaver_table( modulation : wlan_modulation_t ) return integer_array_t is
|
||
|
variable n_cbps : natural ;
|
||
|
variable n_bpsc : natural ;
|
||
|
variable i : natural ;
|
||
|
variable j : natural ;
|
||
|
variable s : natural ;
|
||
|
variable rv : integer_array_t(0 to 287) := (others => 0) ;
|
||
|
begin
|
||
|
case modulation is
|
||
|
when WLAN_BPSK =>
|
||
|
n_bpsc := 1 ;
|
||
|
n_cbps := 48 ;
|
||
|
s := 1 ;
|
||
|
when WLAN_QPSK =>
|
||
|
n_bpsc := 2 ;
|
||
|
n_cbps := 96 ;
|
||
|
s := 1 ;
|
||
|
when WLAN_16QAM =>
|
||
|
n_bpsc := 4 ;
|
||
|
n_cbps := 192 ;
|
||
|
s := 2 ;
|
||
|
when WLAN_64QAM =>
|
||
|
n_bpsc := 6 ;
|
||
|
n_cbps := 288 ;
|
||
|
s := 3 ;
|
||
|
when others =>
|
||
|
end case ;
|
||
|
|
||
|
for k in 0 to n_cbps-1 loop
|
||
|
i := (n_cbps/16)*(k mod 16) + k/16 ;
|
||
|
j := s*integer(floor(real(i)/real(s))) + ((i + n_cbps - (16*i)/n_cbps) mod s) ;
|
||
|
rv(k) := j ;
|
||
|
end loop ;
|
||
|
|
||
|
return rv ;
|
||
|
end function ;
|
||
|
|
||
|
-- Deferred initialization of table
|
||
|
constant WLAN_INTERLEAVER_BPSK : integer_array_t := calculate_interleaver_table( WLAN_BPSK ) ;
|
||
|
constant WLAN_INTERLEAVER_QPSK : integer_array_t := calculate_interleaver_table( WLAN_QPSK ) ;
|
||
|
constant WLAN_INTERLEAVER_16QAM : integer_array_t := calculate_interleaver_table( WLAN_16QAM ) ;
|
||
|
constant WLAN_INTERLEAVER_64QAM : integer_array_t := calculate_interleaver_table( WLAN_64QAM ) ;
|
||
|
|
||
|
end package body ;
|
||
|
|