偶数分频
级联触发器实现2^n偶数分频
采用触发器加反相器,可以构成简单的2分频电路,以这个基本单元进行级联就可以实现4 ,8 ,16 ,2^n 分频
Verilog实现
module even_fre_div1( //偶数分频级联
input clk ,
input rst_n ,
output wire clk_div2 ,
output wire clk_div4 ,
output wire clk_div8 ,
);
reg clk_div2_t ;
reg clk_div4_t ;
reg clk_div8_t ;
//div2
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
clk_div2_t <= 1'b0;
else
clk_div2_t <= ~clk_div2_t ;
end
//
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
clk_div4_t <= 1'b0;
else
clk_div4_t <= ~clk_div4_t;
end
//
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
clk_div8_t <= 1'b0;
else
clk_div8_t <= ~clk_div8_t ;
end
//
assign clk_div2 = clk_div2_t ;
assign clk_div4 = clk_div4_t ;
assign clk_div8 = clk_div8_t ;
endmodule
计数器实现2n偶数分频
module even_fre_div2 #(
parameter div_2n = 12
)(
input clk ,
input rst_n ,
output clk_div2n
);
reg [3:0] cnt ;
reg clk_div2n_t ;
//cnt
always @(posedge clk ,negedge rst_n) begin
if(!rst_n)
cnt<= 1'b0;
else if(cnt==div_2n/2 - 1)begin
cnt <= 1'b0;
end
else
cnt <= cnt+1'b1 ;
end
//out_clk
always @(posedge clk ,negedge rst_n) begin
if(!rst_n)
clk_div2n_t <= 1'b0;
else if(cnt==div_2n/2 - 1)
clk_div2n_t <= ~clk_div2n_t;
else
clk_div2n_t <= clk_div2n_t ;
end
assign clk_div2n = clk_div2n_t ;
endmodule
奇数分频
相较于偶数分频,奇数分频知识点稍微多一些,有占空比50%和非50% ,占空比50%又是最长考的知识点,有相与,相或,相异或三种
奇数分频还涉及到双边计数器
奇数分频,占空比50%
OR操作,2N+1奇数分频
单计数器实现,只在上升沿计数,在上升沿和下降沿采用输出高低电平
module odd_fre_or_div1 #(
parameter DIV_CLK = 9
)(
input clk ,
input rst_n ,
output wire clk_div_odd
);
reg [3:0] cnt ;
reg clkp_odd_r ;
reg clkn_odd_r ;
//cnt
always @(posedge clk ,negedge rst_n) begin
if(!rst_n)
cnt <= 1'b0;
else if(cnt==DIV_CLK - 1)
begin
cnt <= 1'b0 ;
end
else
cnt <= cnt +1'b1 ;
end
//posedge clk_div
always @( posedge clk ,negedge rst_n) begin
if(!rst_n)
clkp_odd_r <= 1'b0;
else if(cnt== (DIV_CLK>>1) - 1)
clkp_odd_r <= 1'b0;
else if(cnt==DIV_CLK -1)
clkp_odd_r <= 1'b1;
else
clkp_odd_r <= clkp_odd_r ;
end
//negedge clk_div
always @( posedge clk ,negedge rst_n) begin
if(!rst_n)
clkn_odd_r <= 1'b0;
else if(cnt== (DIV_CLK>>1) - 1)
clkn_odd_r <= 1'b0;
else if(cnt==DIV_CLK -1)
clkn_odd_r <= 1'b1;
else
clkn_odd_r <= clkn_odd_r ;
end
//or
assign clk_div_odd = clkp_odd_r | clkn_odd_r ;
endmodule
双计数器实现
在上升沿和下降沿计数,在上升沿和下降沿采用输出高低电平
module odd_fre_or_div2 #(
parameter DIV_CLK = 9
)(
input clk ,
input rst_n ,
output wire clk_div_odd
);
reg [3:0] cnt_n ;
reg [3:0] cnt_p ;
reg clkp_odd_r ;
reg clkn_odd_r ;
//pos cnt
always @(posedge clk ,negedge rst_n) begin
if(!rst_n)
cnt_p <= 1'b0;
else if(cnt_p==DIV_CLK - 1)
begin
cnt_p <= 1'b0 ;
end
else
cnt_p <= cnt_p +1'b1 ;
end
//neg cnt
always @(posedge clk ,negedge rst_n) begin
if(!rst_n)
cnt_n <= 1'b0;
else if(cnt_n == DIV_CLK - 1)
begin
cnt_n <= 1'b0 ;
end
else
cnt_n <= cnt_n +1'b1 ;
end
//posedge clk_div
always @( posedge clk ,negedge rst_n) begin
if(!rst_n)
clkp_odd_r <= 1'b0;
else if(cnt_p == (DIV_CLK>>1) - 1)
clkp_odd_r <= 1'b0;
else if(cnt_p == DIV_CLK -1)
clkp_odd_r <= 1'b1;
else
clkp_odd_r <= clkp_odd_r ;
end
//negedge clk_div
always @( posedge clk ,negedge rst_n) begin
if(!rst_n)
clkn_odd_r <= 1'b0;
else if(cnt_n == (DIV_CLK>>1) - 1)
clkn_odd_r <= 1'b0;
else if(cnt_n == DIV_CLK -1)
clkn_odd_r <= 1'b1;
else
clkn_odd_r <= clkn_odd_r ;
end
//or
assign clk_div_odd = clkp_odd_r | clkn_odd_r ;
endmodule
AND操作 2N+1计数分频
单计数器实现
只在上升沿计数,在上升沿和下降沿采用输出高低电平
module odd_fre_or_div3 #(
parameter DIV_CLK = 9
)(
input clk ,
input rst_n ,
output wire clk_div_odd
);
reg [3:0] cnt_p ;
reg clkp_odd_r ;
reg clkn_odd_r ;
//pos cnt
always @(posedge clk ,negedge rst_n) begin
if(!rst_n)
cnt_p <= 1'b0;
else if(cnt_p==DIV_CLK - 1)
begin
cnt_p <= 1'b0 ;
end
else
cnt_p <= cnt_p +1'b1 ;
end
//posedge clk_div
always @( posedge clk ,negedge rst_n) begin
if(!rst_n)
clkp_odd_r <= 1'b0;
else if(cnt_p == (DIV_CLK>>1) )
clkp_odd_r <= 1'b0;
else if(cnt_p == DIV_CLK -1)
clkp_odd_r <= 1'b1;
else
clkp_odd_r <= clkp_odd_r ;
end
//negedge clk_div
always @( posedge clk ,negedge rst_n) begin
if(!rst_n)
clkn_odd_r <= 1'b0;
else if(cnt_p == (DIV_CLK>>1) )
clkn_odd_r <= 1'b0;
else if(cnt_p == DIV_CLK -1)
clkn_odd_r <= 1'b1;
else
clkn_odd_r <= clkn_odd_r ;
end
//and
assign clk_div_odd = clkp_odd_r && clkn_odd_r ;
endmodule
双计数器实现
module odd_fre_or_div4 #(
parameter DIV_CLK = 9
)(
input clk ,
input rst_n ,
output wire clk_div_odd
);
reg [3:0] cnt_n ;
reg [3:0] cnt_p ;
reg clkp_odd_r ;
reg clkn_odd_r ;
//pos cnt
always @(posedge clk ,negedge rst_n) begin
if(!rst_n)
cnt_p <= 1'b0;
else if(cnt_p==DIV_CLK - 1)
begin
cnt_p <= 1'b0 ;
end
else
cnt_p <= cnt_p +1'b1 ;
end
//neg cnt
always @(posedge clk ,negedge rst_n) begin
if(!rst_n)
cnt_n <= 1'b0;
else if(cnt_n == DIV_CLK - 1)
begin
cnt_n <= 1'b0 ;
end
else
cnt_n <= cnt_n +1'b1 ;
end
//posedge clk_div
always @( posedge clk ,negedge rst_n) begin
if(!rst_n)
clkp_odd_r <= 1'b0;
else if(cnt_p == (DIV_CLK>>1) )
clkp_odd_r <= 1'b0;
else if(cnt_p == DIV_CLK -1)
clkp_odd_r <= 1'b1;
else
clkp_odd_r <= clkp_odd_r ;
end
//negedge clk_div
always @( posedge clk ,negedge rst_n) begin
if(!rst_n)
clkn_odd_r <= 1'b0;
else if(cnt_n == (DIV_CLK>>1) )
clkn_odd_r <= 1'b0;
else if(cnt_n == DIV_CLK -1)
clkn_odd_r <= 1'b1;
else
clkn_odd_r <= clkn_odd_r ;
end
//and
assign clk_div_odd = clkp_odd_r && clkn_odd_r ;
endmodule
XOP操作,2N+1奇数分频
module odd_fre_xor_div #(
parameter DIV_CLK = 9
)(
input clk ,
input rst_n ,
output wire clk_div_odd
);
reg [3:0] cnt ;
reg clkp_odd_r ;
reg clkn_odd_r ;
//cnt
always @(posedge clk ,negedge rst_n) begin
if(!rst_n)
cnt <= 1'b0;
else if(cnt==DIV_CLK - 1)
begin
cnt <= 1'b0 ;
end
else
cnt <= cnt +1'b1 ;
end
//posedge clk_div
always @( posedge clk ,negedge rst_n) begin
if(!rst_n)
clkp_odd_r <= 1'b0;
else if(cnt== (DIV_CLK-1)
clkp_odd_r <= ~clkp_odd_r;
else
clkp_odd_r <= clkp_odd_r ;
end
//negedge clk_div
always @( posedge clk ,negedge rst_n) begin
if(!rst_n)
clkn_odd_r <= 1'b0;
else if(cnt== (DIV_CLK >>1)
clkn_odd_r <= ~clkn_odd_r;
else
clkn_odd_r <= clkn_odd_r ;
end
//xor
assign clk_div_odd = clkp_odd_r ^ clkn_odd_r ;
endmodule
奇数分频,占空比非50%
画出本题目的时序图,如图,可以发现,假如Clock是输入的时钟信号,Clock2是输出的50%占空比的三分频信号,那么对于计数器,Clock2实现的操作是:当采样边沿每次遇到count=0的时候进行翻转,每次遇到1的时候再次完成翻转,根据此,加上复位信号,我们即可完成RTL代码。
非50%占空比的三分频电路
module f3(clk, rst_n,clk2);
input clk;
input rst_n;
output clk2;
reg clk2_r;
assign clk2 = clk2_r;
reg [2:0] count;
parameter N = 3;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n || count == N-1)
count <= 3'd0;
else
count <= count +1'd1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
clk2_r <= 3'd0;
else if (count == 3'd0 || count == 3'd1)
clk2_r <= !clk2_r;
else
clk2_r <= clk2_r;
end
endmodule
这里只需要修改N的值,即可改变分频,如N=5,同时改变count的位宽,即可实现五分频,以此类推,即可实现不要求占空比的任意分频电路
小数分频
小数分频不能精确到控制占空比,也没办法控制到精确的小数分频,而是平均频率的小数倍,小数分频涉及到奇数分频,偶数分频以及平均分布的方法
关键点:
完成奇偶分频,确定好分频的次数
确定分频次数后,要合理安排分频的顺序,确保平均
Verilog实现
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2022 All rights reserved
// -----------------------------------------------------------------------------
// Author : HFUT904 1320343336@qq.com
// File : fre_fractional-n.v
// Create : 2022-11-08 14:45:45
// Revise : 2022-11-08 14:45:45
// Editor : HFUT Integrated Circuit Design & Research Center
// Verdion: v1.0
// Description: 小数分频 8.4倍小数
// -----------------------------------------------------------------------------
module fre_fractional-n (
#(
parameter SOURCE_NUM = 84 , //Sorce clocks
parameter DEST_NUM = 10 //div nums 8.4
)
(
input rstn , //Asynchronous reset active low
input clk , //Source Clock
output clk_frac //fractional frequency division
);
parameter SOURCE_DIV = SOURCE_NUM/DEST_NUM ; //8-divisor
parameter DEST_DIV = SOURCE_DIV + 1; //9-divisor
parameter DIFF_ACC = SOURCE_NUM - SOURCE_DIV*DEST_NUM ;
//reg
reg [3:0] cnt_end_r ;
reg [3:0] main_cnt ;
reg clk_frac_r ;
wire diff_cnt_en ;
//difference counter
reg [4:0] diff_cnt_r ;
wire [4:0] diff_cnt ;
//main_cnt
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
main_cnt <= 'b0 ;
clk_frac_r <= 1'b0 ;
end
else if (main_cnt == cnt_end_r) begin
main_cnt <= 'b0 ;
clk_frac_r <= 1'b1 ;
end
else begin
main_cnt <= main_cnt + 1'b1 ;
clk_frac_r <= 1'b0 ;
end
end
//diff_cnt
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
diff_cnt_r <= 0 ;
end
else if (diff_cnt_en) begin
diff_cnt_r <= diff_cnt ;
end
end
// cnt_end
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
cnt_end_r <= SOURCE_DIV-1 ;
end
else if (diff_cnt >= 10) begin
cnt_end_r <= DEST_DIV-1 ;
end
else begin
cnt_end_r <= SOURCE_DIV-1 ;
end
end
//assign
assign clk_frac = clk_frac_r ;
assign diff_cnt_en = (main_cnt == cnt_end_r)?1'b1:1'b0 ;
assign diff_cnt = diff_cnt_r >= DEST_NUM ?
(diff_cnt_r -10 + DIFF_ACC)
: (diff_cnt_r + DIFF_ACC) ;
endmodule
总结:
偶数分频不考虑占空比,是理想的50%
奇数分频需要考虑占空比是否50%,要求使用双边沿逻辑
小数分频涉及到奇数和偶数分频