1 | function deinterleave_mapping_ROM = wlan_rx_deinterleave_rom_gen() |
---|
2 | |
---|
3 | % Define numbers of coded bits per OFDM symbol for each modulation rate |
---|
4 | NCBPS_11a_BPSK = 48; |
---|
5 | NCBPS_11a_QPSK = 96; |
---|
6 | NCBPS_11a_16QAM = 192; |
---|
7 | NCBPS_11a_64QAM = 288; |
---|
8 | |
---|
9 | NCBPS_11n_BPSK = 52; |
---|
10 | NCBPS_11n_QPSK = 104; |
---|
11 | NCBPS_11n_16QAM = 208; |
---|
12 | NCBPS_11n_64QAM = 312; |
---|
13 | |
---|
14 | % Calculate interleaving vectors for each modulation scheme for each PHY mode |
---|
15 | interleave_11a_BPSK = calc_interleave_vec_11a(NCBPS_11a_BPSK, 1); |
---|
16 | interleave_11a_QPSK = calc_interleave_vec_11a(NCBPS_11a_QPSK, 2); |
---|
17 | interleave_11a_16QAM = calc_interleave_vec_11a(NCBPS_11a_16QAM, 4); |
---|
18 | interleave_11a_64QAM = calc_interleave_vec_11a(NCBPS_11a_64QAM, 6); |
---|
19 | interleave_11n_BPSK = calc_interleave_vec_11n(NCBPS_11n_BPSK, 1); |
---|
20 | interleave_11n_QPSK = calc_interleave_vec_11n(NCBPS_11n_QPSK, 2); |
---|
21 | interleave_11n_16QAM = calc_interleave_vec_11n(NCBPS_11n_16QAM, 4); |
---|
22 | interleave_11n_64QAM = calc_interleave_vec_11n(NCBPS_11n_64QAM, 6); |
---|
23 | |
---|
24 | % The interleave_11x vectors define the 1:1 mapping of input bit index to |
---|
25 | % output bit index. The spec places the first bit (output index 0) in the |
---|
26 | % lowest (most negative) frequency subcarrier, subcarrier index -26 for 11a, |
---|
27 | % -28 for 11n. The Rx PHY FFT core outputs subcarriers in in natual order, |
---|
28 | % starting at subcarrier 0 (DC), then +1, +2, etc. Thus the deinterleaving |
---|
29 | % vectors must be rotated to align the bit indices with the IFFT |
---|
30 | % subcarrier indices. This is effectivly an fftshift() operation. |
---|
31 | interleave_11a_BPSK = mod(interleave_11a_BPSK + (NCBPS_11a_BPSK/2), NCBPS_11a_BPSK); |
---|
32 | interleave_11a_QPSK = mod(interleave_11a_QPSK + (NCBPS_11a_QPSK/2), NCBPS_11a_QPSK); |
---|
33 | interleave_11a_16QAM = mod(interleave_11a_16QAM + (NCBPS_11a_16QAM/2), NCBPS_11a_16QAM); |
---|
34 | interleave_11a_64QAM = mod(interleave_11a_64QAM + (NCBPS_11a_64QAM/2), NCBPS_11a_64QAM); |
---|
35 | interleave_11n_BPSK = mod(interleave_11n_BPSK + (NCBPS_11n_BPSK/2), NCBPS_11n_BPSK); |
---|
36 | interleave_11n_QPSK = mod(interleave_11n_QPSK + (NCBPS_11n_QPSK/2), NCBPS_11n_QPSK); |
---|
37 | interleave_11n_16QAM = mod(interleave_11n_16QAM + (NCBPS_11n_16QAM/2), NCBPS_11n_16QAM); |
---|
38 | interleave_11n_64QAM = mod(interleave_11n_64QAM + (NCBPS_11n_64QAM/2), NCBPS_11n_64QAM); |
---|
39 | |
---|
40 | % The Rx PHY deinterleaver uses a single RAM to store all the bits for a |
---|
41 | % single OFDM symbol. The same RAM is used for all rates. The RAM stores |
---|
42 | % coded/punctured data bits for each subcarrier on 32-bit boundaries. By |
---|
43 | % allocating 1 32-bit word per subcarrier the design can use an efficient BRAM |
---|
44 | % architecture with 1 word write per subcarrier (concatenated LLR values) and parallel |
---|
45 | % 2-soft-bit reads (soft values for 2 coded bits). Even with the aspect ratio change |
---|
46 | % write and read operations require a single clock cycle. |
---|
47 | % |
---|
48 | % The vectors above define the interleaver mapping as bit indexes in:out. |
---|
49 | % The operations below convert these to mapping |
---|
50 | % (bit index in) : (interleaver RAM address out) by increasing the |
---|
51 | % output index values to place each subcarrier's bits on a 32-bit boundary. |
---|
52 | % The BRAM output width is 4 bits, so the read addresses below access 8 entries |
---|
53 | % per 32-bit word. |
---|
54 | % |
---|
55 | % floor(x / bits_per_sym) calculates the subcarrier index of each output bit index |
---|
56 | % mod(x, bits_per_sym) calculates the bit index within the subcarrier |
---|
57 | ramaddr_11a_BPSK = mod(interleave_11a_BPSK, 1) + (8 * floor(interleave_11a_BPSK / 1)); |
---|
58 | ramaddr_11a_QPSK = mod(interleave_11a_QPSK, 2) + (8 * floor(interleave_11a_QPSK / 2)); |
---|
59 | ramaddr_11a_16QAM = mod(interleave_11a_16QAM, 4) + (8 * floor(interleave_11a_16QAM / 4)); |
---|
60 | ramaddr_11a_64QAM = mod(interleave_11a_64QAM, 6) + (8 * floor(interleave_11a_64QAM / 6)); |
---|
61 | |
---|
62 | ramaddr_11n_BPSK = mod(interleave_11n_BPSK, 1) + (8 * floor(interleave_11n_BPSK / 1)); |
---|
63 | ramaddr_11n_QPSK = mod(interleave_11n_QPSK, 2) + (8 * floor(interleave_11n_QPSK / 2)); |
---|
64 | ramaddr_11n_16QAM = mod(interleave_11n_16QAM, 4) + (8 * floor(interleave_11n_16QAM / 4)); |
---|
65 | ramaddr_11n_64QAM = mod(interleave_11n_64QAM, 6) + (8 * floor(interleave_11n_64QAM / 6)); |
---|
66 | |
---|
67 | %Concatenate all the mapping vectors into a single vector, to be used as |
---|
68 | % the init value for the ROM which implements the mapping LUT. Each LUT entry |
---|
69 | % is used as a memory address. The Tx PHY logic constructs the RAM write address as: |
---|
70 | % addr[8:0] = {phy_mode_11n[0] mod_sel[1:0] bit_ind[5:0]} |
---|
71 | % Each mod scheme occupies 512 entries (64 subcarriers * 8 RAM bits per subcarrier) |
---|
72 | deinterleave_mapping_ROM = []; |
---|
73 | deinterleave_mapping_ROM = [deinterleave_mapping_ROM ramaddr_11a_BPSK zeros(1, 512-length(ramaddr_11a_BPSK))]; |
---|
74 | deinterleave_mapping_ROM = [deinterleave_mapping_ROM ramaddr_11a_QPSK zeros(1, 512-length(ramaddr_11a_QPSK))]; |
---|
75 | deinterleave_mapping_ROM = [deinterleave_mapping_ROM ramaddr_11a_16QAM zeros(1, 512-length(ramaddr_11a_16QAM))]; |
---|
76 | deinterleave_mapping_ROM = [deinterleave_mapping_ROM ramaddr_11a_64QAM zeros(1, 512-length(ramaddr_11a_64QAM))]; |
---|
77 | deinterleave_mapping_ROM = [deinterleave_mapping_ROM ramaddr_11n_BPSK zeros(1, 512-length(ramaddr_11n_BPSK))]; |
---|
78 | deinterleave_mapping_ROM = [deinterleave_mapping_ROM ramaddr_11n_QPSK zeros(1, 512-length(ramaddr_11n_QPSK))]; |
---|
79 | deinterleave_mapping_ROM = [deinterleave_mapping_ROM ramaddr_11n_16QAM zeros(1, 512-length(ramaddr_11n_16QAM))]; |
---|
80 | deinterleave_mapping_ROM = [deinterleave_mapping_ROM ramaddr_11n_64QAM zeros(1, 512-length(ramaddr_11n_64QAM))]; |
---|
81 | |
---|
82 | %Helper functions to calculate the interleaving vectors |
---|
83 | % These are implementations of the interleaving functions in the 802.11 spec |
---|
84 | function intlv_vec = calc_interleave_vec_11a(cbps, bpsc) |
---|
85 | N_CBPS = cbps; |
---|
86 | N_BPSC = bpsc; |
---|
87 | s = max(N_BPSC/2, 1); |
---|
88 | |
---|
89 | k = 0:N_CBPS-1; |
---|
90 | i = (N_CBPS/16) .* mod(k,16) + floor(k/16); |
---|
91 | j = s * floor(i/s) + mod( (i + N_CBPS - floor(16*i/N_CBPS)), s); |
---|
92 | intlv_vec = j; |
---|
93 | end |
---|
94 | |
---|
95 | function intlv_vec = calc_interleave_vec_11n(cbps, bpsc) |
---|
96 | N_CBPS = cbps; |
---|
97 | N_BPSC = bpsc; |
---|
98 | s = max(N_BPSC/2, 1); |
---|
99 | |
---|
100 | k = 0:N_CBPS-1; |
---|
101 | i = (4 * N_BPSC) .* mod(k,13) + floor(k/13); |
---|
102 | j = s * floor(i/s) + mod( (i + N_CBPS - floor(13*i/N_CBPS)), s); |
---|
103 | intlv_vec = j; |
---|
104 | end |
---|
105 | |
---|
106 | end |
---|