bladeRF-wiphy/fpga/vhdl/wlan_interleaver_p.vhd
2020-12-30 23:19:51 -08:00

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 ;