赞
踩
通常在面试中面试官可能会问到关于奇数分频的实现,比如三分频,五分频,七分频等,根据自己推敲和理解,并且总结规律,给出自己对于奇数分频的实现。首先,为了更好理解什么是三分频,五分频,七分频等,我们假设一个输入时钟的时钟周期为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周期后跳变,值得注意的是,上述分频的实现占空比都是百分之五十(高电平的占比),这也迎合大部分的设计要求,其次,随着分频数的增加,计数器的位宽也需要作出调整,至此,奇数分频的实现就总结完成
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。