FPGA数字锁相环(DPLL)

目录

一、数字锁相环原理

二、数字锁相环FPGA代码

三、数字锁相环FPGA仿真代码

四、滤波器matlab实现

五、数字锁相环仿真和上板实验


一、数字锁相环原理

简单来说,数字锁相环(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抓取

通上板子实验也是可以的

最后,这里是第一次写,请多多指出问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值