The HT-SIG field of 802.11n PLCP preamble contains a 8-bit CRC for the receiver to validate the sanity of the header. Here is how to calculate it.
HT-SIG contains 48 bits and spans in 2 OFDM symbols (BPSK modulated, 1/2 rate). This diagram from the 802.11-2012 standard describes the logic to calculate the CRC for the first 34 bits of the field.
Here is a Python version of the implementation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def calc_crc(bits):
c = [1] * 8
for b in bits:
next_c = [0] * 8
next_c[0] = b ^ c[7]
next_c[1] = b ^ c[7] ^ c[0]
next_c[2] = b ^ c[7] ^ c[1]
next_c[3] = c[2]
next_c[4] = c[3]
next_c[5] = c[4]
next_c[6] = c[5]
next_c[7] = c[6]
c = next_c
return [1-b for b in c[::-1]]
|
c is the 8-bit shift register. For each incoming bits, we calculate the next value of each bit in the register and store them in next_c.
Finally, we perform two operations: reverse and two's complement. Note that c[7] is the first output bit.
The standard also provides a test case.
1 2 3 4 | >>> s = '1 1 1 1 0 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0'
>>> bits = [int(b) for b in s.split()]
>>> calc_crc(bits)
[1, 0, 1, 0, 1, 0, 0, 0]
|
Translating the logic into HDLs such as Verilog is quite straightforward.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | module ht_sig_crc (
input clock,
input enable,
input reset,
input bit,
input input_strobe,
output [7:0] crc
);
reg [7:0] C;
genvar i;
generate
for (i = 0; i < 8; i=i+1) begin: reverse
assign crc[i] = ~C[7-i];
end
endgenerate
always @(posedge clock) begin
if (reset) begin
C <= 8'hff;
end else if (enable) begin
if (input_strobe) begin
C[0] <= bit ^ C[7];
C[1] <= bit ^ C[7] ^ C[0];
C[2] <= bit ^ C[7] ^ C[1];
C[7:3] <= C[6:2];
end
end
end
endmodule
|
Here we use the generate block to do the bit-reverse and negation.