目录
一、数字锁相环原理
简单来说,数字锁相环(DPLL)就像一场“你追我赶”的同步游戏。想象一下你跑步时要和另一个人保持步调一致:当对方加速时,你也要加快;对方减速时,你也要调整节奏。DPLL的作用就是让两个信号(比如接收的信号和本地生成的信号)像这对跑者一样“锁”在同一个节奏上。
它的核心原理分为三步:
比快慢:鉴相器像裁判一样,不断比较输入信号和本地信号的相位差。如果输入信号相位超前,相当于对方跑快了;反之则是本地信号更快。
算误差:环路滤波器像教练,根据裁判的反馈计算需要调整的节奏幅度。它不会直接照搬误差值,而是像给建议一样“平滑处理”,避免步子调整得太大导致摔跤。
调步伐:数控振荡器(NCO)就像运动员的双腿,根据教练的建议调整自己的输出频率。通过不断微调,最终让本地信号的相位和输入信号完全同步。
原理图
二、数字锁相环FPGA代码
fpga顶层代码
module PllTwoOrder(
i_clk,
i_rst_n,
dds_clk,
o_data
);
input i_clk; // 时钟信号, 500KHz
input i_rst_n; // 复位信号
input dds_clk;
wire [11:0] i_data;
output signed [11:0] o_data; // 相干载波信号
parameter Start_Frequency = 28'd16106127; // DDS初始频率输出30k
DDS DDS_ModuleA(
.Clk(dds_clk),
.Reset_n(i_rst_n),
.Mode_Sel(4'd0),
.Fword(2576980),//
.Pword(3000),
.Data(i_data)
);
// 限幅处理
reg signed [11:0] din_d;
always@(posedge i_clk)
if(i_data == 12'b1000_0000_0000)
din_d <= 12'b1000_0000_0001;
else
din_d <= i_data;
// 实例化鉴相乘法器IP核
wire signed [11:0] sine, cosine;
wire signed [23:0] mult_out;
mult_gen_0 u0(
.CLK(i_clk),
.A(din_d),
.B(cosine),
.P(mult_out)
);
// 实例化鉴相滤波器IP核
wire s_axis_data_tready, s_axis_data_tvalid, m_axis_data_tvalid, aresetn;
wire signed [31:0] pd_Filter_out;
assign s_axis_data_tready = 1'b1;
assign s_axis_data_tvalid = 1'b1;
assign aresetn = i_rst_n;
fir_compiler_0 u1(
.aresetn(aresetn),
.aclk(i_clk),
.s_axis_data_tvalid(s_axis_data_tvalid),
.s_axis_data_tready(s_axis_data_tready),
.s_axis_data_tdata(mult_out[22:4]),
.m_axis_data_tvalid(m_axis_data_tvalid),
.m_axis_data_tdata(pd_Filter_out)
);
// 环路滤波器
wire signed [27:0] frequency_df;
LoopFilter u3(
.i_clk(i_clk),
.i_rst_n(i_rst_n),
.i_pd(pd_Filter_out[31:7]),
.o_frequency_df(frequency_df)
);
// 实例化DDS核
wire reset_n,out_valid,clken;
wire signed [27:0] carrier;
wire signed [31:0] sine_cos;
assign sine = sine_cos[27:16];
assign cosine = sine_cos[11:0];
assign clken = 1'b1;
assign carrier = Start_Frequency + frequency_df;
dds_compiler_0 u2(
.aclk(i_clk),
.aclken(clken),
.aresetn(i_rst_n),
.s_axis_config_tvalid(1'b1),
.s_axis_config_tdata(carrier),
.m_axis_data_tvalid(out_valid),
.m_axis_data_tdata(sine_cos)
);
assign o_data = sine;
endmodule
三、数字锁相环FPGA仿真代码
仿真代码,仿真代码比较简单只要给时钟就行了。
`timescale 1ns / 1ps
module PllTwoOrder_tb();
reg i_clk; // 时钟信号, 500KHz
reg i_rst_n; // 复位信号
reg dds_clk;
wire signed [11:0] o_data; // 相干载波信号
PllTwoOrder PllTwoOrder(
.i_clk(i_clk),
.i_rst_n(i_rst_n),
.dds_clk(dds_clk),
.o_data(o_data)
);
initial i_clk = 1;
initial dds_clk = 1;
always #10 dds_clk=~dds_clk;
always #100 i_clk = ~i_clk;
initial begin
i_rst_n = 0;
#100;
i_rst_n = 1;
#200000000;
$stop;
end
endmodule
四、滤波器matlab实现
滤波器这里只要点几下,不用写代码的。
五、数字锁相环仿真和上板实验
仿真这里我用的时钟高一点跑得比较慢还没跑完,但是可以看到是可以锁住的。
仿真图
ILA抓取
通上板子实验也是可以的
最后,这里是第一次写,请多多指出问题。