FPGA数字锁相环(DPLL)
目录
一、数字锁相环原理
二、数字锁相环FPGA代码
三、数字锁相环FPGA仿真代码
四、滤波器matlab实现
五、数字锁相环仿真和上板实验
一、数字锁相环原理
简单来说,数字锁相环(DPLL)就像一场“你追我赶”的同步游戏。想象一下你跑步时要和另一个人保持步调一致:当对方加速时,你也要加快;对方减速时,你也要调整节奏。DPLL的作用就是让两个信号(比如接收的信号和本地生成的信号)像这对跑者一样“锁”在同一个节奏上。
它的核心原理分为三步:
比快慢:鉴相器像裁判一样,不断比较输入信号和本地信号的相位差。如果输入信号相位超前,相当于对方跑快了;反之则是本地信号更快。
算误差:环路滤波器像教练,根据裁判的反馈计算需要调整的节奏幅度。它不会直接照搬误差值,而是像给建议一样“平滑处理”,避免步子调整得太大导致摔跤。
调步伐:数控振荡器(NCO)就像运动员的双腿,根据教练的建议调整自己的输出频率。通过不断微调,最终让本地信号的相位和输入信号完全同步。
原理图
二、数字锁相环FPGA代码
fpga顶层代码
module PllTwoOrder( i_clk,i_rst_n,dds_clk,o_data);input i_clk; // 时钟信号, 500KHzinput i_rst_n; // 复位信号input dds_clk;wire [11:0] i_data;output signed [11:0] o_data; // 相干载波信号parameter Start_Frequency = 28\'d16106127; // DDS初始频率输出30kDDS 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;elsedin_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 / 1psmodule PllTwoOrder_tb(); reg i_clk; // 时钟信号, 500KHzreg 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; endendmodule
四、滤波器matlab实现
滤波器这里只要点几下,不用写代码的。
五、数字锁相环仿真和上板实验
仿真这里我用的时钟高一点跑得比较慢还没跑完,但是可以看到是可以锁住的。
仿真图
ILA抓取
通上板子实验也是可以的
最后,这里是第一次写,请多多指出问题。