“分频”:是累加多个输入时钟信号clk_in的周期,最终使得,输出时钟信号clk_out的周期变大,频率变小。
一、偶数分频
例:计数器要实现6分频,输入时钟信号clk_in的6个周期要变成1个周期输出,输出6分频的输出时钟信号clk_out的半个周期占3个输入时钟信号clk_in的周期,相当于clk_out每次在3进制的计数器下,变换一次极性。
公式:f(高)/ f(低)== 分频数 == 周期的扩大倍数 == M
所以计数器的进制N == M/2,这里分析偶数分频,所以把分频数都看作偶数。
例:要实现6分频的话,计数器的进制N == 3。
以6分频为例的具体波形图如下:
使能信号rst先赋值一个时钟周期的低电平信号,用来初始化变量,之后全部赋值为高电平。
下面是具体思路:
定义一个参数:用作偶数分频计数器的进制数 COUNT_INIT == N
用反馈清零法实现N进制的计数器时,计数值的最大值 == 初始计数值+N(进制数)-1。
所以计数值的最大值是(1+COUNT_INIT-1)-1 == COUNT_ININT-1(初始计数值是从1开始的)(这里的-1是因为计数循环的最后一位是0,要减去这一位。)
再定义一个中间变量count_zero,可以分别控制计数值count和输出时钟clk_out,让输出时钟开始是上升沿(高电平的周期时间)以及控制偶数分频的电平变换(计数值为0时的上升沿,输出时钟的极性发生变换。)最终的输出时钟和输入时钟的时序对齐。
初始计数值是1,先是上升沿(高电平的周期),半个周期的计数值循环是:1->2->0(三进制)
具体代码如下:
//计数器偶数分频
module div_ou
(
clk_in,
rst,
clk_out
);
//************************输入输出*************************//
//inputs:
input clk_in;
input rst;
//outputs:
output clk_out;
//************************参数定义*************************//
parameter COUNT_INIT = 3;//N=M/2
//************************变量定义*************************//
//regs:
reg [2:0] count;
reg clk_out;
//wires:
wire count_zero;
//************************程序定义*************************//
//六分频
//引入中间变量count_zero,可以分别控制计数值count和输出时钟clk_out。
//让输出时钟开始是上升沿(高电平的周期时间)
//控制偶数分频的电平变换(计数值为0时的上升沿,输出时钟的极性发生变换。)
//时钟的计数值从1开始:半个周期的循环是1->2->0
//最终的输出时钟和输入时钟的时序对齐
always@(posedge clk_in or negedge rst)
begin
if(~rst)
count<=1'b0;
else if(count==COUNT_INIT-1)//0~N-1
count<=1'b0;
else
count<=count+1'b1;
end
assign count_zero = (count == 0);
always@(posedge clk_in or negedge rst)
begin
if(~rst)
clk_out<=1'b0;
else if(count_zero)
clk_out<=~clk_out;
end
endmodule
二、奇数分频(50%占空比)
下面讨论奇数分频,M为奇数,此方法是用OR(或)操作:
(1)上升沿分频,高电平保持N周期,低电平保持N+1周期;
(2)下降沿分频,高电平保持N周期,低电平保持N+1周期;
将两个结果输出的时钟信号,相或起来得到最终的输出时钟。
例:实现M(奇数)分频:则2N+1 == M,则高电平周期:N == (M-1)/2,低电平周期:N+1 == (M+1)/2。
因为是对高电平和低电平周期分别进行限定,所以此处的周期数等于计数器的进制数,即要实现一个一个N == (M-1)/2进制(高电平周期)的计数器,和一个N+1 == (M+1)/2进制(低电平周期)的计数器。
因为设计的计数器会使输出时钟先是上升沿(高电平周期),所以先实现N进制的计数器,再在此计数器的基础上实现N+1进制的计数器。
定义两个中间变量用来对高低电平周期变换的最大计数值进行限定:CN_M CN_N
N进制(高电平周期):N == (M-1)/2,计数值从1开始,所以最大计数值CN_M == 1+N-1 == (M-1)/2
所以:CN_M == (M-1)/2
N+1进制(低电平周期):N+1 == (M+1)/2,计数值从N+1 == (M+1)/2开始,所以最大计数值CN_N == ( (M+1)/2+(M+1)/2-1)-1==M-1(初始计数值是从1开始的)(这里的-1是因为计数循环的最后一位是0,要减去这一位。)
所以:CN_N == M-1
再引入两个中间变量:count1_zero和count2_zero,其作用与偶数分频的中间变量类似:计数值从1开始,先是上升沿,高电平的周期,并且可以将输出信号clk初始化为上升沿以及控制奇数分频的第二次极性变换,最终使得输出时钟和输入时钟的时序对齐。
计数值从1开始,先是上升沿(高电平的周期):
高电平计数值循环:1->2
低电平计数值循环:3->4->0
两个参数:
实现N+1进制和N进制,看作两个偶数分频器:
CN_M = (M-1)/2;计数值:(实现N进制)(高电平周期)
CN_N = M-1; 计数值:(实现N+1进制)(低电平周期)
如果仅仅是对输入时钟的上升沿或者下降沿的时钟周期相加,则占空比不会是50%,所以需要同时对其上升沿和下降沿进行限定,再将两个输出时钟相或起来,才能得到占空比为50%的奇数分频。
以五分频为例,CN_M =2, CN_N=4,具体波形图如下:
上升沿波形:
下降沿波形:
最终波形:
具体代码如下:
//计数器奇数分频(占空比50%)
module div_ji
(
clk_in,
rst,
clk_out
);
//************************输入输出*************************//
//inputs:
input clk_in;
input rst;
//outputs:
output clk_out;
//************************参数定义*************************//
parameter CN_M = 2;//(M-1)/2
parameter CN_N = 4;//M-1
//************************变量定义*************************//
//regs:
reg clk1;
reg [2:0] count1;
reg clk2;
reg [2:0] count2;
//wires:
wire count1_zero;
wire count2_zero;
//************************程序定义*************************//
//五分频
//上升沿
always@(posedge clk_in or negedge rst)
begin
if(~rst)
count1<=1'b0;
else if(count1==CN_M)//0~CN_M(0~2)
count1<=count1+1'b1;
else if(count1==CN_N)//CN_M+1~CN_N(3~4)
count1<=1'b0;
else
count1<=count1+1'b1;
end
assign count1_zero = (count1 == 0);
always@(posedge clk_in or negedge rst)
begin
if(~rst)
clk1<=1'b0;
else if(count1==CN_M)//高电平的保持周期:1->2(1->CN_M)
clk1<=~clk1;
//计数值从1开始,先是上升沿,高电平的保持周期。
//将输出信号clk初始化为上升沿(高电平的保持周期)以及控制奇数分频的第二次电平变换。
else if(count1_zero)//低电平的保持周期:3->4->0(CN_M+1->CN_N->0)
clk1<=~clk1;
end
//下降沿
always@(negedge clk_in)
begin
if(~rst)
count2<=1'b0;
else if(count2==CN_M)
count2<=count2+1'b1;
else if(count2==CN_N)
count2<=1'b0;
else
count2<=count2+1'b1;
end
assign count2_zero =(count2 == 0);
always@(negedge clk_in)
begin
if(~rst)
clk2<=1'b0;
else if(count2==CN_M)
clk2<=~clk2;
else if(count2_zero)
clk2<=~clk2;
end
//outputs:
assign clk_out=clk1||clk2;
endmodule
标签:分频,周期,CN,高电平,clk,Verilog,Hdl,时钟
From: https://blog.csdn.net/m0_56351488/article/details/139760918