时钟分频verilog
1、偶分频
举例:将100MHz时钟信号4分频成25MHz。
创建一个计数值为0-3的循环计数器,时钟上升沿,当计数值小于2的时候置为高电平,大于等于2的时候置为低电平,即可得到一个4分频后、占空比为50%的时钟信号。
示意图
代码段
`timescale 1ns/1ps
//实现一个4分频,也就是将100MHz时钟信号4分频成25MHz
module vlg_design(
input clk, //100MHz
input rst_n,
output reg div_clk //25MHz
);
//计数器,从0计到3
reg [2:0] cnt;
localparam CNT_MAX = 4;
always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 'b0;
else if(cnt < (CNT_MAX - 1'b1))
cnt <= cnt + 1'b1;
else
cnt <= 'b0;
//偶分频
localparam DIV_CNT = 2;
always @(posedge clk or negedge rst_n)
if(!rst_n)
div_clk <= 'b0;
else if(cnt < DIV_CNT)
div_clk <= 1'b1;
else
div_clk <= 'b0;
endmodule
仿真图
2、奇分频
举例:将100MHz时钟信号5分频成20MHz。
创建一个计数值为0-4的循环计数器,时钟上升沿,当计数值小于2的时候置为高电平,大于等于2的时候置为低电平,即可得到clk_1。时钟下降沿,当计数值小于2的时候置为高电平,大于等于2的时候置为低电平,即可得到clk_2。将clk_1和clk_2相或即可得到占空比为50%的奇分频信号。
示意图
代码段
`timescale 1ns/1ps
//实现一个5分频,也就是将100MHz时钟信号5分频成20MHz
module vlg_design(
input clk, //100MHz
input rst_n,
output div_clk //20MHz
);
//计数器,从0计到4
reg [2:0] cnt;
localparam CNT_MAX = 5;
always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 'b0;
else if(cnt < (CNT_MAX - 1'b1))
cnt <= cnt + 1'b1;
else
cnt <= 'b0;
//奇分频,需要用2个寄存器相与得到输出时钟
reg clk_1;
reg clk_2;
localparam DIV_CNT = 2;
always @(posedge clk or negedge rst_n)
if(!rst_n)
clk_1 <= 'b0;
else if(cnt < DIV_CNT)
clk_1 <= 1'b1;
else
clk_1 <= 'b0;
always @(negedge clk or negedge rst_n)
if(!rst_n)
clk_2 <= 'b0;
else if(cnt < DIV_CNT)
clk_2 <= 1'b1;
else
clk_2 <= 'b0;
assign div_clk = clk_1 | clk_2;
endmodule
仿真图
3、小数分频(拼接法)
示意图
代码段
`timescale 1ns/1ps
//实现一个12.5分频,也就是将100MHz时钟信号12.5分频成8MHz
module vlg_design(
input clk, //100MHz
input rst_n,
output div_clk //8MHz
);
/*
12 < 12.5 <13
x + y = 10
12x + 13y = 125
x = y = 5
*/
parameter M_N = 8'd125;
parameter div_point = 8'd60;//时钟切换点
parameter div_e = 5'd12; //偶数周期
parameter div_o = 5'd13; //奇数周期
reg [3:0] clk_cnt; //用于产生分频输出。当div_flag==0时,计数最大值是div_e-1;
//当div_flag==1时,计数最大值是div_o-1。
reg [7:0] cyc_cnt; //对clk_in进行计数,达到M_N后清零
//也就是说cyc_cnt里面包含了x个div_e和y个div_o
reg div_flag; //奇偶标志
reg div_clk_r;
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
clk_cnt <= 0;
else if(~div_flag)
clk_cnt <= clk_cnt==(div_e-1)? 0: clk_cnt+1;
else
clk_cnt <= clk_cnt==(div_o-1)? 0: clk_cnt+1;
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
cyc_cnt <= 0;
else
cyc_cnt <= cyc_cnt==(M_N-1)? 0: cyc_cnt+1;
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
div_flag <= 0;
else
div_flag <= cyc_cnt==(M_N-1)||cyc_cnt==(div_point-1)? ~div_flag: div_flag;
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n)
div_clk_r <= 0;
else if(~div_flag)
div_clk_r <= clk_cnt<=((div_e>>2)+1);
else
div_clk_r <= clk_cnt<=((div_o>>2)+1);
end
assign div_clk = div_clk_r;
endmodule
仿真图
分解成5个12分频、5个13分频