使用Verilog来实现奇数分频

        通常在面试中面试官可能会问到关于奇数分频的实现,比如三分频,五分频,七分频等,根据自己推敲和理解,并且总结规律,给出自己对于奇数分频的实现。首先,为了更好理解什么是三分频,五分频,七分频等,我们假设一个输入时钟的时钟周期为1s,则三分频后的输出时钟clk_out的时钟周期则为3s,同理,五分频的为5s,七分频的为7s,为了实现奇数分频,我们首先需要两个计数器,用来数时钟周期个数,一个以时钟上升沿为起点开始数,一个以时钟下降沿为起点开始数,并用这两个计数器来设计得到clk_s和clk_x,则clk_out就等于clk_s和clk_x相与,现在似乎难理解一点,我们先通过代码进行实现,并对波形进行查看就方便理解了

先以三分频为例,先定义两个计数器

上升沿计数器cnt_s如下:

always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
        cnt_s<=0;
end
        else if(add_cnt_s)begin //add_cnt_s表示计数开始条件
                if(end_cnt_s)   //end_cnt_s表示计数结束条件
                cnt_s<=0;
                else
                cnt_s<=cnt_s+1;
        end
end
assign add_cnt_s=1;     //这个让它一直计数
assign end_cnt_s=add_cnt_s && cnt_s==3-1;

下降沿计数器cnt_x如下:

always @(negedge clk or negedge rst_n)begin
        if(!rst_n)begin
        cnt_x<=0;
end
        else if(add_cnt_x)begin //add_cnt_x表示计数开始条件
                if(end_cnt_x)   //end_cnt_x表示计数结束条件
                cnt_x<=0;
                else
                cnt_x<=cnt_x+1;
        end
end
assign add_cnt_x=1;     //这个让它一直计数
assign end_cnt_x=add_cnt_x && cnt_x==3-1;

其总的设计代码如下:

module sanfenpin(clk,rst_n,clk_out);

input clk;
input rst_n;
output clk_out;

reg[3:0] cnt_s;
wire add_cnt_s;
wire end_cnt_s;

reg[3:0] cnt_x;
wire add_cnt_x;
wire end_cnt_x;

reg clk_s;
reg clk_x;
wire clk_out;


always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
        cnt_s<=0;
end
        else if(add_cnt_s)begin //add_cnt_s表示计数开始条件
                if(end_cnt_s)   //end_cnt_s表示计数结束条件
                cnt_s<=0;
                else
                cnt_s<=cnt_s+1;
        end
end
assign add_cnt_s=1;     //这个让它一直计数
assign end_cnt_s=add_cnt_s && cnt_s==3-1;

always @(negedge clk or negedge rst_n)begin
        if(!rst_n)begin
        cnt_x<=0;
end
        else if(add_cnt_x)begin //add_cnt_x表示计数开始条件
                if(end_cnt_x)   //end_cnt_x表示计数结束条件
                cnt_x<=0;
                else
                cnt_x<=cnt_x+1;
        end
end
assign add_cnt_x=1;     //这个让它一直计数
assign end_cnt_x=add_cnt_x && cnt_x==3-1;

always @(posedge clk or negedge rst_n)begin //上升沿计数,设计clk_s
	if(rst_n==1'b0)begin
		clk_s<=0;
		cnt_s<=0;
	end
	else if(add_cnt_s && cnt_s==1-1)begin
		clk_s<=0;
	end
	else if (add_cnt_s &&cnt_s==2-1)begin
		clk_s<=1;
	end
end

always @(negedge clk or negedge rst_n)begin //下降沿计数,定义clk_x
	if(rst_n==1'b0)begin
		clk_x<=0;
		cnt_x<=0;
	end
	else if(add_cnt_x && cnt_x==1-1)begin
		clk_x<=0;
	end
	else if (add_cnt_x &&cnt_x==2-1)begin
		clk_x<=1;
	end
end

assign clk_out= clk_s & clk_x;
endmodule

输入时钟和复位信号,其测试代码如下:

module sanfenpin_tb;

parameter cycle=10;
reg clk;
reg rst_n;
wire clk_out;

sanfenpin uut(
	.clk(clk),
	.rst_n(rst_n),
	.clk_out(clk_out)
);

initial begin 
clk=0;

forever #(cycle/2) begin
	clk=~clk;
end
end

initial begin
#1;
rst_n=0;
#(100*cycle);
rst_n=1;
end
endmodule

运行仿真,其波形如下:

 从波行可以看出,clk_out的周期等于三个clk的周期,说明设计符合要求,对于五分频,测试代码不用变,我们只需要使两个计数器数五个时钟周期,并且使clk_s和clk_x过两个时钟周期后跳变,如下

always @(posedge clk or negedge rst_n)begin
	if(rst_n==1'b0)begin
		clk_s<=0;
		cnt_s<=0;
	end
	else if(add_cnt_s && cnt_s==1-1)begin
		clk_s<=0;
	end
	else if (add_cnt_s &&cnt_s==3-1)begin //clk_s为0和1相隔两个时钟周期,clk_x也是如此
		clk_s<=1;
	end
end

always @(negedge clk or negedge rst_n)begin
	if(rst_n==1'b0)begin
		clk_x<=0;
		cnt_x<=0;
	end
	else if(add_cnt_x && cnt_x==1-1)begin
		clk_x<=0;
	end
	else if (add_cnt_x &&cnt_x==3-1)begin
		clk_x<=1;
	end
end

其波形图如下

 同理七分频,则相隔三个时钟周期进行跳变,运行仿真后,其波形如下:

 通过观察波形,说明设计符合要求,至此,可以总结出规律,N(为奇数)分频,需要定义两个计数器,分别以上升沿和下降沿为起始,计N个数,而clk_s和clk_x相隔(N-1)/2个clk周期后跳变,值得注意的是,上述分频的实现占空比都是百分之五十(高电平的占比),这也迎合大部分的设计要求,其次,随着分频数的增加,计数器的位宽也需要作出调整,至此,奇数分频的实现就总结完成

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值