adxiaowei

奇、偶、半整数 分频(除频器)- verilog

0
阅读(18806)


奇、偶、半整数 分频(除频器)- verilog

 对于时钟比较多的设计,单纯的用PLL分频、倍频,恐怕难以达到设计的要求,比如SPI、I2C的典型时钟分别1MHz、100KHz。在FPGA内部用全局时钟分频则相对比较实用,可移植性好。下面针对奇数分频、偶数分频、半分频分别做介绍。

参考阅读

http://www.cnblogs.com/oomusou/archive/2008/07/31/verilog_clock_divider.html

http://blog.chinaaet.com/detail/37309

http://www.cnblogs.com/crazybingo/archive/2011/07/26/2117162.html

1、偶数分频

     偶数分频相对比较简单--占空比50%,

     verilog代码:

//1 偶分频
//偶分频比较简单,假设为N分频,只需计数到N/2-1,然后时钟翻转、计数清零,如此循环就可以得到N(偶)分频。代码如下。
//可以通过改变参量N的值和计数变量cnt的位宽实现任意偶分频。
module fp_even(clk_out,clk_in,rst);

input clk_in;
input rst;
output clk_out;


reg [1:0] cnt;
reg clk_out;
parameter N=6;

always @ (posedge clk_in or negedge rst)
begin
   if(!rst)
       cnt <= 0;
	else if(cnt==N/2-1)
	    cnt<=0;
	else
	    cnt <= cnt + 1;
	    
end
always @ (posedge clk_in or negedge rst)
begin
   if(!rst)
       clk_out <= 0;

   else if(cnt==N/2-1)
       clk_out <= !clk_out;
	else 
	    clk_out <= clk_out;


end
endmodule
其硬件结构为一个计数器+比较器(清零)、一个比较器+逻辑取反的非门、触发器。

针对代码中的6分频,分析如下:

计数器计数0 1 2 3 4 5   其中0 1 2为低电平,3 4 5为高电平,达到6分频的目的。


testbench


`timescale 1 ns/ 1 ns
module fp_even_vlg_tst();

reg clk_in;
reg rst;
// wires                                               
wire clk_out;

// assign statements (if any)                          
fp_even i1 (
// port map - connection between master ports and signals/registers   
	.clk_in(clk_in),
	.clk_out(clk_out),
	.rst(rst)
);
initial                                                
begin                                                  
  clk_in=0;
  forever #5 clk_in = ~clk_in;  
end

initial
begin
  rst=0;
  #100;
  rst=1;
  #1000;
  $stop;
end                                                    
endmodule

RTL仿真波形图



2、奇数分频

     数分频--占空比50%,

     verilog代码:

//2 奇分频
// 实现奇数(N)分频,分别用上升沿计数到(N-1)/2,再计数到N-1;用下降沿计数到(N-1)/2,再计数到N-1,得到两个波形,然后把它们相或即可得到N分频。代码如下:
module fp_odd(clk_out,clk_p,clk_n,clk_in,rst);

input clk_in,rst;
output clk_out;
output clk_p;
output clk_n;

reg [2:0] cnt_p,cnt_n;
reg clk_p,clk_n;
parameter N=5;

always@(posedge clk_in or negedge rst)
begin
	  if(!rst)     
		   cnt_p <= 0;
	  else if(cnt_p==N-1)   
		   cnt_p <=0;
	  else 
		   cnt_p <= cnt_p + 1;

end
always@(posedge clk_in or negedge rst)
begin
     if(!rst) 
	      clk_p <= 0;
     else if(cnt_p==(N-1)/2)
         //clk_p <= !clk_p;
			clk_p <= 1'b1;
     else if(cnt_p==N-1)
         //clk_p <= !clk_p;
			clk_p <= 1'b0;

end

always@(negedge clk_in or negedge rst)
begin
     if(!rst)     
	       cnt_n <= 0;
     else if(cnt_n==N-1)    
	       cnt_n <=0;
     else 
	       cnt_n <= cnt_n + 1;

end
always@(negedge clk_in or negedge rst)
begin
     if(!rst) 
	       clk_n <= 0;
     else if(cnt_n==(N-1)/2)
          //clk_n <= !clk_n;
			 clk_n <= 1'b1;
     else if(cnt_n==N-1)
          //clk_n <= !clk_n;
			 clk_n <= 1'b0;

end

assign clk_out = clk_p | clk_n;
endmodule


其硬件结构为计数器+比较器+触发器+逻辑门。
针对代码中的5分频,分析如下:

posedge下分频,低电平的数目比高电平多一个时钟周期,比如5分频计数器计数0 1 2 3 4   其中0 1 2为低电平,3 4 为高电平。

同理,negedge下分频,低电平的数目比高电平多一个时钟周期,比如5分频计数器计数0 1 2 3 4   其中0 1 2为低电平,3 4 为高电平

最后将两个时钟相'或'


testbench:


`timescale 1 ns/ 1 ns
module fp_odd_vlg_tst();

reg clk_in;
reg rst;
// wires    
wire clk_out;                                           
wire clk_p;
wire clk_n;

// assign statements (if any)                          
fp_odd i1 (
// port map - connection between master ports and signals/registers   
	.clk_in(clk_in),
	.clk_n(clk_n),
	.clk_out(clk_out),
	.clk_p(clk_p),
	.rst(rst)
);
initial                                                
begin                                                  
  clk_in=0;
  forever #5 clk_in = ~clk_in;  
end                                                    
initial                                                        
begin                                                  
  rst=0;
  #100;
  rst=1;
  #1000;
  $stop;  
end                                                    
endmodule
RTL 仿真波形




3、半整数分频

     半整数分频--占空比50%,

     verilog代码:

//半整数分频器
//
//假设一个10Mhz的时钟信号,想要得到4Mhz的频率,分频系数为2.5。
//
/*该分频器设计方法:设计一个模3计数器,再设计一个脉冲扣除电路,每来3个时钟周期时,扣除半个周期,
  即可实现分频系数为2.5的半整数分频。采用类似方法,可实现任意半整数的分频器。
  如下图所示,采用异或门和2分频模块设计出脉冲扣除电路,脉冲扣除是输入频率和2分频输出相异或的结果。
*/
////http://blog.chinaaet.com/detail/37309
`timescale 1ns/1ns
module FDIV2_5
(
    clk,
	 rst_n,
	 mod_cnt,
	 clk_out
);
input clk;
input rst_n;
output clk_out;
output mod_cnt;

wire clk;
wire rst_n;
wire clk_out;
reg [3:0] mod_cnt;

wire clk_out1;
//xor xor1(OUT,IN1,IN2);
//assign = out = IN1^IN2;
//xor xor1(clk_out1,clk,fb_clk);
reg fb_clk;
assign clk_out1 = clk ^ fb_clk;

localparam N=2;   //2.5   模N计数器
reg clk_out2;

always@(posedge clk_out1 or negedge rst_n)
begin
    if(!rst_n)
		  mod_cnt<=0;
	 else if(mod_cnt==N)
        mod_cnt<=0;
	 else 
        mod_cnt<=mod_cnt+1'b1;

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==N)
        begin
       //     mod_cnt<=0;
            clk_out2<=1'b1;
        end
    else
        begin
         //   mod_cnt<=mod_cnt+1'b1;
            clk_out2<=1'b0;
        end
end
always@(posedge clk_out2 or negedge rst_n)
begin
    if(!rst_n)
        fb_clk<=1'b0;
    else
        fb_clk<=~fb_clk;
end

wire clk_out_r;
assign clk_out_r=(mod_cnt==1) ? 1'b0:1'b1;
//assign clk_out=clk_out2 | clk_out_r;
assign clk_out=clk_out2;

endmodule
其硬件单元为 异或门、计数器、触发器、比较器、非门。

针对代码中的2.5分频,分析如下:

首先利用输入激励clk异或门产生clk_out1,clk_out1作为下一级分频器的激励产生clk_out2,clk_out2作为非门and触发器的激励产生fd_clk,最后输出clk_out2(clk_out)。

testbench:


`timescale 1 ns/ 1 ps
module FDIV2_5_vlg_tst();
// constants
reg clk;
reg rst_n;
// wires
wire clk_out;
wire [3:0]  mod_cnt;

// assign statements (if any)
FDIV2_5 i1 (
// port map - connection between master ports and signals/registers   
	.clk(clk),
	.clk_out(clk_out),
	.mod_cnt(mod_cnt),
	.rst_n(rst_n)
);

initial
begin

      clk=1;
      forever #5 clk = ~clk;
		
end

initial
begin

      rst_n=0;
      #100;
      rst_n=1;
		#1000;
		$stop;

end 
                                                  
endmodule

RTL仿真波形图:



4、最后带你们回味一下大牛的任意分频:

连接http://www.cnblogs.com/crazybingo/archive/2011/07/26/2117162.html

verilog代码:


/***************************************************

* Module Name : clk_generator

* Engineer : Crazy Bingo

* Target Device : EP2C8Q208C8

* Tool versions : Quartus II 9.1SP1

* Create Date : 2011-6-25

* Revision : v1.0

* Description :  

**************************************************/

/*************************************************

fc = 50MHz 50*10^6

fo = fc*K/(2^32)       N=(2^32)  32bit couter

K = fo*(2^32)/fc

= fo*(2^32)/(50*10^6)

**************************************************/

module all_fre_div
(

input clk, //50MHz

input rst_n, //clock reset

output reg clk_out

);

parameter FREQ_WORD = 32'h8000_0000;  //2分频  占空比50%

//--------------------------------------

reg [31:0] max_value;  //N  32Bit

always@(posedge clk or negedge rst_n)

begin

	if(!rst_n)

		max_value <= 1'b0;

	else

		max_value <= max_value + FREQ_WORD;    // K

end

//--------------------------------------

always@(posedge clk or negedge rst_n)

begin

	if(!rst_n)

		clk_out <= 1'b0;

	else

		begin

			if(max_value < 32'h7FFF_FFFF)   //100Hz

				clk_out <= 1'b0;

			else

				clk_out <= 1'b1;    

		end

end




endmodule

详细了解请根据上面对应链接看便知。



永远忠诚于梦想  --  小伟。