前言
时钟对于任何芯片都起着总要作用,但板载晶振提供的时钟信号频率是固定的,不一定满足工程需求,所以使用分频或倍频产生需要的时钟是很有必要的。例如:stm32F103外部采用8MHz无源晶振,通过内部的PLL倍频使系统时钟达到最大72MHz,而自身携带的ADC时钟最大为十几MHz,这时就需要使用时钟分频。FPGA带有IP核,通过设置能实现分频与倍频的功能。但是IP核数量有限,当需要使用多个不同时钟时,就可以采用以下分频方法。
一、偶数分频
module divider
#(parameter divider_time=16'd65_535)//参数化分频系数,程序例化时可以调节分频倍数
(
input wire sys_clk,//系统时钟输入
input wire sys_rst_n,//系统复位
output reg clk_out, //直接分频,分频时钟输出
output reg clk_out2, //采用降频,分频时钟输出
output reg clk_flag
);
reg[7:0] count;//计数器
/*方法一、直接进行计数分频,输出时钟为clk_out*/
//计数器从0记到n,代表着2*n分频,从0到n循环计数
always @(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
count<=8'b0;
else if(count==((divider_time-1)/2))
count<=8'b0;
else
count<=count+1'b1;
always @(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
clk_out<=1'b1;
else if(count==((divider_time-1)/2))
clk_out<=~clk_out;
else
clk_out<=clk_out;
/*方法二、使用标志位来进行时钟分频,推荐使用这种*/
always @(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
clk_flag<=1'b0;
//count的计数值要减去1,这是使用非阻塞赋值的原因
else if(count==(((divider_time-1)/2)-1))
clk_flag<=1'b1;
else
clk_flag<=1'b0;
always @(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
clk_out2<=1'b1;
else if( clk_flag)
clk_out2<=~clk_out2;
else
clk_out2<=clk_out2;
endmodule
Testbench仿真文件 10分频,可以通过变化divider_time中的值得到想要的分频数
`timescale 1ns/1ns
module tb_divider();
reg sys_clk ;
reg sys_rst_n ;
wire clk_out; //直接分频,分频时钟输出
wire clk_out2; //采用降频,分频时钟输出
wire clk_flag;
//初始化系统时钟、全局复位
initial begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#20
sys_rst_n <= 1'b1;
end
//sys_clk:模拟系统时钟,每10ns电平翻转一次,周期为20ns,频率为50Mhz
always #10 sys_clk = ~sys_clk;
//------------- counter_inst --------------
divider
#(.divider_time(9))//参数化分频系数,输入值为分频数减1,程序例化时可调
divider_inst(
.sys_clk(sys_clk),//系统时钟输入
.sys_rst_n(sys_rst_n),//系统复位
.clk_out(clk_out), //直接分频,分频时钟输出
.clk_out2(clk_out2), //采用降频,分频时钟输出
.clk_flag(clk_flag)
);
endmodule