1 | % Mango 802.11 Reference Design |
---|
2 | % WLAN PHY Tx Init script |
---|
3 | % Copyright 2016 Mango Communications |
---|
4 | % Distributed under the Mango Research License: |
---|
5 | % http://mangocomm.com/802.11/license |
---|
6 | |
---|
7 | %clear |
---|
8 | addpath('./util'); |
---|
9 | addpath('./mcode_blocks'); |
---|
10 | addpath('./blackboxes'); |
---|
11 | |
---|
12 | %Define sane values for maximum parameter values; these maximums define |
---|
13 | % the bit widths of various signals throughout the design. Increasing |
---|
14 | % these maximum values will increae resource usage in hardware. |
---|
15 | MAX_NUM_BYTES = 4096; |
---|
16 | MAX_NUM_SC = 64; |
---|
17 | MAX_CP_LEN = 32; |
---|
18 | MAX_NUM_SAMPS = 50e3; |
---|
19 | MAX_NUM_SYMS = 600; |
---|
20 | MAX_DATA_BITS_PER_SYM_PERIOD = 2*260; %64-QAM 5/6 rate N_SS=2 |
---|
21 | MAX_NCBPS = 312; %Max coded bits per OFDM sym sets size of de-interleave RAM |
---|
22 | |
---|
23 | %% |
---|
24 | %Define a few interesting MPDU payloads. These byte sequences start with |
---|
25 | % the MAC header, followed by the MAC payload, followed by the FCS. The FCS |
---|
26 | % is calculated and inserted by the PHY automatically, so 4 zeros are defined |
---|
27 | % as placeholders in each byte sequence below. |
---|
28 | |
---|
29 | %Null data frame: |
---|
30 | % Frame Control field: 0x4811 |
---|
31 | % Duration: 0x2c00 (44 usec) |
---|
32 | % Receiver address: 40-d8-55-04-21-4a |
---|
33 | % Transmitter address: 40-d8-55-04-21-5a |
---|
34 | % Destination address: 40-d8-55-04-21-4a |
---|
35 | % Fragment/Seq Num field: 0xf092 |
---|
36 | % FCS placeholder: 0x00000000 |
---|
37 | MPDU_Null_Data = sscanf('48 11 2c 00 40 d8 55 04 21 4a 40 d8 55 04 21 5a 40 d8 55 04 21 4a f0 92 00 00 00 00', '%02x'); |
---|
38 | |
---|
39 | %Data frames: |
---|
40 | % Frame Control field: 0x0801 |
---|
41 | % Duration: 0x2c00 (44 usec) |
---|
42 | % Receiver address: 40-d8-55-04-21-4a |
---|
43 | % Transmitter address: 40-d8-55-04-21-5a |
---|
44 | % Destination address: 40-d8-55-04-21-6a |
---|
45 | % Fragment/Seq Num field: 0xb090 |
---|
46 | % LLC header: aa-aa-03-00-00-00-08-00 |
---|
47 | % Arbitrary payload: 00-01-02...0f |
---|
48 | % FCS placeholder: 0x00000000 |
---|
49 | |
---|
50 | %Short pkt - 16 payload bytes |
---|
51 | MPDU_Data_short = sscanf(['08 01 2c 00 40 d8 55 04 21 4a 40 d8 55 04 21 5a 40 d8 55 04 21 6a b0 90 aa aa 03 00 00 00 08 00 ' sprintf('%02x ', [0:15]) ' 00 00 00 00'], '%02x'); |
---|
52 | |
---|
53 | %Mid-size pkt - 150 payload bytes |
---|
54 | MPDU_Data_mid = sscanf(['08 01 2c 00 40 d8 55 04 21 4a 40 d8 55 04 21 5a 40 d8 55 04 21 6a b0 90 aa aa 03 00 00 00 08 00 ' sprintf('%02x ', mod([1:513], 256)) ' 00 00 00 00'], '%02x'); |
---|
55 | |
---|
56 | %Long pkt - 1420 payload bytes |
---|
57 | MPDU_Data_long = sscanf(['08 01 2c 00 40 d8 55 04 21 4a 40 d8 55 04 21 5a 40 d8 55 04 21 6a b0 90 aa aa 03 00 00 00 08 00 ' sprintf('%02x ', mod([1:1434], 256)) ' 00 00 00 00'], '%02x'); |
---|
58 | |
---|
59 | %ACK frame: |
---|
60 | % Frame Control field: 0xd400 |
---|
61 | % Duration: 0x0000 (0 usec) |
---|
62 | % Receiver address: 40-d8-55-04-21-4a |
---|
63 | % FCS placeholder: 0x00000000 |
---|
64 | ControlFrame_ACK = sscanf('d4 00 00 00 40 d8 55 04 21 4a 00 00 00 00', '%02x'); |
---|
65 | |
---|
66 | %CTS frame: |
---|
67 | % Frame Control field: 0xc400 |
---|
68 | % Duration: 0x01F4 (500 usec) |
---|
69 | % Receiver address: 40-d8-55-04-21-4a |
---|
70 | % FCS placeholder: 0x00000000 |
---|
71 | ControlFrame_CTS = sscanf('c4 00 F4 01 40 d8 55 04 21 4a 00 00 00 00', '%02x'); |
---|
72 | |
---|
73 | %100-Byte random payload with valid FCS, used with IEEE waveform generator |
---|
74 | %wgen_pyld = sscanf(['26 bd 8e b7 f4 13 e7 5c 31 c6 a4 5b ac 95 e9 5c 7c dc 42 10 6d 73 0f 0c 82 8e d9 b2 c8 48 f3 e2 75 fe 92 20 f4 74 f1 fa e0 ae cb 06 55 70 ed 63 1a 9b e7 6e 2b 61 7a df f4 fc b6 20 ba d1 09 8f 31 ea 8b de 1d 77 ce 78 c3 0b dd 25 d2 55 63 23 7c 31 cd 35 f5 75 1e 08 b2 2e 5b a4 67 3f 95 26 a3 54 37 cd'], '%02x'); |
---|
75 | |
---|
76 | ltg_pyld = sscanf('08 02 26 00 40 d8 55 04 24 f4 40 d8 55 04 24 b6 40 d8 55 04 24 b6 30 f1 aa aa 03 00 00 00 90 90 13 3f bc 02 00 00 00 00 79 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 96 6d 42 55', '%02x'); |
---|
77 | |
---|
78 | %Setup params for the sim |
---|
79 | % In hardware these params are set per packet by the MAC core/code |
---|
80 | % Bypass if running multiple sims via the gen_sim_waveforms script |
---|
81 | if(~exist('gen_waveform_mode', 'var')) |
---|
82 | tx_sim = struct(); |
---|
83 | tx_sim.MAC_payload = ControlFrame_CTS; |
---|
84 | tx_sim.payload_len = length(tx_sim.MAC_payload); |
---|
85 | tx_sim.PHY_mode = 1; %1=11a, 2=11n |
---|
86 | tx_sim.mcs = 0; |
---|
87 | tx_sim.samp_rate = 40; %Must be in [10 20 40] |
---|
88 | tx_sim.num_pkts = 1; |
---|
89 | end |
---|
90 | |
---|
91 | %MCS6, length=57, HTSIG should be: |
---|
92 | % 06 39 00 07 E0 00 (per IEEE waveform gen) |
---|
93 | % instead, current sim is: |
---|
94 | % 06 39 00 07 48 00 - clearly CRC calc is wrong for some MCS/Length values |
---|
95 | |
---|
96 | %Construct the initial value for the simulated packet buffer |
---|
97 | % This code is only for sim - CPU Low handles the packet buffer |
---|
98 | % init in the actual design |
---|
99 | |
---|
100 | %Tx packet buffer bytes (zero indexed): |
---|
101 | %11a Tx: |
---|
102 | % [ 0: 2] SIGNAL field |
---|
103 | % [ 3: 4] SERVICE field (always [0 0]) |
---|
104 | % [ 5:15] Reserved (ignored by Tx PHY logic) |
---|
105 | % [16: N] MAC payload |
---|
106 | % |
---|
107 | %11n Tx: |
---|
108 | % [ 0: 2] L-SIG field |
---|
109 | % [ 3: 8] HT-SIG |
---|
110 | % [ 9:10] SERVICE field (always [0 0]) |
---|
111 | % [11:15] Reserved (ignored by Tx PHY logic) |
---|
112 | % [16: N] MAC payload |
---|
113 | |
---|
114 | PPDU_bytes = zeros(1, MAX_NUM_BYTES); |
---|
115 | |
---|
116 | [SIGNAL, HTSIG] = calc_phy_preamble(tx_sim.PHY_mode, tx_sim.mcs, tx_sim.payload_len); |
---|
117 | |
---|
118 | if(tx_sim.PHY_mode == 1) |
---|
119 | PPDU_bytes(1:3) = SIGNAL; |
---|
120 | |
---|
121 | %Insert SERVICE field (always 0) |
---|
122 | PPDU_bytes(4:5) = [0 0]; |
---|
123 | |
---|
124 | %Reserved bytes |
---|
125 | PPDU_bytes(6:16) = zeros(1,11); |
---|
126 | else |
---|
127 | [SIGNAL, HTSIG] = calc_phy_preamble(2, tx_sim.mcs, tx_sim.payload_len); |
---|
128 | |
---|
129 | %11n mode - L-SIG contains rate=6Mbps, length corresponding to TX_TIME |
---|
130 | PPDU_bytes(1:3) = SIGNAL; |
---|
131 | |
---|
132 | %HT-SIG field |
---|
133 | PPDU_bytes(4:9) = HTSIG; |
---|
134 | |
---|
135 | %Insert SERVICE field (always 0) |
---|
136 | PPDU_bytes(10:11) = [0 0]; |
---|
137 | |
---|
138 | %Reserved bytes |
---|
139 | PPDU_bytes(12:16) = zeros(1, 5); |
---|
140 | end |
---|
141 | |
---|
142 | %Insert MAC payload - payload starts at byte index 16 |
---|
143 | PPDU_bytes(16 + (1:numel(tx_sim.MAC_payload))) = tx_sim.MAC_payload; |
---|
144 | |
---|
145 | %Reshape byte vector to u32 vector, necessary to initialize the 32-bit BRAM in the simulation |
---|
146 | PPDU_bytes4 = reshape(PPDU_bytes, 4, numel(PPDU_bytes)/4); |
---|
147 | PPDU_words = sum(PPDU_bytes4 .* repmat(2.^[0:8:24]', 1, size(PPDU_bytes4,2))); |
---|
148 | |
---|
149 | |
---|
150 | %Define the complex-valued sequence for the preamble ROMs |
---|
151 | PLCP_Preamble = PLCP_Preamble_gen; |
---|
152 | Preamble_IQ = PLCP_Preamble.Preamble_t; |
---|
153 | |
---|
154 | %% Register Init |
---|
155 | |
---|
156 | %Sane initial values for PHY config registers. These values will be overwritten |
---|
157 | % at run-time by the software in CPU Low |
---|
158 | PHY_CONFIG_NUM_SC = 64; |
---|
159 | PHY_CONFIG_CP_LEN = 16; |
---|
160 | PHY_CONFIG_FFT_SCALING = bin2dec('101010'); |
---|
161 | PHY_TX_ACTIVE_EXTENSION = 1; |
---|
162 | PHY_TX_RF_EN_EXTENSION = 50; |
---|
163 | PHY_TX_RXSIG_INVALID_EXTENSION = 120; |
---|
164 | |
---|
165 | REG_Tx_Timing = ... |
---|
166 | 2^0 * (PHY_TX_ACTIVE_EXTENSION) + ... %b[7:0] |
---|
167 | 2^10 * (PHY_TX_RF_EN_EXTENSION) + ... %b[15:8] |
---|
168 | 2^20 * (PHY_TX_RXSIG_INVALID_EXTENSION) + ... %b[23:16] |
---|
169 | 0; |
---|
170 | |
---|
171 | REG_TX_FFT_Config = ... |
---|
172 | 2^0 * (PHY_CONFIG_NUM_SC) +... %b[7:0] |
---|
173 | 2^8 * (PHY_CONFIG_CP_LEN) +... %b[15:8] |
---|
174 | 2^24 * (PHY_CONFIG_FFT_SCALING) + ... b[29:24] |
---|
175 | 0; |
---|
176 | |
---|
177 | REG_TX_Config = ... |
---|
178 | 2^0 * 1 + ... %Force RxEN to radio_controller |
---|
179 | 2^1 * 0 + ... %Reset scrambler per pkt |
---|
180 | 2^2 * 1 + ... %Enable Tx on RF A |
---|
181 | 2^3 * 0 + ... %Enable Tx on RF B |
---|
182 | 2^4 * 0 + ... %Enable Tx on RF C |
---|
183 | 2^5 * 0 + ... %Enable Tx on RF D |
---|
184 | 2^6 * 1 + ... %Use ant mask from MAC hw port |
---|
185 | 2^7 * 0 + ... %Use un-delayed TX_ACTIVE signal on debug port |
---|
186 | 2^12 * 1 + ... %PHY mode (1=11a, 2=11n), only used for software-initiated Tx |
---|
187 | 0; |
---|
188 | |
---|
189 | REG_TX_PKT_BUF_SEL = ... |
---|
190 | 2^0 * 0 + ... %b[3:0] pkt buf index |
---|
191 | 2^4 * 32 + ... %b[9:4] timestamp insert start byte |
---|
192 | 2^10 * 31 + ... %b[15:10] timestamp insert end byte |
---|
193 | 2^16 * 0 + ... %b[23:16] pkt buf address offset |
---|
194 | 0; |
---|
195 | |
---|
196 | REG_TX_Output_Scaling = (2.0 * 2^12) + (2^16 * 2.0 * 2^12); %UFix16_12 values |
---|
197 | |
---|
198 | |
---|
199 | %% Cyclic Redundancy Check parameters |
---|
200 | CRCPolynomial32 = hex2dec('04c11db7'); %CRC-32, for payload FCS |
---|
201 | CRC_Table32 = CRC_table_gen(CRCPolynomial32, 32); |
---|
202 | |
---|
203 | CRCPolynomial8 = hex2dec('07'); %CRC-8, for HT-SIG |
---|
204 | CRC_Table8 = CRC_table_gen(CRCPolynomial8, 8); |
---|
205 | |
---|
206 | %% |
---|
207 | %Load the MCS info table |
---|
208 | [mcs_rom_11ag, mcs_rom_11n] = tx_mcs_info_rom_init(); |
---|
209 | |
---|
210 | |
---|
211 | |
---|
212 | %% Constellation scaling |
---|
213 | |
---|
214 | %Common scaling for preamble and all constellations that keeps all points within |
---|
215 | % numeric range of Fix16_15 values at input to IFFT |
---|
216 | ALL_MOD_SCALING = ( 1.0 - (2^-15) )/(7/sqrt(42)); |
---|
217 | Preamble_IQ_scaled = ALL_MOD_SCALING * Preamble_IQ; |
---|
218 | |
---|
219 | Mod_Constellation_BPSK(1) = ALL_MOD_SCALING * -1; |
---|
220 | Mod_Constellation_BPSK(2) = ALL_MOD_SCALING * 1; |
---|
221 | |
---|
222 | Mod_Constellation_QPSK(1) = ALL_MOD_SCALING * -1/sqrt(2); |
---|
223 | Mod_Constellation_QPSK(2) = ALL_MOD_SCALING * 1/sqrt(2); |
---|
224 | |
---|
225 | Mod_Constellation_16QAM(1) = ALL_MOD_SCALING * -3/sqrt(10); |
---|
226 | Mod_Constellation_16QAM(2) = ALL_MOD_SCALING * -1/sqrt(10); |
---|
227 | Mod_Constellation_16QAM(3) = ALL_MOD_SCALING * 3/sqrt(10); |
---|
228 | Mod_Constellation_16QAM(4) = ALL_MOD_SCALING * 1/sqrt(10); |
---|
229 | |
---|
230 | Mod_Constellation_64QAM(1) = ALL_MOD_SCALING * -7/sqrt(42); |
---|
231 | Mod_Constellation_64QAM(2) = ALL_MOD_SCALING * -5/sqrt(42); |
---|
232 | Mod_Constellation_64QAM(3) = ALL_MOD_SCALING * -1/sqrt(42); |
---|
233 | Mod_Constellation_64QAM(4) = ALL_MOD_SCALING * -3/sqrt(42); |
---|
234 | Mod_Constellation_64QAM(5) = ALL_MOD_SCALING * 7/sqrt(42); |
---|
235 | Mod_Constellation_64QAM(6) = ALL_MOD_SCALING * 5/sqrt(42); |
---|
236 | Mod_Constellation_64QAM(7) = ALL_MOD_SCALING * 1/sqrt(42); |
---|
237 | Mod_Constellation_64QAM(8) = ALL_MOD_SCALING * 3/sqrt(42); |
---|
238 | |
---|
239 | |
---|
240 | %% HT preamble |
---|
241 | |
---|
242 | %Define the frequency domain 20MHz HT-STF (IEEE 802.11-2012 20.3.9.4.5) |
---|
243 | % Array indexes [0 ... 63] correspond to subcarriers [0 1 ... 31 -32 -31 ... -1] |
---|
244 | ht_stf_20_fd = zeros(1,64); |
---|
245 | ht_stf_20_fd(1:27) = [0 0 0 0 -1-1i 0 0 0 -1-1i 0 0 0 1+1i 0 0 0 1+1i 0 0 0 1+1i 0 0 0 1+1i 0 0]; |
---|
246 | ht_stf_20_fd(39:64) = [0 0 1+1i 0 0 0 -1-1i 0 0 0 1+1i 0 0 0 -1-1i 0 0 0 -1-1i 0 0 0 1+1i 0 0 0]; |
---|
247 | |
---|
248 | %Define the frequency domain 20MHz HT-LTF (IEEE 802.11-2012 20.3.9.4.6) |
---|
249 | % Array indexes [0 ... 63] correspond to subcarriers [0 1 ... 31 -32 -31 ... -1] |
---|
250 | ht_ltf_20_fd = [0 1 -1 -1 1 1 -1 1 -1 1 -1 -1 -1 -1 -1 1 1 -1 -1 1 -1 1 -1 1 1 1 1 -1 -1 0 0 0 0 0 0 0 1 1 1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 1 1 -1 -1 1 1 -1 1 -1 1 1 1 1]; |
---|
251 | |
---|
252 | %Define init vector for HT preamble ROM |
---|
253 | % 20MHz HT-STF and HT-LTF are concatenated |
---|
254 | % FIXME: HT-STF scaling isn't quite right - it should be a bit bigger |
---|
255 | % Need to figure out best way to build that, given IFFT Fix16_15 input type |
---|
256 | ht_preamble_rom = [ht_stf_20_fd ALL_MOD_SCALING .* ht_ltf_20_fd]; |
---|
257 | |
---|
258 | %% Interleaver and subcarrier maps |
---|
259 | |
---|
260 | % Use util script to generate interleaver address mapping ROM contents |
---|
261 | wlan_tx_interleave_rom = wlan_tx_interleave_rom_gen(); |
---|
262 | |
---|
263 | %Initialize a vector defining the subcarrier map |
---|
264 | % This vector is used by the interleaver control logic to select which |
---|
265 | % subcarriers carry data symbols. A value of MAX_NUM_SC tells the hardware to |
---|
266 | % not use the subcarrier for data. |
---|
267 | sc_ind_data_11a = [2:7 9:21 23:27 39:43 45:57 59:64]; |
---|
268 | sc_data_sym_map_11a = MAX_NUM_SC*ones(1,MAX_NUM_SC); |
---|
269 | sc_data_sym_map_11a(sc_ind_data_11a) = 0:length(sc_ind_data_11a)-1; |
---|
270 | sc_data_sym_map_11a_bool = double(sc_data_sym_map_11a ~= MAX_NUM_SC); |
---|
271 | |
---|
272 | sc_ind_data_11n = [2:7 9:21 23:29 37:43 45:57 59:64]; |
---|
273 | sc_data_sym_map_11n = MAX_NUM_SC*ones(1,MAX_NUM_SC); |
---|
274 | sc_data_sym_map_11n(sc_ind_data_11n) = 0:length(sc_ind_data_11n)-1; |
---|
275 | sc_data_sym_map_11n_bool = double(sc_data_sym_map_11n ~= MAX_NUM_SC); |
---|
276 | |
---|