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