引言
分频器在实际数字电路设计中是最基础的,也是最重要的。常见的分频器主要有偶数倍分频器,奇数倍分频器,半整数倍分频器,任意小数倍分频器等。本文主要对最常用的偶数倍分频器和奇数倍分频器展开介绍。
1、偶数倍分频器
偶数倍分频器通过计数器可以很简单的实现。基本原理就是如果要进行N倍偶数分频,那么就可以利用待分频的时钟触发计数器,当计数器从0计数到N/2-1的时候,输出时钟翻转一次,并复位计数器,这样循环往复,就可以得到N倍偶数分频,如下图所示就是一个标准的4分频时序图。
2、奇数倍分频器
奇数倍分频器通过计数器也很容易实现。 对于占空比为非50%的奇数倍分频而言,如果要实现N倍奇数分频,那么就可以利用待分频时钟上升沿触发计数器进行模N计数,计数到到某个值进行时钟翻转,然后再经过(N-1)/2个计数值再进行翻转,如下图所示为一个标准的5倍占空比非50%分频器时序图。
如果要实现占空比为50%的奇数倍分频,就需要用待分频时钟的下降沿去触发计数器,其他原理一样,然后将两个时钟相或即可,如下图所示为一个标准的5倍占空比50%分频器的时序图。
3、Verilog代码分享
顶层文件:
module fre_div (
//system signals
input clk ,
input rst_n ,
//
output reg fre_div_4 ,
output reg fre_div_5_1 ,
output reg fre_div_5_2 ,
output fre_div_5_3
);
reg [0:0] count_4 ;
reg [2:0] count_5_1 ;
reg [2:0] count_5_2 ;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// reset
count_4 <= 1'd0;
end
else begin
if (count_4 == 1'd1)
count_4 <= 1'd0;
else
count_4 <= count_4 + 1'b1;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// reset
fre_div_4 <= 1'b0;
end
else if(count_4 == 1'd1)
fre_div_4 <= ~fre_div_4;
else
fre_div_4 <= fre_div_4;
end
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
count_5_1 <= 3'd0;
else begin
if (count_5_1 == 3'd4)
count_5_1 <= 3'd0;
else
count_5_1 <= count_5_1 + 1'b1;
end
end
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
fre_div_5_1 <= 1'b0;
else begin
if (count_5_1 == 3'd1)
fre_div_5_1 <= ~fre_div_5_1;
else if (count_5_1 == 3'd3)
fre_div_5_1 <= ~fre_div_5_1;
else
fre_div_5_1 <= fre_div_5_1;
end
end
always @ (negedge clk or negedge rst_n) begin
if(!rst_n)
count_5_2 <= 3'd0;
else begin
if (count_5_2 == 3'd4)
count_5_2 <= 3'd0;
else
count_5_2 <= count_5_2 + 1'b1;
end
end
always @ (negedge clk or negedge rst_n) begin
if(!rst_n)
fre_div_5_2 <= 1'b0;
else begin
if (count_5_2 == 3'd1)
fre_div_5_2 <= ~fre_div_5_2;
else if (count_5_2 == 3'd3)
fre_div_5_2 <= ~fre_div_5_2;
else
fre_div_5_2 <= fre_div_5_2;
end
end
assign fre_div_5_3 = fre_div_5_1|fre_div_5_2;
endmodule
测试文件:
`timescale 1ns/1ps
module tb ();
reg clk;
reg rst_n;
wire fre_div_4;
wire fre_div_5_1;
wire fre_div_5_2;
wire fre_div_5_3;
initial
begin
clk = 1'b1;
rst_n = 1'b1;
#5 rst_n = 1'b0;
#5 rst_n = 1'b1;
end
always #5 clk = ~clk;
fre_div demo(
//system signals
.clk(clk),
.rst_n(rst_n),
.fre_div_4(fre_div_4),
.fre_div_5_1(fre_div_5_1),
.fre_div_5_2(fre_div_5_2),
.fre_div_5_3(fre_div_5_3)
);
endmodule
完整仿真结果: