openofdm/verilog/deinterleave.v
2020-06-12 10:24:59 +02:00

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