openofdm/verilog/deinterleave.v
2017-04-03 12:52:03 -04:00

160 lines
3.6 KiB
Verilog

/*
* OFDM deinterleaver
*/
module deinterleave
(
input clock,
input reset,
input enable,
input [7:0] rate,
input [5:0] in_bits,
input input_strobe,
output [1: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 [10: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;
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(6), .AWIDTH(6)) ram_inst (
.clka(clock),
.ena(1),
.wea(input_strobe),
.addra(addra),
.dia(in_bits),
.doa(bit_outa),
.clkb(clock),
.enb(1),
.web(0),
.addrb(addrb),
.dib(32'hFFFF),
.dob(bit_outb)
);
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 <= {6'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