`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