openofdm/verilog/phase.v

136 lines
3.4 KiB
Verilog

`include "common_defs.v"
module phase
#(
parameter DATA_WIDTH = 32
)
(
input clock,
input reset,
input enable,
input signed [DATA_WIDTH-1:0] in_i,
input signed [DATA_WIDTH-1:0] in_q,
input input_strobe,
// [-pi, pi) scaled up by 512
output reg signed [15:0] phase,
output output_strobe
);
`include "common_params.v"
reg [DATA_WIDTH-1:0] in_i_delay;
reg [DATA_WIDTH-1:0] in_q_delay;
reg [DATA_WIDTH-1:0] abs_i;
reg [DATA_WIDTH-1:0] abs_q;
reg [DATA_WIDTH-1:0] max;
reg [DATA_WIDTH-1:0] min;
wire [DATA_WIDTH-1:0] dividend;
wire [DATA_WIDTH-`ATAN_LUT_LEN_SHIFT-1:0] divisor;
assign dividend = (max > 8388608) ? min : {min[DATA_WIDTH-`ATAN_LUT_LEN_SHIFT-1:0], {`ATAN_LUT_LEN_SHIFT{1'b0}}};
assign divisor = (max > 8388608) ? max[DATA_WIDTH-1:`ATAN_LUT_LEN_SHIFT] : max[DATA_WIDTH-`ATAN_LUT_LEN_SHIFT-1:0];
wire div_in_stb;
wire [31:0] quotient;
wire div_out_stb;
wire [`ATAN_LUT_LEN_SHIFT-1:0] atan_addr;
wire [`ATAN_LUT_SCALE_SHIFT-1:0] atan_data;
assign atan_addr = (quotient>255?255:quotient[`ATAN_LUT_LEN_SHIFT-1:0]);
wire signed [`ATAN_LUT_SCALE_SHIFT:0] _phase = {1'b0, atan_data};
reg [2:0] quadrant;
wire [2:0] quadrant_delayed;
// 1 cycle for abs
// 1 cycle for quadrant
delayT #(.DATA_WIDTH(1), .DELAY(2)) div_in_inst (
.clock(clock),
.reset(reset),
.data_in(input_strobe),
.data_out(div_in_stb)
);
// 1 cycle for atan_lut
// 1 cycle for quadrant_delayed
delayT #(.DATA_WIDTH(1), .DELAY(2)) output_inst (
.clock(clock),
.reset(reset),
.data_in(div_out_stb),
.data_out(output_strobe)
);
divider div_inst (
.clock(clock),
.enable(enable),
.reset(reset),
.dividend(dividend),
.divisor({{(`ATAN_LUT_LEN_SHIFT-8){1'b0}}, divisor}),
.input_strobe(div_in_stb),
.quotient(quotient),
.output_strobe(div_out_stb)
);
delayT #(.DATA_WIDTH(3), .DELAY(36)) quadrant_inst (
.clock(clock),
.reset(reset),
.data_in(quadrant),
.data_out(quadrant_delayed)
);
atan_lut lut_inst (
.clka(clock),
.addra(atan_addr),
.douta(atan_data)
);
always @(posedge clock) begin
if (reset) begin
max <= 0;
min <= 0;
abs_i <= 0;
abs_q <= 0;
in_i_delay <= 0;
in_q_delay <= 0;
end else if (enable) begin
// 1st cycle
abs_i <= in_i[DATA_WIDTH-1]? ~in_i+1: in_i;
abs_q <= in_q[DATA_WIDTH-1]? ~in_q+1: in_q;
in_i_delay <= in_i;
in_q_delay <= in_q;
// 2nd cycle
if (abs_i >= abs_q) begin
quadrant <= {in_i_delay[DATA_WIDTH-1], in_q_delay[DATA_WIDTH-1], 1'b0};
max <= abs_i;
min <= abs_q;
end else begin
quadrant <= {in_i_delay[DATA_WIDTH-1], in_q_delay[DATA_WIDTH-1], 1'b1};
max <= abs_q;
min <= abs_i;
end
case(quadrant_delayed)
3'b000: phase <= _phase; // [0, PI/4]
3'b001: phase <= PI_2 - _phase; // [PI/4, PI/2]
3'b010: phase <= -_phase; // [-PI/4, 0]
3'b011: phase <= _phase - PI_2; // [-PI/2, -Pi/4]
3'b100: phase <= PI - _phase; // [3/4PI, PI]
3'b101: phase <= PI_2 + _phase; // [PI/2, 3/4PI]
3'b110: phase <= _phase - PI; // [-3/4PI, -PI]
3'b111: phase <= -PI_2 - _phase; // [-PI/2, -3/4PI]
endcase
end
end
endmodule