Verilog-实现时钟分频(1KHZ、奇、偶分频,占空比为50%)

一、将系统时钟50MHZ分为占空比为50%的1khz时钟

本篇文章使用Xilinx公司的ISE软件
1.  频率:1HZ    周期为1/1HZ=1s。按照这个计算公式计算出频率为1khz的周期为1ms
2. 因为占空比为50%,在写代码时需要一个0.5ms的计数器
  PS: 占空比:占空比是指在一个脉冲循环内,通电时间相对于总时间所占的比例。(在FPGA中我的理解为高电平在一个时钟周期所占的时间)

<代码如下>

1khz分频代码
module clk_1KHZ(clk,rst_n,clk_1khz );
 input  clk           ;  //50MHZ 
 input  rst_n         ;
 output reg clk_1khz  ;  //T=1ms 占空比为50%
 
 reg[17:0] cnt;
 
 always @(posedge clk or negedge rst_n)
  begin
   if(!rst_n)
	 cnt <= 1'b0;
	else if (cnt == 18'd25_000 - 1)//
	 cnt <= 18'd0;
	else
	 cnt <= cnt + 1'b1;
  end
  
 always @(posedge clk or negedge rst_n)
  begin
   if(!rst_n)
	 clk_1khz <= 1'b0;
	else if (cnt == 18'd24_999)
	 clk_1khz <= ~clk_1khz ;
	else
	 clk_1khz <= clk_1khz ;
	end
endmodule
1khz分频-testbench
module tb;

	// Inputs
	reg clk;
	reg rst_n;

	// Outputs
	wire clk_1khz;

	// Instantiate the Unit Under Test (UUT)
	clk_1KHZ uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.clk_1khz(clk_1khz)
	);
always #10 clk = ~clk;
	initial begin
		clk = 0;
		rst_n = 0;
		#100;
        rst_n=1;
	end
      
endmodule
仿真图如下

image

二、偶数分频:

  • 通过计数器实现,进行N倍偶数分频,通过时钟触发计数器计数,当计数器从0计数到N/2-1时,输出时钟进行翻转,以此循环下去。(占空比为50%) ,以下代码实现8分频,可根据实际需求改变参数输出需要的时钟。

<代码如下>

偶数分频代码
module clk_div_o(clk,rst_n,div_clk_out);
    input  clk         ;
    input  rst_n       ;
    output div_clk_out ;
    
//偶数分频部分
   parameter N = 8      ;
   reg       div_clk_out;
   reg [7:0] cnt        ;
always @ (posedge clk or negedge rst_n)
  begin
    if(!rst_n)
       begin
          cnt <= 1; //从1计数
          div_clk_out <= 0;
       end
    else begin
       if(cnt==N/2)
          begin 
             div_clk_out <= ~div_clk_out; 
             cnt <= 1; 
          end
       else
          cnt <= cnt + 1;
    end
end

endmodule
偶数分频testbench
module tb;

	// Inputs
	reg clk;
	reg rst_n;

	// Outputs
	wire div_clk_out;

	// Instantiate the Unit Under Test (UUT)
	clk_div_o uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.div_clk_out(div_clk_out)
	);
always #10 clk = ~clk;
	initial begin
		// Initialize Inputs
		clk = 0;
		rst_n = 0;
                #100
                rst_n = 1;
	end
      
endmodule
仿真图如下:

三、奇数分频:

  • 以7分频为例。接下来会介绍两种实现方法(占空比为50%)
    (1)高电平:低电平 = 4 :3(即 1:0 = 4 :3)
    (2)低电平:高电平 = 4 :3(即 0:1 = 4 :3)
    二者实现方式相同,这里只介绍第一种方法
    时序图如下
    image
    由时序图看出分别用时钟上升沿和下降沿得到高电平:低电平 = 4 :3,然后将两者相与就可以得到7分频占空比为50%的时钟

    <代码如下>

奇数分频代码
module clk_div_j(clk,rst_n,clk_out );
   input clk     ;
   input rst_n   ;
   output clk_out;
   
   
  parameter N = 7;//分频数
  reg [7:0] cnt_1;
  reg [7:0] cnt_2;
  reg clk_pos,clk_neg;
 // 1:0   4:3   &
 // 0:1   4:3   |
  always @(posedge clk or negedge rst_n) //上升沿输出clk_pos
  begin
    if(!rst_n)
      begin
        clk_pos <= 0; 
        cnt_1    <= 1; //这里计数器从1开始
      end
    else
      begin
        if(clk_pos == 1) 
          begin
            if(cnt_1 == (N+1)/2) //4
            begin
             clk_pos <= ~clk_pos;
             cnt_1 <= 1;
            end
            else
             cnt_1 <= cnt_1 + 1;
          end
        else if(cnt_1 == (N-1)/2)  //3
            begin
              clk_pos <= ~clk_pos;
              cnt_1 <= 1;
            end
        else
            cnt_1 <= cnt_1 + 1;
      end
  end

  always @(negedge clk or negedge rst_n)
                                //下降沿输出clk_neg
  begin
    if(!rst_n)
      begin
        clk_neg <= 0; 
        cnt_2 <= 1; 
      end
    else
      begin
        if(clk_neg == 1)
          begin
            if(cnt_2 == (N+1)/2)  //4
            begin
             clk_neg <= ~clk_neg;
             cnt_2 <= 1;
            end
            else
              cnt_2 <= cnt_2+1;
          end
        else
          if(cnt_2 == (N-1)/2)  //3
            begin
              clk_neg <= ~clk_neg;
              cnt_2 <= 1;
            end
          else
            cnt_2 <= cnt_2+1;
      end
  end

assign clk_out = clk_pos & clk_neg;

endmodule
奇数分频testbench
module tb;

	// Inputs
	reg clk;
	reg rst_n;

	// Outputs
	wire clk_out;

	// Instantiate the Unit Under Test (UUT)
	clk_div_j uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.clk_out(clk_out)
	);
  always #10 clk = ~clk;
	initial begin
		clk = 0;
		rst_n = 0;
		#100;
        rst_n = 1;

	end
      
endmodule
仿真图如下:

image

本篇随笔为学习记录所用,如有错误,请各位指正批评。

posted @ 2021-02-24 20:18  anzg256  阅读(2128)  评论(0编辑  收藏  举报