`timescale 1ns / 1ns // +------------------------------+ // | | // | | // +---------+------------> shift_ram(depth=1024) +-------------------+ // | | | | // | | | | // | +------------------------------+ | // | | // | | // | | // | +------------+ | // | + | | - | // | | sliding | | // | | window | | // +---------------------> <----------------------------+ // | | // +-----+------+ // | // | average_out // | // v module PAPR #( parameter MAG_WIDTH = 22, parameter WINDOW_DEPTH = 1023 // parameter GATE = 8 ) ( input clk, input rst, input [MAG_WIDTH-1:0] vec_mag, input mag_valid, output reg frame_sync, output reg frame_sync_pulse ); localparam SUM_WIDTH = 32; localparam CNT_START = 16; // 32*4 / 8 * mag_valid signal is active high per 8 clk localparam CNT_END = 44; // 88*4 / 8 localparam PULSE_PERIOD = 50; reg [MAG_WIDTH-1:0] vec_mag_d1; reg [MAG_WIDTH-1:0] vec_mag_d2; reg [MAG_WIDTH-1:0] vec_mag_d3; reg [MAG_WIDTH-1:0] vec_mag_reserved; // accumulate ==> average ==> papr wire [MAG_WIDTH-1:0] vec_mag_1024; reg [ 7:0] cnt; wire [MAG_WIDTH-1:0] data_avg; reg [SUM_WIDTH-1:0] data_sum; assign data_avg = data_sum[SUM_WIDTH-1:10]; always @(posedge clk) begin if (rst) begin vec_mag_d1 <= 0; vec_mag_d2 <= 0; vec_mag_d3 <= 0; end else if (mag_valid) begin vec_mag_d1 <= vec_mag; vec_mag_d2 <= vec_mag_d1; vec_mag_d3 <= vec_mag_d2; end else begin vec_mag_d1 <= vec_mag_d1; vec_mag_d2 <= vec_mag_d2; vec_mag_d3 <= vec_mag_d3; end end shift_reg #( .DATA_WIDTH(MAG_WIDTH), .DEPTH (WINDOW_DEPTH) ) u_shift_reg ( .clk (clk), .rst (rst), .we (mag_valid), .din (vec_mag), .dout(vec_mag_1024) ); always @(posedge clk) begin if (rst) begin data_sum <= 0; end else begin if (mag_valid) begin data_sum <= data_sum + vec_mag - vec_mag_1024; end else begin data_sum <= data_sum; end end end // FSM reg [2:0] cs = 0; reg [2:0] ns = 0; always @(posedge clk) begin cs <= ns; end always @(*) begin ns = cs; case (cs) 0: begin if (mag_valid && vec_mag_1024 != 'd0 && data_avg != 'd0 && ({3'd0, vec_mag_d2[MAG_WIDTH-1:3]} >= data_avg) && (vec_mag_d2 >= vec_mag_d1) && (vec_mag_d2 >= vec_mag_d3) && (vec_mag_d2 >= 22'h5000)) begin ns = 1; end end 1: begin if (cnt == CNT_START - 1) begin ns = 2; end end 2: begin if (vec_mag_reserved < {vec_mag[MAG_WIDTH-3:0], 2'b0}) begin ns = 0; end else if (cnt == CNT_END - 1) begin ns = 3; end end 3: begin // generate pulse ns = 4; end 4: begin if (cnt == PULSE_PERIOD - 1) begin ns = 0; end end endcase end always @(posedge clk) begin if (cs == 0 && ns == 1) begin vec_mag_reserved <= vec_mag_d2; end else if (cs == 0) begin vec_mag_reserved <= 0; end end always @(posedge clk) begin if (cs == 1 || cs == 2) begin if (mag_valid) begin cnt <= cnt + 1; end end else if (cs == 4) begin cnt <= cnt + 1; end else if (cs == 0) begin cnt <= 0; end end always @(posedge clk) begin frame_sync_pulse <= (cs == 3); if (cs == 4) begin frame_sync <= 1; end else begin frame_sync <= 0; end end ila_frame_sync u_ila_frame_sync ( .clk (clk), // input wire clk .probe0(vec_mag), // input wire [21:0] probe0 .probe1(data_avg), // input wire [21:0] probe0 .probe2(cs), // input wire [2:0] probe2 .probe3(cnt), // input wire [7:0] probe2 .probe4(frame_sync) // input wire [0:0] probe2 ); endmodule