一,分频器
- 定义
分频器(Divider)是一种电子电路或设备,用于将输入信号的频率降低到较低的频率。它常用于数字系统、通信系统和计时应用中。 - 原理
整数分频器使用计数器来实现频率的降低。计数器根据输入信号的边沿触发进行计数,当计数值达到预设的分频比时,输出一个脉冲,并将计数器清零重新开始计数。例如,一个2分频器会在每两个输入信号边沿之间输出一个脉冲,将输入信号的频率降低为一半。 - verilog代码实现
在这里所了解的分频器主要是整数分频器,其主要的实现分为奇数分频和偶数分频:
1.偶数分频:即在每个时钟上升沿使计数器+1,当计数器小于N/2-1时使得输出时钟为低,当大于等于N/2-1小于N-1时使输出时钟为高
2.奇数分频:奇数分频的方法有许多种这种展示一下我所理解的跟同学所理解的方法
(1)如果想要计数分频但是寄存器不可以计数分数所以我们可以使用两个中间输出时钟
一个对上升沿敏感。一个对下降沿敏感,分别计数,当分得的时钟高电平比低电平多一个周期时将两个中间时钟相与(即低电平向高电平借用0.5周期),当分得的时钟低电平比高电平多一个周期时将两个中间时钟相或(即高电平向低电平借用0.5周期)
//第一种方法
module pre_N #(parameter N = 8) (
input wire clk, //系统时钟
input wire rst_n, //系统复位
output wire clk_out //调频后信号
);
reg clk_out_r;//调频后的时钟
wire add_cnt;//计数开始使能
wire end_cnt;//计数结束使能
wire add_cnt1;//判断奇偶
reg [5:0] cnt;//计数寄存器
reg clk_out_a;
reg clk_out_b;
reg [5:0] cnt_a;
reg [5:0] cnt_b;
wire clk_out_ab;
assign add_cnt1 = (N%2==0)?1:0;
//计数模块
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 6'b0;
end
else if (add_cnt) begin
if (end_cnt) begin
cnt <= 6'b0;
end
else begin
cnt <= cnt + 1'b1;
end
end
else begin
cnt <= cnt;
end
end
assign add_cnt = 1;
assign end_cnt = add_cnt&&(cnt == N/2-1);
//时钟分频模块
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clk_out_r <= 1'b0;
end
else if (end_cnt) begin
clk_out_r <= ~clk_out_r;
end
else begin
clk_out_r <= clk_out_r;
end
end
//上升沿分频模块
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clk_out_a <= 1'b0;
cnt_a <= 1'b0;
end
else begin
if (cnt_a <N-1) begin
if (cnt_a < (N-1)/2) begin
clk_out_a <= 1'b0;
end
else if (cnt_a >=(N-1)/2) begin
clk_out_a <= 1'b1;
end
else begin
clk_out_a <= clk_out_a;
end
cnt_a <= cnt_a + 1;
end
else begin
clk_out_a <= 1'b0;
cnt_a <= 1'b0;
end
end
end
always @(negedge clk or negedge rst_n) begin
if (!rst_n) begin
clk_out_b <= 1'b0;
cnt_b <= 1'b0;
end
else begin
if (cnt_b <N-1) begin
if (cnt_b < (N-1)/2) begin
clk_out_b <= 1'b0;
end
else if (cnt_b >=(N-1)/2) begin
clk_out_b <= 1'b1;
end
else begin
clk_out_b <= clk_out_b;
end
cnt_b <= cnt_b + 1;
end
else begin
clk_out_b <= 1'b0;
cnt_b <= 1'b0;
end
end
end
assign clk_out_ab = clk_out_a|clk_out_b;
assign clk_out = (N%2==0)?clk_out_r:clk_out_ab;
endmodule
(2)使用组合逻辑对电频敏感,每次电频转换都使计数器+1,当计数器加到N-1时使输出电频翻转
module pre_N_2 #(parameter N = 7)(
input wire clk ,
input wire rst_n ,
output wire clk_out
);
reg [5:0] cnt ;
wire add_cnt ;
wire end_cnt ;
reg clk_out_r;
always @(clk)begin //对于上升沿下降沿都进行计数
if(!rst_n)begin
cnt <= 'd0;
end
else if(add_cnt)begin
if(end_cnt)begin
cnt <= 'd0;
end
else begin
cnt <= cnt + 1'b1;
end
end
end
assign add_cnt = 1;
assign end_cnt = add_cnt && cnt == N-1;
always @(clk)begin
if(!rst_n)begin
clk_out_r <= 'd0;
end
else if(end_cnt)begin
clk_out_r <= ~clk_out_r;//计满翻转
end
else begin
clk_out_r <= clk_out_r;//未计满保持
end
end
assign clk_out = clk_out_r;
endmodule
- tb文件
`timescale 1ns/1ns
module pre_N_tb ();
reg clk;
reg rst_n;
wire clk_out;
parameter CYCLE = 20;
parameter N = 5;
always #(CYCLE/2) clk = ~clk;
initial begin
clk = 1'b0;
rst_n = 1'b0;
#(20)
rst_n = 1'b1;
#(1000)
$stop;
end
pre_N #(.N(N)) pre_N_inst(
.clk (clk),
.rst_n (rst_n),
.clk_out (clk_out)
);
endmodule
`timescale 1ns/1ns
module pre_N_2_tb ();
reg clk;
reg rst_n;
wire clk_out;
parameter CYCLE = 20;
parameter N = 5;
always #(CYCLE/2) clk = ~clk;
initial begin
clk = 1'b0;
rst_n = 1'b0;
#(20)
rst_n = 1'b1;
#(1000)
$stop;
end
pre_N_2 #(.N(N)) pre_N_2_inst(
.clk (clk),
.rst_n (rst_n),
.clk_out (clk_out)
);
endmodule
- 仿真波形
在此只展示一个
二.总结
对于分频器主要需要注意的是整数分频有奇数分频跟偶数分频,分频器主要是对时序逻辑电路中时钟理解的考察,其中的难点主要是奇数分频,只要掌握其中的方法还是比较好做,只要掌握时序逻辑电路的时钟信号的理解分频器还是很简单得。