【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上升沿

经验分享 程序员 微信小程序 职场和发展