任意N进制分频器--占空比50%(N>1)

进行偶分频时对其进行对半计数即可实现占空比为50%。

进行奇分频时,可采用两种方式:方法一,首先对分频进行对半计数,因为是奇数,所以对上升沿和下降沿进行计数时,其占空比定然不是50%,所以当设定占空比小于50%时,最后对上升沿和下降沿的计数结果进行相或取值即可实现占空比为50%的奇分频。方法二,对上升沿和下降沿进行计数时,设定计数的占空比大于50%,最后对两种边沿计数的结果进行相与取值即可实现占空比为50%的奇分频。

module div_fre_28(clk, rst_n,c_1,d_out);

input clk;
input rst_n;
input [3:0]c_1; //div=2-8,4位c_1可实现16以内的任意进制分频.
output d_out;

reg d_out;

reg [3:0]o_counter;
reg [3:0]o_pos_counter;
reg o_pos_out;      
reg o_neg_out;      
reg [3:0]o_out;     
wire o_d_out;       

reg [3:0]e_counter;
reg [3:0]e_out;     
reg e_d_out;

//判断是奇分频还是偶分配
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        d_out <= 1'b0;
    end
    else if(c_1[0] == 1'b1) begin
        o_out <= c_1; //奇分频
    end
    else if(c_1[0] == 1'b0) begin
        e_out <= c_1; //偶分频
    end
    else begin
        d_out <= 1'b0;
    end  
end

//进行选择性输出
always@(e_d_out or o_d_out or c_1) begin
    case(c_1[0])
      0:d_out = e_d_out;//通过输入分频的最低位进行奇偶判断,0为偶分频,1为奇分频
      1:d_out = o_d_out;
      default: d_out = 1'bx;
    endcase
end

//偶分频
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        e_d_out <= 1'b0;
        e_counter <= 4'b0000;
    end
    else begin
      if(e_out[0] == 1'b0) begin
        if(e_counter < (e_out)/2) begin
            e_d_out <= 0;
            e_counter <= e_counter + 1'b1;
        end
        else if(e_counter == e_out-1) begin
            e_counter <= 4'b0000;
            e_d_out <= 1'b1; //考虑当为二分频时,e_counter只能进行0,1计数
        end
        else begin
            e_d_out <= 1;
            e_counter <= e_counter + 1'b1;
        end
       end
       else begin
         e_counter <= 4'b0000;
       end
     end
end

//奇分频,分别以上升沿和下降沿进行计数,后两者相或
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        o_pos_out <= 1'b0;
        o_pos_counter <= 4'b0000;
    end
    else begin
        if(o_out[0] == 1'b1) begin
            if(o_pos_counter < o_out/2 ) begin //设定占空比小于50%
                o_pos_out <= 1'b1;
                o_pos_counter <= o_pos_counter + 1'b1;
            end
            else if(o_pos_counter == o_out-1) begin
                o_pos_counter <= 4'b0000;
                o_pos_out <= 1'b0;
            end
            else begin
                o_pos_out <= 1'b0;
                o_pos_counter <= o_pos_counter + 1'b1;
            end
        end
        else begin
        o_pos_counter <= 4'b0000;   
        end
    end

end
always@(negedge clk or negedge rst_n) begin
    if(!rst_n) begin
        o_neg_out <= 1'b0;
        o_counter <= 4'b0000;
    end
    else begin
        if(o_out[0] == 1'b1) begin
            if(o_counter < o_out/2) begin
            o_neg_out <= 1'b1;
            o_counter <= o_counter + 1'b1;
            end
            else if(o_counter == o_out-1) begin
                o_counter <= 4'b0000;
                o_neg_out <= 1'b0;
            end
            else begin
                o_neg_out <= 1'b0;
                o_counter <= o_counter + 1'b1;
            end
        end
        else begin
            o_counter <= 4'b0000;  
        end
    end
end
assign o_d_out = o_neg_out || o_pos_out;

endmodule

简单tb:

module div_fre_28_tb;

reg clk;
reg rst_n;
reg [3:0]c_1;
wire d_out;

div_fre_28 u1(clk, rst_n,c_1,d_out);

initial begin
  clk = 1'b0;
  rst_n = 1'b0;
  #3;
  rst_n = 1'b1;
end

always #5 clk = ~clk;

initial begin
  c_1 = 4'd2;//二分频
  #200;
  c_1 = 4'd3;//三分频
  #200;
  c_1 = 4'd4;//四分频
  #200;
  c_1 = 4'd5;//五分频
  #200;
  c_1 = 4'd6;//六分频
  #200;
  c_1 = 4'd7;//七分频
  #200;
end

endmodule


                                       

posted @ 2020-07-27 10:05  影-fish  阅读(1557)  评论(0编辑  收藏  举报