module clkFracDiv(
output reg clkout,
input rstn,
input refclk,
input [31:0] fenzi,
input [31:0] fenmu
);
reg [2:0] rstn_syn;
reg [31:0] cnt;
always @(posedge refclk) begin
rstn_syn[0] <= rstn;
rstn_syn[1] <= rstn_syn[0];
rstn_syn[2] <= rstn_syn[1];
end
//1. main algorithm
always @(posedge refclk or negedge rstn_syn[2]) begin
if(!rstn_syn[2]) cnt <= 0;
else begin
if(cnt < fenzi) cnt <= cnt + fenmu;
else cnt <= cnt + fenmu - fenzi;
end
end
always @(posedge refclk or negedge rstn_syn[2]) begin
if(!rstn_syn[2]) clkout <= 0;
else begin
if( ((cnt > (fenzi>>1)) || (cnt == (fenzi>>1)) ) && (cnt < fenzi)) clkout <= 1;
else clkout <= 0;
end
end
endmodule
`timescale 1ns/10ps
module tb_top;
reg refclk;
initial begin
refclk = 0;
end
always #0.2 refclk = !refclk;
reg rstn;
initial begin
rstn = 0;
#100;
rstn = 1;
end
reg [31:0] fenzi;
reg [31:0] fenmu;
reg enable_clkFracDiv;
initial begin
fenzi=32'd13;
fenmu=32'd3;
enable_clkFracDiv=0;
#200;
enable_clkFracDiv=1;
end
clkFracDiv clkFracDiv(
/*output reg */.clkout (clkout),
/*input */.rstn (rstn && enable_clkFracDiv ),
/*input */.refclk (refclk),
/*input [31:0] */.fenzi (fenzi ),//fenzi/fenmu must equal or more than 2
/*input [31:0] */.fenmu (fenmu ) //fenzi/fenmu must equal or more than 2
);
endmodule
![]()