分频或者倍频有两种方式:一种是器件厂商提供的锁相环IP核,另一种是自己动手用Verilog代码描述。
分类:偶数分频和奇数分频
偶数分频以6分频为例,波形图如下所示
频率为原来的六分之一,周期为原来的6倍。计数要计数到0-5吗?不需要,只要0-2即可。
module divider_six
(
input wire sclk ,
input wire rst_n ,
output reg clk_out
);
reg [1:0] cnt;
always@(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
cnt <= 2'd0;
else if(cnt == 2'd2)
cnt <= 2'd0;
else
cnt <= cnt + 1'b1;
always@(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
clk_out <= 1'b0;
else if(cnt == 2'd2)
clk_out <= ~clk_out;
endmodule
仿真文件
`timescale 1ns/1ns
module tb_divider_six();
reg sclk, rst_n;
wire clk_out;
initial begin
sclk = 1'b0;
rst_n <= 1'b0;
#20
rst_n <= 1'b1;
end
always #10 sclk <= ~sclk;
divider_six divider_six_inst
(
.sclk (sclk),
.rst_n (rst_n),
.clk_out (clk_out)
);
endmodule
因为在FPGA中凡是时钟信号都要连接到全局时钟网络上,全局时钟网络也称为全局时钟树,是FPGA厂商专为时钟路径而特殊设计的,它能够使时钟信号到达每个寄存器的时间都尽可能相同,以保证更低的时钟偏斜(Skew)和抖动(Jitter)。而我们用这种分频的方式产生的clk_out信号并没有连接到全局时钟网络上,但sys_clk则是由外部晶振直接通过管脚连接到了FPGA的专用时钟管脚上,自然就会连接到全局时钟网络上,所以在sys_clk时钟工作下的信号要比在clk_out时钟工作下的信号更容易在高速系统中保持稳定。
实用的降频方法
module divider
(
input wire sclk ,
input wire rst_n ,
output reg clk_flag
);
reg [2:0] cnt;
always@(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
cnt <= 3'd0;
else if(cnt == 3'd5)//计数到5
cnt <= 3'd0;
else
cnt <= cnt + 1'b1;
always@(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
clk_flag <= 1'b0;
else if(cnt == 3'd4)//到4
clk_flag <= 1'b1;
else
clk_flag <= 1'b0;
endmodule
仿真文件
`timescale 1ns/1ns
module tb_divider();
reg sclk, rst_n;
wire clk_flag;
initial begin
sclk = 1'b0;
rst_n <= 1'b0;
#20
rst_n <= 1'b1;
end
always #10 sclk <= ~sclk;
divider divider_inst
(
.sclk (sclk),
.rst_n (rst_n),
.clk_flag (clk_flag)
);
endmodule
后续使用这个时钟的时候
always@(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
A <= 4'b0;
else if(clk_flag == 1'b1)
A <= A + 1'b1;