mirror of
https://github.com/Nuand/bladeRF-wiphy.git
synced 2024-12-19 05:38:09 +00:00
219 lines
7.5 KiB
VHDL
219 lines
7.5 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 work ;
|
|
use work.wlan_p.all ;
|
|
use work.wlan_tx_p.all ;
|
|
|
|
entity wlan_scrambler is
|
|
port (
|
|
clock : in std_logic ;
|
|
reset : in std_logic ;
|
|
|
|
params : wlan_tx_params_t ;
|
|
params_valid : in std_logic ;
|
|
|
|
in_data : in std_logic_vector(7 downto 0) ;
|
|
in_valid : in std_logic ;
|
|
in_done : in std_logic ;
|
|
|
|
out_data : out std_logic_vector(7 downto 0) ;
|
|
out_valid : out std_logic ;
|
|
done : out std_logic
|
|
) ;
|
|
end entity ;
|
|
|
|
architecture arch of wlan_scrambler is
|
|
|
|
signal lfsr_advance : std_logic ;
|
|
signal lfsr_data : std_logic_vector(in_data'range) ;
|
|
signal lfsr_valid : std_logic ;
|
|
|
|
type fsm_t is (IDLE, SKIP_SIGNAL_FIELD, SCRAMBLE_DATA, INSERT_TAIL_BITS, SCRAMBLE_PADDING) ;
|
|
|
|
type state_t is record
|
|
fsm : fsm_t ;
|
|
data : std_logic_vector(7 downto 0) ;
|
|
data_valid : std_logic ;
|
|
done : std_logic ;
|
|
symbol_bytes_left : natural range 0 to 27 ;
|
|
bytes_per_symbol : natural range 3 to 27 ;
|
|
puncturing_nibble : std_logic ;
|
|
extra_byte : std_logic ;
|
|
end record ;
|
|
|
|
function NULL_STATE return state_t is
|
|
variable rv : state_t ;
|
|
begin
|
|
rv.fsm := IDLE ;
|
|
rv.data := (others =>'0') ;
|
|
rv.data_valid := '0' ;
|
|
rv.done := '0' ;
|
|
rv.symbol_bytes_left := 3 ;
|
|
rv.puncturing_nibble := '0' ;
|
|
rv.extra_byte := '0' ;
|
|
return rv ;
|
|
end function ;
|
|
|
|
signal current, future : state_t := NULL_STATE ;
|
|
|
|
function reverse(x : std_logic_vector) return std_logic_vector is
|
|
variable rv : std_logic_vector(x'range) ;
|
|
begin
|
|
for i in x'range loop
|
|
rv(x'high-i) := x(i) ;
|
|
end loop ;
|
|
return rv ;
|
|
end function ;
|
|
|
|
signal data_reversed : std_logic_vector(7 downto 0) ;
|
|
|
|
begin
|
|
|
|
data_reversed <= reverse(current.data) ;
|
|
|
|
out_data <= current.data ;
|
|
out_valid <= current.data_valid ;
|
|
done <= current.done ;
|
|
|
|
U_lfsr : entity work.wlan_lfsr
|
|
generic map (
|
|
WIDTH => in_data'length
|
|
) port map (
|
|
clock => clock,
|
|
reset => reset,
|
|
|
|
init => params.lfsr_init,
|
|
init_valid => params_valid,
|
|
|
|
advance => lfsr_advance,
|
|
data => lfsr_data,
|
|
data_valid => lfsr_valid
|
|
) ;
|
|
|
|
sync : process(clock, reset)
|
|
begin
|
|
if( reset = '1' ) then
|
|
current <= NULL_STATE ;
|
|
elsif( rising_edge(clock) ) then
|
|
current <= future ;
|
|
end if ;
|
|
end process ;
|
|
|
|
comb : process(all)
|
|
begin
|
|
future <= current ;
|
|
future.data_valid <= '0' ;
|
|
future.done <= '0' ;
|
|
lfsr_advance <= '0' ;
|
|
case current.fsm is
|
|
|
|
when IDLE =>
|
|
if( params_valid = '1' ) then
|
|
future.fsm <= SKIP_SIGNAL_FIELD ;
|
|
future.symbol_bytes_left <= 3-1 ;
|
|
future.bytes_per_symbol <= params.n_dbps/8 ;
|
|
if( params.datarate = WLAN_RATE_9) then
|
|
future.puncturing_nibble <= '1' ;
|
|
future.extra_byte <= '1' ;
|
|
else
|
|
future.extra_byte <= '0' ;
|
|
future.puncturing_nibble <= '0' ;
|
|
end if ;
|
|
end if ;
|
|
|
|
when SKIP_SIGNAL_FIELD =>
|
|
if( in_valid = '1' ) then
|
|
future.data <= in_data ;
|
|
future.data_valid <= '1' ;
|
|
if( current.symbol_bytes_left = 0 ) then
|
|
future.fsm <= SCRAMBLE_DATA ;
|
|
if( current.puncturing_nibble = '1' ) then
|
|
if( current.extra_byte <= '1' ) then
|
|
future.symbol_bytes_left <= current.bytes_per_symbol ;
|
|
future.extra_byte <= '0' ;
|
|
else
|
|
future.symbol_bytes_left <= current.bytes_per_symbol - 1 ;
|
|
end if;
|
|
else
|
|
future.symbol_bytes_left <= current.bytes_per_symbol - 1 ;
|
|
end if;
|
|
else
|
|
future.symbol_bytes_left <= current.symbol_bytes_left - 1 ;
|
|
end if ;
|
|
end if ;
|
|
|
|
when SCRAMBLE_DATA =>
|
|
lfsr_advance <= in_valid ;
|
|
if( in_valid = '1' ) then
|
|
future.data <= in_data xor lfsr_data ;
|
|
future.data_valid <= '1' ;
|
|
--needs to keep track if it's going to read an extra nibble or if it's going to save one
|
|
if ( current.symbol_bytes_left = 0 ) then
|
|
if( current.extra_byte = '0' ) then
|
|
future.symbol_bytes_left <= current.bytes_per_symbol - 1 ;
|
|
else
|
|
future.symbol_bytes_left <= current.bytes_per_symbol ;
|
|
end if ;
|
|
if( current.puncturing_nibble = '1' ) then
|
|
future.extra_byte <= not current.extra_byte ;
|
|
end if ;
|
|
else
|
|
future.symbol_bytes_left <= current.symbol_bytes_left - 1 ;
|
|
end if ;
|
|
if( in_done = '1' ) then
|
|
future.fsm <= INSERT_TAIL_BITS ;
|
|
end if ;
|
|
end if ;
|
|
|
|
when INSERT_TAIL_BITS =>
|
|
lfsr_advance <= '1' ;
|
|
future.data <= (others =>'0') ;
|
|
future.data_valid <= '1' ;
|
|
if( current.symbol_bytes_left = 0 ) then
|
|
future.fsm <= IDLE ;
|
|
-- Last byte in the symbol so we're good!
|
|
future.done <= '1' ;
|
|
else
|
|
future.symbol_bytes_left <= current.symbol_bytes_left - 1 ;
|
|
future.fsm <= SCRAMBLE_PADDING ;
|
|
end if ;
|
|
|
|
when SCRAMBLE_PADDING =>
|
|
lfsr_advance <= '1' ;
|
|
future.data <= lfsr_data ;
|
|
future.data_valid <= '1' ;
|
|
if( current.symbol_bytes_left = 0 ) then
|
|
future.fsm <= IDLE ;
|
|
future.done <= '1' ;
|
|
else
|
|
future.symbol_bytes_left <= current.symbol_bytes_left - 1 ;
|
|
end if ;
|
|
|
|
when others =>
|
|
future.fsm <= IDLE ;
|
|
end case ;
|
|
end process ;
|
|
|
|
end architecture ;
|
|
|