Files
MM7020/hdl/MagnitudeEstimator.v

127 lines
3.5 KiB
Verilog

`timescale 1ns / 1ns
module MagnitudeEstimator #(
parameter VEC_WIDTH = 21
) (
input clk,
input rst,
input vec_valid,
input [VEC_WIDTH-1:0] I,
input [VEC_WIDTH-1:0] Q,
(* max_fanout=128 *) output reg [ VEC_WIDTH:0] mag, // width is larger than I & Q
(* max_fanout=128 *) output reg mag_valid
);
// input complex vector, calc the magnitude
// first calc the abs
// compare the I and Q
// calc the Mag
// Mag ~=Alpha * max(|I|, |Q|) + Beta * min(|I|, |Q|)
// * 61/64, 3/8
// * mag = max - max/64 - max/32 + min/8 + min/4
// ******** Wire & Reg ********
reg [VEC_WIDTH-1:0] abs_i;
reg [VEC_WIDTH-1:0] abs_q;
reg [VEC_WIDTH-1:0] max;
reg [VEC_WIDTH-1:0] min;
reg [VEC_WIDTH-1:0] max_component1;
reg [VEC_WIDTH-1:0] max_component2;
reg [VEC_WIDTH-1:0] max_component3;
reg [VEC_WIDTH-1:0] min_component1;
reg [VEC_WIDTH-1:0] min_component2;
reg [VEC_WIDTH-1:0] min_component3;
reg [VEC_WIDTH-1:0] max_res;
reg [VEC_WIDTH-1:0] min_res;
reg vec_valid_d1;
reg vec_valid_d2;
// ******** Assingment ********
// ******** Logic Block ********
always @(posedge clk) begin
if (rst) begin
abs_i <= 'd0;
abs_q <= 'd0;
end
else begin
if (vec_valid) begin
abs_i <= (I[VEC_WIDTH-1] == 1'b1) ? -I : I;
abs_q <= (Q[VEC_WIDTH-1] == 1'b1) ? -Q : Q;
end
end
end
always @(posedge clk) begin
if (rst) begin
max <= 'd0;
min <= 'd0;
max_component1 <= 'd0;
max_component2 <= 'd0;
max_component3 <= 'd0;
min_component1 <= 'd0;
min_component2 <= 'd0;
min_component3 <= 'd0;
max_res <= 'd0;
min_res <= 'd0;
end
else begin
if (abs_i < abs_q) begin
max <= abs_q;
min <= abs_i;
end
else begin
max <= abs_i;
min <= abs_q;
end
// TODO: 修改为无符号数
max_component1 <= max;
max_component2 <= {6'd0, max[VEC_WIDTH-1:6]};
max_component3 <= {5'd0, max[VEC_WIDTH-1:5]};
min_component1 <= {3'd0, min[VEC_WIDTH-1:3]};
min_component2 <= {2'd0, min[VEC_WIDTH-1:2]};
// min_component3 <= ;
max_res <= max_component1 - max_component2 - max_component3;
min_res <= min_component1 + min_component2;
end
end
// * mag = max - max/64 - max/32 + min/8 + min/4
always @(posedge clk) begin
if (rst) begin
mag <= 'd0;
end
else begin
mag <= max_res + min_res;
end
end
always @(posedge clk) begin
if (rst) begin
vec_valid_d1 <= 1'd0;
vec_valid_d2 <= 1'd0;
mag_valid <= 1'd0;
end
else begin
vec_valid_d1 <= vec_valid;
vec_valid_d2 <= vec_valid_d1;
mag_valid <= vec_valid_d2;
end
end
// ******** Inst ********
// ******** Debug ********
endmodule