Verilog学习心得之五-----时钟整数分频

时钟整数分频分为奇数和偶数分频,偶数分频较为简单,假如需要进行偶数为N倍分频,则只需对原输入时钟进行从零开始计数count,当计数值count计数到N/2-1,只需将输出时钟反向即可,RTL代码和测试波形如下:

`timescale  1ns/1ps
module clk_div_even(clk_in,rst_n,clk_out);

input  clk_in;  
input  rst_n;

output clk_out;
reg    clk_out;

parameter   N = 16; //????
parameter   COUNT = N/2 - 1;  //????

reg  [3:0]  count;

always @(posedge clk_in or negedge rst_n)
begin
   if(!rst_n)
     count <= 4'b0;
   else if(count == COUNT)
     count <= 4'b0;
   else
     count <= count + 1'b1;
end 

always @(posedge clk_in or negedge rst_n)
begin
    if(!rst_n)
      clk_out <= 1'b0;
    else if(count == COUNT)
      clk_out <= ~clk_out;
    else
      clk_out <= clk_out;
end

endmodule

`timescale  1ns/1ps
module clk_div_even_tb;

reg       clk_in;
reg       rst_n;
wire      clk_out;
  
clk_div_even  u_clk_div_even(
                             .clk_in(clk_in),                             
                             .rst_n(rst_n),
                             .clk_out(clk_out)
                             );
                             
initial 
begin
  clk_in = 1'b0;
  rst_n = 1'b0;
  #100;
  rst_n = 1'b1;
  #50000;
//  $finish;
end

always #10 clk_in = ~clk_in;

endmodule

对输入时钟进行16分频,仿真波形如下所示:

假如需要对输入时钟进行奇数分频,如果不要求占空比为50%的话,也比较容易实现,如进行5分频,通过对待分频时钟上升沿触发器进行模5计数,当计数器计数到1时,输出时钟进行翻转,计数到4时再次进行翻转,这样实现的5分频占空比为2/5或者3/5,RTL代码如下所示:

`timescale  1ns/1ps
module clk_div_odd(clk_in,rst_n,clk_out);

input  clk_in;  
input  rst_n;

output clk_out;
reg    clk_out;

parameter   N = 5;

parameter   COUNT1 = 1;
parameter   COUNT2 = 4;
//parameter   COUNT = N/2 - 1;

reg  [3:0]  count;

always @(posedge clk_in or negedge rst_n)
begin
   if(!rst_n)
     count <= 4'b0;
   else if(count == COUNT2)
     count <= 4'b0;
   else
     count <= count + 1'b1;
end 

always @(posedge clk_in or negedge rst_n)
begin
    if(!rst_n)
      clk_out <= 1'b0;
   else if(count == COUNT1)
      clk_out <= ~clk_out; 
   else if(count == COUNT2)
      clk_out <= ~clk_out;
   else
      clk_out <= clk_out;
end

endmodule


对输入时钟进行5分频,仿真波形如下所示:

对于实现占空比为50%的N倍奇数分频,我们可以分解为两个通道:

(1)上升沿触发进行模N计数,计数选定到某一个值进行输出时钟翻转,然后经过(N-1)/2再次进行翻转得到一个占空比为非50%奇数N分频时钟;

(2)下降沿触发进行模N计数,到和上升沿触发输出时钟翻转选定值相同值相同时,进行输出时钟翻转,同样经过(N-1)/2时,输出时钟再次翻转生成占空比为非50%的奇数N分频时钟。

将这两个占空比非50%的N分频时钟或运算,得到占空比为50%的奇数n分频时钟,如下代码为将输入clk_in按占空比为50%进行5分频:

`timescale  1ns/1ps
module clk_div_odd(clk_in,rst_n,clk_out);

input  clk_in;  
input  rst_n;

output clk_out;
//reg    clk_out;

parameter   N = 5;

parameter   COUNT1 = 2;
parameter   COUNT2 = 4;
//parameter   COUNT = N/2 - 1;

reg  [3:0]  count1;
reg  [3:0]  count2;

reg         clk_out1_r;
reg         clk_out2_r;

always @(posedge clk_in or negedge rst_n)
begin
   if(!rst_n)
     count1 <= 4'b0;
   else if(count1 == COUNT2)
     count1 <= 4'b0;
   else
     count1 <= count1 + 1'b1;
end 

always @(negedge clk_in or negedge rst_n)
begin
  if(!rst_n)
     count2 <= 4'b0;
  else if(count2 == COUNT2)
     count2 <= 4'b0;
 
 else
 
    count2 <= count2 + 1'b1; 
end

always @(posedge clk_in or negedge rst_n)
begin
    if(!rst_n)
      clk_out1_r <= 1'b0;
   else if(count1 == COUNT1)
      clk_out1_r <= ~clk_out1_r; 
   else if(count1 == COUNT2)
      clk_out1_r <= ~clk_out1_r;
   else
      clk_out1_r <= clk_out1_r;
end

always @(negedge clk_in or negedge rst_n)
begin
  
  if(!rst_n)
  
    
clk_out2_r <= 1'b0;
 
   else if(count2 == COUNT1)
 
     clk_out2_r <= ~clk_out2_r;
 
   else if(count2 == COUNT2)
 
     clk_out2_r <= ~clk_out2_r;
 
   else
 
     clk_out2_r <= clk_out2_r;
end

assign clk_out = clk_out1_r | clk_out2_r;
endmodule

使用modelsim仿真结果如下所示:

如图所示,clk_out1_r和clk_out2_r占空比都为40%,同时clk_out1_r较clk_out2_r相差180°的相位差,所以将clk_out1_r与clk_out2_r进行或操作即可得到占空比为50%的5分频。

阅读更多
换一批

没有更多推荐了,返回首页