進行偶分頻時對其進行對半計數即可實現占空比為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