【verilog】 任意小数分频
题目
请设计一个可以实现任意小数分频的时钟分频器,比如说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 = 8d87; parameter change = 8d63; //7*9 -> 3*8 parameter pre_cycle = 5d9; parameter post_cycle = 5d8; //main counter:0->86 reg[6:0]cnt; always@(posedge ci or negedge rst) if(!rst) cnt <= 1b0; else begin if(cnt == 7d86) cnt <= 1d0; else cnt <= cnt + 1d1; end //pre_counter //在0~62里循环计数0~8 reg [3:0] pre_cnt; always@(posedge ci or negedge rst) if(!rst) pre_cnt <= 1d0; else begin if(cnt < change)begin if(pre_cnt == pre_cycle - 1) pre_cnt <= 1d0; else pre_cnt <= pre_cnt + 1d1; end else pre_cnt <= 1d0; end //post_counter //在63~86里循环计0~7 reg [3:0] post_cnt; always@(posedge ci or negedge rst) if(!rst) post_cnt <= 1d0; else begin if(!(cnt < change))begin if(post_cnt == post_cycle - 1) post_cnt <= 1d0; else post_cnt <= post_cnt + 1d1; end else post_cnt <= 1d0; end //0~4时co为1 >4时co为0 reg co_r; always@(posedge ci or negedge rst) if(!rst) co_r <= 1b0; else begin if(cnt < change)begin if(pre_cnt < d4) co_r <= 1b1; else co_r <= 1b0; end else begin if(post_cnt < d4) co_r <= 1b1; else co_r <= 1b0; 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 = 1b0; forever begin #10; clk = ~clk; end end initial begin rst = 1b0; #25; rst = 1b1; end initial begin #5000; $stop; end endmodule
结果
在0~86的计数过程中产生了10个co上升沿
