赞
踩
分频器是指使输出信号频率为输入信号频率整数分之一的电子电路。在许多电子设备中如电子钟、频率合成器等,需要各种不同频率的信号协同工作,常用的方法是以稳定度高的晶体振荡器为主振源,通过变换得到所需要的各种频率成分,分频器是一种主要变换手段。
早期的分频器多为正弦分频器,随着数字集成电路的发展,脉冲分频器(又称数字分频器)逐渐取代了正弦分频器。
采用触发器反向输出端连接到输入端的方式,可构成简单的 2 分频电路。
以此为基础进行级联,可构成 4 分频,8 分频电路。
电路实现如下图所示,用 Verilog 描述时只需使用简单的取反逻辑即可。
如果偶数分频系数过大,就需要对分频系数 N 循环计数进行分频。在计数周期达到分频系数中间数值 N/2 时进行时钟翻转,可保证分频后时钟的占空比为 50%。因为是偶数分频,也可以对分频系数中间数值 N/2 进行循环计数。
偶数分频的 Verilog 描述举例如下。
module even_divisor # (parameter DIV_CLK = 10 ) ( input rstn , input clk, output clk_div2, output clk_div4, output clk_div10 ); //2 分频 reg clk_div2_r ; always @(posedge clk or negedge rstn) begin if (!rstn) begin clk_div2_r <= 'b0 ; end else begin clk_div2_r <= ~clk_div2_r ; end end assign clk_div2 = clk_div2_r ; //4 分频 reg clk_div4_r ; always @(posedge clk_div2 or negedge rstn) begin if (!rstn) begin clk_div4_r <= 'b0 ; end else begin clk_div4_r <= ~clk_div4_r ; end end assign clk_div4 = clk_div4_r ; //N/2 计数 reg [3:0] cnt ; always @(posedge clk or negedge rstn) begin if (!rstn) begin cnt <= 'b0 ; end else if (cnt == (DIV_CLK/2)-1) begin cnt <= 'b0 ; end else begin cnt <= cnt + 1'b1 ; end end //输出时钟 reg clk_div10_r ; always @(posedge clk or negedge rstn) begin if (!rstn) begin clk_div10_r <= 1'b0 ; end else if (cnt == (DIV_CLK/2)-1 ) begin clk_div10_r <= ~clk_div10_r ; end end assign clk_div10 = clk_div10_r ; endmodule
仿真结果如下:
奇数分频如果不要求占空比为 50%,可按照下面任意整数分频和任意占空比的方法进行分频。即计数器对分频系数 N 进行循环计算,然后根据计数值选择一定的占空比输出分频时钟。
如果奇数分频输出时钟的高低电平只差一个 cycle ,则可以利用源时钟双边沿特性并采用"与操作"或"或操作"的方式将分频时钟占空比调整到 50%。
或操作调整占空比:采用"或操作"产生占空比为 50% 的 3 分频时序图如下所示。
利用源时钟上升沿分频出高电平为 1 个 cycle、低电平为 2 个 cycle 的 3 分频时钟。
利用源时钟下降沿分频出高电平为 1 个 cycle、低电平为 2 个 cycle 的 3 分拼时钟。
两个 3 分频时钟应该在计数器相同数值、不同边沿下产生,相位差为半个时钟周期。然后将 2 个时钟进行"或操作",便可以得到占空比为 50%的 3 分频时钟。
同理,9 分频时,则需要在上升沿和下降沿分别产生 4 个高电平、5 个低电平的 9 分频时钟,然后再对两个时钟做"或操作"即可。Verilog 描述如下。
module odo_div_or #(parameter DIV_CLK = 9) ( input rstn , input clk, output clk_div9 ); //计数器 reg [3:0] cnt ; always @(posedge clk or negedge rstn) begin if (!rstn) begin cnt <= 'b0 ; end else if (cnt == DIV_CLK-1) begin cnt <= 'b0 ; end else begin cnt <= cnt + 1'b1 ; end end //在上升沿产生9分频 reg clkp_div9_r ; always @(posedge clk or negedge rstn) begin if (!rstn) begin clkp_div9_r <= 1'b0 ; end else if (cnt == (DIV_CLK>>1)-1 ) begin //计数4-8位低电平 clkp_div9_r <= 0 ; end else if (cnt == DIV_CLK-1) begin //计数 0-3 为高电平 clkp_div9_r <= 1 ; end end //在下降沿产生9分频 reg clkn_div9_r ; always @(negedge clk or negedge rstn) begin if (!rstn) begin clkn_div9_r <= 1'b0 ; end else if (cnt == (DIV_CLK>>1)-1 ) begin clkn_div9_r <= 0 ; end else if (cnt == DIV_CLK-1) begin clkn_div9_r <= 1 ; end end //或操作,往往使用基本逻辑单元库 // or (clk_div9, clkp_div9_r, clkn_div9_r) ; assign clk_div9 = clkp_div9_r | clkn_div9_r ; endmodule
仿真结果如下:
与操作调整占空比:采用"与操作"产生占空比为 50% 的 3 分频时序图如下所示。
利用源时钟上升沿分频出高电平为 2 个 cycle、低电平为 1 个 cycle 的 3 分频时钟。
利用源时钟下降沿分频出高电平为 2 个 cycle、低电平为 1 个 cycle 的 3 分拼时钟。
两个 3 分频时钟应该在计数器相同数值、不同边沿下产生,相位差为半个时钟周期。然后将 2 个时钟进行"与操作",便可以得到占空比为 50%的 3 分频时钟。
同理,9 分频时,则需要在上升沿和下降沿分别产生 5 个高电平、4 个低电平的 9 分频时钟,然后再对两个时钟做"与操作"即可。Verilog 描述如下。
module odo_div_and #( parameter DIV_CLK = 9 ) ( input rstn , input clk, output clk_div9 ); //计数器 reg [3:0] cnt ; always @(posedge clk or negedge rstn) begin if (!rstn) begin cnt <= 'b0 ; end else if (cnt == DIV_CLK-1) begin cnt <= 'b0 ; end else begin cnt <= cnt + 1'b1 ; end end //在上升沿产生9分频 reg clkp_div9_r ; always @(posedge clk or negedge rstn) begin if (!rstn) begin clkp_div9_r <= 1'b0 ; end else if (cnt == (DIV_CLK>>1) ) begin //计数5-8位低电平 clkp_div9_r <= 0 ; end else if (cnt == DIV_CLK-1) begin //计数 0-4 为高电平 clkp_div9_r <= 1 ; end end //在下降沿产生9分频 reg clkn_div9_r ; always @(negedge clk or negedge rstn) begin if (!rstn) begin clkn_div9_r <= 1'b0 ; end else if (cnt == (DIV_CLK>>1) ) begin clkn_div9_r <= 0 ; end else if (cnt == DIV_CLK-1) begin clkn_div9_r <= 1 ; end end //与操作,往往使用基本逻辑单元库 //and (clk_div9, clkp_div9_r, clkn_div9_r) ; assign clk_div9 = clkp_div9_r & clkn_div9_r ; endmodule
仿真结果如下:
利用时钟的双边沿逻辑,可以对时钟进行半整数的分频。但是无论怎么调整,半整数分频的占空比不可能是 50%。半整数分频的方法有很多,这里只介绍一种和奇数分频调整占空比类似的方法。
- (1) 例如进行 3.5 倍分频时,计数器循环计数到 7,分别产生由 4 个和 3 个源时钟周期组成的 2 个分频时钟。从 7 个源时钟产生了 2 个分频时钟的角度来看,该过程完成了 3.5 倍的分频,但是每个分频时钟并不是严格的 3.5 倍分频。
- (2) 下面对周期不均匀的分频时钟进行调整。一次循环计数中,在源时钟下降沿分别产生由 4 个和 3 个源时钟周期组成的 2 个分频时钟。相对于第一次产生的 2 个周期不均匀的时钟,本次产生的 2 个时钟相位一个延迟半个源时钟周期,一个提前半个源时钟周期。
- (3) 将两次产生的时钟进行"或操作",便可以得到周期均匀的 3.5 倍分频时钟。分频波形示意图如下所示。
3.5 倍时钟分频的 Verilog 描述如下:
module half_divisor( input rstn , input clk, output clk_div3p5 ); //计数器 parameter MUL2_DIV_CLK = 7 ; reg [3:0] cnt ; always @(posedge clk or negedge rstn) begin if (!rstn) begin cnt <= 'b0 ; end else if (cnt == MUL2_DIV_CLK-1) begin //计数2倍分频比 cnt <= 'b0 ; end else begin cnt <= cnt + 1'b1 ; end end reg clk_ave_r ; always @(posedge clk or negedge rstn) begin if (!rstn) begin clk_ave_r <= 1'b0 ; end //first cycle: 4 source clk cycle else if (cnt == 0) begin clk_ave_r <= 1 ; end //2nd cycle: 3 source clk cycle else if (cnt == (MUL2_DIV_CLK/2)+1) begin clk_ave_r <= 1 ; end else begin clk_ave_r <= 0 ; end end //adjust reg clk_adjust_r ; always @(negedge clk or negedge rstn) begin if (!rstn) begin clk_adjust_r <= 1'b0 ; end //本次时钟只为调整一致的占空比 else if (cnt == 1) begin clk_adjust_r <= 1 ; end //本次时钟只为调整一致的精确分频比 else if (cnt == (MUL2_DIV_CLK/2)+1 ) begin clk_adjust_r <= 1 ; end else begin clk_adjust_r <= 0 ; end end assign clk_div3p5 = clk_adjust_r | clk_ave_r ; endmodule
仿真结果如下:
在verilog程序设计中,我们往往要对一个频率进行任意分频,而且占空比也有一定的要求。这样的话,对于程序有一定的要求。现在在前面两个实验的基础上做一个简单的总结,实现对一个频率的任意占空比的任意分频。
比如: FPGA系统时钟是50MHz,而我们要产生的频率是880Hz,那么,我们需要对系统时钟进行分频。很容易想到用计数的方式来分频:50000000/880 = 56818。显然这个数字不是2的整幂次方,那么我们可以设定一个参数,让它到56818的时候重新计数就可以实现了。程序如下:
//rtl module div( clk, rst_n, clk_div ); input clk,rst_n; output clk_div; reg [15:0] counter; always @(posedge clk or negedge rst_n) if(!rst_n) counter <= 0; else if(counter==56817) counter <= 0; else counter <= counter+1; assign clk_div = counter[15]; endmodule
分频的应用很广泛,一般的做法是先用高频时钟计数,然后使用计数器的某一位输出作为工作时钟进行其他的逻辑设计,上面的程序就是一个体现。
下面我们来算一下上面产生的时钟的占空比:
我们清楚地知道,这个输出波形在counter为0到32767(2的15次方)的时候为低,在32768到56817的时候为高,占空比为40%多一些,如果我们需要占空比为50%,那么我们需要再设定一个参数,使它为56817的一半,使达到它的时候波形翻转,就可以实现结果了。程序如下:
28408=56818/2-1,计数到28408就清零,翻转,其余的计数期间,保持不变。
//rtl module div( clk, rst_n, clk_div ); input clk,rst_n; output clk_div; reg clk_div; reg [14:0] counter; always @(posedge clk or negedge rst_n) if(!rst_n) counter <= 0; else if(counter==28408) counter <= 0; else counter <= counter+1; always @(posedge clk or negedge rst_n) if(!rst_n) clk_div <= 0; else if(counter==28408) clk_div <= ~clk_div; endmodule
继续让我们来看如何实现任意占空比,比如还是由50M分频产生880Hz,而分频得到的信号的占空比为30%。56818×30%=17045:
//rtl module div( clk, rst_n, clk_div, ); input clk,rst_n; output clk_div; reg clk_div; reg [15:0] counter; always @(posedge clk) if(!rst_n) counter <= 0; else if(counter==56817) counter <= 0; else counter <= counter+1; always @(posedge clk) if(!rst_n) clk_div <= 0; else if(counter<17045) clk_div <= 1; else clk_div <= 0; endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。