mirror of
https://github.com/jhshi/openofdm.git
synced 2024-12-24 15:57:10 +00:00
239 lines
6.7 KiB
Verilog
239 lines
6.7 KiB
Verilog
/*
|
|
* OFDM deinterleaver
|
|
*/
|
|
module deinterleave
|
|
(
|
|
input clock,
|
|
input reset,
|
|
input enable,
|
|
|
|
input [7:0] rate,
|
|
input [5:0] in_bits,
|
|
input [5:0] soft_in_bits,
|
|
input [3:0] soft_in_bits_pos,
|
|
input input_strobe,
|
|
input soft_decoding,
|
|
|
|
output reg [5:0] out_bits,
|
|
output [1:0] erase,
|
|
output output_strobe
|
|
);
|
|
|
|
wire ht = rate[7];
|
|
|
|
wire [5:0] num_data_carrier = ht? 52: 48;
|
|
wire [5:0] half_data_carrier = ht? 26: 24;
|
|
|
|
reg [5:0] addra;
|
|
reg [5:0] addrb;
|
|
|
|
reg [11:0] lut_key;
|
|
wire [21:0] lut_out;
|
|
wire [21:0] lut_out_delayed;
|
|
|
|
reg lut_valid;
|
|
wire lut_valid_delayed;
|
|
|
|
assign erase[0] = lut_out_delayed[21];
|
|
assign erase[1] = lut_out_delayed[20];
|
|
|
|
wire [2:0] lut_bita = lut_out_delayed[7:5];
|
|
wire [2:0] lut_bitb = lut_out_delayed[4:2];
|
|
|
|
wire [5:0] bit_outa;
|
|
wire [5:0] bit_outb;
|
|
wire [5:0] soft_bit_outa;
|
|
wire [5:0] soft_bit_outb;
|
|
wire [3:0] soft_bit_outa_pos;
|
|
wire [3:0] soft_bit_outb_pos;
|
|
|
|
// Soft and hard decoding
|
|
wire [4:0] MOD_TYPE = {rate[7], rate[3:0]};
|
|
wire BPSK = MOD_TYPE == 5'b01011 || MOD_TYPE == 5'b01111 || MOD_TYPE == 5'b10000;
|
|
wire QPSK = MOD_TYPE == 5'b01010 || MOD_TYPE == 5'b01110 || MOD_TYPE == 5'b10001 || MOD_TYPE == 5'b10010;
|
|
wire QAM_16 = MOD_TYPE == 5'b01001 || MOD_TYPE == 5'b01101 || MOD_TYPE == 5'b10011 || MOD_TYPE == 5'b10100;
|
|
wire QAM_64 = MOD_TYPE == 5'b01000 || MOD_TYPE == 5'b01100 || MOD_TYPE == 5'b10101 || MOD_TYPE == 5'b10110 || MOD_TYPE == 5'b10111;
|
|
|
|
wire [2:0] N_BPSC_DIV_2 = BPSK ? 3'b000 : (QPSK ? 3'b001 : (QAM_16 ? 3'b010: (QAM_64 ? 3'b011 : 3'b111)));
|
|
|
|
always @* begin
|
|
if(lut_valid_delayed == 1'b1) begin
|
|
|
|
// Soft decoding
|
|
if(soft_decoding && (BPSK || QPSK || QAM_16 || QAM_64)) begin
|
|
if(BPSK || lut_bita < N_BPSC_DIV_2) begin
|
|
if(lut_bita[1:0] == soft_bit_outa_pos[1:0]) begin
|
|
out_bits[2:0] = soft_bit_outa[2:0];
|
|
end else begin
|
|
if(bit_outa[lut_bita] == 1'b1)
|
|
out_bits[2:0] = 3'b111;
|
|
else
|
|
out_bits[2:0] = 3'b011;
|
|
end
|
|
end else begin
|
|
if(lut_bita == ({1'b0,soft_bit_outa_pos[3:2]} + N_BPSC_DIV_2)) begin
|
|
out_bits[2:0] = soft_bit_outa[5:3];
|
|
end else begin
|
|
if(bit_outa[lut_bita] == 1'b1)
|
|
out_bits[2:0] = 3'b111;
|
|
else
|
|
out_bits[2:0] = 3'b011;
|
|
end
|
|
end
|
|
|
|
if(BPSK || lut_bitb < N_BPSC_DIV_2) begin
|
|
if(lut_bitb[1:0] == soft_bit_outb_pos[1:0]) begin
|
|
out_bits[5:3] = soft_bit_outb[2:0];
|
|
end else begin
|
|
if(bit_outb[lut_bitb] == 1'b1)
|
|
out_bits[5:3] = 3'b111;
|
|
else
|
|
out_bits[5:3] = 3'b011;
|
|
end
|
|
end else begin
|
|
if(lut_bitb == ({1'b0,soft_bit_outb_pos[3:2]} + N_BPSC_DIV_2)) begin
|
|
out_bits[5:3] = soft_bit_outb[5:3];
|
|
end else begin
|
|
if(bit_outb[lut_bitb] == 1'b1)
|
|
out_bits[5:3] = 3'b111;
|
|
else
|
|
out_bits[5:3] = 3'b011;
|
|
end
|
|
end
|
|
|
|
// Hard decoding
|
|
end else begin
|
|
if(bit_outa[lut_bita] == 1'b1)
|
|
out_bits[2:0] = 3'b111;
|
|
else
|
|
out_bits[2:0] = 3'b011;
|
|
|
|
if(bit_outb[lut_bitb] == 1'b1)
|
|
out_bits[5:3] = 3'b111;
|
|
else
|
|
out_bits[5:3] = 3'b011;
|
|
end
|
|
end else begin
|
|
out_bits[2:0] = 0;
|
|
out_bits[5:3] = 0;
|
|
end
|
|
end
|
|
|
|
//assign out_bits[0] = lut_valid_delayed? bit_outa[lut_bita]: 0;
|
|
//assign out_bits[1] = lut_valid_delayed? bit_outb[lut_bitb]: 0;
|
|
assign output_strobe = enable & lut_valid_delayed & lut_out_delayed[1];
|
|
|
|
wire [5:0] lut_addra = lut_out[19:14];
|
|
wire [5:0] lut_addrb = lut_out[13:8];
|
|
wire lut_done = lut_out[0];
|
|
|
|
reg ram_delay;
|
|
reg ht_delayed;
|
|
|
|
ram_2port #(.DWIDTH(16), .AWIDTH(6)) ram_inst (
|
|
.clka(clock),
|
|
.ena(1),
|
|
.wea(input_strobe),
|
|
.addra(addra),
|
|
.dia({in_bits, soft_in_bits, soft_in_bits_pos}),
|
|
.doa({bit_outa,soft_bit_outa,soft_bit_outa_pos}),
|
|
.clkb(clock),
|
|
.enb(1),
|
|
.web(0),
|
|
.addrb(addrb),
|
|
.dib(32'hFFFF),
|
|
.dob({bit_outb,soft_bit_outb,soft_bit_outb_pos})
|
|
);
|
|
|
|
deinter_lut lut_inst (
|
|
.clka(clock),
|
|
.addra(lut_key),
|
|
.douta(lut_out)
|
|
);
|
|
|
|
delayT #(.DATA_WIDTH(23), .DELAY(2)) delay_inst (
|
|
.clock(clock),
|
|
.reset(reset),
|
|
|
|
.data_in({lut_valid, lut_out}),
|
|
.data_out({lut_valid_delayed, lut_out_delayed})
|
|
);
|
|
|
|
|
|
localparam S_INPUT = 0;
|
|
localparam S_GET_BASE = 1;
|
|
localparam S_OUTPUT = 2;
|
|
|
|
reg [1:0] state;
|
|
|
|
always @(posedge clock) begin
|
|
if (reset) begin
|
|
addra <= num_data_carrier>>1;
|
|
addrb <= 0;
|
|
|
|
lut_key <= 0;
|
|
lut_valid <= 0;
|
|
ht_delayed <= 0;
|
|
|
|
ram_delay <= 0;
|
|
state <= S_INPUT;
|
|
end else if (enable) begin
|
|
ht_delayed <= ht;
|
|
if (ht != ht_delayed) begin
|
|
addra <= num_data_carrier>>1;
|
|
end
|
|
|
|
case(state)
|
|
S_INPUT: begin
|
|
if (input_strobe) begin
|
|
if (addra == half_data_carrier-1) begin
|
|
lut_key <= {7'b0, ht, rate[3:0]};
|
|
ram_delay <= 0;
|
|
lut_valid <= 0;
|
|
state <= S_GET_BASE;
|
|
end else begin
|
|
if (addra == num_data_carrier-1) begin
|
|
addra <= 0;
|
|
end else begin
|
|
addra <= addra + 1;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
S_GET_BASE: begin
|
|
if (ram_delay) begin
|
|
lut_key <= lut_out;
|
|
ram_delay <= 0;
|
|
state <= S_OUTPUT;
|
|
end else begin
|
|
ram_delay <= 1;
|
|
end
|
|
end
|
|
|
|
S_OUTPUT: begin
|
|
if (ram_delay) begin
|
|
addra <= lut_addra;
|
|
addrb <= lut_addrb;
|
|
if (lut_done) begin
|
|
lut_key <= 0;
|
|
lut_valid <= 0;
|
|
state <= S_INPUT;
|
|
end else begin
|
|
lut_valid <= 1;
|
|
lut_key <= lut_key + 1;
|
|
end
|
|
end else begin
|
|
ram_delay <= 1;
|
|
lut_valid <= 1;
|
|
lut_key <= lut_key + 1;
|
|
end
|
|
end
|
|
default: begin
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
endmodule
|