一、分频电路
1. 2^m分频
这类分频最基础的就是实现一个二分频电路。使用简单级联2分频电路即可完成2^m分频。
1.1 使用D触发器完成2分频电路
其思路就是在D触发输出在clk上升沿或者下降沿完成一次翻转即可。
电路如下,将Q非连接到D端即可。
时序图如下:
1.2 从Verilog的角度
从Verilog的角度来说,这类分频可以使用计数器来实现。下面考虑占空比为50%的情况。实际上这种方式可以覆盖偶次分频的情况,不仅仅是2的幂次分频。
module div(
input clk_in,
input rst_n,
output reg clk_out
);
parameter N = 12;
reg [4:0] cnt;
always@(posedge clk_in or negedge rst_n)
//初始化
if(rst_n == 0) begin
cnt <= 0;
clk_out <= 0;
end
//计数翻转
else if(cnt == N/2 - 1) begin
cnt <= 0;
clk_out <= ~clk_out;
end
//计数
else cnt <= cnt + 1 ;
endmodule
2. 奇数次分频
2.1 使用JK触发完成3分频
事实上,使用D触发完成3分频也是计数的思路。正常的clk是0101两个状态跳变,3分频之后就应该是3个状态在边沿跳变。如00->01->10->00…
电路表示如下,初始化JK触发为0;
2.2 使用Verilog完成3分频电路
- 思路1:使用双边沿触发
即在每个正/负边沿进行技术,三次之后就进行翻转。和上面偶次分频不同的是双边沿触发。
`timescale 1ns/1ps
//moduel & IO definition
module div_3_f(
input i_clk,
input i_rst_n,
output reg o_clk
);
//wire & reg definition
reg [1:0] cnt;
always@(posedge i_clk or negedge i_clk or negedge i_rst_n)
if(i_rst_n == 0)begin
cnt <= 0;
o_clk <= 0;
end
else if (cnt == 2) begin
cnt <= 0;
o_clk <= ~o_clk;
end
else cnt <= cnt + 1;
endmodule
但是这种使用双边沿触发虽然简单但是不好,因为混合时钟沿电路虽然并不会影响功能仿真结果,但是会影响电路的时序性能。双边沿操作相当于使用了原时钟的2倍频单信号边沿进行驱动电路。
其他类似的思路还有如下,分解成红框信号与绿框信号的和。
module div(
input clk_in,
input rst_n,
output clk_out
);
reg clk_p, clk_n;
reg [9:0] cnt;
parameter N = 5;
assign clk_out = clk_p | clk_n;
always@(posedge clk_in or negedge rst_n)
if(rst_n == 0) begin
cnt <= 0;
clk_p <= 0;
end
else if(cnt == (N-1)/2) begin
cnt <= cnt + 1;
clk_p <= ~clk_p;
end
else if(cnt == N-1) begin
cnt <= 0;
clk_p <= ~clk_p;
end
else cnt <= cnt + 1;
always@(negedge clk_in or negedge rst_n)
if(rst_n == 0) clk_n <= 0;
else clk_n <= clk_p;
endmodule
- 思路2:在FPGA中,由于双边沿触发会导致时钟恶化…这里可以使用将时钟倍频,再对单边沿进行操作。
这里简要说明倍频电路。具体操作为将clk相移45°得到clk_1;再讲两个信号进行异或操作即可。
【参考】
1-分频电路学习记录-https://zhuanlan.zhihu.com/p/100871040
2-FPGA三分频电路实现-https://blog.csdn.net/qq_34975667/article/details/84984482