This repository has been archived on 2024-01-14. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
vivado-202401/projects/duifei/duifei_online_acq_par/rtl/rx_dmf.v
T
josh c32d684223 change online acq pn code length, change 814 online acq to the same
修改了在线捕获程序的PN码长和频偏搜索步进,修改了地检发送程序的PN码长,使用对飞相控阵进行了测试,得到正确结果;将程序移植到814平台,同样能够正常工作;对地检程序(20230512),对飞程序(20230512)和814程序(20230415)进行归档
2023-05-14 12:51:10 +08:00

473 lines
16 KiB
Verilog

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// _ _ ____
// | | ___ ___| |__ / ___| __ _ ___
// _ | |/ _ \/ __| '_ \ | | _ / _` |/ _ \
// | |_| | (_) \__ \ | | | | |_| | (_| | (_) |
// \___/ \___/|___/_| |_| \____|\__,_|\___/
//
// Create Date: 04/25/2023 05:53:44 PM
// Design Name:
// Module Name: rx_dmf
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module rx_dmf
#(
// length of pseudorandom bit sequence, need to be a power of 2
parameter PRBS_LEN = 1024,
// interpolation of input signal, need to be a power of 2
parameter INTERP_RATE = 32,
// signal processing interpolation, need to be a power of 2
parameter PROCESS_INTERP = 2,
// possible position of pn code
parameter PRBS_POS = PRBS_LEN*PROCESS_INTERP,
parameter MAX_DMF_NUM = 64,
parameter DATA_I_WIDTH = 12,
parameter DATA_O_WIDTH = 18
)
(
input clk ,
input rst ,
input dmf_start ,
output dmf_busy ,
input din_valid ,
input [DATA_I_WIDTH-1 : 0] din_real ,
input [DATA_I_WIDTH-1 : 0] din_imag ,
input [$clog2(MAX_DMF_NUM+1)-1 : 0] dmf_num ,
input dmf_continuous ,
output peak_valid ,
output last_peak_valid ,
output [DATA_O_WIDTH-1 : 0] peak_value_abs ,
output [DATA_O_WIDTH-1 : 0] peak_value_i ,
output [DATA_O_WIDTH-1 : 0] peak_value_q ,
output [$clog2(PRBS_POS)-1 : 0] peak_index
);
localparam CMPLX_DIM = 2;
localparam APPROX_ABS_WIDTH = 29;
localparam ABS_WIDTH = 18;
localparam DMF_I_WIDTH = 12;
localparam DMF_O_WIDTH = DMF_I_WIDTH+$clog2(PRBS_POS);
localparam AXIS_DMF_I_WIDTH = 8*((DMF_I_WIDTH-1)/8+1);
localparam AXIS_DMF_O_WIDTH = 8*((DMF_O_WIDTH-1)/8+1);
genvar m;
integer i;
////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Center State Control /////////////////////////////
////////////////////////////////////////////////////////////////////////////////
reg dmf_busy_buf = 'b0;
reg dmf_start_d1 = 'b0;
reg dmf_start_d2 = 'b0;
reg [$clog2(MAX_DMF_NUM)-1 : 0] cnt_dmf_num = 'b0;
reg moduli_max_valid = 'b0;
assign dmf_busy = dmf_busy_buf;
always @(posedge clk) begin
dmf_start_d1 <= dmf_start;
dmf_start_d2 <= dmf_start_d1;
end
always @(posedge clk) begin
if (rst) begin
cnt_dmf_num <= 'b0;
end
else if (dmf_busy) begin
cnt_dmf_num <= (moduli_max_valid) ? cnt_dmf_num + 1'b1 : cnt_dmf_num;
end
else begin
cnt_dmf_num <= 'b0;
end
end
always @(posedge clk) begin
if (rst) begin
dmf_busy_buf <= 'b0;
end
else if (cnt_dmf_num == dmf_num+1 && ~dmf_continuous) begin
// clear when output is valid
dmf_busy_buf <= 'b0;
end
else if (din_valid && (dmf_start_d2 != dmf_start_d1) && (dmf_num != 'b0)) begin
// set when either edge is detected
dmf_busy_buf <= 1'b1;
end
else begin
// otherwise keep
dmf_busy_buf <= dmf_busy_buf;
end
end
////////////////////////////////////////////////////////////////////////////////
////////////////////////////// Decimation Counter //////////////////////////////
////////////////////////////////////////////////////////////////////////////////
reg [$clog2(INTERP_RATE/PROCESS_INTERP)-1 : 0] cnt_deci = 'b0;
reg din_deci_valid = 'b0;
always @(posedge clk) begin
if (rst) begin
cnt_deci <= 'b0;
end
else if (dmf_busy && din_valid) begin
cnt_deci <= cnt_deci + 1'b1;
end
else begin
cnt_deci <= 'b0;
end
end
always @(posedge clk) begin
if (rst) begin
din_deci_valid <= 'b0;
end
else begin
din_deci_valid <= (cnt_deci == INTERP_RATE/PROCESS_INTERP-1) ? 1'b1 : 'b0;
end
end
////////////////////////////////////////////////////////////////////////////////
//////////////////////////// Digital Matched Filter ////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// input & output signals
wire [AXIS_DMF_I_WIDTH-1 : 0] dmf_axis_i_real;
wire [AXIS_DMF_I_WIDTH-1 : 0] dmf_axis_i_imag;
wire signed [AXIS_DMF_O_WIDTH-1 : 0] dmf_axis_o_real;
wire signed [AXIS_DMF_O_WIDTH-1 : 0] dmf_axis_o_imag;
wire signed [DMF_O_WIDTH-1 : 0] dmf_o_real;
wire signed [DMF_O_WIDTH-1 : 0] dmf_o_imag;
wire dmf_o_valid;
// dmf input data formatting
if (AXIS_DMF_I_WIDTH > DATA_I_WIDTH) begin
// sign extension to fit 8-bit axis data format
assign dmf_axis_i_real = {{(AXIS_DMF_I_WIDTH-DATA_I_WIDTH){din_real[DATA_I_WIDTH-1]}},din_real};
assign dmf_axis_i_imag = {{(AXIS_DMF_I_WIDTH-DATA_I_WIDTH){din_imag[DATA_I_WIDTH-1]}},din_imag};
end
else begin
// truncate msb
assign dmf_axis_i_real = din_real[DATA_I_WIDTH-1 -: AXIS_DMF_I_WIDTH];
assign dmf_axis_i_imag = din_imag[DATA_I_WIDTH-1 -: AXIS_DMF_I_WIDTH];
end
// dmf output data formatting, truncate valid bits
assign dmf_o_real = dmf_axis_o_real[DMF_O_WIDTH-1 -: DMF_O_WIDTH];
assign dmf_o_imag = dmf_axis_o_imag[DMF_O_WIDTH-1 -: DMF_O_WIDTH];
// fir port definition
wire s_axis_data_tvalid_real;
wire s_axis_data_tready_real;
wire [AXIS_DMF_I_WIDTH-1 : 0] s_axis_data_ttdata_real;
wire m_axis_data_tvalid_real;
wire [AXIS_DMF_O_WIDTH-1 : 0] m_axis_data_ttdata_real;
wire s_axis_data_tvalid_imag;
wire s_axis_data_tready_imag;
wire [AXIS_DMF_I_WIDTH-1 : 0] s_axis_data_ttdata_imag;
wire m_axis_data_tvalid_imag;
wire [AXIS_DMF_O_WIDTH-1 : 0] m_axis_data_ttdata_imag;
// fir port connection
assign s_axis_data_tvalid_real = din_deci_valid;
assign s_axis_data_ttdata_real = dmf_axis_i_real;
assign dmf_axis_o_real = m_axis_data_ttdata_real;
assign s_axis_data_tvalid_imag = din_deci_valid;
assign s_axis_data_ttdata_imag = dmf_axis_i_imag;
assign dmf_axis_o_imag = m_axis_data_ttdata_imag;
assign dmf_o_valid = m_axis_data_tvalid_real;
// fir ip core instantiation
fir_prbs10_invert_rep2 u_dmf_real
(
.aclk (clk ), // input wire aclk
.aresetn (dmf_busy ), // input aresetn
.s_axis_data_tvalid (s_axis_data_tvalid_real), // input wire s_axis_data_tvalid
.s_axis_data_tready (s_axis_data_tready_real), // output wire s_axis_data_tready
.s_axis_data_tdata (s_axis_data_ttdata_real), // input wire [15 : 0] s_axis_data_tdata
.m_axis_data_tvalid (m_axis_data_tvalid_real), // output wire m_axis_data_tvalid
.m_axis_data_tdata (m_axis_data_ttdata_real) // output wire [23 : 0] m_axis_data_tdata
);
fir_prbs10_invert_rep2 u_dmf_imag
(
.aclk (clk ), // input wire aclk
.aresetn (dmf_busy ), // input aresetn
.s_axis_data_tvalid (s_axis_data_tvalid_imag), // input wire s_axis_data_tvalid
.s_axis_data_tready (s_axis_data_tready_imag), // output wire s_axis_data_tready
.s_axis_data_tdata (s_axis_data_ttdata_imag), // input wire [15 : 0] s_axis_data_tdata
.m_axis_data_tvalid (m_axis_data_tvalid_imag), // output wire m_axis_data_tvalid
.m_axis_data_tdata (m_axis_data_ttdata_imag) // output wire [23 : 0] m_axis_data_tdata
);
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// Chip Counter /////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
localparam PEAK_ABS_DELAY = 6; // 5 for multiplier, 1 for adder
reg [$clog2(PRBS_POS)-1 : 0] cnt_chip = 'b0;
reg [$clog2(PRBS_POS)-1 : 0] cnt_chip_delay [0 : PEAK_ABS_DELAY-1];
always @(posedge clk) begin
if (rst) begin
cnt_chip <= 'b0;
end
else if (dmf_busy) begin
cnt_chip <= (dmf_o_valid) ? cnt_chip + 1'b1 : cnt_chip;
end
else begin
cnt_chip <= 'b0;
end
end
always @(posedge clk) begin
for (i = 1; i < PEAK_ABS_DELAY; i = i + 1) begin
cnt_chip_delay[i] <= cnt_chip_delay[i-1];
end
cnt_chip_delay[0] <= cnt_chip;
end
////////////////////////////////////////////////////////////////////////////////
////////////////////////// Accumulation & Peak Search //////////////////////////
////////////////////////////////////////////////////////////////////////////////
// moduli
wire moduli_valid;
reg moduli_valid_delay [0 : PEAK_ABS_DELAY-1];
wire [ABS_WIDTH-1 : 0] moduli_real;
wire [ABS_WIDTH-1 : 0] moduli_imag;
reg [ABS_WIDTH-1 : 0] moduli_real_delay [0 : PEAK_ABS_DELAY-1];
reg [ABS_WIDTH-1 : 0] moduli_imag_delay [0 : PEAK_ABS_DELAY-1];
assign moduli_valid = dmf_o_valid;
if (ABS_WIDTH > DMF_O_WIDTH) begin
// append zeros
assign moduli_real = {dmf_o_real,{(ABS_WIDTH-DMF_O_WIDTH){1'b0}}};
assign moduli_imag = {dmf_o_imag,{(ABS_WIDTH-DMF_O_WIDTH){1'b0}}};
end
else begin
// truncate msb
assign moduli_real = dmf_o_real[DMF_O_WIDTH-1 -: ABS_WIDTH];
assign moduli_imag = dmf_o_imag[DMF_O_WIDTH-1 -: ABS_WIDTH];
end
always @(posedge clk) begin
for (i = 1; i < PEAK_ABS_DELAY; i = i + 1) begin
moduli_valid_delay[i] <= moduli_valid_delay[i-1];
moduli_real_delay[i] <= moduli_real_delay[i-1];
moduli_imag_delay[i] <= moduli_imag_delay[i-1];
end
moduli_valid_delay[0] <= moduli_valid;
moduli_real_delay[0] <= moduli_real;
moduli_imag_delay[0] <= moduli_imag;
end
wire [2*ABS_WIDTH-1 : 0] moduli_real_square;
wire [2*ABS_WIDTH-1 : 0] moduli_imag_square;
reg [ABS_WIDTH-1 : 0] moduli_abs_square = 'b0;
wire [DATA_O_WIDTH-1 : 0] moduli_abs;
wire moduli_abs_valid;
assign moduli_abs_valid = moduli_valid_delay[PEAK_ABS_DELAY-1];
if (DATA_O_WIDTH > ABS_WIDTH) begin
// append zeros
assign moduli_abs = {moduli_abs_square,{(DATA_O_WIDTH-ABS_WIDTH){1'b0}}};
end
else begin
// truncate msb
assign moduli_abs = moduli_abs_square[ABS_WIDTH-1 -: DATA_O_WIDTH];
end
always @(posedge clk) begin
if (rst) begin
moduli_abs_square <= 'b0;
end
else begin
moduli_abs_square <= moduli_real_square[(2*ABS_WIDTH-1) -: (ABS_WIDTH-1)] + moduli_imag_square[(2*ABS_WIDTH-1) -: (ABS_WIDTH-1)];
end
end
mult_18x18 u_mult_real
(
.CLK(clk ), // input wire CLK
.A (moduli_real ), // input wire [17 : 0] A
.B (moduli_real ), // input wire [17 : 0] B
.P (moduli_real_square ) // output wire [17 : 0] P
);
mult_18x18 u_mult_imag
(
.CLK(clk ), // input wire CLK
.A (moduli_imag ), // input wire [17 : 0] A
.B (moduli_imag ), // input wire [17 : 0] B
.P (moduli_imag_square ) // output wire [17 : 0] P
);
// wire accum_current_valid;
// assign accum_current_valid = dmf_o_valid;
// wire [APPROX_ABS_WIDTH-2 : 0] accum_moduli_real;
// wire [APPROX_ABS_WIDTH-2 : 0] accum_moduli_imag;
// wire [APPROX_ABS_WIDTH-1 : 0] accum_moduli_abs ;
// wire accum_current_abs_valid;
// wire [DATA_O_WIDTH-1 : 0] accum_current_abs;
// if (APPROX_ABS_WIDTH-1 > DMF_O_WIDTH) begin
// // append zeros
// assign accum_moduli_real = {dmf_o_real,{(APPROX_ABS_WIDTH-1-DMF_O_WIDTH){1'b0}}};
// assign accum_moduli_imag = {dmf_o_imag,{(APPROX_ABS_WIDTH-1-DMF_O_WIDTH){1'b0}}};
// end
// else begin
// // truncate msb
// assign accum_moduli_real = dmf_o_real[DMF_O_WIDTH-1 -: (APPROX_ABS_WIDTH-1)];
// assign accum_moduli_imag = dmf_o_imag[DMF_O_WIDTH-1 -: (APPROX_ABS_WIDTH-1)];
// end
// if (DATA_O_WIDTH > APPROX_ABS_WIDTH) begin
// // append zeros
// assign accum_current_abs = {accum_moduli_abs,{(DATA_O_WIDTH-APPROX_ABS_WIDTH){1'b0}}};
// end
// else begin
// // truncate msb
// assign accum_current_abs = accum_moduli_abs[APPROX_ABS_WIDTH-1 -: DATA_O_WIDTH];
// end
// ApproxAbs u_accum_abs
// (
// .clk (clk ),
// .Nd (accum_current_valid ),
// .Dini (accum_moduli_real ),
// .Dinq (accum_moduli_imag ),
// .Abs_Rdy (accum_current_abs_valid),
// .Abs_Dout (accum_moduli_abs )
// );
// peak record
reg [DATA_O_WIDTH-1 : 0] moduli_max_abs = 'b0;
reg [DATA_O_WIDTH-1 : 0] moduli_max_real = 'b0;
reg [DATA_O_WIDTH-1 : 0] moduli_max_imag = 'b0;
reg [$clog2(PRBS_POS)-1 : 0] moduli_max_index = 'b0;
always @(posedge clk) begin
if (rst) begin
moduli_max_valid <= 'b0;
moduli_max_abs <= 'b0;
moduli_max_real <= 'b0;
moduli_max_imag <= 'b0;
moduli_max_index <= 'b0;
end
else if (dmf_busy) begin
if (moduli_abs_valid) begin
if ((cnt_chip_delay[PEAK_ABS_DELAY-1] == 0) || (moduli_abs > moduli_max_abs)) begin
// reset when chip counter reaches zero or record peak
moduli_max_abs <= moduli_abs ;
moduli_max_real <= moduli_real_delay[PEAK_ABS_DELAY-1];
moduli_max_imag <= moduli_imag_delay[PEAK_ABS_DELAY-1];
moduli_max_index <= cnt_chip_delay[PEAK_ABS_DELAY-1] ;
end
else begin
moduli_max_abs <= moduli_max_abs;
moduli_max_real <= moduli_max_real;
moduli_max_imag <= moduli_max_imag;
moduli_max_index <= moduli_max_index;
end
if (cnt_chip_delay[PEAK_ABS_DELAY-1] == PRBS_POS-1) begin
// peak record valid when chip counter reaches maximum value
moduli_max_valid <= 1'b1;
end
else begin
moduli_max_valid <= 'b0;
end
end
else begin
moduli_max_valid <= 'b0;
moduli_max_abs <= moduli_max_abs;
moduli_max_real <= moduli_max_real;
moduli_max_imag <= moduli_max_imag;
moduli_max_index <= moduli_max_index;
end
end
else begin
moduli_max_valid <= 'b0;
moduli_max_abs <= 'b0;
moduli_max_real <= 'b0;
moduli_max_imag <= 'b0;
moduli_max_index <= 'b0;
end
end
// register output
reg peak_valid_buf = 1'b0;
reg last_peak_valid_buf = 1'b0;
reg [DATA_O_WIDTH-1 : 0] peak_value_abs_buf = 'b0;
reg [DATA_O_WIDTH-1 : 0] peak_value_i_buf = 'b0;
reg [DATA_O_WIDTH-1 : 0] peak_value_q_buf = 'b0;
reg [$clog2(PRBS_POS)-1 : 0] peak_index_buf = 'b0;
assign peak_valid = peak_valid_buf ;
assign last_peak_valid = last_peak_valid_buf;
assign peak_value_abs = peak_value_abs_buf ;
assign peak_value_i = peak_value_i_buf ;
assign peak_value_q = peak_value_q_buf ;
assign peak_index = peak_index_buf ;
always @(posedge clk) begin
if (rst) begin
peak_valid_buf <= 'b0;
last_peak_valid_buf <= 'b0;
peak_value_abs_buf <= 'b0;
peak_value_i_buf <= 'b0;
peak_value_q_buf <= 'b0;
peak_index_buf <= 'b0;
end
else if (moduli_max_valid && (cnt_dmf_num != 'b0)) begin
peak_valid_buf <= 1'b1;
peak_value_abs_buf <= moduli_max_abs ;
peak_value_i_buf <= moduli_max_real ;
peak_value_q_buf <= moduli_max_imag ;
peak_index_buf <= moduli_max_index;
last_peak_valid_buf<= ((cnt_dmf_num == dmf_num) && ~dmf_continuous) ? 1'b1 : 'b0;
end
else begin
peak_valid_buf <= 1'b0;
last_peak_valid_buf <= 1'b0;
peak_value_abs_buf <= peak_value_abs_buf;
peak_value_i_buf <= peak_value_i_buf ;
peak_value_q_buf <= peak_value_q_buf ;
peak_index_buf <= peak_index_buf ;
end
end
endmodule