任意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


                                       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM