zoukankan      html  css  js  c++  java
  • FPGA等占空比奇偶分频和半整数分频

    1. 偶数分频比较简单,如果分频系数是N(如果N是偶数,那么N/2是整数),那么在输入时钟的每隔N/2个周期时(计数器从0到N/2-1),改变输出时钟的电平即可得到50%固定占空比的时钟。需要的代码如下

    module even(clk_in,clk_out,rst_n);
    input clk_in;
    input rst_n;
    output clk_out;
    
    parameter N=6;
    
    reg [3:0] cnt;
    reg clk_out;
    
    always @(posedge clk_in or negedge rst_n) begin
    if(!rst_n) begin    
        cnt<=4'b0000;
        clk_out<=0;
    end
    else if(cnt==(N/2-1)) begin
    clk_out<=~clk_out;
    cnt<=4'b0000;
    end else cnt<=cnt+1; 
    end
    endmodule

    2. 如果N是奇数,那么N/2非整数,使用2个寄存器,分别用上升沿寄存器计数到(N-1)/2-1电平翻转信号A,再计数到N-1电平翻转信号A,再用下降沿寄存器计数到(N-1)/2-1电平翻转信号B,再计数到N-1电平翻转信号B,,得到两个波形A和B,然后A和B相或即可,代码如下:

    module div3(clk,clk_out,rst_n);
    input clk,rst_n;
    output clk_out;
    
    reg [3:0] cnt_p,cnt_n;
    reg clk_p,clk_n;
    parameter N=5;
    
    always @(posedge clk or negedge rst_n) begin
      if(!rst_n)
        cnt_p<=4'h0;
      else if(cnt_p==N-1)
        cnt_p<=0;
      else cnt_p<=cnt_p+1;
      end
      
      always @(negedge clk or negedge rst_n) begin
      if(!rst_n)
        cnt_n<=4'h0;
      else if(cnt_n==N-1)
        cnt_n<=0;
      else cnt_n<=cnt_n+1;
      end
      
    always @(posedge clk or negedge rst_n) begin
      if(!rst_n)
        clk_p<=1;
      else if(cnt_p==(N-1)/2-1)
        clk_p<=~clk_p;
      else if(cnt_p==(N-1))
        clk_p<=~clk_p;
      end
    
    always @(negedge clk or negedge rst_n) begin
      if(!rst_n)
        clk_n<=1;
      else if(cnt_n==(N-1)/2-1)
        clk_n<=~clk_n;
      else if(cnt_n==(N-1))
        clk_n<=~clk_n;
      end  
     assign clk_out=clk_n|clk_p;
     endmodule

    仿真截图如下

    3. 半整数分频,本次以2.5分频为例子

    //===========================================================
    // Author: seuchenrui@126.com
    //
    // Description:
    // This is a simple verilog code for clock frequency division
    // this code can be used to get 
    // 1. divided by 2.5
    //===========================================================
    module iCLK_div_shift_register_25
    (
        input   iCLK,
        input   iRESET,
        output  oCLK
    );
    
    wire    [4:0] tmp_shift;
    
    reg tmp_0_;
    reg tmp_2_;
    reg tmp_3_;
    
    reg [4:0] tmp;
    assign  tmp_shift = 5'b0_0001;
    
    always@(posedge iCLK or negedge iRESET)
    begin
        if(!iRESET)
            tmp<=tmp_shift;
        else
            tmp<={tmp[3:0], tmp[4]};
    end
    
    always@(negedge iCLK or negedge iRESET)
    begin
        if(!iRESET)
            tmp_0_<=1'b0;
        else
            tmp_0_<=tmp[0];
    end
    
    always@(negedge iCLK or negedge iRESET)
    begin
        if(!iRESET)
            tmp_2_<=1'b0;
        else
            tmp_2_<=tmp[2];
    end
    
    always@(negedge iCLK or negedge iRESET)
    begin
        if(!iRESET)
            tmp_3_<=1'b0;
        else
            tmp_3_<=tmp[3];
    end
    
    assign oCLK = tmp[0]|tmp[1]|tmp_0_|tmp_2_|tmp_3_|tmp[3];
    
    endmodule

    3. 半整数分频,这个主要是利用时钟的上升沿和下降沿进行计数。不过分出来的占空比不是50%。问题在于如果被分的时钟不是50%占空比,那么按照下面出来的时钟频率还对吗?不对。

    //2.5分频
    
    module div_5(clk,clk_div, rst, temp_out1, temp_out2);//N+0.5
    input clk;
    input rst;
    output clk_div;
    reg [3:0] cnt1,cnt2;
    //output reg temp1,temp2;
    reg temp1,temp2;
    output temp_out1, temp_out2;
    parameter N = 2;  //设定分频系数为N+0.5
    reg start_negedge;
    //inital语句不可被综合
    //initial 
    //begin 
    //    temp1=0;temp2=1;
    //end   //首先进行初始化,temp1=0;temp2=1
    
    //所有的判断信号都要写入
    
    
    always @(posedge clk or negedge rst)  //temp1上升沿跳变
    begin
    
       if(!rst)
        begin 
            cnt1<=4'b0;
            temp1<=0; 
            start_negedge <= 0;
            end
            
        else begin
        
        
        if(cnt1 == 2*N)
            begin cnt1<=4'b0;end
            
        else begin cnt1 <= cnt1 + 4'b1;end
        
        if(cnt1==4'b0) begin temp1<=1; start_negedge <= 1;end   //高电平时间为N+1;
        else if(cnt1==N+1) begin temp1<=0;end   //低电平时间为N;
        end
    
    end
    
    always@(negedge clk or negedge rst)  //temp2下降沿跳变
    begin
       if(!rst) 
        begin 
            cnt2<=4'b0;
            temp2<=1; end
        else if(start_negedge == 0)
            begin 
            cnt2<=4'b0;
            temp2<=1; end
        else begin
        
        if(cnt2==2*N)  //2*N
            begin cnt2<=4'd0;end
        else begin cnt2<=cnt2+4'd1;end
        if(cnt2==4'd0) begin temp2<=0;end     //低电平时间为N;
        else if(cnt2==N) begin temp2<=1;end    //高电平时间为N+1;
        end
        
    end
    
    assign clk_div=temp1&temp2;  //逻辑与
    assign  temp_out1 = temp1;
    assign  temp_out2 = temp2;
    endmodule

    仿真截图如下

  • 相关阅读:
    分布式发布订阅消息系统 Kafka 架构设计[转]
    KAFKA分布式消息系统[转]
    文本协议与二进制协议的选择
    实现程序的热升级
    实现程序的热升级
    一个Socket数据处理模型
    关于GC进行垃圾回收的时机
    多线程
    线程同步(AutoResetEvent与ManualResetEvent)
    异步
  • 原文地址:https://www.cnblogs.com/429512065qhq/p/8576670.html
Copyright © 2011-2022 走看看