Files
MM7020/hdl/power_measure.v
2024-08-02 20:51:37 +08:00

313 lines
10 KiB
Verilog

// * Engineer:
// * *************************************************** *
// * ███████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗ *
// * ╚══███╔╝██╔═══██╗██╔══██╗██╔═══██╗██╔════╝ ██║ ██║ *
// * ███╔╝ ██║ ██║██████╔╝██║ ██║██║ ███╗███████║ *
// * ███╔╝ ██║ ██║██╔══██╗██║ ██║██║ ██║██╔══██║ *
// * ███████╗╚██████╔╝██║ ██║╚██████╔╝╚██████╔╝██║ ██║ *
// * ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ *
// * *************************************************** *
// * Update Date: 2024/7/16
// * NOTE : this file use the sign bit number to estimate the
// * NOTE : signal power, the drawback of this module is that
// * NOTE : little amplitude over the threhold will be treated
// * NOTE : as overflow, thus indicating a flag_too_high pulse
// * NOTE :
// * NOTE : as improvemnt, we can use a number as the threshold
// * NOTE : such as 1800 ( under the 12bit input ).
// * NOTE :
module power_measure (
input clk,
input rst,
input start,
// data input
input wire [11:0] data_i,
input wire [11:0] data_q,
output reg flag_too_high,
output reg flag_too_low,
output reg power_measure_done_pulse
);
localparam CNT_WAIT_9361_MAX = 80; //* 等待周期数
localparam CNT_MEASURING_MAX = 256; // * 观察64个周期
localparam CNT_ADJUST_TIMES_MAX = 25;
localparam CNT_AMP_TOO_HIGH_THRESHOLD = 6;
// ******** Wire & Reg ********
// * NOTE: during measuring, the sign bit numbers changes .
// * NOTE: as the signal amplitude(power) changes.
// * NOTE: thus, measuring the sign bit numbers can indicate
// * NOTE: the power of the signal.
// * NOTE:
// * NOTE: the sign bit number min, represents the minimum of
// * NOTE: the sign bit number, meaning the highest signal power.
// * NOTE: if sign_bit_num_min_* is too small (1 or 2), we should
// * NOTE: decrease the input signal power.
// * NOTE:
// * NOTE: reversely, the sign_bit_num_max_* means the maximum of
// * NOTE: the amplitude, if signal power is too small, it will be
// * NOTE: small, indicating increasing the input signal power.
// * NOTE:
// * NOTE: for a modulated signal, the power can not be indicated by
// * NOTE: max sign bit number, so we should only control the min sign
// * NOTE: bit numer.
reg [ 3:0] sign_bit_num_i;
reg [ 3:0] sign_bit_num_min_i;
reg [ 3:0] sign_bit_num_q;
reg [ 3:0] sign_bit_num_min_q;
// startup
reg [ 7:0] cnt_startup; // set rx gain to max each time start posedge comes
reg [ 3:0] cnt_amp_too_high; // for short cuirt
// abs
reg [11:0] data_i_abs;
reg [11:0] data_q_abs;
// measuring the signal power
reg [15:0] cnt_measuring;
// for waiting ad9361 adjust done
reg [15:0] cnt_wait_9361;
// the times fsm have adjust already
reg [ 7:0] cnt_adjust_times;
// fsm var
localparam S_MEASURE_IDLE = 0;
localparam S_MEASURE_ING = 1;
localparam S_MEASURE_DONE = 2;
localparam S_MEASURE_ADJ = 3;
localparam S_MEASURE_STARTUP = 4;
reg [2:0] cs = S_MEASURE_IDLE;
reg [2:0] ns = S_MEASURE_IDLE;
// ******** Assingment ********
// ******** Logic Block ********
always @(posedge clk) begin
if (rst || start) begin
cnt_startup <= 0;
end
else if (cs == S_MEASURE_STARTUP && cnt_startup < 255) begin
cnt_startup <= cnt_startup + 1;
end
end
always @(posedge clk) begin
if (rst) begin
cs <= S_MEASURE_IDLE;
end
else begin
cs <= ns;
end
end
// fsm
always @(*) begin
case (cs)
S_MEASURE_IDLE: begin
if (start) begin
ns = S_MEASURE_STARTUP;
end
else begin
ns = S_MEASURE_IDLE;
end
end
S_MEASURE_STARTUP: begin
if (cnt_startup == 255) begin
ns = S_MEASURE_ING;
end
else begin
ns = S_MEASURE_STARTUP;
end
end
S_MEASURE_ING: begin
if (cnt_measuring == CNT_MEASURING_MAX - 1 || cnt_amp_too_high == CNT_AMP_TOO_HIGH_THRESHOLD - 1) begin
ns = S_MEASURE_DONE;
end
else begin
ns = S_MEASURE_ING;
end
end
S_MEASURE_DONE: begin
ns = S_MEASURE_ADJ;
end
S_MEASURE_ADJ: begin
// mgc adjust done
if (cnt_adjust_times == CNT_ADJUST_TIMES_MAX - 1) begin
ns = S_MEASURE_IDLE;
end
// wait ad9361 feedback
else if (cnt_wait_9361 == CNT_WAIT_9361_MAX - 1) begin
ns = S_MEASURE_ING;
end
else begin
ns = S_MEASURE_ADJ;
end
end
default: begin
ns = S_MEASURE_IDLE;
end
endcase
end
always @(posedge clk) begin
if (cs == S_MEASURE_ING) begin
cnt_measuring <= cnt_measuring + 1;
end
else begin
cnt_measuring <= 0;
end
end
always @(posedge clk) begin
if (cs == S_MEASURE_ADJ) begin
cnt_wait_9361 <= cnt_wait_9361 + 1;
end
else begin
cnt_wait_9361 <= 0;
end
end
always @(posedge clk) begin
if (cs == S_MEASURE_DONE) begin
cnt_adjust_times <= cnt_adjust_times + 1;
end
else if (cs == S_MEASURE_IDLE) begin
cnt_adjust_times <= 0;
end
end
always @(posedge clk) begin
if (cs == S_MEASURE_ING && (sign_bit_num_i == 1 || sign_bit_num_q == 1)) begin
cnt_amp_too_high <= cnt_amp_too_high + 1;
end
else if (cs == S_MEASURE_ADJ || cs == S_MEASURE_IDLE) begin
cnt_amp_too_high <= 0;
end
else begin
cnt_amp_too_high <= cnt_amp_too_high;
end
end
always @(posedge clk) begin
if (cs == S_MEASURE_ADJ && ns == S_MEASURE_IDLE) begin
power_measure_done_pulse <= 1;
end
else begin
power_measure_done_pulse <= 0;
end
end
// get the abs value
always @(posedge clk) begin
// i
if (data_i[11]) begin
data_i_abs <= -data_i;
end
else begin
data_i_abs <= data_i;
end
// q
if (data_q[11]) begin
data_q_abs <= -data_q;
end
else begin
data_q_abs <= data_q;
end
end
// get the sign number bit number of the temporary 12 bit number
always @(*) begin
casez (data_i_abs)
12'b1000_0000_0000: sign_bit_num_i <= 8'd1;
12'b01??_????_????: sign_bit_num_i <= 8'd1;
12'b001?_????_????: sign_bit_num_i <= 8'd2;
12'b0001_????_????: sign_bit_num_i <= 8'd3;
12'b0000_1???_????: sign_bit_num_i <= 8'd4;
12'b0000_01??_????: sign_bit_num_i <= 8'd5;
12'b0000_001?_????: sign_bit_num_i <= 8'd6;
12'b0000_0001_????: sign_bit_num_i <= 8'd7;
12'b0000_0000_1???: sign_bit_num_i <= 8'd8;
12'b0000_0000_01??: sign_bit_num_i <= 8'd9;
12'b0000_0000_001?: sign_bit_num_i <= 8'd10;
12'b0000_0000_0001: sign_bit_num_i <= 8'd11;
default: begin
sign_bit_num_i <= 8'd12;
end
endcase
end
// get the sign number bit number of the temporary 12 bit number
always @(*) begin
casez (data_q_abs)
12'b1000_0000_0000: sign_bit_num_q <= 8'd1;
12'b01??_????_????: sign_bit_num_q <= 8'd1;
12'b001?_????_????: sign_bit_num_q <= 8'd2;
12'b0001_????_????: sign_bit_num_q <= 8'd3;
12'b0000_1???_????: sign_bit_num_q <= 8'd4;
12'b0000_01??_????: sign_bit_num_q <= 8'd5;
12'b0000_001?_????: sign_bit_num_q <= 8'd6;
12'b0000_0001_????: sign_bit_num_q <= 8'd7;
12'b0000_0000_1???: sign_bit_num_q <= 8'd8;
12'b0000_0000_01??: sign_bit_num_q <= 8'd9;
12'b0000_0000_001?: sign_bit_num_q <= 8'd10;
12'b0000_0000_0001: sign_bit_num_q <= 8'd11;
default: begin
sign_bit_num_q <= 8'd12;
end
endcase
end
always @(posedge clk) begin
if (cs == S_MEASURE_IDLE || cs == S_MEASURE_ADJ) begin
sign_bit_num_min_i <= 8'd11;
sign_bit_num_min_q <= 8'd11;
end
else if (cs == S_MEASURE_ING) begin
if (sign_bit_num_min_i > sign_bit_num_i) begin
sign_bit_num_min_i <= sign_bit_num_i;
end
if (sign_bit_num_min_q > sign_bit_num_q) begin
sign_bit_num_min_q <= sign_bit_num_q;
end
end
end
// * flag_too_* generate logic, the core of the module
always @(posedge clk) begin
if (cnt_startup[2:0] == 3'b101 && cnt_startup <= 200) begin
flag_too_high <= 0;
flag_too_low <= 1;
end
else if (cs == S_MEASURE_DONE) begin
// * 若符号位太多,则信号太小,需要增加信号功率
if (sign_bit_num_min_i >= 3 || sign_bit_num_min_q >= 3) begin
flag_too_low <= 1;
end
// * 若符号位太少,则信号太大,需要降低信号功率
else if (sign_bit_num_min_i <= 1 || sign_bit_num_min_q <= 1 || cnt_amp_too_high >= CNT_AMP_TOO_HIGH_THRESHOLD - 1) begin
flag_too_high <= 1;
end
end
else begin
flag_too_high <= 0;
flag_too_low <= 0;
end
end
endmodule