震撼!FPGA实现负反馈控制纯数字锁相环!

今日头条

1152人已加入

描述

作者:包春,胡建东QQ:1758931664 

   

    很多小伙伴说控制原理真**难学小编深有同感于是发布此文帮助在控制原理里面不停挣扎的小伙伴们帮你们拨开迷雾此文专门告诉你怎么实现数字负反馈控制一切高深理论均不涉及!  

      首先我们做一个模块输入信号T,代表输出时钟周期输出时钟周期严格等于T,对于熟悉FPGA的小伙伴应该很容易下面是小编的代码简单的说就是建立一个状态机对输入周期参数在产生时钟的每个周期第一时刻更新值然后进入下一个状态计数计数到和输入周期一致的时候又回到初始状态 

1. module clk_gen(  

2.     input               clk,  

3.     input     [15:0]    T  ,//it can not be 0!  

4.     output reg          clk_gen   

5. );  

6.        

7.     reg       [15:0]    cnt_div = 0;  

8.     reg       [15:0]    period = 0;  

9.     reg       [ 1:0]    now_s  = 0;  

10.     reg       [ 1:0]    next_s = 0;  

11.       

12.     always@(posedge clk)  

13.     begin  

14.        now_s <= next_s;  

15.     end       

16.       

17.     always@(*)  

18.     begin  

19.        case(now_s)  

20.           2'h0  : next_s = (T > 0) ? 1 : 0;  

21.           2'h1  : next_s = (cnt_div < (period>>1)) ? 1: 3;//跑前半周期  

22.           2'h3  : next_s = (cnt_div < (period-1)) ? 3: 0; //跑后半周期  

23.           default: next_s =0;  

24.        endcase  

25.     end   

26.       

27.     always@(posedge clk)  

28.     begin  

29.        case(next_s)  

30.           2'h0  : begin period  <= T;                         cnt_div <= 0;           clk_gen <= 1'b0; end  

31.           2'h1  : begin period  <= (now_s == 0) ? T : period; cnt_div <= cnt_div + 1; clk_gen <= 1'b0; end//刷新T  

32.           2'h3  : begin                                       cnt_div <= cnt_div + 1; clk_gen <= 1'b1; end  

33.           default: begin period  <= 10;                       cnt_div <= 0;           clk_gen <= 1'b0; end  

34.        endcase  

35.     end   

36. endmodule   

       上面这个模块就是我们的控制对象也就是说我们要想办法让他的时钟频率Fo = 系统给定时钟频率Fi*N,也就是说:                                                    输出时钟周期To = 系统时钟周期Ti/N。

       小编采用如下环路实现从中可以看出小编的方法反馈控制的是周期所以一切参数都转化到周期上输入和反馈输出都是通过周期控制从图中可以得出结论输出时钟周期To=N/(M*N+1) 

FPGA设计


    输入时钟要求稳定并且比系统时钟慢的越多越好因为这样测量更准确下面就是我们测量时钟周期的代码反馈非常重要因为他涉及到整个反馈环路的精度和运作效率除以N的部分我们在另一个模块实现因为测量时钟周期的模块是相对独立的输入和反馈都要用到独立出来可以加强代码可重用性这段代码就是在每个输入时钟上升沿电脑时候更新周期值以保证周期的准确性 

1. module figure_T(  

2.     input                clk,  

3.     input                clk_in,  

4.     output reg[15:0]     T = 0  

5.     );  

6.       

7.     localparam           PE = 2'b01;  

8.       

9.     reg       [ 1:0]     clk_buf = 0;  

10.     reg       [15:0]     cnt_T = 0;  

11.     reg                  state = 0;  

12.       

13.     always@(posedge clk) begin clk_buf <= {clk_buf[0],clk_in}; end  

14.       

15.     always@(posedge clk)  

16.     begin  

17.        case(state)  

18.           0:begin state <= (clk_buf == PE) ? 1 : 0; cnt_T <= (clk_buf == PE) ? 1 : 0; end  

19.           1:begin state <= (clk_buf == PE) ? 0 : 1; cnt_T <= cnt_T + 1; T <= (clk_buf == PE) ? cnt_T : T; end  

20.           default: state <= 0;  

21.        endcase  

22.     end  

23. endmodule   

    控制对象和输入反馈参数产生都已经好了剩下的就是按照控制框图搭建反馈环路代码如下图代码中的Ti是在顶层产生的输入时钟被测量后才把Ti给到环路输入34行是将反馈的时钟周期乘以反馈增益1/N,35行是将反馈误差乘以开环增益1/M至此整个环路已经搭建完成 

1. module feedback(  

2.     input                clk,  

3.     input     [15:0]     Ti,  

4.     output               clk_out  

5.     );  

6.       

7.     parameter            M  = 10;//参数  

8.     parameter            N  = 10;//参数  

9.       

10.     wire      [15:0]     T_clk_out;  

11.     reg       [15:0]     T;  

12.     reg       [15:0]     err;  

13.     //反馈误差  

14.     always@(posedge clk) begin err <= Ti - (T_clk_out/N); end  

15.     always@(posedge clk) begin T   <= err/M; end  

16.     //被控制对象  

17.     clk_gen u_clk_gen(  

18.         .clk    ( clk     ),  

19.         .T      ( T       ),  

20.         .clk_gen( clk_out )  

21.     );  

22.     //输出时钟周期反馈  

23.     figure_T uT(  

24.        .clk   ( clk       ),  

25.        .clk_in( clk_out   ),  

26.        .T     ( T_clk_out )  

27.     );  

28. endmodule 

       这里附上小编顶层代码这里从30行开始的模块就是产生上文说的Ti用的输入时钟直接测量后变成是种病周期T输入到feedback模块 

1. module dll(  

2.     input          clk,       

3.     input          clk_in,       

4.     output         clk_out       

5. );  

6.       

7.     wire    [15:0] T;  

8.       

9.     figure_T uT(  

10.        .clk   ( clk ),  

11.        .clk_in( clk_in ),  

12.        .T     ( T )  

13.     );  

14.     //  

15.     feedback #(  

16.         .M      ( 9  ),  

17.         .N      ( 1  )  

18.     ) u_fb(  

19.         .clk    ( clk ),  

20.         .Ti     ( T   ),  

21.         .clk_out( clk_out )  

22.     );  

23.         

24. endmodule  

    那么实际效果咋样呢能工作吗工作起来是啥样子小编接下来就测试给大家看测试代码如下输出时钟周期在反馈的代码里面找输入时钟周期是给定的这两个找出来对比看看与理论差多远就知道了这里令M = 10,N=10。 这两个参数完全决定了输出时钟频率。

1. module tb_dll;  

2.     parameter     HT = 100;  

3.     // Inputs  

4.     reg clk;  

5.     reg rst;  

6.     reg clk_in;  

7.   

8.     // Outputs  

9.     wire clk_out;  

10.     wire [15:0] Tclk_out;  

11.     wire [15:0] Tclk_in;  

12.   

13.   

14.     initial begin  

15.         // Initialize Inputs  

16.         clk = 0;  

17.         rst = 0;  

18.         clk_in = 0;  

19.   

20.         // Wait 100 ns for global reset to finish  

21.         #100;  

22.           

23.         // Add stimulus here  

24.   

25.     end  

26.       

27.     always begin clk    = 0;#1   clk    = 1;  #1;  end//主时钟产生   

28.     always begin clk_in = 0;#HT  clk_in = 1;  #HT; end//输入时钟产生   

29.     // Instantiate the Unit Under Test (UUT)  

30.     dll uut (  

31.         .clk    ( clk    ),   

32.         .clk_in ( clk_in ),   

33.         .clk_out( clk_out)  

    34.     );   

35.

35.   

36.   

37. endmodule   

    仿真结果如下看图1可知输出时钟周期稳定后为To = 10*2ns,输入时钟为Ti=100*2ns,所以To/Ti = 0.1。而理论值为N/(M*N+1)=10/(10*10+1)=0.099。

误差err = |0.1-0.099|/0.1=1% ! 

FPGA设计

FPGA设计

    我们看看下图的波形输出时钟周期的震荡是不是很像连续系统的二阶震荡环节的阶跃响应只不过超调不大震荡周期比较少和控制原理书上很近似看看离散控制部分会更觉得近似)。小编今天讲到这里有任何疑问请对公众号“玩儿转FPGA”发消息提问”,就可以获得小编联系方式并提问,或者加QQ1758931664 一起探讨共同进步


声明:此文是作者原创内容,未经允许严禁抄袭!!原文出自微信公众号“玩儿转FPGA”,历史消息里面有,大家可以查看作者和日期,是纯原创,希望大家支持!











打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分