add multi_ch_cal module for xc7k410tffg900-2

This commit is contained in:
2024-01-30 10:35:04 +08:00
parent 5defedcc88
commit 9eea2b693a
7 changed files with 19310 additions and 0 deletions
@@ -0,0 +1,118 @@
%% File Header/文件说明
%
% 调零算法对幅相一致性的要求较高,且 AD9361 多片同步的精度随机性较大,因此需要对
% AD9361 多片同步误差进行精细校准。采用收发扩频码的方式在校准过程中对两片 AD9361
% 的两个接收通道进行幅相测量,在接收端使用加法器进行非相干相关峰累积,累积 N 个
% 符号后出峰,根据相关峰的高度差和相位差,在接收端对信号的幅度和相位进行补偿。
%
clc; clear; close all;
%% initial system parameters/初始系统参数
rng(0);
Eb_N0 = 30; % energy per bit to noise power spectral density ratio
interp = 8; % interpolation factor
SNR = 10*log10(2/interp) + Eb_N0; % signal-to-noise power ration
channelNum = 2;
deltaAmp = 1-(2*rand-1)*0.05; % random amplitude error, range: [0.95,1.05]
deltaAngRad = (2*rand-1)*pi; % random phase error, range: [-pi,pi]
deltaAngDeg = deltaAngRad/pi*180;
angleInit = 20/pi*180;
% standard pn sequence
pnSequence = comm.PNSequence('Polynomial','x^7+x^6+1', ...
'InitialConditions',[zeros(1,6),1],'SamplesPerFrame',2^7-1);
PRBS7 = pnSequence();
PRBS7_polar = 1-2*[PRBS7;0];
chipLen = length(PRBS7_polar); % pn chip length
accumSymbolNum = 16;
totalSymbolNum = accumSymbolNum+1;
randomChipIndex_ch1 = randi(chipLen*interp*2-1)-chipLen*interp; % random rx chip index
randomChipIndex_ch2 = randomChipIndex_ch1 + (randi(2*interp-1)-interp); % random rx chip index
% randomChipIndex_ch1 = -2; % random rx chip index
% randomChipIndex_ch2 = 5; % random rx chip index
%%
% 发送信号:方波成型
seqTx = kron(repmat(PRBS7_polar,totalSymbolNum,1),ones(interp,1));
% 接收信号:随机初始相位,加噪,随机幅度误差,随机相位误差
seqRx = awgn(seqTx,SNR,'measured').*[1,deltaAmp].*[exp(1i*angleInit),...
exp(1i*(angleInit+deltaAngRad))];
seqRx(:,1) = circshift(seqRx(:,1),randomChipIndex_ch1);
seqRx(:,2) = circshift(seqRx(:,2),randomChipIndex_ch2);
% 降采样,与 Verilog 实现一样在码片中心采样
seqRxDown = zeros(chipLen*accumSymbolNum,channelNum,interp);
for i = 0:interp-1
% 补偿 Verilog 模块的读数延迟
seqRxDown(:,:,i+1) = downsample(seqRx((1:accumSymbolNum*chipLen*interp)+2,:),interp,i);
end
% 取符号位
seqRxMsbReal = zeros(size(seqRxDown));
seqRxMsbImag = zeros(size(seqRxDown));
seqRxMsbReal(real(seqRxDown)>0) = 1;
seqRxMsbReal(real(seqRxDown)<0) = -1;
seqRxMsbImag(imag(seqRxDown)>0) = 1;
seqRxMsbImag(imag(seqRxDown)<0) = -1;
% 符号位累积
seqRxMsbRealAccum = zeros(chipLen,channelNum,interp);
seqRxMsbImagAccum = zeros(chipLen,channelNum,interp);
for i = 0:chipLen-1
% PN 码圆周移位,遍历所有 PN 码相位
PRBS7_cshift = circshift(repmat(PRBS7_polar,accumSymbolNum,1),-i); % 负号为了和 Verilog 程序对应
% 累积,若当前比特与 PN 码相同,结果 +1;否则结果 -1
seqRxMsbRealAccum(i+1,:,:) = sum(PRBS7_cshift==seqRxMsbReal)-...
sum(PRBS7_cshift~=seqRxMsbReal);
seqRxMsbImagAccum(i+1,:,:) = sum(PRBS7_cshift==seqRxMsbImag)-...
sum(PRBS7_cshift~=seqRxMsbImag);
end
seqRxMsbAccum = seqRxMsbRealAccum+1i*seqRxMsbImagAccum;
% 通过相关峰位置判断目标信号位置
maxPeakIndex = zeros(2,interp);
for i = 1:2
for j = 1:interp
maxPeakIndex(i,j) = find(abs(seqRxMsbAccum(:,i,j))==max(abs(seqRxMsbAccum(:,i,j))),1); % PN 码相位
end
end
maxPeakIndexDiff = zeros(channelNum,1); % 相位差
for i = 1:channelNum
for j = 1:interp
if (maxPeakIndex(i,j)==maxPeakIndex(i,1))
maxPeakIndexDiff(i) = j;
end
end
end
% 以下条件仅对双通道有效
if (maxPeakIndex(1,1) == maxPeakIndex(2,1))
relativeDelay = maxPeakIndexDiff(2) - maxPeakIndexDiff(1);
desiredPointIndex = [1,1]+[0,chipLen];
elseif (mod(maxPeakIndex(1,1)-1,chipLen) == mod(maxPeakIndex(2,1),chipLen))
relativeDelay = maxPeakIndexDiff(2) - maxPeakIndexDiff(1) + interp;
desiredPointIndex = [1,2]+[0,chipLen];
elseif (mod(maxPeakIndex(1,1)+1,chipLen) == mod(maxPeakIndex(2,1),chipLen))
relativeDelay = maxPeakIndexDiff(2) - maxPeakIndexDiff(1) - interp;
desiredPointIndex = [2,1]+[0,chipLen];
end
% 输入信号累加
seqRxDownAccum = squeeze(sum(reshape(seqRxDown(:,:,1),128,[],2),2));
% 取目标位置信号
desiredPoint = seqRxDownAccum(desiredPointIndex);
ampEst = abs(desiredPoint)./abs(desiredPoint(1));
angleEst = (angle(desiredPoint) - angle(desiredPoint(1)))/pi*180;
seqRxExport = round([real(seqRx(:,1)),imag(seqRx(:,1)),real(seqRx(:,2)),...
imag(seqRx(:,2))]/max(abs(seqRx),[],'all')*(2^11-1));
writematrix(seqRxExport,'./fine_cal_data.txt');
@@ -0,0 +1,168 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// _ _ ____
// | | ___ ___| |__ / ___| __ _ ___
// _ | |/ _ \/ __| '_ \ | | _ / _` |/ _ \
// | |_| | (_) \__ \ | | | | |_| | (_| | (_) |
// \___/ \___/|___/_| |_| \____|\__,_|\___/
//
// Create Date: 2023/02/17 16:51:52
// Design Name:
// Module Name: tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description: testbench for [multi_ch_cal]
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module tb_multi_ch_cal;
localparam DATA_FILE_PATH = "../fine_cal_data.txt";
localparam DATA_LEN = 16384;
localparam DATA_WIDTH = 12;
localparam ACCUM_SYMBOL_NUM = 4;
// localparam DATA_FILE_PATH = "D:\\iladata_pn_trx_4.csv";
// localparam DATA_LEN = 131072;
// localparam DATA_WIDTH = 12;
reg clk = 'b0;
reg rst = 1'b1;
reg ad9361_1_cal_start = 'b0;
wire ad9361_1_cal_done ;
reg ad9361_2_cal_start = 'b0;
wire ad9361_2_cal_done ;
wire ad9361_cal_result ;
wire ad9361_cal_valid;
reg ad9361_recal = 'b0;
// phase difference of 180 degree
reg signed [11:0] rx_ch1_i = 'b0;
reg signed [11:0] rx_ch1_q = 'b0;
reg signed [11:0] rx_ch2_i = 'b0;
reg signed [11:0] rx_ch2_q = 'b0;
reg signed [11:0] rx_ch3_q = 'b0;
reg signed [11:0] rx_ch3_i = 'b0;
reg signed [11:0] rx_ch4_i = 'b0;
reg signed [11:0] rx_ch4_q = 'b0;
wire [11:0] rx_cal_ch1_i;
wire [11:0] rx_cal_ch2_i;
wire [11:0] rx_cal_ch3_i;
wire [11:0] rx_cal_ch4_i;
wire [11:0] rx_cal_ch1_q;
wire [11:0] rx_cal_ch2_q;
wire [11:0] rx_cal_ch3_q;
wire [11:0] rx_cal_ch4_q;
integer i = 0;
integer r_file;
multi_ch_cal #(
.ACCUM_SYMBOL_NUM (ACCUM_SYMBOL_NUM )
) u_multi_ch_cal
(
// clock & reset
.clk (clk ), // input clk
.rst (rst ), // input rst
// control interface
.ad9361_1_cal_start (ad9361_1_cal_start ), // input ad9361_1_cal_start
.ad9361_1_cal_done (ad9361_1_cal_done ), // output ad9361_1_cal_done
.ad9361_2_cal_start (ad9361_2_cal_start ), // input ad9361_2_cal_start
.ad9361_2_cal_done (ad9361_2_cal_done ), // output ad9361_2_cal_done
.ad9361_cal_result (ad9361_cal_result ), // output ad9361_cal_result
.ad9361_cal_valid (ad9361_cal_valid ), // output ad9361_cal_valid
.ad9361_recal (ad9361_recal ), // input ad9361_recal
// input data interface
.rx_ch1_i (rx_ch1_i ), // input [11:0] rx_ch1_i
.rx_ch2_i (rx_ch2_i ), // input [11:0] rx_ch2_i
.rx_ch3_i (rx_ch3_i ), // input [11:0] rx_ch3_i
.rx_ch4_i (rx_ch4_i ), // input [11:0] rx_ch4_i
.rx_ch1_q (rx_ch1_q ), // input [11:0] rx_ch1_q
.rx_ch2_q (rx_ch2_q ), // input [11:0] rx_ch2_q
.rx_ch3_q (rx_ch3_q ), // input [11:0] rx_ch3_q
.rx_ch4_q (rx_ch4_q ), // input [11:0] rx_ch4_q
// output data interface
.rx_cal_ch1_i (rx_cal_ch1_i ), // output [11:0] rx_cal_ch1_i
.rx_cal_ch2_i (rx_cal_ch2_i ), // output [11:0] rx_cal_ch2_i
.rx_cal_ch3_i (rx_cal_ch3_i ), // output [11:0] rx_cal_ch3_i
.rx_cal_ch4_i (rx_cal_ch4_i ), // output [11:0] rx_cal_ch4_i
.rx_cal_ch1_q (rx_cal_ch1_q ), // output [11:0] rx_cal_ch1_q
.rx_cal_ch2_q (rx_cal_ch2_q ), // output [11:0] rx_cal_ch2_q
.rx_cal_ch3_q (rx_cal_ch3_q ), // output [11:0] rx_cal_ch3_q
.rx_cal_ch4_q (rx_cal_ch4_q ) // output [11:0] rx_cal_ch4_q
);
initial begin
r_file = $fopen(DATA_FILE_PATH,"r");
#102
rst = 1'b0;
#100
ad9361_1_cal_start = 1'b1;
end
always @(posedge clk) begin
if (ad9361_1_cal_start) begin
if (i == DATA_LEN-1) begin
$fscanf(r_file,"%d,%d,%d,%d",
rx_ch2_i,
rx_ch2_q,
rx_ch4_i,
rx_ch4_q);
$fclose(r_file);
r_file = $fopen(DATA_FILE_PATH,"r");
i <= 0;
end
else begin
$fscanf(r_file,"%d,%d,%d,%d",
rx_ch2_i,
rx_ch2_q,
rx_ch4_i,
rx_ch4_q);
i <= i + 1;
end
end
end
always begin
#10 clk = ~clk;
end
// initial begin
// #10000
// ad9361_recal = 1'b1;
// #20
// ad9361_recal = 1'b0;
// end
always @(posedge clk) begin
if (ad9361_1_cal_done) begin
ad9361_2_cal_start <= 1'b1;
end
else begin
ad9361_2_cal_start <= 1'b0;
end
end
always @(posedge clk) begin
if (ad9361_2_cal_done) begin
#2000
ad9361_recal <= 1'b1;
end
else begin
ad9361_recal <= 1'b0;
end
end
endmodule
@@ -0,0 +1,188 @@
{
"schema": "xilinx.com:schema:json_instance:1.0",
"ip_inst": {
"xci_name": "atan2_16b",
"component_reference": "xilinx.com:ip:cordic:6.0",
"ip_revision": "20",
"gen_directory": "../../../../multi_ch_cal.gen/sources_1/ip/atan2_16b",
"parameters": {
"component_parameters": {
"Component_Name": [ { "value": "atan2_16b", "resolve_type": "user", "usage": "all" } ],
"Functional_Selection": [ { "value": "Arc_Tan", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
"Architectural_Configuration": [ { "value": "Parallel", "resolve_type": "user", "usage": "all" } ],
"Pipelining_Mode": [ { "value": "Maximum", "resolve_type": "user", "usage": "all" } ],
"Data_Format": [ { "value": "SignedFraction", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
"Phase_Format": [ { "value": "Scaled_Radians", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
"Input_Width": [ { "value": "16", "resolve_type": "user", "format": "long", "usage": "all" } ],
"Output_Width": [ { "value": "16", "resolve_type": "user", "format": "long", "usage": "all" } ],
"Round_Mode": [ { "value": "Truncate", "resolve_type": "user", "usage": "all" } ],
"Iterations": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "all" } ],
"Precision": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "all" } ],
"Coarse_Rotation": [ { "value": "true", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"Compensation_Scaling": [ { "value": "No_Scale_Compensation", "resolve_type": "user", "usage": "all" } ],
"cartesian_has_tuser": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"cartesian_tuser_width": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
"cartesian_has_tlast": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"phase_has_tuser": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"phase_tuser_width": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
"phase_has_tlast": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"flow_control": [ { "value": "NonBlocking", "resolve_type": "user", "usage": "all" } ],
"optimize_goal": [ { "value": "Performance", "resolve_type": "user", "usage": "all" } ],
"out_tready": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"out_tlast_behv": [ { "value": "Null", "resolve_type": "user", "usage": "all" } ],
"ACLKEN": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"ARESETN": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ]
},
"model_parameters": {
"C_ARCHITECTURE": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_CORDIC_FUNCTION": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_COARSE_ROTATE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_DATA_FORMAT": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_XDEVICEFAMILY": [ { "value": "kintex7", "resolve_type": "generated", "usage": "all" } ],
"C_HAS_ACLKEN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_ACLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_CARTESIAN": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_PHASE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_ARESETN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_INPUT_WIDTH": [ { "value": "16", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_ITERATIONS": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_OUTPUT_WIDTH": [ { "value": "16", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_PHASE_FORMAT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_PIPELINE_MODE": [ { "value": "-2", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_PRECISION": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_ROUND_MODE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_SCALE_COMP": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_THROTTLE_SCHEME": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_TLAST_RESOLUTION": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_PHASE_TUSER": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_PHASE_TLAST": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_S_AXIS_PHASE_TDATA_WIDTH": [ { "value": "16", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_S_AXIS_PHASE_TUSER_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_CARTESIAN_TUSER": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_CARTESIAN_TLAST": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_S_AXIS_CARTESIAN_TDATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_S_AXIS_CARTESIAN_TUSER_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_M_AXIS_DOUT_TDATA_WIDTH": [ { "value": "16", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_M_AXIS_DOUT_TUSER_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ]
},
"project_parameters": {
"ARCHITECTURE": [ { "value": "kintex7" } ],
"BASE_BOARD_PART": [ { "value": "" } ],
"BOARD_CONNECTIONS": [ { "value": "" } ],
"DEVICE": [ { "value": "xc7k410t" } ],
"PACKAGE": [ { "value": "ffg900" } ],
"PREFHDL": [ { "value": "VERILOG" } ],
"SILICON_REVISION": [ { "value": "" } ],
"SIMULATOR_LANGUAGE": [ { "value": "MIXED" } ],
"SPEEDGRADE": [ { "value": "-2" } ],
"STATIC_POWER": [ { "value": "" } ],
"TEMPERATURE_GRADE": [ { "value": "" } ]
},
"runtime_parameters": {
"IPCONTEXT": [ { "value": "IP_Flow" } ],
"IPREVISION": [ { "value": "20" } ],
"MANAGED": [ { "value": "TRUE" } ],
"OUTPUTDIR": [ { "value": "../../../../multi_ch_cal.gen/sources_1/ip/atan2_16b" } ],
"SELECTEDSIMMODEL": [ { "value": "" } ],
"SHAREDDIR": [ { "value": "." } ],
"SWVERSION": [ { "value": "2023.2.1" } ],
"SYNTHESISFLOW": [ { "value": "OUT_OF_CONTEXT" } ]
}
},
"boundary": {
"ports": {
"aclk": [ { "direction": "in", "driver_value": "0x1" } ],
"s_axis_cartesian_tvalid": [ { "direction": "in", "driver_value": "0x0" } ],
"s_axis_cartesian_tdata": [ { "direction": "in", "size_left": "31", "size_right": "0", "driver_value": "0" } ],
"m_axis_dout_tvalid": [ { "direction": "out", "driver_value": "0x0" } ],
"m_axis_dout_tdata": [ { "direction": "out", "size_left": "15", "size_right": "0", "driver_value": "0" } ]
},
"interfaces": {
"S_AXIS_CARTESIAN": {
"vlnv": "xilinx.com:interface:axis:1.0",
"abstraction_type": "xilinx.com:interface:axis_rtl:1.0",
"mode": "slave",
"parameters": {
"TDATA_NUM_BYTES": [ { "value": "4", "value_src": "auto", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TDEST_WIDTH": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TID_WIDTH": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TUSER_WIDTH": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TREADY": [ { "value": "0", "value_src": "auto", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TSTRB": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TKEEP": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TLAST": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"FREQ_HZ": [ { "value": "100000000", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"PHASE": [ { "value": "0.0", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ],
"CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"LAYERED_METADATA": [ { "value": "undef", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
},
"port_maps": {
"TDATA": [ { "physical_name": "s_axis_cartesian_tdata" } ],
"TVALID": [ { "physical_name": "s_axis_cartesian_tvalid" } ]
}
},
"aclk_intf": {
"vlnv": "xilinx.com:signal:clock:1.0",
"abstraction_type": "xilinx.com:signal:clock_rtl:1.0",
"mode": "slave",
"parameters": {
"ASSOCIATED_BUSIF": [ { "value": "M_AXIS_DOUT:S_AXIS_PHASE:S_AXIS_CARTESIAN", "value_src": "constant", "usage": "all" } ],
"ASSOCIATED_RESET": [ { "value": "aresetn", "value_src": "constant", "usage": "all" } ],
"ASSOCIATED_CLKEN": [ { "value": "aclken", "value_src": "constant", "usage": "all" } ],
"FREQ_HZ": [ { "value": "1000000", "resolve_type": "user", "format": "long", "usage": "all" } ],
"FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"PHASE": [ { "value": "0.0", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ],
"CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
},
"port_maps": {
"CLK": [ { "physical_name": "aclk" } ]
}
},
"aresetn_intf": {
"vlnv": "xilinx.com:signal:reset:1.0",
"abstraction_type": "xilinx.com:signal:reset_rtl:1.0",
"mode": "slave",
"parameters": {
"POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ],
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
}
},
"aclken_intf": {
"vlnv": "xilinx.com:signal:clockenable:1.0",
"abstraction_type": "xilinx.com:signal:clockenable_rtl:1.0",
"mode": "slave",
"parameters": {
"POLARITY": [ { "value": "ACTIVE_HIGH", "value_src": "constant", "usage": "all" } ]
}
},
"M_AXIS_DOUT": {
"vlnv": "xilinx.com:interface:axis:1.0",
"abstraction_type": "xilinx.com:interface:axis_rtl:1.0",
"mode": "master",
"parameters": {
"TDATA_NUM_BYTES": [ { "value": "2", "value_src": "auto", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TDEST_WIDTH": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TID_WIDTH": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TUSER_WIDTH": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TREADY": [ { "value": "0", "value_src": "auto", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TSTRB": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TKEEP": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TLAST": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"FREQ_HZ": [ { "value": "100000000", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"PHASE": [ { "value": "0.0", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ],
"CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"LAYERED_METADATA": [ { "value": "undef", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
},
"port_maps": {
"TDATA": [ { "physical_name": "m_axis_dout_tdata" } ],
"TVALID": [ { "physical_name": "m_axis_dout_tvalid" } ]
}
}
}
}
}
}
@@ -0,0 +1,214 @@
{
"schema": "xilinx.com:schema:json_instance:1.0",
"ip_inst": {
"xci_name": "rotate_16b",
"component_reference": "xilinx.com:ip:cordic:6.0",
"ip_revision": "20",
"gen_directory": "../../../../multi_ch_cal.gen/sources_1/ip/rotate_16b",
"parameters": {
"component_parameters": {
"Component_Name": [ { "value": "rotate_16b", "resolve_type": "user", "usage": "all" } ],
"Functional_Selection": [ { "value": "Rotate", "resolve_type": "user", "usage": "all" } ],
"Architectural_Configuration": [ { "value": "Parallel", "resolve_type": "user", "usage": "all" } ],
"Pipelining_Mode": [ { "value": "Maximum", "resolve_type": "user", "usage": "all" } ],
"Data_Format": [ { "value": "SignedFraction", "resolve_type": "user", "usage": "all" } ],
"Phase_Format": [ { "value": "Scaled_Radians", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
"Input_Width": [ { "value": "16", "resolve_type": "user", "format": "long", "usage": "all" } ],
"Output_Width": [ { "value": "16", "resolve_type": "user", "format": "long", "usage": "all" } ],
"Round_Mode": [ { "value": "Truncate", "resolve_type": "user", "usage": "all" } ],
"Iterations": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "all" } ],
"Precision": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "all" } ],
"Coarse_Rotation": [ { "value": "true", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"Compensation_Scaling": [ { "value": "No_Scale_Compensation", "resolve_type": "user", "usage": "all" } ],
"cartesian_has_tuser": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"cartesian_tuser_width": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
"cartesian_has_tlast": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"phase_has_tuser": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"phase_tuser_width": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
"phase_has_tlast": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"flow_control": [ { "value": "NonBlocking", "resolve_type": "user", "usage": "all" } ],
"optimize_goal": [ { "value": "Performance", "resolve_type": "user", "usage": "all" } ],
"out_tready": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"out_tlast_behv": [ { "value": "Null", "resolve_type": "user", "usage": "all" } ],
"ACLKEN": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
"ARESETN": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ]
},
"model_parameters": {
"C_ARCHITECTURE": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_CORDIC_FUNCTION": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_COARSE_ROTATE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_DATA_FORMAT": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_XDEVICEFAMILY": [ { "value": "kintex7", "resolve_type": "generated", "usage": "all" } ],
"C_HAS_ACLKEN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_ACLK": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_CARTESIAN": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_PHASE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_ARESETN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_INPUT_WIDTH": [ { "value": "16", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_ITERATIONS": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_OUTPUT_WIDTH": [ { "value": "16", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_PHASE_FORMAT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_PIPELINE_MODE": [ { "value": "-2", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_PRECISION": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_ROUND_MODE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_SCALE_COMP": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_THROTTLE_SCHEME": [ { "value": "3", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_TLAST_RESOLUTION": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_PHASE_TUSER": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_PHASE_TLAST": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_S_AXIS_PHASE_TDATA_WIDTH": [ { "value": "16", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_S_AXIS_PHASE_TUSER_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_CARTESIAN_TUSER": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_HAS_S_AXIS_CARTESIAN_TLAST": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_S_AXIS_CARTESIAN_TDATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_S_AXIS_CARTESIAN_TUSER_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_M_AXIS_DOUT_TDATA_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ],
"C_M_AXIS_DOUT_TUSER_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ]
},
"project_parameters": {
"ARCHITECTURE": [ { "value": "kintex7" } ],
"BASE_BOARD_PART": [ { "value": "" } ],
"BOARD_CONNECTIONS": [ { "value": "" } ],
"DEVICE": [ { "value": "xc7k410t" } ],
"PACKAGE": [ { "value": "ffg900" } ],
"PREFHDL": [ { "value": "VERILOG" } ],
"SILICON_REVISION": [ { "value": "" } ],
"SIMULATOR_LANGUAGE": [ { "value": "MIXED" } ],
"SPEEDGRADE": [ { "value": "-2" } ],
"STATIC_POWER": [ { "value": "" } ],
"TEMPERATURE_GRADE": [ { "value": "" } ]
},
"runtime_parameters": {
"IPCONTEXT": [ { "value": "IP_Flow" } ],
"IPREVISION": [ { "value": "20" } ],
"MANAGED": [ { "value": "TRUE" } ],
"OUTPUTDIR": [ { "value": "../../../../multi_ch_cal.gen/sources_1/ip/rotate_16b" } ],
"SELECTEDSIMMODEL": [ { "value": "" } ],
"SHAREDDIR": [ { "value": "." } ],
"SWVERSION": [ { "value": "2023.2.1" } ],
"SYNTHESISFLOW": [ { "value": "OUT_OF_CONTEXT" } ]
}
},
"boundary": {
"ports": {
"aclk": [ { "direction": "in", "driver_value": "0x1" } ],
"s_axis_phase_tvalid": [ { "direction": "in", "driver_value": "0x0" } ],
"s_axis_phase_tdata": [ { "direction": "in", "size_left": "15", "size_right": "0", "driver_value": "0" } ],
"s_axis_cartesian_tvalid": [ { "direction": "in", "driver_value": "0x0" } ],
"s_axis_cartesian_tdata": [ { "direction": "in", "size_left": "31", "size_right": "0", "driver_value": "0" } ],
"m_axis_dout_tvalid": [ { "direction": "out", "driver_value": "0x0" } ],
"m_axis_dout_tdata": [ { "direction": "out", "size_left": "31", "size_right": "0", "driver_value": "0" } ]
},
"interfaces": {
"S_AXIS_CARTESIAN": {
"vlnv": "xilinx.com:interface:axis:1.0",
"abstraction_type": "xilinx.com:interface:axis_rtl:1.0",
"mode": "slave",
"parameters": {
"TDATA_NUM_BYTES": [ { "value": "4", "value_src": "auto", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TDEST_WIDTH": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TID_WIDTH": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TUSER_WIDTH": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TREADY": [ { "value": "0", "value_src": "auto", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TSTRB": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TKEEP": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TLAST": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"FREQ_HZ": [ { "value": "100000000", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"PHASE": [ { "value": "0.0", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ],
"CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"LAYERED_METADATA": [ { "value": "undef", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
},
"port_maps": {
"TDATA": [ { "physical_name": "s_axis_cartesian_tdata" } ],
"TVALID": [ { "physical_name": "s_axis_cartesian_tvalid" } ]
}
},
"aclk_intf": {
"vlnv": "xilinx.com:signal:clock:1.0",
"abstraction_type": "xilinx.com:signal:clock_rtl:1.0",
"mode": "slave",
"parameters": {
"ASSOCIATED_BUSIF": [ { "value": "M_AXIS_DOUT:S_AXIS_PHASE:S_AXIS_CARTESIAN", "value_src": "constant", "usage": "all" } ],
"ASSOCIATED_RESET": [ { "value": "aresetn", "value_src": "constant", "usage": "all" } ],
"ASSOCIATED_CLKEN": [ { "value": "aclken", "value_src": "constant", "usage": "all" } ],
"FREQ_HZ": [ { "value": "1000000", "resolve_type": "user", "format": "long", "usage": "all" } ],
"FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"PHASE": [ { "value": "0.0", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ],
"CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
},
"port_maps": {
"CLK": [ { "physical_name": "aclk" } ]
}
},
"aresetn_intf": {
"vlnv": "xilinx.com:signal:reset:1.0",
"abstraction_type": "xilinx.com:signal:reset_rtl:1.0",
"mode": "slave",
"parameters": {
"POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ],
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
}
},
"aclken_intf": {
"vlnv": "xilinx.com:signal:clockenable:1.0",
"abstraction_type": "xilinx.com:signal:clockenable_rtl:1.0",
"mode": "slave",
"parameters": {
"POLARITY": [ { "value": "ACTIVE_HIGH", "value_src": "constant", "usage": "all" } ]
}
},
"S_AXIS_PHASE": {
"vlnv": "xilinx.com:interface:axis:1.0",
"abstraction_type": "xilinx.com:interface:axis_rtl:1.0",
"mode": "slave",
"parameters": {
"TDATA_NUM_BYTES": [ { "value": "2", "value_src": "auto", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TDEST_WIDTH": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TID_WIDTH": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TUSER_WIDTH": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TREADY": [ { "value": "0", "value_src": "auto", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TSTRB": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TKEEP": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TLAST": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"FREQ_HZ": [ { "value": "100000000", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"PHASE": [ { "value": "0.0", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ],
"CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"LAYERED_METADATA": [ { "value": "undef", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
},
"port_maps": {
"TDATA": [ { "physical_name": "s_axis_phase_tdata" } ],
"TVALID": [ { "physical_name": "s_axis_phase_tvalid" } ]
}
},
"M_AXIS_DOUT": {
"vlnv": "xilinx.com:interface:axis:1.0",
"abstraction_type": "xilinx.com:interface:axis_rtl:1.0",
"mode": "master",
"parameters": {
"TDATA_NUM_BYTES": [ { "value": "4", "value_src": "auto", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TDEST_WIDTH": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TID_WIDTH": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"TUSER_WIDTH": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TREADY": [ { "value": "0", "value_src": "auto", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TSTRB": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TKEEP": [ { "value": "0", "value_src": "constant", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"HAS_TLAST": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"FREQ_HZ": [ { "value": "100000000", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
"PHASE": [ { "value": "0.0", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ],
"CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"LAYERED_METADATA": [ { "value": "undef", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
},
"port_maps": {
"TDATA": [ { "physical_name": "m_axis_dout_tdata" } ],
"TVALID": [ { "physical_name": "m_axis_dout_tvalid" } ]
}
}
}
}
}
}
@@ -0,0 +1,893 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// _ _ ____
// | | ___ ___| |__ / ___| __ _ ___
// _ | |/ _ \/ __| '_ \ | | _ / _` |/ _ \
// | |_| | (_) \__ \ | | | | |_| | (_| | (_) |
// \___/ \___/|___/_| |_| \____|\__,_|\___/
//
// Create Date: 2023/02/15 17:47:17
// Last Modified Date: 2023/03/04 12:30:00
// Design Name:
// Module Name: multi_ch_cal
// Project Name:
// Target Devices:
// Tool Versions:
// Description: 本程序用于
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// 20230304-1230
// 1. 修改相位差计算结果,原计算结果可能超出 [-pi,pi] 范围,现在会进行修正;
// 2. 修改 CORDIC IP 核相位输入输出为 Scaled Radians 模式;
// 3. 修改 [cnt_decim] 在校准完成状态下的值为 0;
// 4. 通道间相对延迟计算不正确,修改 [peak_index_num] 为无符号数即可;
// 5. 修改 [atan2_data_xxxx] 在累积结果长度小于 CORDIC AXIS 位宽时的符号位扩展方法。
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module multi_ch_cal
#(
parameter ADC_DATA_WIDTH = 12,
parameter PRBS = 128'b00000011000010100011110010001011001110101001111101000011100010010011011010110111101100011010010111011100110010101011111110000001, // inverse pseudorandom bit sequence, [0,flip(PRSB7)]
parameter PRBS_LEN = 128, // length of pseudorandom bit sequence
parameter INTERP_FACTOR = 8, // interpolation factor, max inter-channel delay ranges in [-INTERP_FACTOR+1,INTERP_FACTOR-1]
parameter ACCUM_SYMBOL_NUM = 16,
parameter CORDIC_WIDTH = 16, // input and output data width of cordic-ip-based atan2 and rotation operation
parameter CHANNEL_NUM = 2 // the channel number of current algorithm is LIMITED to 2
)
(
// clock & reset
input clk ,
input rst ,
// control interface
input ad9361_1_cal_start ,
output ad9361_1_cal_done ,
input ad9361_2_cal_start ,
output ad9361_2_cal_done ,
output ad9361_cal_result ,
output ad9361_cal_valid ,
input ad9361_recal ,
// input data interface
input [ADC_DATA_WIDTH-1 : 0] rx_ch1_i ,
input [ADC_DATA_WIDTH-1 : 0] rx_ch1_q ,
input [ADC_DATA_WIDTH-1 : 0] rx_ch2_i ,
input [ADC_DATA_WIDTH-1 : 0] rx_ch2_q ,
input [ADC_DATA_WIDTH-1 : 0] rx_ch3_i ,
input [ADC_DATA_WIDTH-1 : 0] rx_ch3_q ,
input [ADC_DATA_WIDTH-1 : 0] rx_ch4_i ,
input [ADC_DATA_WIDTH-1 : 0] rx_ch4_q ,
// output data interface
output [ADC_DATA_WIDTH-1 : 0] rx_cal_ch1_i ,
output [ADC_DATA_WIDTH-1 : 0] rx_cal_ch1_q ,
output [ADC_DATA_WIDTH-1 : 0] rx_cal_ch2_i ,
output [ADC_DATA_WIDTH-1 : 0] rx_cal_ch2_q ,
output [ADC_DATA_WIDTH-1 : 0] rx_cal_ch3_i ,
output [ADC_DATA_WIDTH-1 : 0] rx_cal_ch3_q ,
output [ADC_DATA_WIDTH-1 : 0] rx_cal_ch4_i ,
output [ADC_DATA_WIDTH-1 : 0] rx_cal_ch4_q
);
localparam STATE_IDLE = 2'd0; // idle state
localparam STATE_CAL_1 = 2'd1; // correlation, accumulation and peak finding
localparam STATE_CAL_2 = 2'd2; // phase calculation, rotation and delay compensation
localparam STATE_DONE = 2'd3; // done state
localparam signed POS_PI_2Q13_SCALED = 16'b001_00000_00000_000;
localparam signed NEG_PI_2Q13_SCALED = 16'b111_00000_00000_000;
integer i, j;
genvar m, n;
////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Center State Machine /////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// buffer input control signals (clock domain crossing from ps to pl clock domain)
reg ad9361_1_cal_start_d1 = 'b0;
reg ad9361_1_cal_start_d2 = 'b0;
reg ad9361_2_cal_start_d1 = 'b0;
reg ad9361_2_cal_start_d2 = 'b0;
reg ad9361_recal_d1 = 'b0;
reg ad9361_recal_d2 = 'b0;
always @(posedge clk) begin
ad9361_1_cal_start_d1 <= ad9361_1_cal_start;
ad9361_1_cal_start_d2 <= ad9361_1_cal_start_d1;
ad9361_2_cal_start_d1 <= ad9361_2_cal_start;
ad9361_2_cal_start_d2 <= ad9361_2_cal_start_d1;
ad9361_recal_d1 <= ad9361_recal;
ad9361_recal_d2 <= ad9361_recal_d1;
end
// center state machine
reg [ 1:0] curr_state = STATE_IDLE;
always @(posedge clk) begin
if (rst) begin
curr_state <= STATE_IDLE;
end
else begin
case (curr_state)
STATE_IDLE: begin
// move to next state when [ad9361_1_cal_start] asserts
curr_state <= ad9361_1_cal_start_d2 ? STATE_CAL_1 : STATE_IDLE;
end
STATE_CAL_1: begin
// move to next state when 1st cal finishes and [ad9361_2_cal_start] asserts
curr_state <= ad9361_1_cal_done ? STATE_CAL_2 : STATE_CAL_1;
end
STATE_CAL_2: begin
// move to next state when 2nd cal finishes
curr_state <= ad9361_2_cal_done ? STATE_DONE : STATE_CAL_2;
end
STATE_DONE: begin
// move to IDLE state when it needs to recal
curr_state <= (ad9361_recal_d2) ? STATE_IDLE : STATE_DONE;
end
default: begin
curr_state <= STATE_IDLE;
end
endcase
end
end
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// Accumulation /////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// state counter
reg [$clog2(INTERP_FACTOR)-1 : 0] cnt_decim = 'b0; // downsample counter, mod [INTERP_FACTOR]
reg [$clog2(PRBS_LEN)-1 : 0] cnt_chip_in = 'b0; // input chip counter, mod [PRBS_LEN]
reg [$clog2(PRBS_LEN)-1 : 0] pn_curr_addr = 'b0; // current local pn address, mod [PRBS_LEN]
reg [$clog2(ACCUM_SYMBOL_NUM)-1 : 0] cnt_symbol = 'b0; // accumulation symbol counter, mod [ACCUM_SYMBOL_NUM]
reg [$clog2(PRBS_LEN)-1 : 0] cnt_accum = 'b0; // accumulation result index indicator, mod [PRBS_LEN]
always @(posedge clk) begin
// downsample counter, each clock cycles increase by 1 during calibration state
if (rst) begin
cnt_decim <= 'b0;
end
else begin
case (curr_state)
STATE_IDLE : cnt_decim <= 'b0;
STATE_CAL_1: cnt_decim <= cnt_decim + 1'b1;
STATE_CAL_2: cnt_decim <= cnt_decim + 1'b1;
STATE_DONE : cnt_decim <= 'b0;
default : cnt_decim <= 'b0;
endcase
end
end
always @(posedge clk) begin
if (rst) begin
cnt_chip_in <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
// reset at IDLE state
cnt_chip_in <= 'b0;
end
else if (cnt_decim == INTERP_FACTOR-1) begin
// each time the number of samples received is [INTERP_FACTOR], increase the counter by 1,
// indicating a new chip is received
cnt_chip_in <= cnt_chip_in + 1'b1;
end
else begin
cnt_chip_in <= cnt_chip_in;
end
end
always @(posedge clk) begin
if (rst) begin
pn_curr_addr <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
// reset at IDLE state
pn_curr_addr <= 'b0;
end
else if (cnt_decim == INTERP_FACTOR-1) begin
// each time the number of samples received is [INTERP_FACTOR], if the number of complete symbols
// accumulated is [ACCUM_SYMBOL_NUM], increase the address by 2; otherwise by 1. The increasing-by-2
// behaviour is analogous to `circshift` operation in MATLAB.
pn_curr_addr <= (cnt_symbol == ACCUM_SYMBOL_NUM-1 && cnt_chip_in == PRBS_LEN-1) ? pn_curr_addr + 2'd2 : pn_curr_addr + 2'd1;
end
else begin
pn_curr_addr <= pn_curr_addr;
end
end
always @(posedge clk) begin
if (rst) begin
cnt_symbol <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
// reset at IDLE state
cnt_symbol <= 'b0;
end
else if (cnt_chip_in == PRBS_LEN-1 && cnt_decim == INTERP_FACTOR-1) begin
// each time the number of complete chips received is [PRBS_LEN], increase the counter by 1,
// indicating a complete symbol is received
cnt_symbol <= cnt_symbol + 1'b1;
end
else begin
cnt_symbol <= cnt_symbol;
end
end
always @(posedge clk) begin
if (rst) begin
cnt_accum <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
// reset at IDLE state
cnt_accum <= 'b0;
end
else if (cnt_symbol == ACCUM_SYMBOL_NUM-1 && cnt_chip_in == PRBS_LEN-1 && cnt_decim == INTERP_FACTOR-1) begin
// each time the number of complete symbols received is [ACCUM_SYMBOL_NUM], increase the counter by 1,
// indicating the accumulation of current pn code phased is finished
cnt_accum <= cnt_accum + 1'b1;
end
else begin
cnt_accum <= cnt_accum;
end
end
// accumulate the msb of input data at different sample position
localparam MSB_ACCUM_LEN = $clog2(PRBS_LEN*ACCUM_SYMBOL_NUM)+2; // extra 2 bits to ensure signed operation and to prevent overflow
reg signed [MSB_ACCUM_LEN-1 : 0] msb_accum_i [0 : CHANNEL_NUM-1][0 : INTERP_FACTOR-1];
reg signed [MSB_ACCUM_LEN-1 : 0] msb_accum_q [0 : CHANNEL_NUM-1][0 : INTERP_FACTOR-1];
always @(posedge clk) begin
if (rst) begin
for (i = 0; i < CHANNEL_NUM; i = i + 1) begin
for (j = 0; j < INTERP_FACTOR; j = j + 1) begin
msb_accum_i[i][j] <= 'b0;
msb_accum_q[i][j] <= 'b0;
end
end
end
else if (curr_state == STATE_CAL_1) begin
if (cnt_symbol == 'b0 && cnt_chip_in == 'b0) begin
// set the initial value to 1 when msb equals current pn code, otherwise set to -1
msb_accum_i[0][cnt_decim] <= (rx_ch2_i[ADC_DATA_WIDTH-1] == PRBS[pn_curr_addr]) ? 1'b1 : -1'b1;
msb_accum_q[0][cnt_decim] <= (rx_ch2_q[ADC_DATA_WIDTH-1] == PRBS[pn_curr_addr]) ? 1'b1 : -1'b1;
msb_accum_i[1][cnt_decim] <= (rx_ch4_i[ADC_DATA_WIDTH-1] == PRBS[pn_curr_addr]) ? 1'b1 : -1'b1;
msb_accum_q[1][cnt_decim] <= (rx_ch4_q[ADC_DATA_WIDTH-1] == PRBS[pn_curr_addr]) ? 1'b1 : -1'b1;
end
else begin
// increase when msb equals current pn code, otherwise decrease
msb_accum_i[0][cnt_decim] <= (rx_ch2_i[ADC_DATA_WIDTH-1] == PRBS[pn_curr_addr]) ? (msb_accum_i[0][cnt_decim] + 1'b1) : (msb_accum_i[0][cnt_decim] - 1'b1);
msb_accum_q[0][cnt_decim] <= (rx_ch2_q[ADC_DATA_WIDTH-1] == PRBS[pn_curr_addr]) ? (msb_accum_q[0][cnt_decim] + 1'b1) : (msb_accum_q[0][cnt_decim] - 1'b1);
msb_accum_i[1][cnt_decim] <= (rx_ch4_i[ADC_DATA_WIDTH-1] == PRBS[pn_curr_addr]) ? (msb_accum_i[1][cnt_decim] + 1'b1) : (msb_accum_i[1][cnt_decim] - 1'b1);
msb_accum_q[1][cnt_decim] <= (rx_ch4_q[ADC_DATA_WIDTH-1] == PRBS[pn_curr_addr]) ? (msb_accum_q[1][cnt_decim] + 1'b1) : (msb_accum_q[1][cnt_decim] - 1'b1);
end
end
else begin
for (i = 0; i < CHANNEL_NUM; i = i + 1) begin
for (j = 0; j < INTERP_FACTOR; j = j + 1) begin
msb_accum_i[i][j] <= 'b0;
msb_accum_q[i][j] <= 'b0;
end
end
end
end
// flag signal indicating the accumulation within one symbol (i.e. one kind of pn phase) is finished
reg symbol_msb_accum_valid = 'b0;
// preserve pn phase index for approximate moduli module
reg [$clog2(PRBS_LEN)-1 : 0] symbol_msb_accum_index = 'b0;
always @(posedge clk) begin
if (rst) begin
symbol_msb_accum_valid <= 'b0;
end
else if (cnt_symbol == ACCUM_SYMBOL_NUM-1 && cnt_chip_in == PRBS_LEN-1 && cnt_decim == INTERP_FACTOR-1) begin
symbol_msb_accum_valid <= 1'b1;
end
else begin
symbol_msb_accum_valid <= 'b0;
end
end
always @(posedge clk) begin
if (rst) begin
symbol_msb_accum_index <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
symbol_msb_accum_index <= 'b0;
end
else if (cnt_symbol == ACCUM_SYMBOL_NUM-1 && cnt_chip_in == PRBS_LEN-1 && cnt_decim == INTERP_FACTOR-1) begin
symbol_msb_accum_index <= cnt_accum;
end
else begin
symbol_msb_accum_index <= symbol_msb_accum_index;
end
end
// truncate or shift to fit in 26-bit data format & get the absolute value
wire [25 : 0] msb_accum_i_26b [0 : CHANNEL_NUM-1][0 : INTERP_FACTOR-1];
wire [25 : 0] msb_accum_q_26b [0 : CHANNEL_NUM-1][0 : INTERP_FACTOR-1];
wire [25 : 0] msb_accum_abs [0 : CHANNEL_NUM-1][0 : INTERP_FACTOR-1];
wire msb_accum_abs_valid [0 : CHANNEL_NUM-1][0 : INTERP_FACTOR-1];
generate
for (m = 0; m < CHANNEL_NUM; m = m + 1) begin
for (n = 0; n < INTERP_FACTOR; n = n + 1) begin
assign msb_accum_i_26b[m][n] = (MSB_ACCUM_LEN > 26) ? msb_accum_i[m][n][MSB_ACCUM_LEN-1 -: 26] : {{(26-MSB_ACCUM_LEN){msb_accum_i[m][n][MSB_ACCUM_LEN-1]}},msb_accum_i[m][n]};
assign msb_accum_q_26b[m][n] = (MSB_ACCUM_LEN > 26) ? msb_accum_q[m][n][MSB_ACCUM_LEN-1 -: 26] : {{(26-MSB_ACCUM_LEN){msb_accum_q[m][n][MSB_ACCUM_LEN-1]}},msb_accum_q[m][n]};
ApproxModuli_26bit u_msb_accum_abs
(
.clk (clk ),
.din_valid (symbol_msb_accum_valid ),
.din_I (msb_accum_i_26b[m][n] ),
.din_Q (msb_accum_q_26b[m][n] ),
.dout_valid (msb_accum_abs_valid[m][n] ),
.dout (msb_accum_abs[m][n] )
);
end
end
endgenerate
// record the peak index and corresponding value
reg [25 : 0] msb_accum_abs_peak [0 : CHANNEL_NUM-1][0 : INTERP_FACTOR-1];
reg [$clog2(PRBS_LEN)-1 : 0] msb_accum_abs_peak_index [0 : CHANNEL_NUM-1][0 : INTERP_FACTOR-1];
generate
for (m = 0; m < CHANNEL_NUM; m = m + 1) begin
for (n = 0; n < INTERP_FACTOR; n = n + 1) begin
always @(posedge clk) begin
if (rst) begin
msb_accum_abs_peak[m][n] <= 'b0;
msb_accum_abs_peak_index[m][n] <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
msb_accum_abs_peak[m][n] <= 'b0;
msb_accum_abs_peak_index[m][n] <= 'b0;
end
else if (msb_accum_abs_valid[m][n]) begin
msb_accum_abs_peak[m][n] <= (msb_accum_abs_peak[m][n] >= msb_accum_abs[m][n]) ? msb_accum_abs_peak[m][n] : msb_accum_abs[m][n];
msb_accum_abs_peak_index[m][n] <= (msb_accum_abs_peak[m][n] >= msb_accum_abs[m][n]) ? msb_accum_abs_peak_index[m][n] : symbol_msb_accum_index;
end
end
end
end
endgenerate
// accumulate input data at the 1st sample position and the 1st and 2nd chip position
// during the last msb accumulation cycle
localparam DATA_ACCUM_LEN = $clog2(ACCUM_SYMBOL_NUM)+ADC_DATA_WIDTH;
reg signed [DATA_ACCUM_LEN-1 : 0] rx_i_accum [0 : CHANNEL_NUM-1][0 : 1];
reg signed [DATA_ACCUM_LEN-1 : 0] rx_q_accum [0 : CHANNEL_NUM-1][0 : 1];
always @(posedge clk) begin
if (rst) begin
for(i = 0; i < CHANNEL_NUM; i = i + 1) begin
for(j = 0; j < 2; j = j + 1) begin
rx_i_accum[i][j] <= 'b0;
rx_q_accum[i][j] <= 'b0;
end
end
end
else if (curr_state == STATE_IDLE) begin
for(i = 0; i < CHANNEL_NUM; i = i + 1) begin
for(j = 0; j < 2; j = j + 1) begin
// reset at IDLE state
rx_i_accum[i][j] <= 'b0;
rx_q_accum[i][j] <= 'b0;
end
end
end
else if (cnt_accum == PRBS_LEN-1 && cnt_decim == 'b0) begin
case (cnt_chip_in)
1'b0: begin
rx_i_accum[0][0] <= rx_i_accum[0][0] + {{(DATA_ACCUM_LEN-ADC_DATA_WIDTH){rx_ch2_i[ADC_DATA_WIDTH-1]}},rx_ch2_i};
rx_q_accum[0][0] <= rx_q_accum[0][0] + {{(DATA_ACCUM_LEN-ADC_DATA_WIDTH){rx_ch2_q[ADC_DATA_WIDTH-1]}},rx_ch2_q};
rx_i_accum[1][0] <= rx_i_accum[1][0] + {{(DATA_ACCUM_LEN-ADC_DATA_WIDTH){rx_ch4_i[ADC_DATA_WIDTH-1]}},rx_ch4_i};
rx_q_accum[1][0] <= rx_q_accum[1][0] + {{(DATA_ACCUM_LEN-ADC_DATA_WIDTH){rx_ch4_q[ADC_DATA_WIDTH-1]}},rx_ch4_q};
end
1'b1: begin
rx_i_accum[0][1] <= rx_i_accum[0][1] + {{(DATA_ACCUM_LEN-ADC_DATA_WIDTH){rx_ch2_i[ADC_DATA_WIDTH-1]}},rx_ch2_i};
rx_q_accum[0][1] <= rx_q_accum[0][1] + {{(DATA_ACCUM_LEN-ADC_DATA_WIDTH){rx_ch2_q[ADC_DATA_WIDTH-1]}},rx_ch2_q};
rx_i_accum[1][1] <= rx_i_accum[1][1] + {{(DATA_ACCUM_LEN-ADC_DATA_WIDTH){rx_ch4_i[ADC_DATA_WIDTH-1]}},rx_ch4_i};
rx_q_accum[1][1] <= rx_q_accum[1][1] + {{(DATA_ACCUM_LEN-ADC_DATA_WIDTH){rx_ch4_q[ADC_DATA_WIDTH-1]}},rx_ch4_q};
end
default: begin
for(i = 0; i < CHANNEL_NUM; i = i + 1) begin
for(j = 0; j < 2; j = j + 1) begin
rx_i_accum[i][j] <= rx_i_accum[i][j];
rx_q_accum[i][j] <= rx_q_accum[i][j];
end
end
end
endcase
end
else begin
for(i = 0; i < CHANNEL_NUM; i = i + 1) begin
for(j = 0; j < 2; j = j + 1) begin
rx_i_accum[i][j] <= rx_i_accum[i][j];
rx_q_accum[i][j] <= rx_q_accum[i][j];
end
end
end
end
// flag signal indicating the accumulation stage of calculation is finished
reg ad9361_1_cal_done_buf = 'b0;
assign ad9361_1_cal_done = ad9361_1_cal_done_buf;
always @(posedge clk) begin
if (rst) begin
ad9361_1_cal_done_buf <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
// reset at IDLE state
ad9361_1_cal_done_buf <= 'b0;
end
else if (cnt_accum == PRBS_LEN-1 && cnt_symbol == ACCUM_SYMBOL_NUM-1 && cnt_chip_in == PRBS_LEN-1 && cnt_decim == INTERP_FACTOR-1) begin
ad9361_1_cal_done_buf <= 1'b1;
end
else begin
ad9361_1_cal_done_buf <= ad9361_1_cal_done_buf;
end
end
////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// Accumulation /////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// indicating the peak finding process is finished
reg peak_index_valid = 'b0;
always @(posedge clk) begin
if (rst) begin
peak_index_valid <= 'b0;
end
else if (curr_state == STATE_CAL_2) begin
peak_index_valid <= msb_accum_abs_valid[0][0] ? 1'b1 : peak_index_valid;
end
else begin
peak_index_valid <= 'b0;
end
end
// count the number of same peak index
reg [$clog2(INTERP_FACTOR)-1 : 0] peak_index_num [0 : CHANNEL_NUM-1];
reg peak_index_num_valid = 'b0;
reg signed [$clog2(INTERP_FACTOR) : 0] peak_index_num_diff = 'b0; // currently limit channel number to 2
reg peak_index_num_diff_valid = 'b0;
always @(posedge clk) begin
if (rst) begin
for (i = 0; i < CHANNEL_NUM; i = i + 1) begin
peak_index_num[i] <= 'b0;
end
end
else if (curr_state == STATE_CAL_2 && cnt_chip_in == 2'd2) begin
for (i = 0; i < CHANNEL_NUM; i = i + 1) begin
if (msb_accum_abs_peak_index[i][cnt_decim] == msb_accum_abs_peak_index[i][0]) begin
peak_index_num[i] <= cnt_decim;
end
else begin
peak_index_num[i] <= peak_index_num[i];
end
end
end
end
always @(posedge clk) begin
if (rst) begin
peak_index_num_valid <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
peak_index_num_valid <= 'b0;
end
else if (curr_state == STATE_CAL_2 && cnt_chip_in == 2'd2 && cnt_decim == INTERP_FACTOR-1) begin
peak_index_num_valid <= 1'b1;
end
else begin
peak_index_num_valid <= 'b0;
end
end
always @(posedge clk) begin
if (rst) begin
peak_index_num_diff <= 'b0;
end
else if (peak_index_num_valid) begin
peak_index_num_diff <= peak_index_num[1] - peak_index_num[0];
end
end
always @(posedge clk) begin
if (rst) begin
peak_index_num_diff_valid <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
peak_index_num_diff_valid <= 'b0;
end
else begin
peak_index_num_diff_valid <= peak_index_num_valid;
end
end
//
reg [$clog2(PRBS_LEN)-1 : 0] peak_index_plus_minus [0 : 2];
always @(posedge clk) begin
if (rst) begin
for (i = 0; i < 3; i = i + 1) begin
peak_index_plus_minus[i] <= 'b0;
end
end
else if (curr_state == STATE_CAL_2) begin
peak_index_plus_minus[0] <= msb_accum_abs_peak_index[0][0];
peak_index_plus_minus[1] <= msb_accum_abs_peak_index[0][0] - 1'b1;
peak_index_plus_minus[2] <= msb_accum_abs_peak_index[0][0] + 1'b1;
end
end
// get target downsample position
localparam CORDIC_LATENCY = 20;
reg target_accum_index [0 : CHANNEL_NUM-1];
reg target_accum_index_valid = 'b0;
reg [$clog2(INTERP_FACTOR+CORDIC_LATENCY)-1 : 0] relative_delay = 'b0; // compensate cordic delay
reg ad9361_cal_result_buf = 'b0;
assign ad9361_cal_result = ad9361_cal_result_buf;
always @(posedge clk) begin
if (rst) begin
for (i = 0; i < CHANNEL_NUM; i = i + 1) begin
target_accum_index[i] <= 'b0;
end
end
else if (peak_index_num_diff_valid) begin
if (msb_accum_abs_peak_index[1][0] == peak_index_plus_minus[0]) begin
target_accum_index[0] <= 1'b0;
target_accum_index[1] <= 1'b0;
relative_delay <= peak_index_num_diff + (CORDIC_LATENCY-1);
ad9361_cal_result_buf <= 1'b1;
end
else if (msb_accum_abs_peak_index[1][0] == peak_index_plus_minus[1]) begin
target_accum_index[0] <= 1'b0;
target_accum_index[1] <= 1'b1;
relative_delay <= peak_index_num_diff + INTERP_FACTOR + (CORDIC_LATENCY-1);
ad9361_cal_result_buf <= 1'b1;
end
else if (msb_accum_abs_peak_index[1][0] == peak_index_plus_minus[2]) begin
target_accum_index[0] <= 1'b1;
target_accum_index[1] <= 1'b0;
relative_delay <= peak_index_num_diff - INTERP_FACTOR + (CORDIC_LATENCY-1);
ad9361_cal_result_buf <= 1'b1;
end
else begin
target_accum_index[0] <= 1'b0;
target_accum_index[1] <= 1'b0;
relative_delay <= peak_index_num_diff + (CORDIC_LATENCY-1);
ad9361_cal_result_buf <= 1'b0;
end
end
else begin
for (i = 0; i < CHANNEL_NUM; i = i + 1) begin
target_accum_index[i] <= target_accum_index[i];
end
relative_delay <= relative_delay;
end
end
always @(posedge clk) begin
if (rst) begin
target_accum_index_valid <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
target_accum_index_valid <= 'b0;
end
else begin
target_accum_index_valid <= peak_index_num_diff_valid;
end
end
// get target data
reg [DATA_ACCUM_LEN-1 : 0] rx_i_accum_target [0 : CHANNEL_NUM-1];
reg [DATA_ACCUM_LEN-1 : 0] rx_q_accum_target [0 : CHANNEL_NUM-1];
reg rx_accum_target_valid = 'b0;
always @(posedge clk) begin
if (rst) begin
for (i = 0; i < CHANNEL_NUM; i = i + 1) begin
rx_i_accum_target[i] <= 'b0;
rx_q_accum_target[i] <= 'b0;
end
end
else if (target_accum_index_valid) begin
for (i = 0; i < CHANNEL_NUM; i = i + 1) begin
rx_i_accum_target[i] <= rx_i_accum[i][target_accum_index[i]];
rx_q_accum_target[i] <= rx_q_accum[i][target_accum_index[i]];
end
end
end
always @(posedge clk) begin
if (rst) begin
rx_accum_target_valid <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
rx_accum_target_valid <= 'b0;
end
else begin
rx_accum_target_valid <= target_accum_index_valid;
end
end
// calculate phase difference
localparam AXIS_CORDIC_WIDTH = 8*((CORDIC_WIDTH-1)/8+1);
wire [AXIS_CORDIC_WIDTH-1 : 0] atan2_data_real [0 : CHANNEL_NUM-1];
wire [AXIS_CORDIC_WIDTH-1 : 0] atan2_data_imag [0 : CHANNEL_NUM-1];
wire [2*AXIS_CORDIC_WIDTH-1:0] atan2_data [0 : CHANNEL_NUM-1];
wire atan2_valid_i [0 : CHANNEL_NUM-1];
wire signed [AXIS_CORDIC_WIDTH-1:0] atan2_phase [0 : CHANNEL_NUM-1];
wire atan2_valid_o [0 : CHANNEL_NUM-1];
generate
for (m = 0; m < CHANNEL_NUM; m = m + 1) begin
assign atan2_data_real[m] = (DATA_ACCUM_LEN > AXIS_CORDIC_WIDTH) ? rx_i_accum_target[m][DATA_ACCUM_LEN-1 -: AXIS_CORDIC_WIDTH] : {{(AXIS_CORDIC_WIDTH-DATA_ACCUM_LEN){rx_i_accum_target[m][DATA_ACCUM_LEN-1]}},rx_i_accum_target[m]};
assign atan2_data_imag[m] = (DATA_ACCUM_LEN > AXIS_CORDIC_WIDTH) ? rx_q_accum_target[m][DATA_ACCUM_LEN-1 -: AXIS_CORDIC_WIDTH] : {{(AXIS_CORDIC_WIDTH-DATA_ACCUM_LEN){rx_q_accum_target[m][DATA_ACCUM_LEN-1]}},rx_q_accum_target[m]};
assign atan2_data[m] = {atan2_data_imag[m],atan2_data_real[m]};
assign atan2_valid_i[m] = rx_accum_target_valid;
atan2_16b u_atan2
(
.aclk (clk ), // input wire aclk
.s_axis_cartesian_tvalid(atan2_valid_i[m] ), // input wire s_axis_cartesian_tvalid
.s_axis_cartesian_tdata (atan2_data[m] ), // input wire [31 : 0] s_axis_cartesian_tdata
.m_axis_dout_tvalid (atan2_valid_o[m] ), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata (atan2_phase[m] ) // output wire [15 : 0] m_axis_dout_tdata
);
end
endgenerate
reg signed [AXIS_CORDIC_WIDTH-1:0] phase_diff_raw = 'b0;
reg phase_diff_raw_valid = 'b0;
reg signed [AXIS_CORDIC_WIDTH-1:0] phase_diff = 'b0;
reg phase_diff_valid = 'b0;
always @(posedge clk) begin
if (rst) begin
phase_diff_raw <= 'b0;
end
else if (atan2_valid_o[0]) begin
// here calculate the phase difference from target channel to another channel,
// then rotate another channel to target channel
phase_diff_raw <= atan2_phase[0] - atan2_phase[1];
end
else begin
phase_diff_raw <= phase_diff_raw;
end
end
always @(posedge clk) begin
if (rst) begin
phase_diff_raw_valid <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
phase_diff_raw_valid <= 'b0;
end
else if (atan2_valid_o[0]) begin
phase_diff_raw_valid <= 1'b1;
end
else begin
phase_diff_raw_valid <= phase_diff_raw_valid;
end
end
always @(posedge clk) begin
if (rst) begin
phase_diff <= 'b0;
end
else if (phase_diff_raw_valid) begin
if (phase_diff_raw > POS_PI_2Q13_SCALED) begin
phase_diff <= phase_diff_raw - (2*POS_PI_2Q13_SCALED);
end
else if (phase_diff_raw < NEG_PI_2Q13_SCALED) begin
phase_diff <= phase_diff_raw + (2*POS_PI_2Q13_SCALED);
end
else begin
phase_diff <= phase_diff_raw;
end
end
end
always @(posedge clk) begin
if (rst) begin
phase_diff_valid <= 'b0;
end
else if (curr_state == STATE_IDLE) begin
phase_diff_valid <= 'b0;
end
else begin
phase_diff_valid <= phase_diff_raw_valid;
end
end
// rotate the 3rd and 4th channel
wire rotate_phase_valid;
wire [AXIS_CORDIC_WIDTH-1 : 0] rotate_phase_data;
wire rotate_cart_valid;
wire [AXIS_CORDIC_WIDTH-1 : 0] rotate_cart_ch3_data_real;
wire [AXIS_CORDIC_WIDTH-1 : 0] rotate_cart_ch3_data_imag;
wire [AXIS_CORDIC_WIDTH-1 : 0] rotate_cart_ch4_data_real;
wire [AXIS_CORDIC_WIDTH-1 : 0] rotate_cart_ch4_data_imag;
wire [2*AXIS_CORDIC_WIDTH-1 : 0] rotate_cart_ch3_data;
wire [2*AXIS_CORDIC_WIDTH-1 : 0] rotate_cart_ch4_data;
wire rotate_dout_ch3_valid;
wire rotate_dout_ch4_valid;
wire [2*AXIS_CORDIC_WIDTH-1 : 0] rotate_dout_ch3_data;
wire [2*AXIS_CORDIC_WIDTH-1 : 0] rotate_dout_ch4_data;
wire [AXIS_CORDIC_WIDTH-1 : 0] rx_ch3_rotate_i;
wire [AXIS_CORDIC_WIDTH-1 : 0] rx_ch3_rotate_q;
wire [AXIS_CORDIC_WIDTH-1 : 0] rx_ch4_rotate_i;
wire [AXIS_CORDIC_WIDTH-1 : 0] rx_ch4_rotate_q;
assign rotate_phase_valid = phase_diff_valid;
assign rotate_phase_data = phase_diff;
assign rotate_cart_valid = 1'b1;
assign rotate_cart_ch3_data_real = (ADC_DATA_WIDTH > AXIS_CORDIC_WIDTH) ? rx_ch3_i[ADC_DATA_WIDTH-1 -: AXIS_CORDIC_WIDTH] : {rx_ch3_i,{(AXIS_CORDIC_WIDTH-ADC_DATA_WIDTH){1'b0}}};
assign rotate_cart_ch3_data_imag = (ADC_DATA_WIDTH > AXIS_CORDIC_WIDTH) ? rx_ch3_q[ADC_DATA_WIDTH-1 -: AXIS_CORDIC_WIDTH] : {rx_ch3_q,{(AXIS_CORDIC_WIDTH-ADC_DATA_WIDTH){1'b0}}};
assign rotate_cart_ch4_data_real = (ADC_DATA_WIDTH > AXIS_CORDIC_WIDTH) ? rx_ch4_i[ADC_DATA_WIDTH-1 -: AXIS_CORDIC_WIDTH] : {rx_ch4_i,{(AXIS_CORDIC_WIDTH-ADC_DATA_WIDTH){1'b0}}};
assign rotate_cart_ch4_data_imag = (ADC_DATA_WIDTH > AXIS_CORDIC_WIDTH) ? rx_ch4_q[ADC_DATA_WIDTH-1 -: AXIS_CORDIC_WIDTH] : {rx_ch4_q,{(AXIS_CORDIC_WIDTH-ADC_DATA_WIDTH){1'b0}}};
assign rotate_cart_ch3_data = {rotate_cart_ch3_data_imag,rotate_cart_ch3_data_real};
assign rotate_cart_ch4_data = {rotate_cart_ch4_data_imag,rotate_cart_ch4_data_real};
assign {rx_ch3_rotate_q,rx_ch3_rotate_i} = rotate_dout_ch3_data;
assign {rx_ch4_rotate_q,rx_ch4_rotate_i} = rotate_dout_ch4_data;
rotate_16b u_rotate_16b_ch3
(
.aclk (clk ), // input wire aclk
.s_axis_phase_tvalid (rotate_phase_valid ), // input wire s_axis_phase_tvalid
.s_axis_phase_tdata (rotate_phase_data ), // input wire [15 : 0] s_axis_phase_tdata
.s_axis_cartesian_tvalid(rotate_cart_valid ), // input wire s_axis_cartesian_tvalid
.s_axis_cartesian_tdata (rotate_cart_ch3_data ), // input wire [31 : 0] s_axis_cartesian_tdata
.m_axis_dout_tvalid (rotate_dout_ch3_valid ), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata (rotate_dout_ch3_data ) // output wire [31 : 0] m_axis_dout_tdata
);
rotate_16b u_rotate_16b_ch4
(
.aclk (clk ), // input wire aclk
.s_axis_phase_tvalid (rotate_phase_valid ), // input wire s_axis_phase_tvalid
.s_axis_phase_tdata (rotate_phase_data ), // input wire [15 : 0] s_axis_phase_tdata
.s_axis_cartesian_tvalid(rotate_cart_valid ), // input wire s_axis_cartesian_tvalid
.s_axis_cartesian_tdata (rotate_cart_ch4_data ), // input wire [31 : 0] s_axis_cartesian_tdata
.m_axis_dout_tvalid (rotate_dout_ch4_valid ), // output wire m_axis_dout_tvalid
.m_axis_dout_tdata (rotate_dout_ch4_data ) // output wire [31 : 0] m_axis_dout_tdata
);
localparam TOTAL_LATENCY = CORDIC_LATENCY+INTERP_FACTOR-1;
reg [ADC_DATA_WIDTH-1 : 0] rx_ch1_i_delay [0 : TOTAL_LATENCY-1];
reg [ADC_DATA_WIDTH-1 : 0] rx_ch1_q_delay [0 : TOTAL_LATENCY-1];
reg [ADC_DATA_WIDTH-1 : 0] rx_ch2_i_delay [0 : TOTAL_LATENCY-1];
reg [ADC_DATA_WIDTH-1 : 0] rx_ch2_q_delay [0 : TOTAL_LATENCY-1];
always @(posedge clk) begin
if (rst) begin
for (i = 0; i < TOTAL_LATENCY; i = i + 1) begin
rx_ch1_i_delay[i] <= 'b0;
rx_ch1_q_delay[i] <= 'b0;
rx_ch2_i_delay[i] <= 'b0;
rx_ch2_q_delay[i] <= 'b0;
end
end
else begin
for (i = 1; i < TOTAL_LATENCY; i = i + 1) begin
rx_ch1_i_delay[i] <= rx_ch1_i_delay[i-1];
rx_ch1_q_delay[i] <= rx_ch1_q_delay[i-1];
rx_ch2_i_delay[i] <= rx_ch2_i_delay[i-1];
rx_ch2_q_delay[i] <= rx_ch2_q_delay[i-1];
end
rx_ch1_i_delay[0] <= rx_ch1_i;
rx_ch1_q_delay[0] <= rx_ch1_q;
rx_ch2_i_delay[0] <= rx_ch2_i;
rx_ch2_q_delay[0] <= rx_ch2_q;
end
end
reg [ADC_DATA_WIDTH-1 : 0] rx_cal_ch1_i_buf = 'b0;
reg [ADC_DATA_WIDTH-1 : 0] rx_cal_ch1_q_buf = 'b0;
reg [ADC_DATA_WIDTH-1 : 0] rx_cal_ch2_i_buf = 'b0;
reg [ADC_DATA_WIDTH-1 : 0] rx_cal_ch2_q_buf = 'b0;
reg [ADC_DATA_WIDTH-1 : 0] rx_cal_ch3_i_buf = 'b0;
reg [ADC_DATA_WIDTH-1 : 0] rx_cal_ch3_q_buf = 'b0;
reg [ADC_DATA_WIDTH-1 : 0] rx_cal_ch4_i_buf = 'b0;
reg [ADC_DATA_WIDTH-1 : 0] rx_cal_ch4_q_buf = 'b0;
assign rx_cal_ch1_i = rx_cal_ch1_i_buf;
assign rx_cal_ch1_q = rx_cal_ch1_q_buf;
assign rx_cal_ch2_i = rx_cal_ch2_i_buf;
assign rx_cal_ch2_q = rx_cal_ch2_q_buf;
assign rx_cal_ch3_i = rx_cal_ch3_i_buf;
assign rx_cal_ch3_q = rx_cal_ch3_q_buf;
assign rx_cal_ch4_i = rx_cal_ch4_i_buf;
assign rx_cal_ch4_q = rx_cal_ch4_q_buf;
always @(posedge clk) begin
if (rst) begin
rx_cal_ch1_i_buf <= 'b0;
rx_cal_ch1_q_buf <= 'b0;
rx_cal_ch2_i_buf <= 'b0;
rx_cal_ch2_q_buf <= 'b0;
rx_cal_ch3_i_buf <= 'b0;
rx_cal_ch3_q_buf <= 'b0;
rx_cal_ch4_i_buf <= 'b0;
rx_cal_ch4_q_buf <= 'b0;
end
else if (rotate_dout_ch3_valid) begin
rx_cal_ch1_i_buf <= rx_ch1_i_delay[relative_delay];
rx_cal_ch1_q_buf <= rx_ch1_q_delay[relative_delay];
rx_cal_ch2_i_buf <= -rx_ch2_i_delay[relative_delay];
rx_cal_ch2_q_buf <= -rx_ch2_q_delay[relative_delay];
rx_cal_ch3_i_buf <= rx_ch3_rotate_i[AXIS_CORDIC_WIDTH-1 -: ADC_DATA_WIDTH];
rx_cal_ch3_q_buf <= rx_ch3_rotate_q[AXIS_CORDIC_WIDTH-1 -: ADC_DATA_WIDTH];
rx_cal_ch4_i_buf <= -rx_ch4_rotate_i[AXIS_CORDIC_WIDTH-1 -: ADC_DATA_WIDTH];
rx_cal_ch4_q_buf <= -rx_ch4_rotate_q[AXIS_CORDIC_WIDTH-1 -: ADC_DATA_WIDTH];
end
else begin
rx_cal_ch1_i_buf <= rx_ch1_i;
rx_cal_ch1_q_buf <= rx_ch1_q;
rx_cal_ch2_i_buf <= rx_ch2_i;
rx_cal_ch2_q_buf <= rx_ch2_q;
rx_cal_ch3_i_buf <= rx_ch3_i;
rx_cal_ch3_q_buf <= rx_ch3_q;
rx_cal_ch4_i_buf <= rx_ch4_i;
rx_cal_ch4_q_buf <= rx_ch4_q;
end
end
//
reg ad9361_2_cal_done_buf = 'b0;
assign ad9361_2_cal_done = ad9361_2_cal_done_buf;
assign ad9361_cal_valid = ad9361_2_cal_done_buf;
always @(posedge clk) begin
if (rst) begin
ad9361_2_cal_done_buf <= 'b0;
end
else begin
ad9361_2_cal_done_buf <= rotate_dout_ch3_valid;
end
end
endmodule
@@ -0,0 +1,321 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Product Version: Vivado v2023.2.1 (64-bit) -->
<!-- -->
<!-- Copyright 1986-2022 Xilinx, Inc. All Rights Reserved. -->
<!-- Copyright 2022-2023 Advanced Micro Devices, Inc. All Rights Reserved. -->
<Project Product="Vivado" Version="7" Minor="65" Path="/home/josh/Workspace/vivado/vivado_pub/modules/xc7k410tffg900-2/multi_ch_cal/multi_ch_cal.xpr">
<DefaultLaunch Dir="$PRUNDIR"/>
<Configuration>
<Option Name="Id" Val="3d8cac293e8046f6ba9154243a7267d4"/>
<Option Name="Part" Val="xc7k410tffg900-2"/>
<Option Name="CompiledLibDir" Val="$PCACHEDIR/compile_simlib"/>
<Option Name="CompiledLibDirXSim" Val=""/>
<Option Name="CompiledLibDirModelSim" Val="$PCACHEDIR/compile_simlib/modelsim"/>
<Option Name="CompiledLibDirQuesta" Val="$PCACHEDIR/compile_simlib/questa"/>
<Option Name="CompiledLibDirXcelium" Val="$PCACHEDIR/compile_simlib/xcelium"/>
<Option Name="CompiledLibDirVCS" Val="$PCACHEDIR/compile_simlib/vcs"/>
<Option Name="CompiledLibDirRiviera" Val="$PCACHEDIR/compile_simlib/riviera"/>
<Option Name="CompiledLibDirActivehdl" Val="$PCACHEDIR/compile_simlib/activehdl"/>
<Option Name="SimulatorInstallDirModelSim" Val=""/>
<Option Name="SimulatorInstallDirQuesta" Val=""/>
<Option Name="SimulatorInstallDirXcelium" Val=""/>
<Option Name="SimulatorInstallDirVCS" Val=""/>
<Option Name="SimulatorInstallDirRiviera" Val=""/>
<Option Name="SimulatorInstallDirActiveHdl" Val=""/>
<Option Name="SimulatorGccInstallDirModelSim" Val=""/>
<Option Name="SimulatorGccInstallDirQuesta" Val=""/>
<Option Name="SimulatorGccInstallDirXcelium" Val=""/>
<Option Name="SimulatorGccInstallDirVCS" Val=""/>
<Option Name="SimulatorGccInstallDirRiviera" Val=""/>
<Option Name="SimulatorGccInstallDirActiveHdl" Val=""/>
<Option Name="SimulatorVersionXsim" Val="2023.2"/>
<Option Name="SimulatorVersionModelSim" Val="2023.2"/>
<Option Name="SimulatorVersionQuesta" Val="2023.2"/>
<Option Name="SimulatorVersionXcelium" Val="23.03.002"/>
<Option Name="SimulatorVersionVCS" Val="U-2023.03-1"/>
<Option Name="SimulatorVersionRiviera" Val="2022.10"/>
<Option Name="SimulatorVersionActiveHdl" Val="14.1"/>
<Option Name="SimulatorGccVersionXsim" Val="9.3.0"/>
<Option Name="SimulatorGccVersionModelSim" Val="7.4.0"/>
<Option Name="SimulatorGccVersionQuesta" Val="7.4.0"/>
<Option Name="SimulatorGccVersionXcelium" Val="9.3.0"/>
<Option Name="SimulatorGccVersionVCS" Val="9.2.0"/>
<Option Name="SimulatorGccVersionRiviera" Val="9.3.0"/>
<Option Name="SimulatorGccVersionActiveHdl" Val="9.3.0"/>
<Option Name="BoardPart" Val=""/>
<Option Name="ActiveSimSet" Val="sim_1"/>
<Option Name="DefaultLib" Val="xil_defaultlib"/>
<Option Name="ProjectType" Val="Default"/>
<Option Name="IPOutputRepo" Val="$PCACHEDIR/ip"/>
<Option Name="IPDefaultOutputPath" Val="$PGENDIR/sources_1"/>
<Option Name="IPCachePermission" Val="read"/>
<Option Name="IPCachePermission" Val="write"/>
<Option Name="EnableCoreContainer" Val="FALSE"/>
<Option Name="EnableResourceEstimation" Val="FALSE"/>
<Option Name="SimCompileState" Val="TRUE"/>
<Option Name="CreateRefXciForCoreContainers" Val="FALSE"/>
<Option Name="IPUserFilesDir" Val="$PIPUSERFILESDIR"/>
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
<Option Name="EnableBDX" Val="FALSE"/>
<Option Name="FeatureSet" Val="FeatureSet_Classic"/>
<Option Name="WTXSimLaunchSim" Val="3"/>
<Option Name="WTModelSimLaunchSim" Val="0"/>
<Option Name="WTQuestaLaunchSim" Val="0"/>
<Option Name="WTIesLaunchSim" Val="0"/>
<Option Name="WTVcsLaunchSim" Val="0"/>
<Option Name="WTRivieraLaunchSim" Val="0"/>
<Option Name="WTActivehdlLaunchSim" Val="0"/>
<Option Name="WTXSimExportSim" Val="2"/>
<Option Name="WTModelSimExportSim" Val="2"/>
<Option Name="WTQuestaExportSim" Val="2"/>
<Option Name="WTIesExportSim" Val="0"/>
<Option Name="WTVcsExportSim" Val="2"/>
<Option Name="WTRivieraExportSim" Val="2"/>
<Option Name="WTActivehdlExportSim" Val="2"/>
<Option Name="GenerateIPUpgradeLog" Val="TRUE"/>
<Option Name="XSimRadix" Val="hex"/>
<Option Name="XSimTimeUnit" Val="ns"/>
<Option Name="XSimArrayDisplayLimit" Val="1024"/>
<Option Name="XSimTraceLimit" Val="65536"/>
<Option Name="SimTypes" Val="rtl"/>
<Option Name="SimTypes" Val="bfm"/>
<Option Name="SimTypes" Val="tlm"/>
<Option Name="SimTypes" Val="tlm_dpi"/>
<Option Name="MEMEnableMemoryMapGeneration" Val="TRUE"/>
<Option Name="DcpsUptoDate" Val="TRUE"/>
<Option Name="ClassicSocBoot" Val="FALSE"/>
<Option Name="LocalIPRepoLeafDirName" Val="ip_repo"/>
</Configuration>
<FileSets Version="1" Minor="32">
<FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR/sources_1" RelGenDir="$PGENDIR/sources_1">
<Filter Type="Srcs"/>
<File Path="$PPRDIR/../../../common/ApproxModuli_26bit.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/multi_ch_cal.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="multi_ch_cal"/>
<Option Name="TopAutoSet" Val="TRUE"/>
</Config>
</FileSet>
<FileSet Name="constrs_1" Type="Constrs" RelSrcDir="$PSRCDIR/constrs_1" RelGenDir="$PGENDIR/constrs_1">
<Filter Type="Constrs"/>
<Config>
<Option Name="ConstrsType" Val="XDC"/>
</Config>
</FileSet>
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1" RelGenDir="$PGENDIR/sim_1">
<File Path="$PSRCDIR/sim_1/new/tb_multi_ch_cal.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="tb_multi_ch_cal"/>
<Option Name="TopLib" Val="xil_defaultlib"/>
<Option Name="TopAutoSet" Val="TRUE"/>
<Option Name="TransportPathDelay" Val="0"/>
<Option Name="TransportIntDelay" Val="0"/>
<Option Name="SelectedSimModel" Val="rtl"/>
<Option Name="PamDesignTestbench" Val=""/>
<Option Name="PamDutBypassFile" Val="xil_dut_bypass"/>
<Option Name="PamSignalDriverFile" Val="xil_bypass_driver"/>
<Option Name="PamPseudoTop" Val="pseudo_tb"/>
<Option Name="SrcSet" Val="sources_1"/>
</Config>
</FileSet>
<FileSet Name="utils_1" Type="Utils" RelSrcDir="$PSRCDIR/utils_1" RelGenDir="$PGENDIR/utils_1">
<Filter Type="Utils"/>
<Config>
<Option Name="TopAutoSet" Val="TRUE"/>
</Config>
</FileSet>
<FileSet Name="atan2_16b" Type="BlockSrcs" RelSrcDir="$PSRCDIR/atan2_16b" RelGenDir="$PGENDIR/atan2_16b">
<File Path="$PSRCDIR/sources_1/ip/atan2_16b/atan2_16b.xci">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<Config>
<Option Name="TopModule" Val="atan2_16b"/>
<Option Name="UseBlackboxStub" Val="1"/>
</Config>
</FileSet>
<FileSet Name="rotate_16b" Type="BlockSrcs" RelSrcDir="$PSRCDIR/rotate_16b" RelGenDir="$PGENDIR/rotate_16b">
<File Path="$PSRCDIR/sources_1/ip/rotate_16b/rotate_16b.xci">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<Config>
<Option Name="TopModule" Val="rotate_16b"/>
<Option Name="UseBlackboxStub" Val="1"/>
</Config>
</FileSet>
</FileSets>
<Simulators>
<Simulator Name="XSim">
<Option Name="Description" Val="Vivado Simulator"/>
<Option Name="CompiledLib" Val="0"/>
</Simulator>
<Simulator Name="ModelSim">
<Option Name="Description" Val="ModelSim Simulator"/>
</Simulator>
<Simulator Name="Questa">
<Option Name="Description" Val="Questa Advanced Simulator"/>
</Simulator>
<Simulator Name="Xcelium">
<Option Name="Description" Val="Xcelium Parallel Simulator"/>
</Simulator>
<Simulator Name="VCS">
<Option Name="Description" Val="Verilog Compiler Simulator (VCS)"/>
</Simulator>
<Simulator Name="Riviera">
<Option Name="Description" Val="Riviera-PRO Simulator"/>
</Simulator>
</Simulators>
<Runs Version="1" Minor="21">
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7k410tffg900-2" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="true" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/synth_1" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/synth_1" AutoRQSDir="$PSRCDIR/utils_1/imports/synth_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2023">
<Desc>Vivado Synthesis Defaults</Desc>
</StratHandle>
<Step Id="synth_design"/>
</Strategy>
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2023"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
<Run Id="atan2_16b_synth_1" Type="Ft3:Synth" SrcSet="atan2_16b" Part="xc7k410tffg900-2" ConstrsSet="atan2_16b" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" Dir="$PRUNDIR/atan2_16b_synth_1" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/atan2_16b_synth_1" AutoRQSDir="$PSRCDIR/utils_1/imports/atan2_16b_synth_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2023">
<Desc>Vivado Synthesis Defaults</Desc>
</StratHandle>
<Step Id="synth_design"/>
</Strategy>
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2023"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
<Run Id="rotate_16b_synth_1" Type="Ft3:Synth" SrcSet="rotate_16b" Part="xc7k410tffg900-2" ConstrsSet="rotate_16b" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" Dir="$PRUNDIR/rotate_16b_synth_1" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/rotate_16b_synth_1" AutoRQSDir="$PSRCDIR/utils_1/imports/rotate_16b_synth_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2023">
<Desc>Vivado Synthesis Defaults</Desc>
</StratHandle>
<Step Id="synth_design"/>
</Strategy>
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2023"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7k410tffg900-2" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" SynthRun="synth_1" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1" AutoRQSDir="$PSRCDIR/utils_1/imports/impl_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2023">
<Desc>Default settings for Implementation.</Desc>
</StratHandle>
<Step Id="init_design"/>
<Step Id="opt_design"/>
<Step Id="power_opt_design"/>
<Step Id="place_design"/>
<Step Id="post_place_power_opt_design"/>
<Step Id="phys_opt_design"/>
<Step Id="route_design"/>
<Step Id="post_route_phys_opt_design"/>
<Step Id="write_bitstream"/>
</Strategy>
<ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2023"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
<Run Id="atan2_16b_impl_1" Type="Ft2:EntireDesign" Part="xc7k410tffg900-2" ConstrsSet="atan2_16b" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" SynthRun="atan2_16b_synth_1" IncludeInArchive="false" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/atan2_16b_impl_1" AutoRQSDir="$PSRCDIR/utils_1/imports/atan2_16b_impl_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2023">
<Desc>Default settings for Implementation.</Desc>
</StratHandle>
<Step Id="init_design"/>
<Step Id="opt_design"/>
<Step Id="power_opt_design"/>
<Step Id="place_design"/>
<Step Id="post_place_power_opt_design"/>
<Step Id="phys_opt_design"/>
<Step Id="route_design"/>
<Step Id="post_route_phys_opt_design"/>
<Step Id="write_bitstream"/>
</Strategy>
<ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2023"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
<Run Id="rotate_16b_impl_1" Type="Ft2:EntireDesign" Part="xc7k410tffg900-2" ConstrsSet="rotate_16b" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" SynthRun="rotate_16b_synth_1" IncludeInArchive="false" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/rotate_16b_impl_1" AutoRQSDir="$PSRCDIR/utils_1/imports/rotate_16b_impl_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2023">
<Desc>Default settings for Implementation.</Desc>
</StratHandle>
<Step Id="init_design"/>
<Step Id="opt_design"/>
<Step Id="power_opt_design"/>
<Step Id="place_design"/>
<Step Id="post_place_power_opt_design"/>
<Step Id="phys_opt_design"/>
<Step Id="route_design"/>
<Step Id="post_route_phys_opt_design"/>
<Step Id="write_bitstream"/>
</Strategy>
<ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2023"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
</Runs>
<Board/>
<DashboardSummary Version="1" Minor="0">
<Dashboards>
<Dashboard Name="default_dashboard">
<Gadgets>
<Gadget Name="drc_1" Type="drc" Version="1" Row="2" Column="0">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_drc_0 "/>
</Gadget>
<Gadget Name="methodology_1" Type="methodology" Version="1" Row="2" Column="1">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_methodology_0 "/>
</Gadget>
<Gadget Name="power_1" Type="power" Version="1" Row="1" Column="0">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_power_0 "/>
</Gadget>
<Gadget Name="timing_1" Type="timing" Version="1" Row="0" Column="1">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_timing_summary_0 "/>
</Gadget>
<Gadget Name="utilization_1" Type="utilization" Version="1" Row="0" Column="0">
<GadgetParam Name="REPORTS" Type="string_list" Value="synth_1#synth_1_synth_report_utilization_0 "/>
<GadgetParam Name="RUN.STEP" Type="string" Value="synth_design"/>
<GadgetParam Name="RUN.TYPE" Type="string" Value="synthesis"/>
</Gadget>
<Gadget Name="utilization_2" Type="utilization" Version="1" Row="1" Column="1">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_place_report_utilization_0 "/>
</Gadget>
</Gadgets>
</Dashboard>
<CurrentDashboard>default_dashboard</CurrentDashboard>
</Dashboards>
</DashboardSummary>
</Project>