openofdm/verilog/dot11.v

856 lines
24 KiB
Coq
Raw Normal View History

2017-04-03 16:52:03 +00:00
`include "common_defs.v"
module dot11 (
input clock,
input enable,
input reset,
2017-04-03 18:31:25 +00:00
// setting registers
2019-12-10 13:09:31 +00:00
//input set_stb,
//input [7:0] set_addr,
//input [31:0] set_data,
// add ports for register based inputs
input [15:0] power_thres,
input [15:0] window_size,
input [31:0] num_sample_to_skip,
input num_sample_changed,
input [31:0] min_plateau,
2017-04-03 16:52:03 +00:00
// INPUT: I/Q sample
input [31:0] sample_in,
input sample_in_strobe,
// OUTPUT: bytes and FCS status
2017-04-21 17:41:49 +00:00
output reg pkt_begin,
output reg pkt_ht,
output reg [7:0] pkt_rate,
output reg [15:0] pkt_len,
2017-04-03 16:52:03 +00:00
output byte_out_strobe,
2017-04-21 17:41:49 +00:00
output [7:0] byte_out,
2017-04-03 16:52:03 +00:00
output reg fcs_out_strobe,
output reg fcs_ok,
2019-12-10 13:09:31 +00:00
output wire [63:0] data_out,
output wire data_out_valid,
2017-04-03 16:52:03 +00:00
/////////////////////////////////////////////////////////
// DEBUG PORTS
/////////////////////////////////////////////////////////
// decode status
output reg [3:0] state,
output reg [3:0] status_code,
output state_changed,
// power trigger
output power_trigger,
2019-12-10 13:09:31 +00:00
output [1:0] pw_state_spy,
2017-04-03 16:52:03 +00:00
// sync short
output short_preamble_detected,
output [31:0] phase_offset,
// sync long
output [31:0] sync_long_metric,
output sync_long_metric_stb,
output long_preamble_detected,
output [31:0] sync_long_out,
output sync_long_out_strobe,
output [2:0] sync_long_state,
// equalizer
output [31:0] equalizer_out,
output equalizer_out_strobe,
output [2:0] equalizer_state,
2017-04-21 17:41:49 +00:00
// legacy signal info
output reg legacy_sig_stb,
output [3:0] legacy_rate,
output legacy_sig_rsvd,
output [11:0] legacy_len,
output legacy_sig_parity,
output legacy_sig_parity_ok,
output [5:0] legacy_sig_tail,
2019-12-10 13:09:31 +00:00
output [23:0] sig_bits_spy,
output [31:0] byte_count_spy,
2017-04-03 16:52:03 +00:00
// ht signal info
2017-04-21 17:41:49 +00:00
output reg ht_sig_stb,
output [6:0] ht_mcs,
output ht_cbw,
2017-04-03 16:52:03 +00:00
output [15:0] ht_len,
2017-04-21 17:41:49 +00:00
output ht_smoothing,
output ht_not_sounding,
output ht_aggregation,
output [1:0] ht_stbc,
output ht_fec_coding,
2017-04-03 16:52:03 +00:00
output ht_sgi,
2017-04-21 17:41:49 +00:00
output [1:0] ht_num_ext,
2017-04-03 16:52:03 +00:00
output reg ht_sig_crc_ok,
2017-04-21 17:41:49 +00:00
// decoding pipeline
2017-04-03 16:52:03 +00:00
output [5:0] demod_out,
output demod_out_strobe,
output [1:0] deinterleave_out,
output deinterleave_out_strobe,
output conv_decoder_out,
output conv_decoder_out_stb,
output descramble_out,
output descramble_out_strobe
);
`include "common_params.v"
////////////////////////////////////////////////////////////////////////////////
// Shared rotation LUT for sync_long and equalizer
////////////////////////////////////////////////////////////////////////////////
wire [`ROTATE_LUT_LEN_SHIFT-1:0] sync_long_rot_addr;
wire [31:0] sync_long_rot_data;
wire [`ROTATE_LUT_LEN_SHIFT-1:0] eq_rot_addr;
wire [31:0] eq_rot_data;
rot_lut rot_lut_inst (
.clka(clock),
.addra(sync_long_rot_addr),
.douta(sync_long_rot_data),
.clkb(clock),
.addrb(eq_rot_addr),
.doutb(eq_rot_data)
);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Shared phase module for sync_short and equalizer
////////////////////////////////////////////////////////////////////////////////
wire [31:0] sync_short_phase_in_i;
wire [31:0] sync_short_phase_in_q;
wire sync_short_phase_in_stb;
wire [31:0] sync_short_phase_out;
wire sync_short_phase_out_stb;
wire [31:0] eq_phase_in_i;
wire [31:0] eq_phase_in_q;
wire eq_phase_in_stb;
wire [31:0] eq_phase_out;
wire eq_phase_out_stb;
wire[31:0] phase_in_i = state == S_SYNC_SHORT?
sync_short_phase_in_i: eq_phase_in_i;
wire[31:0] phase_in_q = state == S_SYNC_SHORT?
sync_short_phase_in_q: eq_phase_in_q;
wire phase_in_stb = state == S_SYNC_SHORT?
sync_short_phase_in_stb: eq_phase_in_stb;
wire [31:0] phase_out;
wire phase_out_stb;
assign sync_short_phase_out = phase_out;
assign sync_short_phase_out_stb = phase_out_stb;
assign eq_phase_out = phase_out;
assign eq_phase_out_stb = phase_out_stb;
phase phase_inst (
.clock(clock),
.reset(reset),
.enable(enable),
.in_i(phase_in_i),
.in_q(phase_in_q),
.input_strobe(phase_in_stb),
.phase(phase_out),
.output_strobe(phase_out_stb)
);
////////////////////////////////////////////////////////////////////////////////
2019-12-10 13:09:31 +00:00
(* mark_debug = "true" *) reg sync_short_reset;
(* mark_debug = "true" *) reg sync_long_reset;
(* mark_debug = "true" *) wire sync_short_enable = state == S_SYNC_SHORT;
(* mark_debug = "true" *) reg sync_long_enable;
2017-04-03 16:52:03 +00:00
reg equalizer_reset;
reg equalizer_enable;
reg ht_next;
wire eq_out_stb_delayed;
wire [15:0] eq_out_i = equalizer_out[31:16];
wire [15:0] eq_out_q = equalizer_out[15:0];
wire [15:0] eq_out_i_delayed;
wire [15:0] eq_out_q_delayed;
reg [15:0] abs_eq_i;
reg [15:0] abs_eq_q;
reg [3:0] rot_eq_count;
reg [3:0] normal_eq_count;
// OFDM control
reg ofdm_reset;
reg ofdm_enable;
reg ofdm_in_stb;
reg [15:0] ofdm_in_i;
reg [15:0] ofdm_in_q;
reg do_descramble;
reg [31:0] num_bits_to_decode;
reg short_gi;
reg [3:0] old_state;
assign state_changed = state != old_state;
// SIGNAL information
reg [23:0] signal_bits;
reg [31:0] byte_count;
2019-12-10 13:09:31 +00:00
assign sig_bits_spy = signal_bits;
assign byte_count_spy = byte_count ;
2017-04-03 16:52:03 +00:00
2017-04-21 17:41:49 +00:00
assign legacy_rate = signal_bits[3:0];
assign legacy_sig_rsvd = signal_bits[4];
assign legacy_len = signal_bits[16:5];
assign legacy_sig_parity = signal_bits[17];
assign legacy_sig_tail = signal_bits[23:18];
assign legacy_sig_parity_ok = ~^signal_bits[17:0];
2017-04-03 16:52:03 +00:00
// HT-SIG information
reg [23:0] ht_sig1;
reg [23:0] ht_sig2;
2017-04-21 17:41:49 +00:00
assign ht_mcs = ht_sig1[6:0];
assign ht_cbw = ht_sig1[7];
2017-04-03 16:52:03 +00:00
assign ht_len = ht_sig1[23:8];
2017-04-21 17:41:49 +00:00
assign ht_smoothing = ht_sig2[0];
assign ht_not_sounding = ht_sig2[1];
assign ht_aggregation = ht_sig2[3];
assign ht_stbc = ht_sig2[5:4];
assign ht_fec_coding = ht_sig2[6];
2017-04-03 16:52:03 +00:00
assign ht_sgi = ht_sig2[7];
2017-04-21 17:41:49 +00:00
assign ht_num_ext = ht_sig2[9:8];
2017-04-03 16:52:03 +00:00
wire ht_rsvd = ht_sig2[2];
wire [7:0] crc = ht_sig2[17:10];
wire [5:0] ht_sig_tail = ht_sig2[23:18];
reg crc_in_stb;
reg crc_in;
reg [7:0] crc_count;
reg crc_reset;
wire [7:0] crc_out;
reg [31:0] sample_count;
wire fcs_enable = state == S_DECODE_DATA && byte_out_strobe;
wire fcs_reset = state_changed && state == S_DECODE_DATA;
wire [7:0] byte_reversed;
wire [31:0] pkt_fcs;
assign byte_reversed[0] = byte_out[7];
assign byte_reversed[1] = byte_out[6];
assign byte_reversed[2] = byte_out[5];
assign byte_reversed[3] = byte_out[4];
assign byte_reversed[4] = byte_out[3];
assign byte_reversed[5] = byte_out[2];
assign byte_reversed[6] = byte_out[1];
assign byte_reversed[7] = byte_out[0];
reg [15:0] sync_long_out_count;
integer i;
power_trigger power_trigger_inst (
.clock(clock),
.enable(enable),
.reset(reset),
.sample_in(sample_in),
.sample_in_strobe(sample_in_strobe),
2019-12-10 13:09:31 +00:00
.power_thres(power_thres),
.window_size(window_size),
.num_sample_to_skip(num_sample_to_skip),
.num_sample_changed(num_sample_changed),
2017-04-03 16:52:03 +00:00
2019-12-10 13:09:31 +00:00
.pw_state_spy(pw_state_spy),
2017-04-03 16:52:03 +00:00
.trigger(power_trigger)
);
sync_short sync_short_inst (
.clock(clock),
.reset(reset | sync_short_reset),
.enable(enable & sync_short_enable),
2019-12-10 13:09:31 +00:00
.min_plateau(min_plateau),
2017-04-03 16:52:03 +00:00
.sample_in(sample_in),
.sample_in_strobe(sample_in_strobe),
.phase_in_i(sync_short_phase_in_i),
.phase_in_q(sync_short_phase_in_q),
.phase_in_stb(sync_short_phase_in_stb),
.phase_out(sync_short_phase_out),
.phase_out_stb(sync_short_phase_out_stb),
.short_preamble_detected(short_preamble_detected),
.phase_offset(phase_offset)
);
sync_long sync_long_inst (
.clock(clock),
.reset(reset | sync_long_reset),
.enable(enable & sync_long_enable),
.sample_in(sample_in),
.sample_in_strobe(sample_in_strobe),
.phase_offset(phase_offset),
.short_gi(short_gi),
.rot_addr(sync_long_rot_addr),
.rot_data(sync_long_rot_data),
.metric(sync_long_metric),
.metric_stb(sync_long_metric_stb),
.long_preamble_detected(long_preamble_detected),
.state(sync_long_state),
.sample_out(sync_long_out),
.sample_out_strobe(sync_long_out_strobe)
);
equalizer equalizer_inst (
.clock(clock),
.reset(reset | equalizer_reset),
.enable(enable & equalizer_enable),
.sample_in(sync_long_out),
.sample_in_strobe(sync_long_out_strobe),
.ht_next(ht_next),
.phase_in_i(eq_phase_in_i),
.phase_in_q(eq_phase_in_q),
.phase_in_stb(eq_phase_in_stb),
.phase_out(eq_phase_out),
.phase_out_stb(eq_phase_out_stb),
.rot_addr(eq_rot_addr),
.rot_data(eq_rot_data),
.sample_out(equalizer_out),
.sample_out_strobe(equalizer_out_strobe),
.state(equalizer_state)
);
delayT #(.DATA_WIDTH(33), .DELAY(6)) eq_delay_inst (
.clock(clock),
.reset(reset),
.data_in({equalizer_out_strobe, equalizer_out}),
.data_out({eq_out_stb_delayed, eq_out_i_delayed, eq_out_q_delayed})
);
ofdm_decoder ofdm_decoder_inst (
.clock(clock),
.reset(reset|ofdm_reset),
.enable(enable & ofdm_enable),
.sample_in({ofdm_in_i, ofdm_in_q}),
.sample_in_strobe(ofdm_in_stb),
.do_descramble(do_descramble),
.num_bits_to_decode(num_bits_to_decode),
2017-04-21 17:41:49 +00:00
.rate(pkt_rate),
2017-04-03 16:52:03 +00:00
.byte_out(byte_out),
.byte_out_strobe(byte_out_strobe),
.demod_out(demod_out),
.demod_out_strobe(demod_out_strobe),
.deinterleave_out(deinterleave_out),
.deinterleave_out_strobe(deinterleave_out_strobe),
.conv_decoder_out(conv_decoder_out),
.conv_decoder_out_stb(conv_decoder_out_stb),
.descramble_out(descramble_out),
.descramble_out_strobe(descramble_out_strobe)
);
ht_sig_crc crc_inst (
.clock(clock),
.enable(enable),
.reset(reset | crc_reset),
.bit(crc_in),
.input_strobe(crc_in_stb),
.crc(crc_out)
);
crc32 fcs_inst (
.clk(clock),
.crc_en(enable & fcs_enable),
.rst(reset | fcs_reset),
.data_in(byte_reversed),
.crc_out(pkt_fcs)
);
2019-12-10 13:09:31 +00:00
intf_64bit intf64bit_inst (
.clock(clock),
.reset(reset | sync_short_reset),
.enable(enable),
.pkt_len(pkt_len),
.byte_index(byte_count),
.byte_in(byte_out),
.byte_strobe(byte_out_strobe),
.data_out(data_out),
.output_strobe(data_out_valid)
);
2017-04-03 16:52:03 +00:00
always @(posedge clock) begin
if (reset) begin
status_code <= E_OK;
state <= S_WAIT_POWER_TRIGGER;
old_state <= 0;
sync_short_reset <= 0;
sync_long_reset <= 0;
sync_long_enable <= 0;
byte_count <= 0;
2017-04-21 17:41:49 +00:00
pkt_begin <= 0;
pkt_ht <= 0;
2017-04-03 16:52:03 +00:00
rot_eq_count <= 0;
normal_eq_count <= 0;
abs_eq_i <= 0;
abs_eq_q <= 0;
do_descramble <= 0;
num_bits_to_decode <= 0;
short_gi <= 0;
2017-04-21 17:41:49 +00:00
pkt_rate <= 0;
2017-04-03 16:52:03 +00:00
equalizer_reset <= 0;
equalizer_enable <= 0;
ht_next <= 0;
2017-04-21 17:41:49 +00:00
pkt_len <= 0;
2017-04-03 16:52:03 +00:00
ofdm_reset <= 0;
ofdm_enable <= 0;
ofdm_in_stb <= 0;
ofdm_in_i <= 0;
ofdm_in_q <= 0;
sample_count <= 0;
sync_long_out_count <= 0;
signal_bits <= 0;
2017-04-21 17:41:49 +00:00
legacy_sig_stb <= 0;
2017-04-03 16:52:03 +00:00
ht_sig1 <= 0;
ht_sig2 <= 0;
crc_in_stb <= 0;
crc_in <= 0;
crc_count <= 0;
crc_reset <= 0;
ht_sig_crc_ok <= 0;
2017-04-21 17:41:49 +00:00
ht_sig_stb <= 0;
2017-04-03 16:52:03 +00:00
fcs_out_strobe <= 0;
fcs_ok <= 0;
end else if (enable) begin
old_state <= state;
case(state)
S_WAIT_POWER_TRIGGER: begin
sync_long_enable <= 0;
equalizer_enable <= 0;
ofdm_enable <= 0;
if (power_trigger) begin
`ifdef DEBUG_PRINT
$display("Power triggered.");
`endif
sync_short_reset <= 1;
state <= S_SYNC_SHORT;
end
end
S_SYNC_SHORT: begin
if (sync_short_reset) begin
sync_short_reset <= 0;
end
if (~power_trigger) begin
// power level drops before finding STS
state <= S_WAIT_POWER_TRIGGER;
end
if (short_preamble_detected) begin
`ifdef DEBUG_PRINT
$display("Short preamble detected");
`endif
sync_long_reset <= 1;
sync_long_enable <= 1;
sample_count <= 0;
state <= S_SYNC_LONG;
end
end
S_SYNC_LONG: begin
if (sync_long_reset) begin
sync_long_reset <= 0;
end
if (sample_in_strobe) begin
sample_count <= sample_count + 1;
end
if (sample_count > 320) begin
state <= S_WAIT_POWER_TRIGGER;
end
if (~power_trigger) begin
state <= S_WAIT_POWER_TRIGGER;
end
if (long_preamble_detected) begin
2017-04-21 17:41:49 +00:00
pkt_rate <= {1'b0, 3'b0, 4'b1011};
2017-04-03 16:52:03 +00:00
do_descramble <= 0;
num_bits_to_decode <= 48;
ofdm_reset <= 1;
ofdm_enable <= 1;
equalizer_enable <= 1;
equalizer_reset <= 1;
byte_count <= 0;
state <= S_DECODE_SIGNAL;
end
end
S_DECODE_SIGNAL: begin
if (ofdm_reset) begin
ofdm_reset <= 0;
end
if (equalizer_reset) begin
equalizer_reset <= 0;
end
ofdm_in_stb <= equalizer_out_strobe;
ofdm_in_i <= eq_out_i;
ofdm_in_q <= eq_out_q;
if (byte_out_strobe) begin
signal_bits <= {byte_out, signal_bits[23:8]};
byte_count <= byte_count + 1;
end
if (byte_count == 3) begin
byte_count <= 0;
`ifdef DEBUG_PRINT
2017-04-21 17:41:49 +00:00
$display("[SIGNAL] rate = %04b, ", legacy_rate,
"length = %012b (%d), ", legacy_len, legacy_len,
"parity = %b, ", legacy_sig_parity,
"tail = %6b", legacy_sig_tail);
2017-04-03 16:52:03 +00:00
`endif
ofdm_reset <= 1;
state <= S_CHECK_SIGNAL;
end
end
S_CHECK_SIGNAL: begin
if (ofdm_reset) begin
ofdm_reset <= 0;
end
2017-04-21 17:41:49 +00:00
if (~legacy_sig_parity_ok) begin
2017-04-03 16:52:03 +00:00
status_code <= E_PARITY_FAIL;
state <= S_SIGNAL_ERROR;
2017-04-21 17:41:49 +00:00
end else if (legacy_sig_rsvd) begin
2017-04-03 16:52:03 +00:00
status_code <= E_WRONG_RSVD;
state <= S_SIGNAL_ERROR;
2017-04-21 17:41:49 +00:00
end else if (|legacy_sig_tail) begin
2017-04-03 16:52:03 +00:00
status_code <= E_WRONG_TAIL;
state <= S_SIGNAL_ERROR;
end else begin
2017-04-21 17:41:49 +00:00
legacy_sig_stb <= 1;
2017-04-03 16:52:03 +00:00
status_code <= E_OK;
2017-04-21 17:41:49 +00:00
if (legacy_rate == 4'b1011) begin
2017-04-03 16:52:03 +00:00
abs_eq_i <= 0;
abs_eq_q <= 0;
rot_eq_count <= 0;
normal_eq_count <= 0;
state <= S_DETECT_HT;
end else begin
2017-04-21 17:41:49 +00:00
pkt_rate <= {1'b0, 3'b0, legacy_rate};
num_bits_to_decode <= (legacy_len+3)<<4;
2017-04-03 16:52:03 +00:00
do_descramble <= 1;
ofdm_reset <= 1;
byte_count <= 0;
2017-04-21 17:41:49 +00:00
pkt_len <= legacy_len;
2017-04-03 16:52:03 +00:00
byte_count <= 0;
2017-04-21 17:41:49 +00:00
pkt_begin <= 1;
pkt_ht <= 0;
2017-04-03 16:52:03 +00:00
state <= S_DECODE_DATA;
end
end
end
S_SIGNAL_ERROR: begin
state <= S_WAIT_POWER_TRIGGER;
end
S_DETECT_HT: begin
2017-04-21 17:41:49 +00:00
legacy_sig_stb <= 0;
2017-04-03 16:52:03 +00:00
if (equalizer_out_strobe) begin
abs_eq_i <= eq_out_i[15]? ~eq_out_i+1: eq_out_i;
abs_eq_q <= eq_out_q[15]? ~eq_out_q+1: eq_out_q;
if (abs_eq_q > abs_eq_i) begin
rot_eq_count <= rot_eq_count + 1;
end else begin
normal_eq_count <= normal_eq_count + 1;
end
end
if (rot_eq_count >= 4) begin
// HT-SIG detected
byte_count <= 0;
2017-04-21 17:41:49 +00:00
pkt_rate <= {1'b0, 3'b0, 4'b1011};
2017-04-03 16:52:03 +00:00
num_bits_to_decode <= 96;
do_descramble <= 0;
ofdm_reset <= 1;
state <= S_HT_SIGNAL;
end else if (normal_eq_count > 4) begin
2017-04-21 17:41:49 +00:00
pkt_len <= legacy_len;
num_bits_to_decode <= (legacy_len+3)<<4;
2017-04-03 16:52:03 +00:00
do_descramble <= 1;
ofdm_reset <= 1;
byte_count <= 0;
2017-04-21 17:41:49 +00:00
pkt_begin <= 1;
pkt_ht <= 0;
2017-04-03 16:52:03 +00:00
state <= S_DECODE_DATA;
end
end
S_HT_SIGNAL: begin
if (ofdm_reset) begin
ofdm_reset <= 0;
end
ofdm_in_stb <= eq_out_stb_delayed;
// rotate clockwise by 90 degree
ofdm_in_i <= eq_out_q_delayed;
ofdm_in_q <= ~eq_out_i_delayed+1;
if (byte_out_strobe) begin
if (byte_count < 3) begin
ht_sig1 <= {byte_out, ht_sig1[23:8]};
end else begin
ht_sig2 <= {byte_out, ht_sig2[23:8]};
end
byte_count <= byte_count + 1;
end
if (byte_count == 6) begin
byte_count <= 0;
`ifdef DEBUG_PRINT
2017-04-21 17:41:49 +00:00
$display("[HT SIGNAL] mcs = %07b (%d), ", ht_mcs, ht_mcs,
"CBW: %d, ", ht_cbw? 40: 20,
2017-04-03 16:52:03 +00:00
"length = %012b (%d), ", ht_len, ht_len,
"rsvd = %d, ", ht_rsvd,
2017-04-21 17:41:49 +00:00
"aggr = %d, ", ht_aggregation,
"stbd = %02b, ", ht_stbc,
"fec = %d, ", ht_fec_coding,
2017-04-03 16:52:03 +00:00
"sgi = %d, ", ht_sgi,
2017-04-21 17:41:49 +00:00
"num_ext = %d, ", ht_num_ext,
2017-04-03 16:52:03 +00:00
"crc = %08b, ", crc,
"tail = %06b", ht_sig_tail);
`endif
crc_count <= 0;
crc_reset <= 1;
crc_in_stb <= 0;
ht_sig_crc_ok <= 0;
state <= S_CHECK_HT_SIG_CRC;
end
end
S_CHECK_HT_SIG_CRC: begin
crc_reset <= 0;
crc_count <= crc_count + 1;
if (crc_count < 24) begin
crc_in_stb <= 1;
crc_in <= ht_sig1[crc_count];
end else if (crc_count < 34) begin
crc_in_stb <= 1;
crc_in <= ht_sig2[crc_count-24];
end else if (crc_count == 34) begin
crc_in_stb <= 0;
end else if (crc_count == 35) begin
if (crc_out ^ crc) begin
status_code <= E_WRONG_CRC;
2017-04-21 17:41:49 +00:00
ht_sig_stb <= 1;
2017-04-03 16:52:03 +00:00
state <= S_HT_SIG_ERROR;
end else begin
`ifdef DEBUG_PRINT
$display("[HT SIGNAL] CRC OK");
`endif
ht_sig_crc_ok <= 1;
2017-04-21 17:41:49 +00:00
ht_sig_stb <= 1;
2017-04-03 16:52:03 +00:00
ofdm_reset <= 1;
state <= S_CHECK_HT_SIG;
end
end
end
S_CHECK_HT_SIG: begin
ofdm_reset <= 0;
2017-04-21 17:41:49 +00:00
ht_sig_stb <= 0;
if (ht_mcs > 7) begin
2017-04-03 16:52:03 +00:00
status_code <= E_UNSUPPORTED_MCS;
state <= S_HT_SIG_ERROR;
2017-04-21 17:41:49 +00:00
end else if (ht_cbw) begin
2017-04-03 16:52:03 +00:00
status_code <= E_UNSUPPORTED_CBW;
state <= S_HT_SIG_ERROR;
end else if (ht_rsvd == 0) begin
status_code <= E_HT_WRONG_RSVD;
state <= S_HT_SIG_ERROR;
2017-04-21 17:41:49 +00:00
end else if (ht_stbc != 0) begin
2017-04-03 16:52:03 +00:00
status_code <= E_UNSUPPORTED_STBC;
state <= S_HT_SIG_ERROR;
2017-04-21 17:41:49 +00:00
end else if (ht_fec_coding) begin
2017-04-03 16:52:03 +00:00
status_code <= E_UNSUPPORTED_FEC;
state <= S_HT_SIG_ERROR;
end else if (short_gi) begin
status_code <= E_UNSUPPORTED_SGI;
state <= S_HT_SIG_ERROR;
2017-04-21 17:41:49 +00:00
end else if (ht_num_ext != 0) begin
2017-04-03 16:52:03 +00:00
status_code <= E_UNSUPPORTED_SPATIAL;
state <= S_HT_SIG_ERROR;
end else if (ht_sig_tail != 0) begin
status_code <= E_HT_WRONG_TAIL;
state <= S_HT_SIG_ERROR;
end else begin
sync_long_out_count <= 0;
state <= S_HT_STS;
end
end
S_HT_SIG_ERROR: begin
2017-04-21 17:41:49 +00:00
ht_sig_stb <= 0;
2017-04-03 16:52:03 +00:00
state <= S_WAIT_POWER_TRIGGER;
end
S_HT_STS: begin
if (sync_long_out_strobe) begin
sync_long_out_count <= sync_long_out_count + 1;
end
if (sync_long_out_count == 64) begin
sync_long_out_count <= 0;
ht_next <= 1;
state <= S_HT_LTS;
end
end
S_HT_LTS: begin
short_gi <= ht_sgi;
if (sync_long_out_strobe) begin
sync_long_out_count <= sync_long_out_count + 1;
end
if (sync_long_out_count == 64) begin
ht_next <= 0;
num_bits_to_decode <= (ht_len+3)<<4;
2017-04-21 17:41:49 +00:00
pkt_rate <= {1'b1, ht_mcs};
2017-04-03 16:52:03 +00:00
do_descramble <= 1;
ofdm_reset <= 1;
byte_count <= 0;
2017-04-21 17:41:49 +00:00
pkt_len <= ht_len;
pkt_begin <= 1;
pkt_ht <= 1;
2017-04-03 16:52:03 +00:00
state <= S_DECODE_DATA;
end
end
S_DECODE_DATA: begin
2017-04-21 17:41:49 +00:00
pkt_begin <= 0;
legacy_sig_stb <= 0;
2017-04-03 16:52:03 +00:00
if (ofdm_reset) begin
ofdm_reset <= 0;
end
ofdm_in_stb <= eq_out_stb_delayed;
ofdm_in_i <= eq_out_i_delayed;
ofdm_in_q <= eq_out_q_delayed;
if (byte_out_strobe) begin
`ifdef DEBUG_PRINT
2017-04-21 17:41:49 +00:00
$display("[BYTE] [%4d / %-4d] %02x", byte_count+1, pkt_len,
2017-04-03 16:52:03 +00:00
byte_out);
`endif
byte_count <= byte_count + 1;
end
2017-04-21 17:41:49 +00:00
if (byte_count >= pkt_len) begin
2017-04-03 16:52:03 +00:00
fcs_out_strobe <= 1;
if (pkt_fcs == EXPECTED_FCS) begin
fcs_ok <= 1;
status_code <= E_OK;
end else begin
fcs_ok <= 0;
status_code <= E_WRONG_FCS;
end
state <= S_DECODE_DONE;
end
end
S_DECODE_DONE: begin
`ifdef DEBUG_PRINT
$display("===== PACKET DECODE DONE =====");
if (status_code == E_OK) begin
$display("FCS CORRECT");
end else begin
$display("FCS WRONG");
end
`endif
fcs_out_strobe <= 0;
2019-12-10 13:09:31 +00:00
fcs_ok <= 0 ;
2017-04-03 16:52:03 +00:00
state <= S_WAIT_POWER_TRIGGER;
end
default: begin
state <= S_WAIT_POWER_TRIGGER;
end
endcase
end
end
endmodule