手撕代码-奇偶分频

1.偶分频

占空比,一个周期内,高电平时间在整个周期时间的占比。

D触发器

2分频

​ 使用一个D触发器,把输出Q的取反,作为输入,实现电平的翻转。因为T0时刻,Q反传入输入D,需要等下一个时钟上升沿T1,才会传到输出,所以实现了2分频。

请添加图片描述

4分频

使用两个D触发器串联,以第一个D触发器的输出Q,作为第二个触发器的时钟。

请添加图片描述

verilog代码如下:

module d_div2_4(
  input clk,
  input rst_n,
  output clk_div2,
  output clk_div4);

  reg reg2;
  reg reg4;

  always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
      reg1 <= 1'b0;
    end
    else begin
      reg2 <= ~reg2; 
    end
  end

  always @(posedge reg1 or negedge rst_n) begin
    if(!rst_n) begin
      reg4 <= 1'b0;
    end
    else
      reg4 <= ~reg4;
  end
  assign clk_div2 = reg2;
  assign clk_div4 = reg4;
endmodule

仿真代码如下:

module tb();
  reg				clk  	;
  reg				rst_n	;
  wire			clk_div2;
  wire			clk_div4;
                                          
  parameter		CLOCK_CYCLE = 20;    
                                          
  d_div2_4 DUT(
    .clk          (clk        ),
    .rst_n        (rst_n      ),
    .clk_div2     (clk_div2   ),     
    .clk_div4     (clk_div4   )     
  );

  initial 		clk = 1'b0;		   

  always #(CLOCK_CYCLE/2) clk = ~clk;  		
                                                   
  initial  begin						       		
    rst_n = 1'b1;																
    #(CLOCK_CYCLE*2);				            
    rst_n = 1'b0;							
    #(CLOCK_CYCLE*2);				            
    rst_n = 1'b1;

    #(CLOCK_CYCLE*50);
    $finish();
  end
  initial	begin
	  $fsdbDumpfile();	    
    $fsdbDumpvars;
  end

endmodule 	

波形如下:

请添加图片描述

  • 实现2 分频和4 分频

计数器

N(N为偶数)分频,在(N/2)- 1翻转。偶分频的占空比都为50%。

使用计数器实现6分频。

verilog代码如下:

module counter_div_6(
  input clk,
  input rst_n,
  output clk_div_6);

  parameter a = 6;
  reg [3:0] counter;
  reg clk_div;

  always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
      counter <= 0;
      clk_div <= 0;
    end
    else begin
      if(counter == (a/2 -1)) begin 
        clk_div <= ~clk_div;
        counter <= 0;
      end
      else
        counter++;
    end
  end
  assign clk_div_6 = clk_div;
endmodule

仿真代码如下:

module tb();
  reg				clk  	;
  reg				rst_n	;
  wire				clk_div2;
  wire				clk_div_6  ;
                                          
  parameter		CLOCK_CYCLE = 20;    
                                          
  counter_div_6 DUT(
    .clk          (clk        ),
    .rst_n        (rst_n      ),   
    .clk_div_6     (clk_div_6  )     
  );

  initial 		clk = 1'b0;		   

  always #(CLOCK_CYCLE/2) clk = ~clk;  		
                                                   
  initial  begin						       		
    rst_n = 1'b1;																
    #(CLOCK_CYCLE*2);				            
    rst_n = 1'b0;							
    #(CLOCK_CYCLE*2);				            
    rst_n = 1'b1;

    #(CLOCK_CYCLE*50);
    $finish();
  end
  initial	begin
	  $fsdbDumpfile();	    
      $fsdbDumpvars;
  end

endmodule 	

波形如下:

请添加图片描述

2.奇分频

2.1占空比50%

计数器

① 设计2个分别用上升、下降沿触发的计数器

② 利用上升、下降沿计数器生成两个分频时钟clk_p和clk_n

③ 利用clk_p和clk_n通过逻辑运算 “与” 生成占空比为50%的分频时钟

verilog代码如下:

module div7_5_5(
  input clk,
  input rst_n,
  output clk_div7
  );

  reg [3:0] counter1;
  reg [3:0] counter2;

  reg clk_reg1;
  reg clk_reg2;

  parameter D = 7; 

  always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
      clk_reg1 <= 0;
    end
    else begin
      if(counter1 == 6) begin
        counter1 <= 0;
        clk_reg1 <= ~clk_reg1;
      end
      else begin
        if(counter1 == 2) begin
          clk_reg1 <= ~clk_reg1;
        end
      end
    end
  end
  
  always @(negedge clk or negedge rst_n) begin
    if(~rst_n) begin
      clk_reg2 <= 0;
    end
    else begin
      if(counter2 == 6) begin
        counter2 <= 0;
        clk_reg2 <= ~clk_reg2;
      end
      else begin
        if(counter2 == 2) begin
          clk_reg2 <= ~clk_reg2;
        end
      end
    end
  end

  always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
      counter1 <= 0;
    else
      counter1++;
  end

  always @(negedge clk or negedge rst_n) begin
    if(~rst_n)
      counter2 <= 0;
    else
      counter2++;
  end

  assign clk_div7 = clk_reg1 & clk_reg2;
endmodule

仿真代码如下:

module tb();
  reg				clk  	;
  reg				rst_n	;
  wire			clk_div7;
                                          
  parameter		CLOCK_CYCLE = 20;    
                                          
  div7_5_5 DUT(
    .clk         (clk ),
    .rst_n        (rst_n),
    .clk_div7     (clk_div7)     
  );

  initial 		clk = 1'b0;		       		
  always #(CLOCK_CYCLE/2) clk = ~clk;  		
                                                   
  initial  begin						       		
    rst_n = 1'b1;																
    #(CLOCK_CYCLE*2);				            
    rst_n = 1'b0;							
    #(CLOCK_CYCLE*2);				            
    rst_n = 1'b1;

    #(CLOCK_CYCLE*50);
    $finish();
  end

  initial	begin
	  $fsdbDumpfile();	    
    $fsdbDumpvars;
  end

endmodule

波形如下:

请添加图片描述

2.2占空比非50%

计数器

源时钟sclk,目标时钟dclk。以7分频,占空比为4/7为例。以sclk的一个period为最小计数单位。即dclk的一个clock period中,电平低占了3个 sclk 时钟周期,高电平占4个 sclk 时钟周期。如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o5h5szSV-1651066744111)(C:/Users/61582/Documents/Typora/tmpC74.png)]

只要当dclk在counter = 2 时,dclk翻转一次,当counter计数到6时,再翻转一次,同时counter重新计数(counter = 0)即可得到我们需要的波形。

verilog代码如下:

module div_7(
  input clk,
  input rst_n,
  output clk_div7
  );

  reg [3:0] counter;
  reg clk_reg;
    
  always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
      clk_reg <= 0;
    end
    else begin
        if(counter == 6) begin
          counter <= 0;
       	  clk_reg <= ~clk_reg;
      end
      else begin
        if(counter == 2) begin
          clk_reg <= ~clk_reg;
        end
      end
    end
  end
  always @(posedge clk or negedge rst_n) begin
    if(~rst_n)
      counter <= 0;
    else
      counter++;
  end
    
  assign clk_div7 = clk_reg;
    
endmodule

仿真代码如下:

module tb();
  reg				clk;
  reg				rst_n;
  wire			clk_div7;
                                          
    parameter		CLOCK_CYCLE = 20;    
                                          
  div_7 DUT(
    .clk         (clk ),
    .rst_n        (rst_n),
    .clk_div7     (clk_div7)     
  );

  initial 		clk = 1'b0;		       		
  always #(CLOCK_CYCLE/2) clk = ~clk;  		
                                                   
  initial  begin						       		
    rst_n = 1'b1;																
    #(CLOCK_CYCLE*2);				            
    rst_n = 1'b0;							
    #(CLOCK_CYCLE*2);				            
    rst_n = 1'b1;

    #(CLOCK_CYCLE*50);
    $finish();
  end
//generate wave
  initial	begin
	$fsdbDumpfile();	    
    $fsdbDumpvars;
  end

endmodule

波形如下:

请添加图片描述

  • 复位后,clk_div7为0,所clk_div7的波形是以低电平开始。
  • 光标处,采样到的counter值为6,而不是0;

N(N为奇数)分频电路,第一次dclk的翻转时间取决于占空比,第二次翻转为当counter == N-1时。

如是3分频电路,占空比为(1/3),则,当counter == 1时dclk翻转一次,counter == 2时dclk翻转一次。

状态机

Moore状态机即可实现输入时钟的5分频。占空比为3/5。

verilog代码如下:

module fsm_div5(
  input clk,
  output reg clk_div5,
  input rst_n
);
  reg [2:0] state;
  reg [2:0] next_state;

  parameter s1 = 3'b000,
            s2 = 3'b001,
            s3 = 3'b010,
            s4 = 3'b011,
            s5 = 3'b100;

  always @(posedge clk) begin
    if(!rst_n) begin
      state <= s1;
    end
    else begin
      state <= next_state;
    end
  end

  always @(*) begin
    case(state)
      s1: next_state = s2;
      s2: next_state = s3;
      s3: next_state = s4;
      s4: next_state = s5;
      s5: next_state = s1;
      default: next_state = s1;
    endcase
  end
  
  always @(*) begin
    if(!rst_n)
      clk_div5 = 0;
    else begin
      case(state)
        s1: clk_div5 = 0;
        s2: clk_div5 = 0;
        s3: clk_div5 = 1;
        s4: clk_div5 = 1;
        s5: clk_div5 = 1;
        default: clk_div5 = 0;
      endcase
    end
  end
endmodule

仿真代码如下:

module tb();
  reg				clk  	;
  reg				rst_n	;
  wire			clk_div5;
                                          
  parameter		CLOCK_CYCLE = 20;    
                                          
  fsm_div5 DUT(
    .clk         (clk ),
    .rst_n        (rst_n),
    .clk_div5     (clk_div5)     
  );

  initial 		clk = 1'b0;		       		
  always #(CLOCK_CYCLE/2) clk = ~clk;  		
                                                   
  initial  begin						       		
    rst_n = 1'b1;																
    #(CLOCK_CYCLE*2);				            
    rst_n = 1'b0;							
    #(CLOCK_CYCLE*2);				            
    rst_n = 1'b1;

    #(CLOCK_CYCLE*50);
    $finish();
  end

  initial	begin
	  $fsdbDumpfile();	    
    $fsdbDumpvars;
  end

endmodule

波形如下:

请添加图片描述

  • 20
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值