XU.J.P

特殊的分频计数器技巧总结

0
阅读(3812)

软件使用版本:Quartus II 13.0+Modelsim_Altera10.1d

最近一帮朋友忙着找工作,期间面试问了我很多分频计数的题目,当时我傻了。感觉自己学的真是一坨坨。。。反思之后,也查了不少资料。逐渐把这问题解决掉,现简单地总结下。

1、 奇数分频器

如何实现占空比为50%的方波波形的奇数分频?

方法:用两个计数器,分别由时钟的上升沿和下降沿奇数,将其输出结果相或。即可得到占空比为50%的方波波形。

写了个奇数为9,占空比为50%的分频计数器。

`timescale 1ns/1ns module Odd_count(rst_n,clk,odd_cout,pos_cnt,neg_cnt,pos_out,neg_out); input clk; input rst_n; output odd_cout; output [3:0] pos_cnt; output [3:0] neg_cnt; output pos_out; output neg_out; reg [3:0] pos_cnt; reg [3:0] neg_cnt; reg pos_out; reg neg_out; always@(posedge clk) begin if(!rst_n) pos_cnt<=4'd0; else if(pos_cnt==4'd8) pos_cnt<=4'd0; else pos_cnt<=pos_cnt+1'b1; end always@(posedge clk) begin if(!rst_n) pos_out<=1'b0; else if(pos_cnt<4'd4) pos_out<=1'b1; else pos_out<=1'b0; end always@(negedge clk) if(!rst_n) neg_cnt<=4'd0; else if(neg_cnt==4'd8) neg_cnt<=4'd0; else neg_cnt<=neg_cnt+1'b1; always@(negedge clk) if(!rst_n) neg_out<=1'b0; else if(neg_cnt<4'd4) neg_out<=1'b1; else neg_out<=1'b0; assign odd_cout=pos_out|neg_out; endmodule
仿真图如下所示:

2、半整数分频器

假设一个10Mhz的时钟信号,想要得到4Mhz的频率,分频系数为2.5

该分频器设计方法:设计一个模3计数器,再设计一个脉冲扣除电路,每来3个时钟周期时,扣除半个周期,即可实现分频系数为2.5的半整数分频。采用类似方法,可实现任意半整数的分频器。如下图所示,采用异或门和2分频模块设计出脉冲扣除电路,脉冲扣除是输入频率和2分频输出相异或的结果。

当然,改方法得到的脉冲信号并非占空比为50%的,但可以增加两行代码来近似做占空比为50%的周期信号。如下代码中,2.5倍分频结果,输出CLK_OUT2。再通过或逻辑得到近似占空比为50%CLK_OUT

`timescale 1ns/1ns module FDIV2_5(CLK,RST_N,MOD_CNT,CLK_OUT); input CLK; input RST_N; output CLK_OUT; output MOD_CNT; reg FB_CLK; wire CLK_OUT1; reg [3:0] MOD_CNT; wire odd_out; reg CLK_OUT2; always@(posedge CLK_OUT2 or negedge RST_N) begin if(!RST_N) FB_CLK<=1'b0; else FB_CLK<=~FB_CLK; end always@(posedge CLK_OUT1 or negedge RST_N) begin if(!RST_N) begin MOD_CNT<=0; CLK_OUT2<=1'b0; end else if(MOD_CNT==2) begin MOD_CNT<=0; CLK_OUT2<=1'b1; end else begin MOD_CNT<=MOD_CNT+1'b1; CLK_OUT2<=1'b0; end end xor xor1(CLK_OUT1,CLK,FB_CLK); wire CLK_OUT_R; assign CLK_OUT_R=(MOD_CNT==1) ? 1'b0:1'b1; assign CLK_OUT=CLK_OUT2 | CLK_OUT_R; endmodule

仿真图如下所示:

3、DDS思想的任意分频

曾经在CB的《从零开始走进FPGA的世界》当中看到的一种分频思想,当时不以为然。不过现在想想,这种思想还真不错。

根据相位累加的原理,流程如下所示:

下面写了个输入频率50Mhz,输出10Mhz的例程。

`timescale 1ns/1ns module DDS_DIV #( parameter FREQ_WORD=32'd859000000 //1Khz ) ( clk,rst_n,clk_out ); input clk; input rst_n; output reg clk_out; reg [31:0] max_value; always@(posedge clk or negedge rst_n) begin if(!rst_n) max_value<=32'd0; else max_value<=max_value+FREQ_WORD; end always@(posedge clk or negedge rst_n) begin if(!rst_n) clk_out<=1'b0; else begin if(max_value<=32'h7FFF_FFFF) clk_out<=1'b0; else clk_out<=1'b1; end end endmodule

仿真结果如下:

当然,网上还有许多分频思路。其中一种就是利用脉冲删减电路,进行小数分频,但该方法得到的时钟不符合自己的习惯,也就不深入研究了。


Baidu
map