modify tx_qpsk, analyze ant data

tx wave of tx_qpsk is changed to bpsk format; the matlab script analyzing ant and self-loop data is tested
This commit is contained in:
2023-03-27 20:31:18 +08:00
parent bd032a8474
commit 26fa3e9e50
22 changed files with 1573094 additions and 524437 deletions
@@ -138,14 +138,14 @@ hrc_64_12_025 u_hrc_q (
//////////////////////////// Square Shaping Filter ///////////////////////////// //////////////////////////// Square Shaping Filter /////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// address // address
reg [$clog2(BIT_DATA_LEN)-2 : 0] hsq_data_addr = 'b0; reg [$clog2(BIT_DATA_LEN)-1 : 0] hsq_data_addr = 'b0;
always @(posedge clk) begin always @(posedge clk) begin
if (rst) begin if (rst) begin
hsq_data_addr <= 'b0; hsq_data_addr <= 'b0;
end end
else else
hsq_data_addr <= {cnt[$clog2(SQUARE_INTERP) +: ($clog2(BIT_DATA_LEN)-2)]}; hsq_data_addr <= {cnt[$clog2(SQUARE_INTERP) +: $clog2(BIT_DATA_LEN)]};
end end
// bit data // bit data
@@ -31,7 +31,7 @@ reg clk = 1'b0 ;
reg rst = 1'b1 ; reg rst = 1'b1 ;
reg tx_on = 1'b1 ; reg tx_on = 1'b1 ;
reg [31:0] freq_set ; reg [31:0] freq_set ;
reg [ 1:0] waveform_sel = 2'b00; reg [ 1:0] waveform_sel = 2'd1 ;
reg [ 1:0] iq_sel = 2'b11 ; reg [ 1:0] iq_sel = 2'b11 ;
wire [11:0] tx_data_i ; wire [11:0] tx_data_i ;
wire [11:0] tx_data_q ; wire [11:0] tx_data_q ;
@@ -1,90 +0,0 @@
%% File Header/文件说明
%
% 调零算法对幅相一致性的要求较高,且 AD9361 多片同步的精度随机性较大,因此需要对
% AD9361 多片同步误差进行精细校准。采用收发扩频码的方式在校准过程中对两片 AD9361
% 的两个接收通道进行幅相测量,在接收端使用加法器进行非相干相关峰累积,累积 N 个
% 符号后出峰,根据相关峰的高度差和相位差,在接收端对信号的幅度和相位进行补偿。
%
clc; clear;
%% initial system parameters/初始系统参数
interp = 8; % interpolation factor
channelNum = 4;
dataLen = 131072;
fs = 48e6;
fd = -25427;
% 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
symbolNum = dataLen/chipLen/interp;
rxdata = readmatrix("iladata_prsb7_interp8_1-1.csv");
seqRx(:,1) = (rxdata(:, 4) + 1i*rxdata(:, 5)).'.*exp(1i*2*pi*fd/fs*(0:dataLen-1));
seqRx(:,2) = (rxdata(:, 6) + 1i*rxdata(:, 7)).'.*exp(1i*2*pi*fd/fs*(0:dataLen-1));
seqRx(:,3) = (rxdata(:, 8) + 1i*rxdata(:, 9)).'.*exp(1i*2*pi*fd/fs*(0:dataLen-1));
seqRx(:,4) = (rxdata(:,10) + 1i*rxdata(:,11)).'.*exp(1i*2*pi*fd/fs*(0:dataLen-1));
% 降采样
seqRxDown = downsample(seqRx,interp,0);
% 取符号位
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;
% 符号累积
seqRxAccum = zeros(chipLen,channelNum);
for i = 0:chipLen-1
% PN 码圆周移位,遍历所有 PN 码相位
PRBS7_cshift = circshift(repmat(PRBS7_polar(1:32),symbolNum*4,1),-i); % 负号为了和 Verilog 程序对应
% 累积,若当前比特与 PN 码相同,结果 +1;否则结果 -1
seqRxAccum(i+1,:) = sum(seqRxDown(PRBS7_cshift==seqRxMsbReal))-...
sum(seqRxDown(PRBS7_cshift~=seqRxMsbReal));
end
% % 通过相关峰位置判断目标信号位置
% 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;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,105 @@
%% File Header/文件说明
%
% Beamforming with phased array derives signal characteristics from phase
% differences between sensors. Therefore the amplitude-phase consistence is
% vital to phased systems.
%
% The script analyzes the amp-phase relations of ILA captured data, the format
% of which is square-shaped pseudorandorm bit sequence. Each channel is
% processed seperately with different frequency shifts and different optimum
% sampling points. The estimation of amplitude and phase are based on
% acculumated correlation peaks.
%
clc; clear;
%% initial parameters/初始参数
interp = 8; % interpolation factor
channelNum = 4;
dataLen = 1024*8;
fs = 48e6;
dataFile = "iladata_ant_3-1.csv";
% 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
symNum = dataLen/chipLen/interp; % total symbol number
symNumPerAccum = 1; % symbol nbumber of each accumulation
accNum = symNum/symNumPerAccum; % total accumulation numbers, i.e. peak numbers
%% data analysis
% read data, and swap ch1 and ch2, because loop data locate at ch2 and ch4
rxdata = readmatrix(dataFile);
seqRx(:,1) = (rxdata(:, 6) + 1i*rxdata(:, 7)).';
seqRx(:,2) = (rxdata(:, 4) + 1i*rxdata(:, 5)).';
seqRx(:,3) = (rxdata(:, 8) + 1i*rxdata(:, 9)).';
seqRx(:,4) = (rxdata(:,10) + 1i*rxdata(:,11)).';
% compensate frequecny deviation and downsample at optimum sample position based
% on the varience of constellation
if dataFile.contains("loop")
[seqRxDown,fd,samplePos] = suqareShapeFreqEst(seqRx,interp,fs,-50,50,5);
else
[seqRxDown,fd,samplePos] = suqareShapeFreqEst(seqRx,interp,fs,24900,25100,10);
end
% split [seqRxDown] into multiple groups, each group contains several symbols to
% be correlated with PRBS7 and accumulated
seqRxDownSplit = reshape(seqRxDown(1:dataLen/interp,:),chipLen*symNumPerAccum, ...
accNum,channelNum);
seqRxAcc = zeros(chipLen,accNum,channelNum);
desiredPnt = zeros(accNum,channelNum);
ampEstSym = zeros(accNum,channelNum);
angleEstSym = zeros(accNum,channelNum);
for i = 1:accNum
for j = 1:channelNum
% correlation & multi-symbol accumulation
groupCorrAcc = sum(reshape(conv(flip(seqRxDownSplit(:,i,j)), ...
PRBS7_polar,'same'),chipLen,symNumPerAccum),2)';
seqRxAcc(:,i,j) = groupCorrAcc;
% peak position
desiredPnt(i,j) = groupCorrAcc(abs(groupCorrAcc)==max(abs(groupCorrAcc)));
end
end
for i = 1:channelNum
ampEstSym(:,i) = abs(desiredPnt(:,i))./abs(desiredPnt(:,1));
angleEstSym(:,i) = mod((angle(desiredPnt(:,i))-angle(desiredPnt(:,1)))/pi*180,360);
end
%% figures
figure(1);
if dataFile.contains("loop")
subplot(121);
plot(ampEstSym(:,[1,4]));
legend({"ch1","ch4"});
title("Amplitude Estimation");
ylim([min(ampEstSym(:,[1,4]),[],'all')-0.1,max(ampEstSym(:,[1,4]),[],'all')+0.1])
subplot(122);
plot(angleEstSym(:,[1,4]));
legend({"ch1","ch4"});
title("Angle Estimation");
ylim([min(angleEstSym(:,[1,4]),[],'all')-10,max(angleEstSym(:,[1,4]),[],'all')+10])
else
subplot(121);
plot(ampEstSym);
legend({"ch1","ch2","ch3","ch4"});
title("Amplitude Estimation");
ylim([min(ampEstSym,[],'all')-0.2,max(ampEstSym,[],'all')+0.2])
subplot(122);
plot(angleEstSym);
legend({"ch1","ch2","ch3","ch4"});
title("Angle Estimation");
ylim([min(angleEstSym,[],'all')-10,max(angleEstSym,[],'all')+10])
end
@@ -0,0 +1,50 @@
function [dataOut, fdTarget, samplePosTarget] = suqareShapeFreqEst(dataIn, interp, fs, fmin, fmax, fd)
%suqareShapeFreqEst - 利用星座图的集中程度在一定频率范围内使用频率步进估计方波成形信号的频偏
%
% data - input complex data, row vector
% dataLen - data length
% interp - interpolation rate
% fs - sampling rate, in Herts
% fmin - minimum estimation frequency, in Herts
% fmax - maximum estimation frequency, in Herts
% fd - estimation frequency step, in Herts
% dimension
[dataLen,channelNum] = size(dataIn);
freqList = fmin:fd:fmax;
freqNum = length(freqList);
varRecord = zeros(freqNum,interp);
dataOut = zeros(dataLen/interp,channelNum);
fdTarget = zeros(channelNum,1);
samplePosTarget = zeros(channelNum,1);
for channel = 1:channelNum
for freq = 1:freqNum
% carrier
cxr = exp(-1i*2*pi*freqList(freq)/fs*(0:dataLen-1)');
% apply frequency shift onto input data
seqRx = dataIn(:,channel).*cxr;
for samplePos = 0:interp-1
seqRxDown = downsample(seqRx,interp,samplePos); % 下采样
seqRxDownQuaterOne = abs(real(seqRxDown)) + 1i*abs(imag(seqRxDown)); % 集中到第一象限
varRecord(freq,samplePos+1) = var(seqRxDownQuaterOne);
end
end
[fdIndex, samplePosIndex] = find(varRecord==min(min(varRecord)));
fdTarget(channel) = freqList(fdIndex);
samplePosTarget(channel) = samplePosIndex-1;
cxrTarget = exp(-1i*2*pi*fdTarget(channel)/fs*(0:dataLen-1)');
seqRxTarget = dataIn(:,channel).*cxrTarget;
dataOut(:,channel) = downsample(seqRxTarget,interp,samplePosTarget(channel));
end
end
@@ -3020,44 +3020,44 @@
"portIndex": 0, "portIndex": 0,
"nets": [ "nets": [
{ {
"name": "tx_ch1_i", "name": "tx_data_i",
"isBus": true, "isBus": true,
"subnets": [ "subnets": [
{ {
"name": "tx_ch1_i[11]" "name": "tx_data_i[11]"
}, },
{ {
"name": "tx_ch1_i[10]" "name": "tx_data_i[10]"
}, },
{ {
"name": "tx_ch1_i[9]" "name": "tx_data_i[9]"
}, },
{ {
"name": "tx_ch1_i[8]" "name": "tx_data_i[8]"
}, },
{ {
"name": "tx_ch1_i[7]" "name": "tx_data_i[7]"
}, },
{ {
"name": "tx_ch1_i[6]" "name": "tx_data_i[6]"
}, },
{ {
"name": "tx_ch1_i[5]" "name": "tx_data_i[5]"
}, },
{ {
"name": "tx_ch1_i[4]" "name": "tx_data_i[4]"
}, },
{ {
"name": "tx_ch1_i[3]" "name": "tx_data_i[3]"
}, },
{ {
"name": "tx_ch1_i[2]" "name": "tx_data_i[2]"
}, },
{ {
"name": "tx_ch1_i[1]" "name": "tx_data_i[1]"
}, },
{ {
"name": "tx_ch1_i[0]" "name": "tx_data_i[0]"
} }
] ]
} }
@@ -3074,44 +3074,44 @@
"portIndex": 1, "portIndex": 1,
"nets": [ "nets": [
{ {
"name": "tx_ch1_q", "name": "tx_data_q",
"isBus": true, "isBus": true,
"subnets": [ "subnets": [
{ {
"name": "tx_ch1_q[11]" "name": "tx_data_q[11]"
}, },
{ {
"name": "tx_ch1_q[10]" "name": "tx_data_q[10]"
}, },
{ {
"name": "tx_ch1_q[9]" "name": "tx_data_q[9]"
}, },
{ {
"name": "tx_ch1_q[8]" "name": "tx_data_q[8]"
}, },
{ {
"name": "tx_ch1_q[7]" "name": "tx_data_q[7]"
}, },
{ {
"name": "tx_ch1_q[6]" "name": "tx_data_q[6]"
}, },
{ {
"name": "tx_ch1_q[5]" "name": "tx_data_q[5]"
}, },
{ {
"name": "tx_ch1_q[4]" "name": "tx_data_q[4]"
}, },
{ {
"name": "tx_ch1_q[3]" "name": "tx_data_q[3]"
}, },
{ {
"name": "tx_ch1_q[2]" "name": "tx_data_q[2]"
}, },
{ {
"name": "tx_ch1_q[1]" "name": "tx_data_q[1]"
}, },
{ {
"name": "tx_ch1_q[0]" "name": "tx_data_q[0]"
} }
] ]
} }
@@ -3020,44 +3020,44 @@
"portIndex": 0, "portIndex": 0,
"nets": [ "nets": [
{ {
"name": "tx_ch1_i", "name": "tx_data_i",
"isBus": true, "isBus": true,
"subnets": [ "subnets": [
{ {
"name": "tx_ch1_i[11]" "name": "tx_data_i[11]"
}, },
{ {
"name": "tx_ch1_i[10]" "name": "tx_data_i[10]"
}, },
{ {
"name": "tx_ch1_i[9]" "name": "tx_data_i[9]"
}, },
{ {
"name": "tx_ch1_i[8]" "name": "tx_data_i[8]"
}, },
{ {
"name": "tx_ch1_i[7]" "name": "tx_data_i[7]"
}, },
{ {
"name": "tx_ch1_i[6]" "name": "tx_data_i[6]"
}, },
{ {
"name": "tx_ch1_i[5]" "name": "tx_data_i[5]"
}, },
{ {
"name": "tx_ch1_i[4]" "name": "tx_data_i[4]"
}, },
{ {
"name": "tx_ch1_i[3]" "name": "tx_data_i[3]"
}, },
{ {
"name": "tx_ch1_i[2]" "name": "tx_data_i[2]"
}, },
{ {
"name": "tx_ch1_i[1]" "name": "tx_data_i[1]"
}, },
{ {
"name": "tx_ch1_i[0]" "name": "tx_data_i[0]"
} }
] ]
} }
@@ -3074,44 +3074,44 @@
"portIndex": 1, "portIndex": 1,
"nets": [ "nets": [
{ {
"name": "tx_ch1_q", "name": "tx_data_q",
"isBus": true, "isBus": true,
"subnets": [ "subnets": [
{ {
"name": "tx_ch1_q[11]" "name": "tx_data_q[11]"
}, },
{ {
"name": "tx_ch1_q[10]" "name": "tx_data_q[10]"
}, },
{ {
"name": "tx_ch1_q[9]" "name": "tx_data_q[9]"
}, },
{ {
"name": "tx_ch1_q[8]" "name": "tx_data_q[8]"
}, },
{ {
"name": "tx_ch1_q[7]" "name": "tx_data_q[7]"
}, },
{ {
"name": "tx_ch1_q[6]" "name": "tx_data_q[6]"
}, },
{ {
"name": "tx_ch1_q[5]" "name": "tx_data_q[5]"
}, },
{ {
"name": "tx_ch1_q[4]" "name": "tx_data_q[4]"
}, },
{ {
"name": "tx_ch1_q[3]" "name": "tx_data_q[3]"
}, },
{ {
"name": "tx_ch1_q[2]" "name": "tx_data_q[2]"
}, },
{ {
"name": "tx_ch1_q[1]" "name": "tx_data_q[1]"
}, },
{ {
"name": "tx_ch1_q[0]" "name": "tx_data_q[0]"
} }
] ]
} }
@@ -812,8 +812,8 @@ vio_ant_rd u_vio_ant_rd (
ila_tx u_ila_tx ila_tx u_ila_tx
( (
.clk (sys_clk ), // input wire clk .clk (sys_clk ), // input wire clk
.probe0 (tx_ch1_i ), // input wire [11:0] probe0 .probe0 (tx_data_i ), // input wire [11:0] probe0
.probe1 (tx_ch1_q ) // input wire [11:0] probe1 .probe1 (tx_data_q ) // input wire [11:0] probe1
); );
wire trig_1_out, trig_1_out_ack; wire trig_1_out, trig_1_out_ack;