时钟分频是数字电路设计的基础,我们在数字系统设计过程会遇到多种分频需求,常见的有偶数分频、奇数分频,和一些非整数的分频等。
在某些设计中,对分频出时钟的占空比也有严格的要求。
常见的分频思路(这里以50%占空比情况举例):
一、偶数分频:
比如分频系数为N,声明一个计数器count,count从0计数到N-1,if语句直接判断令前半周期为0,后半个周期为1即可
如下例子:N2是一个偶数,clk3是输出时钟;
always @(posedge clk or negedge rst)
begin
if (!rst)
begin
count3<=4'd0;
clk3<=1'b0;
end
else
if(count3<N2-1)
begin
count3<=count3+1'b1;
if(count3<(N2/2-1))
clk3<=1'b0;
else
clk3<=1'b1;
end
else
begin
count3<=4'd0;
clk3<=1'b0;
end
end
二、奇数分频
设计思想
对于实现占空比为50%的N倍奇数分频,由于输出时钟的上升沿是在系统时钟的下降沿,因此不能只通过上升沿或者下降沿决定时钟翻转。
首先进行上升沿触发进行模N计数,计数到某一个值n时输出时钟进行翻转,然后再计数(N-1)/2次,再次进行翻转得到一个占空比非50%奇数n分频时钟。同理,同时进行下降沿触发的模N计数,等计数到n时,输出时钟进行翻转,同样再计数(N-1)/2次,输出时钟再次翻转生成占空比非50%的奇数n分频时钟。两个占空比非50%的n分频时钟进行相或运算,即得到占空比为50%的奇数N分频时钟。
always @(posedge clk or negedge rst)
begin
if (!rst)
begin
count1<=4'd0;
clk1<=1'b0;
end
else
if(count1<N1-1)
begin
count1<=count1+1'b1;
if(count1<(N1-1)/2)
clk1<=1'b0;
else
clk1<=1'b1;
end
else
begin
count1<=4'd0;
clk1<=1'b0;
end
end
always @(negedge clk or negedge rst)
begin
if (!rst)
begin
count2<=4'd0;
clk2<=1'b0;
end
else
if(count2<N1-1)
begin
count2<=count2+1'b1;
if(count2<(N1-1)/2)
clk2<=1'b0;
else
clk2<=1'b1;
end
else
begin
count2<=4'd0;
clk2<=1'b0;
end
end
三、非整数分频
结合前面两中分频原理的思想,既用整数分频又用奇数分频,如10/3分频,可以做两个3倍分频和一个4倍分频;
计数器在前六个时钟设为奇数分频状态,后四个时钟切换到偶数分频状态;
代码如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: BUPT,abs_Lab
// Engineer: Mr.Bai
//
// Create Date: 10:11:46 02/27/2014
// Design Name:
// Module Name: div1
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module div1(clk,rst,clk_out);
input clk;
input rst;
output clk_out;
parameter N1=3;
parameter N2=4;
parameter IDLE=3'b000;
parameter SA = 3'b010;
parameter SB = 3'b100;
reg [3:0] count=4'd0;
reg [3:0] count1=4'd0;
reg [3:0] count2=4'd0;
reg [3:0] count3=4'd0;
reg [2:0] state=IDLE;
reg clk1=1'b0;
reg clk2=1'b0;
reg clk3=1'b0;
assign clk_out=clk1 | clk2 | clk3;
always @(posedge clk or negedge rst)
begin
if(!rst)
begin
count<=4'd0;
state<=IDLE;
end
else
if(count<9)
begin
count<=count+1'b1;
if(count<5)
state<=SA;
else
state<=SB;
end
else
begin
count<=4'd0;
state<=SA;
end
end
always @(posedge clk )
begin
case (state)
IDLE: state<=SA;
SA: if (!rst)
begin
count1<=4'd0;
clk1<=1'b0;
end
else
if(count1<N1-1)
begin
count1<=count1+1'b1;
if(count1<(N1-1)/2)
clk1<=1'b0;
else
clk1<=1'b1;
end
else
begin
count1<=4'd0;
clk1<=1'b0;
end
SB: if (!rst)
begin
count3<=4'd0;
clk3<=1'b0;
end
else
if(count3<N2-1)
begin
count3<=count3+1'b1;
if(count3<(N2/2-1))
clk3<=1'b0;
else
clk3<=1'b1;
end
else
begin
count3<=4'd0;
clk3<=1'b0;
end
// default:state<=IDLE;
endcase
end
always @(negedge clk )
begin
case(state)
SA:
if (!rst)
begin
count2<=4'd0;
clk2<=1'b0;
end
else
if(count2<N1-1)
begin
count2<=count2+1'b1;
if(count2<(N1-1)/2)
clk2<=1'b0;
else
clk2<=1'b1;
end
else
begin
count2<=4'd0;
clk2<=1'b0;
end
// default:state<=IDLE;
endcase
end
endmodule
xilinx ISE 仿真如下:
modelsim 仿真图