时钟分频也是笔试题里面经常出现的,(我已经遇到过了),看完这一篇,分分钟掌握!
目录
偶数分频
D触发器级联法
计数器法
奇数分频
占空比50% 的奇数分频
占空比无要求的奇数分频
任意小数分频
偶数分频
文章图片
如上图输入给clk,输出将其变成周期为2倍的clk_out2, 将其变成周期为4倍的clk_out4,将其变成周期为8倍的clk_out8,占空比为50%
D触发器级联法
对于偶数分频电路,在不考虑时钟同步时钟延迟的问题时,直接使用D触发器级联来实现:关键在于,上升沿才能触发翻转,但是一个周期只有一个上升沿,因此周期翻倍
文章图片
`timescale 1ns/1nsmodule even_div
(
inputwire rst ,
inputwire clk_in,
outputwire clk_out2,
outputwire clk_out4,
outputwire clk_out8
);
reg clk_out2_r, clk_out4_r, clk_out8_r;
always@(posedge clk_in or negedge rst) begin
if(~rst)
clk_out2_r <= 0;
else
clk_out2_r <= ~clk_out2_r;
endalways@(posedge clk_out2 or negedge rst) begin
if(~rst)
clk_out4_r <= 0;
else
clk_out4_r <= ~clk_out4_r;
endalways@(posedge clk_out4 or negedge rst) begin
if(~rst)
clk_out8_r <= 0;
else
clk_out8_r <= ~clk_out8_r;
endassign clk_out2 = clk_out2_r;
assign clk_out4 = clk_out4_r;
assign clk_out8 = clk_out8_r;
endmodule
计数器法
2、4、8恰好是2的次方,可构造一个3位计数器,依靠第0位,第1位,第2位的变化速度来实现:
2分频的输出=cnt第0位(由于计数器在clk=高电平时才+1,因此本身就是2倍的周期)
【FPGA——时钟分频】4分频输出=cnt第1位
8分频输出=cnt第2位
eg 4分频:000 001 010 011 100 101 110 111 000
`timescale 1ns/1ns
module even_div
(
inputwire rst ,
inputwire clk_in,
outputwire clk_out2,
outputwire clk_out4,
outputwire clk_out8
);
reg [2:0]cnt;
always@(posedge clk_in or negedge rst)
if(!rst)
cnt <= 3'b111;
//初始赋全1
else
cnt <= cnt+1;
assign clk_out2 = ~cnt[0];
//根据波形,一开始全为高电平
assign clk_out4 = ~cnt[1];
assign clk_out8 = ~cnt[2];
endmodule
奇数分频 占空比50% 的奇数分频
文章图片
设计一个同时输出7分频的时钟分频器,占空比要求为50%
对于奇数分频电路,主要难点在于50%占空比的实现。单触发沿在奇数分频中是没有办法实现50%占空比的,因此需要考虑使用双边沿加组合逻辑实现50%占空比
文章图片
设置计数器,计数器从0→6,当计数器==3,上升沿触发得到clk_pos,下降沿触发得到clk_neg,
而输出的7分频clk,上升沿在clk_neg触发,下降沿在clk_pos触发,是clk_neg和clk_pos进行或运算的结果
根据这个思路,我们可以得到任意奇数分频,占空比为50%的输出,修改N值即可,代码如下:
`timescale 1ns/1nsmodule odo_div_or
#(parameter N = 7)
(
inputwirerst ,
inputwireclk_in,
outputwireclk_out7
);
reg [3:0]cnt ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
cnt<= 'b0 ;
end
else if (cnt == N-1) begin
cnt<= 'b0 ;
end
else begin
cnt<= cnt + 1'b1 ;
end
endregclkp ;
always @(posedge clk_in or negedge rst) begin
if (!rst) begin
clkp <= 1'b0 ;
end
else if (cnt == (N>>1)) begin
clkp <= 1 ;
end
else if (cnt == N-1) begin
clkp <= 0 ;
end
endregclkn ;
always @(negedge clk_in or negedge rst) begin
if (!rst) begin
clkn <= 1'b0 ;
end
else if (cnt == (N>>1) ) begin
clkn <= 1 ;
end
else if (cnt == N-1) begin
clkn <= 0 ;
end
endassign clk_out7 = clkp | clkn ;
endmodule
占空比无要求的奇数分频
实现一个5分频clk,占空比可修改
由于一个cnt其实=2个clk_in ,所以在占空比不要求的情况下,即使是奇数分频也=一个偶数,我们可以把这个偶数分成2个偶数的和,(例如5分频相当于10clk_in,10=4+6,可以4clk_in低电平,6clk_in高电平)(而要求占空比的时候,10=5+5,需要参考上面的做法)
一个完整的clk周期要包含5个clk_in,但是占空比不要求,那么设置一个计数器
cnt
,计数范围0-4,每个clk_in
周期加1。当计数器数值在0~1时,clk_out5==1
;当计数器数值在2~4时,clk_out5==0
。这样就实现了周期为5、占空比为3/5 ?的clk_out5
`timescale 1ns/1nsmodule odd_div (
inputwire rst ,
inputwire clk_in,
outputwire clk_out5
);
reg [2:0] cnt;
reg clk_out5_r;
always@(posedge clk_in or negedge rst) begin
if(~rst)
clk_out5_r <= 0;
else
clk_out5_r <=1;
endalways@(posedge clk_in or negedge rst) begin
if(~rst)
cnt <= 0;
else
cnt <= cnt==4? 0: cnt+1;
endassign clk_out5 = clk_out5_r;
endmodule
任意小数分频
文章图片
文章图片
小数分频器是分频器中最难的一种,而且不能像整数分频那样得到均匀且占空比为50%的分频输出
文章图片
文章图片
文章图片
`timescale 1ns/1nsmodule div_M_N(
inputwire clk_in,
inputwire rst,
output wire clk_out
);
parameter M_N = 8'd87;
parameter c89 = 8'd24;
// 8/9时钟切换点
parameter div_e = 5'd8;
//偶数周期
parameter div_o = 5'd9;
//奇数周期
//*************code***********//
reg [3:0] clk_cnt;
reg [6:0] cyc_cnt;
reg div_flag;
reg clk_out_r;
always@(posedge clk_in or negedge rst) begin
if(~rst)
clk_cnt <= 0;
else if(~div_flag)
clk_cnt <= clk_cnt==(div_e-1)? 0: clk_cnt+1;
else
clk_cnt <= clk_cnt==(div_o-1)? 0: clk_cnt+1;
endalways@(posedge clk_in or negedge rst) begin
if(~rst)
cyc_cnt <= 0;
else
cyc_cnt <= cyc_cnt==(M_N-1)? 0: cyc_cnt+1;
endalways@(posedge clk_in or negedge rst) begin
if(~rst)
div_flag <= 0;
else
div_flag <= cyc_cnt==(M_N-1)||cyc_cnt==(c89-1)? ~div_flag: div_flag;
endalways@(posedge clk_in or negedge rst) begin
if(~rst)
clk_out_r <= 0;
else if(~div_flag)
clk_out_r <= clk_cnt<=((div_e>>2)+1);
else
clk_out_r <= clk_cnt<=((div_o>>2)+1);
endassign clk_out = clk_out_r;
//*************code***********//
endmodule
推荐阅读
- FPGA时序约束
- java|FPGA时序约束分享01_约束四大步骤
- FPGA约束方法与技巧|(05)FPGA时序约束三大步骤
- FPGA20个例程|FPGA 20个例程篇(10.遍历DDR3内存颗粒读写循环校验)
- FPGA20个例程|FPGA 20个例程篇(11.USB2.0接收并回复CRC16位校验)
- fpga开发|博客更新计划的说明
- FPGA20个例程|FPGA 20个例程篇(7.FLASH读写断电存储)
- FPGA20个例程|FPGA 20个例程篇(1.不同按键控制不同LED亮灭)
- FPGA20个例程|FPGA 20个例程篇(3.RS232通信缓存数据)