VHDL学习第二则

"分频"

Posted by LiYanXin on April 1, 2020

VHDL-learning

VHDL FPGA学习

分频问题

虽然现在大部分涉及时钟分频的设计里主要都调用锁相环(PLL)IP 核来实现,精度很高,也十分灵活、方便,但毕竟使用的资源稍高。如果对时钟精度要求不高的情况下,还是可以使用语言直接描述分频过程的。 分频主要可以分为最简单的偶数分频,奇数分频和小数分频。

偶数分频

偶数分频是最容易实现的,可以细分为2^N 分频和非2^N分频

  • 对于非2^N分频,我们可以直接设计一个计数器,控制时钟的翻转。假设我们要设计一个N倍分频,当计数器计数到N/2 - 1时,翻转时钟即可。
    例如一个10分频电路:

<div align=center></div>

<div align=center></div>

产生一个周期为10的计数器,在count = 4的时候翻转即可。

  • 对于2^N分频,我们可以直接使用二进制位翻转

<div align=center></div>

<div align=center></div>

对2,4,8分频,我们直接利用计数器的第0,1,2位翻转即可。

奇数分频

奇数分频相对偶数分频要难一些。 以3分频为例,我们可以采用上升沿和下降沿产生两个时钟相与的方法产生。

<div align=center></div>

如上图所示,在上升沿和下降沿各产生一个3分频信号,每个占空比为2:4,但由于时钟交错了半个clock,相与以后就是占空比50%的时钟了!

1
2
3
4
5
6
7
8
<div align=center><img width="250" height="250" src="/img/3_div_1.jpg"></div>  

<div align=center><img width="250" height="250" src="/img/3_div_2.jpg"></div>  

<div align=center><img width="250" height="250" src="/img/3_div_3.jpg"></div>  

类似得,我们可以将算法推广到5分频,只要计数器循环范围改为000-100,clk1在001和011处的上升沿翻转(占2个数,即两个时钟),
clk2在001和011处的下降沿翻转(比clk1提前半个时钟),再相与(相当于2个时钟 + 半个时钟 = 2.5个时钟 = 5/2)就可以了。  

小数分频

  • 首先先看比较常见的 N.5分频,比如2.5分频,可以理解为2.5个时钟出一个新的时钟,这样看来,关键在于如何凑出0.5个时钟,与上述的奇数分频类似,采用上下沿各产生一个clk的方法即可。

<div align=center></div>

1
示意图如上,在上升沿和下降沿各输出2个clk的高电平,中间相隔0.5个低电平,这样凑出了2.5个时钟周期。
  • 其余的小数分频 任意小数均可以化为分数,例如要进行5.3分频即53/10分频,因此之后全部以分数来表示。 以13/4分频为例,我们首先要想明白什么是13/4分频。 什么是2分频呢?就是每两个输入时钟得到一个输出时钟,4分频就是4/1即四个输入时钟得到一个输出时钟,因此13/4分频其实就是13个输入时钟得到4个输出时钟, 想明白这一点很重要。 13/4分频其实就是13个输入时钟得到4个输出时钟,因此脉冲删除小数分频相对比较简单。 意思就是在13个输入时钟里我删掉9个时钟周期,这样不就输出了4个时钟周期了么,就是这样。那应该怎么删呢,查了一些论文后得到结论:

    1.设置寄存器cnt位宽自定,我用的[7:0],初始值为0;

    2.在clk_in的上升沿+4,并判断是否大于13,若大于13在下一周期-13;

    3.cnt小于13时候,删除脉冲信号delete=1,大于13时候delete=0;

    说起来比较乱,画个表表示下,每12个周期我们作为一个循环来看:

    时钟序号 cnt值 是否删除
    0 4 Y
    1 8 Y
    2 12 Y
    3 (16->)3 N
    4 7 Y
    5 11 Y
    6 (15->)2 N
    7 6 Y
    8 10 Y
    9 (14->)1 N
    10 5 Y
    11 9 Y
    12 (13->)0 N
    0 4  

从表中可以看到每13个周期有4个周期没有被删除,刚好满足要求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
我们再来试一个,11/9吧:  

时钟序号 |	cnt值 		|	是否删除
	0 	|		9 		|	Y
	1 	|		18->7 	|  **N**
	2 	|		16->5 	|  **N**
	3 	|		14->3 	|  **N**
	4 	|		12->1 	|  **N**
	5 	|		10 		|	Y
	6 	|		19->8 	|  **N**
	7 	|		17->6 	|  **N**
	8 	|		15->4 	|  **N**
	9 	|		13->2 	|  **N**
	10 	|		11->0 	|  **N**
	0 	|		9 	 |

可以看到11个时钟里有删除了2个,输出了9个,完美。