题目
请设计一个可以实现任意小数分频的时钟分频器,比如说8.7分频的时钟信号
注意rst为低电平复位
信号示意图:
分频原理
假设输入时钟名为ci,输出时钟名为co
若实现3分频,则每3个ci上升沿,出一个co上升沿。
若实现4分频,则每4个ci上升沿,出一个co上升沿。
若实现8.7分频,则每8.7个ci上升沿,出一个co上升沿。
即为:每87个ci上升沿出10个co上升沿
87个ci上升沿可以拆分为63+24个
在前63个ci上升沿里,每9个ci上升沿出1个co上升沿,一共能得到7个co上升沿
在后24个ci上升沿里,每8个ci上升沿出1个co上升沿,一共能得到3个co上升沿
综上,在87个上升沿一共得到10个co上升沿
verilog部分
//8.7 div clk
module f_pll(
input wire ci,
input wire rst,
output wire co
);
parameter ci_pose = 8'd87;
parameter change = 8'd63; //7*9 -> 3*8
parameter pre_cycle = 5'd9;
parameter post_cycle = 5'd8;
//main counter:0->86
reg[6:0]cnt;
always@(posedge ci or negedge rst)
if(!rst)
cnt <= 1'b0;
else begin
if(cnt == 7'd86)
cnt <= 1'd0;
else
cnt <= cnt + 1'd1;
end
//pre_counter
//在0~62里循环计数0~8
reg [3:0] pre_cnt;
always@(posedge ci or negedge rst)
if(!rst)
pre_cnt <= 1'd0;
else begin
if(cnt < change)begin
if(pre_cnt == pre_cycle - 1)
pre_cnt <= 1'd0;
else
pre_cnt <= pre_cnt + 1'd1;
end
else
pre_cnt <= 1'd0;
end
//post_counter
//在63~86里循环计0~7
reg [3:0] post_cnt;
always@(posedge ci or negedge rst)
if(!rst)
post_cnt <= 1'd0;
else begin
if(!(cnt < change))begin
if(post_cnt == post_cycle - 1)
post_cnt <= 1'd0;
else
post_cnt <= post_cnt + 1'd1;
end
else
post_cnt <= 1'd0;
end
//0~4时co为1 >4时co为0
reg co_r;
always@(posedge ci or negedge rst)
if(!rst)
co_r <= 1'b0;
else begin
if(cnt < change)begin
if(pre_cnt < 'd4)
co_r <= 1'b1;
else
co_r <= 1'b0;
end
else begin
if(post_cnt < 'd4)
co_r <= 1'b1;
else
co_r <= 1'b0;
end
end
assign co = co_r;
endmodule
tb
module tb;
reg clk;
reg rst;
f_pll inst1(
.ci(clk),
.rst(rst),
.co()
);
initial begin clk = 1'b0; forever begin #10; clk = ~clk; end end
initial begin rst = 1'b0; #25; rst = 1'b1; end
initial begin #5000; $stop; end
endmodule
结果
在0~86的计数过程中产生了10个co上升沿