奇偶分频器(简介和Verilog实现)

偶数分频

级联触发器实现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%,要求使用双边沿逻辑

小数分频涉及到奇数和偶数分频

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值