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间隔出现,证明了本次仿真是正确的。

  • 相关阅读:
    three.js raycaster射线碰撞的坑 (当canvas大小 不是屏幕大小是解决拾取物体的办法)
    如何去掉IE文本框后的那个X css代码
    解决input 有readonly属性 各个浏览器的光标兼容性问题
    centos的基本命令03(du 查看文件详情,echo清空文件内容)
    centos的 / ~
    centos的基本命令02
    centos的基本命令01
    关系性数据库和非关系型数据库
    绝对路径和相对路径的理解
    linux的目录和基本的操作命令
  • 原文地址:https://www.cnblogs.com/429512065qhq/p/8525549.html
Copyright © 2011-2022 走看看