zoukankan      html  css  js  c++  java
  • FPGA数字鉴相鉴频器的开发记录

    1. 对于电机的锁相控制,需要对相差进行PI性质的环路滤波,但现有的锁相环中鉴频鉴相器输出为相差脉冲而非数字量,难以直接进行PI特性的环路滤波。

    通过对晶振的非整数分频获取准确的参考时钟,基于触发器机制实现了PFD相差脉冲的数字量化,且可以输出频差数字量。锁相环是频率和相位的同步控制系统,实现输入参考信号和反馈信号的频率相等,相位差恒定。利用锁相环技术可实现数字信号的同步,将这个思想引入电机的速度控制系统中,则能够实现稳态精度很高的转速控制。综合起来就是电机转速的控制反馈系统,因为要求相位差恒定,所以需要准确的检测相位差,而本次的设计就是检测相位差。锁相环和数字鉴相鉴频器是两个东西,前者是控制,后者是检测。

    2. Pi性质的环路滤波?难道是PID控制,在反馈系统中,用输出的实际值和理论值的差值去反馈进系统的输入。PID就是反馈的比例,积分和微分。不过这里的滤波是什么?电机的锁相环控制中,电机加霍尔传感器是二阶系统。什么是二阶系统? y=ax^2+bx+c?

    3. 做鉴相鉴频器的目的是为了稳速,不过现在还没明白,如何提高速度。这并不是我们关心的,假设电机转速500转每秒(霍尔传感器采样得到500MHz),晶振时钟是40MHz。

    4.为了得到500 Hz的参考时钟,需要对40 MHz的晶振时钟进行两次分频操作。分频系数为N-0.5(N为整数)时,就是半整数分频。本次需要实现奇数分频,还有半整数分频。对40 MHz的晶振时钟先后进行等占空比125分频和2. 5半整数分频,得到320 kHz和128 kHz的时钟,经过时钟预分频器分频后的固定占空比128  kHz的时钟信号经过8位计数器,得到500  Hz的参考输入信号,反馈时钟输入并检测到其上升沿。

    5. 在每个反馈信号的上升沿保存8位寄存器的值,这个值就是频率差(非线性)和相位差(线性)。同时用一个标志位,为1说明有上升沿,为0说明无上升沿,代码如下

    module pfd(reset, clk_40mhz, clk_128k, clk_fb_500, phase_value, clk_ref_out);
    
    input reset;
    input clk_128k;  //两次分频得到的128Khz的时钟
    input clk_fb_500; //电机的反馈时钟500hz
    input clk_40mhz;
    
    reg  clk_ref_500;
    output [7:0] phase_value;
    reg [7:0] phase_reg;
    output clk_ref_out;
    
    reg [7:0] cout_8bit; //8位计数器
    reg [7:0] ph_reg; //8位寄存器
    reg have_flag;
    reg clk_fb_prv;
    reg clk_ref_prv;
    reg [7:0] phase_value_1;
    reg [7:0] phase_value_tmp;
    parameter PHASE_MAX_VALUE = 8'h7F;
    
    wire cout_en;
    
    //8位计数器,一个always里面可以写2个if语句吗?
    always @(posedge clk_128k or negedge reset) begin
        if(!reset)
            cout_8bit <= 8'b0;
        else 
            cout_8bit <= cout_8bit + 1'b1;    
    end
    
    //产生参考时钟500HZ
    always @(posedge clk_40mhz) begin
    
        if(cout_8bit == 8'h0) 
            clk_ref_500 <= 0;
        else if(cout_8bit == 8'h7f)
            clk_ref_500 <= 1;
        else
            clk_ref_500 <= clk_ref_500;
    end
    
    //D触发器,边沿检测反馈信号上升沿和参考信号下降沿
    /*
    always @(posedge clk_fb_500 or negedge clk_ref_500) begin
        if(clk_fb_500 == 1) begin
            have_flag = 1;
            clk_fb_prv = clk_fb_500;
            phase_value_1 = cout_8bit; end
        else if(clk_ref_500 == 0) begin 
            have_flag = 0;
            phase_value = phase_value_tmp; end
       else 
           have_flag = 0;
    
    end
    */
    
    always @(posedge clk_40mhz) begin
        clk_fb_prv <= clk_fb_500;
        clk_ref_prv <= clk_ref_500;
        if({clk_fb_prv,clk_fb_500} == 2'b01) begin //判断反馈信号的上升沿
            have_flag <= 1;
            phase_value_1 <= cout_8bit; end
        else if({clk_ref_prv,clk_ref_500} == 2'b01) begin  //判断参考信号的上升沿
            have_flag <= 0;
            phase_reg <= phase_value_tmp; end
       else 
           have_flag <= have_flag;
    
    end
    
    //怎么去解决一个周期内有2个反馈信号的上升沿的问题?
    //总线选通开关
    always @(posedge clk_40mhz)begin 
        if(have_flag == 1)
            phase_value_tmp <= phase_value_1;
        else
            phase_value_tmp <= PHASE_MAX_VALUE;
            
    end
    //PFD输出
    //always @(posedge clk_128k)
    
    assign clk_ref_out = clk_ref_500;
    assign phase_value = phase_reg;
    endmodule

    6. 实际仿真如下,当反馈信号滞后于参考信号1/4周期的时候,输出为0xc0,那么高位为1,说明是滞后(0xff-0xc0=0xff/4),不过波形都是相对的周期,换种说法说是超前0xc0也是对的,主要是看对比前一个参考上升沿还是下一个参考上升沿。两种定义都可以。

    7. 当反馈信号超前于参考信号的时候,输出为0x4d,那么高位为0,说明是超前(0x4d)

    8. 频率差,当反馈信号的频率高于参考信号时,在一个参考时钟周期内会有多个反馈时钟的上升沿出现,PFD的输出将会是最后一个反馈时钟沿对应的寄存的值,是一个负数,表明反馈信号超前参考信号。锁相环路将会降低VCO的输出降低反馈信号的频率。当反馈信号的频率低于参考信号时,在某个参考时钟周期内将不会有反馈信号的上升沿出现,此时PFD会复位触发器,输出对应于最大滞后量的7FH,此时锁相环路将会提高VCO的输出提高反馈信号的频率。下图是输出0X7FH的仿真。当然在下一个周期,仍然会检测到反馈信号的上升沿,所以0X7FH和0X66H间隔出现,证明了本次仿真是正确的。

  • 相关阅读:
    BZOJ2219数论之神——BSGS+中国剩余定理+原根与指标+欧拉定理+exgcd
    Luogu 3690 Link Cut Tree
    CF1009F Dominant Indices
    CF600E Lomsat gelral
    bzoj 4303 数列
    CF1114F Please, another Queries on Array?
    CF1114B Yet Another Array Partitioning Task
    bzoj 1858 序列操作
    bzoj 4852 炸弹攻击
    bzoj 3564 信号增幅仪
  • 原文地址:https://www.cnblogs.com/429512065qhq/p/8525549.html
Copyright © 2011-2022 走看看