赞
踩
级联触发器实现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%又是最长考的知识点,有相与,相或,相异或三种
奇数分频还涉及到双边计数器
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代码。
- 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%,要求使用双边沿逻辑
小数分频涉及到奇数和偶数分频
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。