ZT等占空比任意整数分频器的verilog语言实现

尽管在FPGA设计中,广泛使用芯片厂家集成的锁相环资源如altera的PLL,Xilinx的DLL来进行时钟的分频,倍频以及相移。但在对时钟要求 不高或资源有限的情况下,使用硬件描述语言设计电路来进行时钟的分频相移非常实用。因此分频器的设计仍然是FPGA中比较常用的一个设计,同时又被许多公司拿来作为面试题,称其为经典设计也不为过。本文所要讨论的是使用Verilog语言来设计等占空比任意整数分频器。为方便使用和比较,将不同分频倍数的分频器放在了一个模块中。

以下是设计的Verilog实现:freq_divide.v

`timescale 1ns / 100ps
////////////////////////////////////////////////////////////////////////////////
// Company: hangzhou dianzi university
// Engineer: D.H.j.
//
// Create Date: 2011.10.13
// Design Name: freq_divide
// Module Name: freq_divide
// Target Device: <target device>
// Tool versions: QuartusII9.0
// Description:
//    等占空比任意整数分频的verilog语言实现
////////////////////////////////////////////////////////////////////////////////
            
module freq_divide(
clkin,
rst_n,
clkout1,//2分频
clkout2,//2的n次方分频
clkout3,//偶数倍(2J)分频
clkout4,
clkout5,
clkout6//奇数倍(2K+1)分频
);

input clkin;//50MHz
input rst_n;
output reg clkout1;
output clkout2;
output reg clkout3;
output reg clkout4;
output reg clkout5;
output  clkout6;

//counter
reg[7:0] cnt1;
reg[7:0] cnt2;
reg[7:0] cnt3;
reg[7:0] cnt4;

/*
reg[7:0] cnt;//counter
always@( posedge clkin or negedge rst_n )
begin
    if(!rst_n)
      cnt <= 0;
    else 
      cnt <= cnt + 1'b1;    
end
*/

//*****************任意整数分频*****************//华丽的分割线

//最简单的2分频
always@( posedge clkin or negedge rst_n )
begin
   if(!rst_n) 
      clkout1 <= 0;
   else 
      clkout1 <= ~clkout1;    
end

//2的n次方分频
/*
  2 0010
  4 0100
  8 1000
  ...
*/
parameter I = 2;//实现4分频 4=2^I I=2
always@( posedge clkin or negedge rst_n )
begin
    if(!rst_n) 
      cnt1 <= 0;
    else 
      cnt1 <= cnt1 + 1'b1;
end
assign clkout2 = cnt1[I-1];
 
//偶数倍(2J)分频
//计数器计到一半时,输出时钟翻转,计数器复位
parameter J = 3;//实现6分频 6=2M J=3
always@( posedge clkin or negedge rst_n )
begin
    if(!rst_n) begin
      clkout3 <= 0;
      cnt2 <= 0;
      end
    else begin
        if(cnt2==J-1) begin
        clkout3 <= ~clkout3;    
          cnt2 <= 0;end
        else 
        cnt2 <= cnt2 + 1'b1;
    end
end

//奇数倍(2K+1)分频 经典面试题
/*
分别利用上升沿和下降沿触发产生两个占空比为(K+1)/(2K+1)的时钟,
再将两个时钟进行逻辑与操作,得到奇数倍分频的时钟
*/
parameter K = 5;//实现11分频 11=2K+1 K=5
//上升沿计数器
always@( posedge clkin or negedge rst_n )
begin
    if(!rst_n) begin
      cnt3 <= 0;
      end
    else begin
      if(cnt3==2*K)
        cnt3 <= 0;
      else
        cnt3 <= cnt3 + 1'b1;
    end
end

//一个周期内,正电平占(K+1)/(2K+1)
always@( posedge clkin or negedge rst_n )
begin
    if(!rst_n) begin
      clkout4 <= 0;
      end
    else begin
      if(cnt3==K-1) 
        clkout4 <= 1;    
      else if(cnt3==2*K)
        clkout4 <= 0;
     end
end

//下降沿计数器
always@( negedge clkin or negedge rst_n )
begin
    if(!rst_n) begin
      cnt4 <= 0;
      end
    else begin
      if(cnt4==2*K)
        cnt4 <= 0;
      else
        cnt4 <= cnt4 + 1'b1;
    end
end

always@( negedge clkin or negedge rst_n )
begin
    if(!rst_n) begin
      clkout5 <= 0;
      end
    else begin
      if(cnt4==K-1) 
        clkout5 <= 1;    
      else if(cnt4==2*K)
        clkout5 <= 0;
     end
end

assign clkout6 = clkout4 & clkout5;

endmodule

 

 

 以下是testbench代码:freq_divide_tb.v

////////////////////////////////////////////////////////////////////////////////
// Company: hangzhou dianzi university
// Engineer: D.H.j.
//
// Create Date: 2011.10.13
// Design Name: freq_divide_tb
// Module Name: freq_divide_tb
// Target Device: <target device>
// Tool versions: QuartusII9.0
// Description:
//    等占空比任意整数分频的verilog语言实现testbench
////////////////////////////////////////////////////////////////////////////////
    
module freq_divide_tb;

reg clkin;
reg rst_n;
//counter
reg[7:0] cnt1;
reg[7:0] cnt2;
reg[7:0] cnt3;
reg[7:0] cnt4;

always #10 clkin = ~clkin;//50MHz

initial
begin
clkin = 0;
rst_n = 0;
#10 rst_n = 1;
end

freq_divide u(
.clkin(clkin),
.rst_n(rst_n),
.clkout1(clkout1),
.clkout2(clkout2),
.clkout3(clkout3),
.clkout4(clkout4),
.clkout5(clkout5),
.clkout6(clkout6)
);

endmodule

 

 

仿真图如下

posted @ 2013-10-17 22:48  卧室龙头  阅读(450)  评论(0编辑  收藏  举报