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

仿真截图如下

原文地址:https://www.cnblogs.com/429512065qhq/p/8576670.html