赞
踩
如果用锁相环倍频的话,那假如设计一个输入时钟clk_in的3.5分频。使用2倍频的话,其实就相当于设计的是clk_in 2倍频之后的7分频(即一个奇数分频);而使用4倍频的话,其实就相当于设计的是clk_in 4倍频之后的14分频(即一个偶数分频)。
这样虽然设计出来了,但是却比较浪费资源,并且也根本算不上是小数分频。
常规设计思路如下:
假设设计一个3.5分频,我们令半个clk_in周期为一个clk,后面我们以clk为单位,而不用clk_in的一个完整周期。
3.5分频即有7个clk为它的一个完整周期,N.5分频就有2N+1个clk,那么肯定高电平时间和低电平时间是不可能一样的,具体原理如下图,这也是仿真结果图(其实就是自己不想画图):
说明一下:第一行是时钟信号clk_in; 第二行是复位信号rst_n; 第三行是clk_p,上升沿翻转时钟;
第四行是clk_n,下降沿翻转时钟; 第五行是clk_N_point5,就是输出时钟
假设从最左侧蓝线处算作初始化,(注意:初始化的时候,也就是下降沿复位的话,对clk_p和clk_n的赋值一定要相反,可以让clk_p为0,clk_n为1)
具体如何计数呢?
复位之后,在一个上升沿进行上升沿计数,计数到6清零,并且在0和4的时候进行翻转(计数到2N清零,并且在0和N+1的时候进行翻转),得到clk_p;
复位之后,在一个下降沿进行下降沿计数,计数到6清零,并且在0和3的时候进行翻转(计数到2N清零,并且在0和N的时候进行翻转),得到clk_n;
最后,对clk_p和clk_n进行与运算,得到clk_N_point5 ; clk_N_point5 = clk_p && clk_n;
仿真效果如下:
但是可以看到:输出时钟的占空比非常低,占空比为 1:2N+1,如果N更大一些,占空比会更小。
不想画图,放出改进后的原理图:
复位之后,在一个上升沿进行上升沿计数,计数到6清零,并且在0和5的时候进行翻转,得到clk_p;
复位之后,在一个下降沿进行下降沿计数,计数到6清零,并且在1和3的时候进行翻转,得到clk_n;
最后,对clk_p和clk_n进行与运算,得到clk_N_point5 ; clk_N_point5 = clk_p && clk_n;
这是当N==3的时候,在这些地方翻转,那当N为其他值呢?经过我的带入—纸上—递归法得到:
对任意N:复位之后,在一个上升沿进行上升沿计数,计数到2N清零,并且在0和N+1+N/2的时候进行翻转,得到clk_p;
复位之后,在一个下降沿进行下降沿计数,计数到6清零,并且在N/2和N的时候进行翻转,得到clk_n。
N=3:
N=5:
N=20:
可以看出:高低电平总是只相差半个clk_in,当N越大,输出时钟的占空比也越大,越接近50%
1、源代码
`timescale 1ns / 1ps module divider_point5 #(parameter CLK_N = 2) ( input clk_in, input rst_n, output reg clk_2in, // 2N倍频时钟 output reg clk_2in_2, // 下降沿2N倍频时钟 //output clk_en, output clk_N_point5, output reg clk_out ); reg [7:0] cnt_2N; // 2N倍频时钟计数 reg [7:0] cnt_2N_2; // 下降沿2N倍频时钟计数 reg clk_out_g1; assign clk_N_point5 = clk_2in && clk_2in_2; // 上升沿生成2N分频时钟电路 always@(posedge clk_in or negedge rst_n) begin if(!rst_n) cnt_2N <= 8'b0; else if(cnt_2N == 2*CLK_N) cnt_2N <= 8'b0; else cnt_2N <= cnt_2N + 1'b1; end always@(posedge clk_in or negedge rst_n) begin if(!rst_n) clk_2in <= 1'b0; //else if((cnt_2N == CLK_N+1) ||( cnt_2N ==0 )) begin // 这个是占空比为1:2N+1,未改进 else if((cnt_2N == CLK_N+1+CLK_N/2) ||( cnt_2N ==0 )) begin // 这个是占空比尽量靠近0.5的方式 clk_2in <= ~clk_2in; end else clk_2in <= clk_2in; end // 下降沿生成2N分频时钟电路 always@(negedge clk_in or negedge rst_n) begin if(!rst_n) cnt_2N_2 <= 8'b0; else if(cnt_2N_2 == 2*CLK_N) cnt_2N_2 <= 8'b0; else cnt_2N_2 <= cnt_2N_2 + 1'b1; end always@(negedge clk_in or negedge rst_n) begin if(!rst_n) clk_2in_2 <= 1'b1; //else if((cnt_2N_2 == CLK_N) ||( cnt_2N_2 == 0 )) begin // 这个是占空比为1:2N+1,未改进 else if((cnt_2N_2 == CLK_N) ||( cnt_2N_2 == CLK_N/2 )) begin // 这个是占空比尽量靠近0.5的方式 clk_2in_2 <= ~clk_2in_2; end else clk_2in_2 <= clk_2in_2; end endmodule
2、仿真文件
`timescale 1ns / 1ps `define clk_period 20 module divider_point5_tb(); parameter CLK_N = 20; reg clk_in; reg rst_n; wire clk_2in; wire clk_2in_2; wire clk_N_point5; initial begin rst_n = 1; clk_in = 0; #2; rst_n = 0; #3; rst_n = 1; end always #(`clk_period/2) clk_in = ~clk_in; divider_point5 #(.CLK_N (CLK_N)) divider_point5( .clk_in (clk_in), .rst_n (rst_n), .clk_2in (clk_2in), .clk_2in_2 (clk_2in_2), .clk_N_point5 (clk_N_point5) ); endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。