1.DDC(Direct Digital Controller)
DDC即在数字系统中对信号进行下变频,实现从射频(中频)信号到基带信号的转变。模拟上下变频的系统框图如下:
对于QAM等调制信号,通常有同相和正交两路基带信号,对应正弦和余弦两路同频载波,其模拟上下变频的系统框图如下:
上图描述的过程可用的数学表达如下:
s ( t ) = I ( t ) cos ( 2 π f c t ) − Q ( t ) sin ( 2 π f c t ) I 路 : s ( t ) cos ( 2 π f c t ) = I ( t ) cos 2 ( 2 π f c t ) − Q ( t ) cos ( 2 π f c t ) sin ( 2 π f c t ) = I ( t ) 1 + cos ( 2 π ∗ 2 f c t ) 2 − Q ( t ) sin ( 2 π 2 ∗ f c t ) 2 = = L P F I ( t ) 2 Q 路 : s ( t ) ( − sin ( 2 π f c t ) ) = I ( t ) cos ( 2 π f c t ) sin ( 2 π f c t ) + Q ( t ) sin 2 ( 2 π f c t ) = I ( t ) sin ( 2 π 2 ∗ f c t ) 2 + Q ( t ) 1 − cos ( 2 π ∗ 2 f c t ) 2 = = L P F Q ( t ) 2 s(t)=I(t)\cos(2\pi f_ct)-Q(t)\sin(2\pi f_ct)\\ I路:s(t)\cos(2\pi f_ct)=I(t)\cos^2(2\pi f_ct)-Q(t)\cos(2\pi f_ct)\sin(2\pi f_ct)\\=I(t)\frac{1+\cos (2\pi*2f_ct)}{2}-Q(t)\frac{\sin(2\pi 2*f_ct)}{2}\overset{LPF}{==}\frac{I(t)}{2}\\ Q路:s(t)(-\sin(2\pi f_ct))=I(t)\cos(2\pi f_ct) \sin (2\pi f_ct)+Q(t)\sin^2(2\pi f_ct)\\=I(t)\frac{\sin(2\pi 2*f_ct)}{2}+Q(t)\frac{1-\cos (2\pi*2f_ct)}{2}\overset{LPF}{==}\frac{Q(t)}{2} s(t)=I(t)cos(2πfct)−Q(t)sin(2πfct)I路:s(t)cos(2πfct)=I(t)cos2(2πfct)−Q(t)cos(2πfct)sin(2πfct)=I(t)21+cos(2π∗2fct)−Q(t)2sin(2π2∗fct)==LPF2I(t)Q路:s(t)(−sin(2πfct))=I(t)cos(2πfct)sin(2πfct)+Q(t)sin2(2πfct)=I(t)2sin(2π2∗fct)+Q(t)21−cos(2π∗2fct)==LPF2Q(t)
若使用复信号表述该过程,则有:
上述过程的数学表达如下:
s ( t ) = ( I + j Q ) e j 2 π f c t = ( I + j Q ) ( cos ( 2 π f c t ) + j sin ( 2 π f c t ) ) = I cos ( 2 π f c t ) + j I sin ( 2 π f c t ) + j Q cos ( 2 π f c t ) − Q sin ( 2 π f c t ) 取 其 实 部 , 则 有 s t x ( t ) = I cos ( 2 π f c t ) − Q sin ( 2 π f c t ) 恢 复 过 程 : s t x ( t ) e − j 2 π f c t = ( I cos ( 2 π f c t ) − Q sin ( 2 π f c t ) ) ( cos ( 2 π f c t ) − j sin ( 2 π f c t ) ) = I ( cos 2 ( 2 π f c t ) ) − j I ( cos ( 2 π f c t ) sin ( 2 π f c t ) ) − Q ( sin ( 2 π f c t ) cos ( 2 π f c t ) ) + j Q ( sin 2 ( 2 π f c t ) ) = I 1 + cos ( 2 π 2 ∗ f c t ) 2 − j I sin ( 2 π 2 ∗ f c t ) 2 − Q sin ( 2 π 2 ∗ f c t ) 2 + j Q 1 − cos ( 2 π 2 ∗ f c t ) 2 = = L P F I + j Q s(t)=(I+jQ)e^{j2\pi f_ct}=(I+jQ)(\cos(2\pi f_ct)+j\sin(2\pi f_ct))\\=I\cos(2\pi f_ct)+jI\sin(2\pi f_ct)+jQ\cos(2\pi f_ct)-Q\sin(2\pi f_ct)\\取其实部,则有s_{tx}(t)=I\cos(2\pi f_ct)-Q\sin(2\pi f_ct)\\恢复过程:s_{tx}(t)e^{-j2\pi f_ct}=(I\cos(2\pi f_ct)-Q\sin(2\pi f_ct))(\cos(2\pi f_ct)-j\sin(2\pi f_ct))\\=I(\cos^2(2\pi f_c t))-jI(\cos(2\pi f_ct)\sin(2\pi f_ct))-Q(\sin(2\pi f_ct)\cos(2\pi f_ct))+jQ(\sin^2(2\pi f_ct))\\=I\frac{1+\cos(2\pi 2*f_c t)}{2}-jI\frac{\sin(2\pi 2*f_c t)}{2}-Q\frac{\sin(2\pi 2*f_c t)}{2}+jQ\frac{1-\cos(2\pi 2*f_c t)}{2}\overset{LPF}{==}I+jQ s(t)=(I+jQ)ej2πfct=(I+jQ)(cos(2πfct)+jsin(2πfct))=Icos(2πfct)+jIsin(2πfct)+jQcos(2πfct)−Qsin(2πfct)取其实部,则有stx(t)=Icos(2πfct)−Qsin(2πfct)恢复过程:stx(t)e−j2πfct=(Icos(2πfct)−Qsin(2πfct))(cos(2πfct)−jsin(2πfct))=I(cos2(2πfct))−jI(cos(2πfct)sin(2πfct))−Q(sin(2πfct)cos(2πfct))+jQ(sin2(2πfct))=I21+cos(2π2∗fct)−jI2sin(2π2∗fct)−Q2sin(2π2∗fct)+jQ21−cos(2π2∗fct)==LPFI+jQ
为什么使用复信号?
复信号的引入已有几十年的历史。无线通信中,往往使用一对正交的信号传输信息,以提高带宽利用率,有效的减少带内和带外干扰。为了简单明了的描述这对信号,这些系统常被描述为一个复信号,系统的传递函数也用复数描述。使用复信号的好处有:
it often allows for image-reject architectures to be described more compactly and simply; it leads to a graphical or signal-flflow graph (SFG) description of signal-processing systems providing insight, and it often leads to the development of new systems where the use of high-frequency highly selective image-reject fifilters is minimized. The result is more highly integrated systems using less power and requiring less physical space[1].
即,使用复信号可以使得消除镜像频谱的结构的描述变得更简洁;使得描述信号处理系统的信号流图变得更为直观;在开发新系统时,减少高频高选择性的镜频滤波器的使用;最终使得系统的集成度更高,有更小的体积和更少的功耗。
但该论文的题目《Complex Signal Processing is Not Complex》[1]亦指出,复信号的处理并不是复数(复杂)的,在论文中,作者给每一幅复数信号流图都配上了对应的等价实数信号流图。如下:
在实际处理中,还是使用实数信号流图对应的物理结构,如ADI公司在一个回复当利用ADC内部数字下变频(DDC)处理进行抽取时,我的单音实数输入信号丢失了6 dB功率的问题时中提及的处理框图如下:
Matlab根据波形生成.coe文件代码:
f = 115e6; %中频125MHz,则f0 = 115MHz 115-135MHz
t_p = 50e-6; %脉宽50us
b = 20e6; %带宽20MHz
beta = b/t_p; %调频斜率
f_s =100e6; %采样率 100MHz
t = 0: 1/f_s:20480/f_s;
chrip_s = cos(2*pi*f.*t+beta.*(t).^2); %ADC采集的实信号
gencoeInitialROM(16,8192,chrip_s,'BRAM.coe');
%将任意信号转为对应位宽,长度的Xilinx ROM初始化格式,并写入文件
%input: width,ROM数据位宽; depth,ROM数据深度; signal,待写入信号; filepath,文件路径及文件名
%output: 无,直接查看转化后文件
function gencoeInitialROM(width,depth,signal,filepath)
signal = signal(1:depth); %取信号的前depth位
signal=floor(signal*(2^(width-1)-1)); % 转换成对应位宽的整数
figure;
plot(signal); %查看转换结果
fid=fopen(filepath,'w'); %创建.coe文件
start_line1 = 'memory_initialization_radix=10;';
start_line2 = 'memory_initialization_vector =';
fprintf(fid,'%s \n',start_line1);
fprintf(fid,'%s \n',start_line2);
fprintf(fid,'%d,\n',signal); %向.coe文件中写入数据
fseek(fid,-2, 'eof'); %将文件指针移至最后一个逗号处
fwrite(fid,';') %将最后一个逗号改为分号
fclose(fid); %关闭.coe文件
end
带通信号经过带通采样,再经DDC变换到基带的MATLAB代码如下:
`
clear;
close all;
clc;
f = 115e6; %中频125MHz,则f0 = 115MHz 115-135MHz
t_p = 50e-6; %脉宽50us
b = 20e6; %带宽20MHz
beta = b/t_p; %调频斜率
f_s =100e6; %采样率 100MHz
f_l = 25e6; %NCO 25MHz
t = 0: 1/f_s:16383/f_s;
NCO = exp(-1i.*2.*pi.*f_l.*t); %复本振
figure;plot3(t(1:200),real(NCO(1:200)),imag(NCO(1:200)));title('复本振时域波形');xlabel('时间');ylabel('实部');zlabel('虚部');
fft_plot(NCO,f_s,'复本振信号');
G = rectpuls(t-t_p/2,t_p);
chrip_bs = G.*exp(1i.*pi.*beta.*t.^2); %发送的复基带信号
IF = exp(1i.*2.*pi.*f.*t); %复中频载波
chrip = chrip_bs.*IF;
fft_plot(chrip,f_s,'待发射复基带信号'); %复信号频谱
chrip_tx = real(chrip); %发射中频的实部,也是ADC采集进入进行下变频的信号
fft_plot(chrip_tx,f_s,'发射实信号'); %ADC采集的信号的频谱
chrip_LO = chrip_tx.*NCO;
fft_plot((chrip_LO),f_s,'乘以复本振后信号'); %乘以复本振后信号频谱
[b,a] = fir1(50,15e6*2/f_s);
[H,W] = freqz(b,a);
Hf=abs(H); %取幅度值实部
Hx=angle(H); %取相位值对应相位角
figure;
plot(W,20*log(Hf)) %幅值变换为分贝单位
title('滤波器系统幅频特性曲线')
figure;
plot(W,Hx)
title('滤波器系统相频特性曲线')
chrip_b = filter(b,a,chrip_LO);
fft_plot((chrip_b),f_s,'低通滤波后信号');
chrip_fake_d = fake_decimation(chrip_b,4); %假4倍抽取
fft_plot((chrip_fake_d),f_s,'假的4倍抽取后信号');
chrip_bD = resample(chrip_b,f_s/2,f_s);%信号降采样以降低数据率
fft_plot((chrip_bD),f_s/4,'4倍抽取后信号');
figure;
plot(t(1:2:4000),real(chrip_bD(1:2000)));
title('I');xlabel('时间');
figure;
plot(t(1:2:4000),imag(chrip_bD(1:2000)));
title('Q');xlabel('时间');
%% 虚假的抽取,只是隔位置零,采样率不变,以获取周期延拓
%% input:x,待抽取信号;n,抽取倍数
%% output: 抽取后信号
function yn= fake_decimation(x,n)
yn = zeros(1,length(x));
for i = 1 : length(x)
if mod(i,n)== 1
yn(i) = x(i);
else
x(i) = 0;
end
end
end
%% 对信号做FFT,并画图
%% input: y,待分析信号;fs,采样率;s_name,信号名字
function fft_plot(y,fs,s_name)
L_i = length(y)*2;
s_i_fft = fft(y,L_i);
s_i_fftshfit = fftshift(s_i_fft);
P = abs(s_i_fftshfit/L_i);
fshift = (-L_i/2:L_i/2-1)*(fs/L_i);
figure;
plot(fshift,P);
title([s_name,'的双边谱 ']);
xlabel('f (Hz)');
ylabel('|P(f)|');
end
信号处理过程中的频谱如下:
只有正频率
发射时只有取实部,实信号有对称的双边谱
乘以复本振,被单向搬移(由于是带通采样,有频谱周期延拓,且FFT仅能绘制[-Fs/2,Fs/2]区间的频谱)
低通滤波,取基带部分信号
4倍抽取的中间过程
4倍抽取,以降低后续数据量
I路基带信号时域
Q路基带时域
FPGA处理流程,及波形
FPGA实现过程基于实数形式的信号流图,主要涉及到DDS产生两路正交本振,ROM存储待下变频信号,乘法模块,FIR滤波,时域抽取等。大部分有现成IP核可供调用。
代码:
module DDC(
input clk,
input en,
input rst,
output [55:0] i_d4,
output [55:0] q_d4,
output [55:0] i_data,
output [55:0] q_data,
output [15:0] sin,
output [15:0] cos,
output [15:0] LFM,
output [31:0] i_cos,
output [31:0] q_sin
);
wire [15:0] douta;
wire [31:0]m_axis_data_tdata;
wire [31:0]m_axis_phase_tdata;
wire [31:0] P_i;
wire [31:0] P_q;
reg [12:0]addra;
always @(posedge clk or posedge rst) begin
if (rst) begin
addra <= 1'b0;
end
else begin
addra <= addra + 1'b1;
end
end
assign LFM = douta;
assign sin = m_axis_data_tdata[15:0];
assign cos = m_axis_data_tdata[31:16];
assign i_cos= P_i;
assign q_sin= P_q;
blk_mem_gen_0 LFMWAVE (
.clka(clk), // input wire clka
.addra(addra), // input wire [12 : 0] addra
.douta(douta) // output wire [15 : 0] douta
);
LO sin_cos (
.aclk(clk), // input wire aclk
.m_axis_data_tvalid(), // output wire m_axis_data_tvalid
.m_axis_data_tdata(m_axis_data_tdata), // output wire [31 : 0] m_axis_data_tdata
.m_axis_phase_tvalid(), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata(m_axis_phase_tdata) // output wire [31 : 0] m_axis_phase_tdata
);
mult_i mult_i (
.CLK(clk), // input wire CLK
.A(douta), // input wire [15 : 0] A
.B(m_axis_data_tdata[15:0]), // input wire [15 : 0] B
.P(P_i) // output wire [31 : 0] P
);
mult_i mult_q (
.CLK(clk), // input wire CLK
.A(douta), // input wire [15 : 0] A
.B(m_axis_data_tdata[31:16]), // input wire [15 : 0] B
.P(P_q) // output wire [31 : 0] P
);
fir_compiler_0 fir_i (
.aclk(clk), // input wire aclk
.s_axis_data_tvalid(en), // input wire s_axis_data_tvalid
.s_axis_data_tready(), // output wire s_axis_data_tready
.s_axis_data_tdata(P_i), // input wire [31 : 0] s_axis_data_tdata
.m_axis_data_tvalid(), // output wire m_axis_data_tvalid
.m_axis_data_tdata(i_data) // output wire [55 : 0] m_axis_data_tdata
);
fir_compiler_0 fir_q (
.aclk(clk), // input wire aclk
.s_axis_data_tvalid(en), // input wire s_axis_data_tvalid
.s_axis_data_tready(), // output wire s_axis_data_tready
.s_axis_data_tdata(P_q), // input wire [31 : 0] s_axis_data_tdata
.m_axis_data_tvalid(), // output wire m_axis_data_tvalid
.m_axis_data_tdata(q_data) // output wire [55 : 0] m_axis_data_tdata
);
decimation#(
.NDEC(56)
) inst_decimation_i (
.clk (clk),
.rst (rst),
.en (en),
.din (i_data),
.valid (),
.dout (i_d4)
);
decimation#(
.NDEC(56)
) inst_decimation_q (
.clk (clk),
.rst (rst),
.en (en),
.din (q_data),
.valid (),
.dout (q_d4)
);
endmodule
抽取模块代码:
module decimation
#(parameter NDEC = 56)
(
input clk,
input rst,
input en,
input [NDEC-1:0] din,
output valid,
output [NDEC-1:0] dout);
reg valid_r ;
reg [2:0] cnt ;
reg [NDEC-1:0] dout_r ;
//counter
always @(posedge clk or posedge rst) begin
if (rst) begin
cnt <= 3'b0;
end
else if (en) begin
if (cnt==3) begin
cnt <= 'b0 ;
end
else begin
cnt <= cnt + 1'b1 ;
end
end
end
//data, valid
always @(posedge clk or posedge rst) begin
if (rst) begin
valid_r <= 1'b0 ;
dout_r <= 'b0 ;
end
else if (en) begin
if (cnt==3) begin
valid_r <= 1'b1 ;
dout_r <= din;
end
else begin
valid_r <= 1'b0 ;
end
end
end
assign dout = dout_r ;
assign valid = valid_r ;
endmodule
FPGA仿真波形
综合RTL视图:
可见,与实数信号流图描述结构相同。