d
else if (cnt == 2) begin //计数器从0计数,到2清零
cnt <= 4'b0 ;
end
else begin //计数累加
cnt <= cnt + 1'b1 ;
end
end
//6分频时钟输出模块
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
clk_div6_r <= 1'b0;
end
else if (cnt == 2 ) begin //3个周期信号翻转得到6分频时钟
clk_div6_r <= ~clk_div6_r;
end
end
assign clk_div6 = clk_div6_r; //延时输出,消除亚稳态
endmodule
2.4 Testbench
`timescale 1ns/1ns //时间刻度:单位1ns,精度1ns
module clk_div_even_tb;
//信号申明
reg clk ;
reg rst_n;
wire clk_div2;
wire clk_div4;
wire clk_div6;
wire clk_div8;
//定义源时钟信号一周期时间
parameter DIV_CLK = 10;
//复位信号生成
initial begin
clk = 0; //时钟信号赋初值
rst_n = 1; //复位信号赋初值
#(1.5*DIV_CLK) rst_n = 0;
#DIV_CLK rst_n = 1;
#(30*DIV_CLK);
end
//源时钟信号生成
always #(DIV_CLK/2) clk = ~ clk;
//模块例化
clk_div_even u_clk_div_even
(
.clk (clk),
.rst_n (rst_n),
.clk_div2 (clk_div2),
.clk_div4 (clk_div4),
.clk_div6 (clk_div6),
.clk_div8 (clk_div8)
);
endmodule
2.5 仿真结果
三、奇数分频
3.1 占空比非50%奇数分频
若要实现N分频(N为奇数),只需将计数器在待分频时钟上升沿触发循环计数,计数到0时输出时钟翻转,当计数到(N-1)/2后再次将输出时钟翻转。
以三分频为例,电路需要实现的是:计数器从0开始计数至2,计数器到0时且在上升沿信号翻转,计数器到1时且在上升沿信号清零,具体的时序图如下(图由TimeGen绘制,该软件功能实用,推荐使用)。
3.2 占空比50%奇数分频
如果对于占空比要求不高的话,只需要简单地对信号计数并且在对应的计数器位置上升沿触发信号翻转即可以得到一个奇数分频,此奇数分频往往占空比达不到50%的要求。
那么如何得到一个50%占空比的奇数分频呢?
从50%占空比奇数分频波形看,信号的翻转对应的源时钟信号分别是上升沿和下降沿,但是双边沿触发在电路设计的时候是不允许的。
那么如何实现这种“类双边沿触发”的效果呢?
对于50%占空比奇数分频,就是分别利用待分频时钟的上升沿触发生成一个时钟,然后用下降沿触发生成另一个时钟,然后将两个时钟信号进行或/与运算得到占空比为50%的奇数分频。
以三分频为例,电路需要实现的是:设计2个分别用上升、下降沿触发的计数器cnt_p和cnt_n,设计2个分别用上升、下降沿触发的计数器clk_p和clk_n,利用clk_p和clk_n通过或逻辑运算生成占空比为50%的分频时钟,具体的时序图如下(图由TimeGen绘制,该软件功能实用,推荐使用)。
此处我们通过两个计数器分别对上升沿和下降沿信号进行翻转,最后通过或运算得到占空比50%的分屏信号。
Tips:此处亦可借用与逻辑运算,对比上面的clk_p和clk_n稍稍不同,大家可以试着自己画出对应时序图。
3.3 Verilog代码
//奇数分频电路设计(占空比非50%的3分频和占空比50%的3分频)
module clk_div_odd (
input clk, //时钟信号
input rst_n, //复位信号
output clk_div3_1, //占空比非50%的3分频时钟信号输出
output clk_div3_2 //占空比50%的3分频时钟信号输出
);
//定义分频的数目
parameter N = 3;
reg [3:0] cnt_p; //上升沿触发计数器计数
reg [3:0] cnt_n; //下降沿触发计数器计数
reg clk_p; //上升沿触发生成的时钟信号
reg clk_n; //下降沿触发生成的时钟信号
//上升沿触发计数器模块
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt_p <= 4'b0000;
else if (cnt_p == N-1) //计数器从0计数,到2清零
cnt_p <= 4'b0000;
else
cnt_p <= cnt_p + 1'b1; //计数器累加
end
//下降沿触发计数器模块
always @(negedge clk or negedge rst_n) begin
if(!rst_n)
cnt_n <= 4'b0000;
else if(cnt_n == N-1) //计数器从0计数,到2清零
cnt_n <= 4'b0000;
else
cnt_n <= cnt_n + 1'b1; //计数器累加
end
//上升沿触发生成的时钟信号模块
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
clk_p <= 1'b0;
else if(cnt_p == (N-1)/2) //计数器到1且在上升沿,时钟信号翻转
clk_p <= ~clk_p;
else if (cnt_p <= 0) //计数器到0且在上升沿,时钟信号翻转
clk_p <= ~clk_p;
else
clk_p <= clk_p; //防止latch产生
end
//下降沿触发生成的时钟信号模块
always @(negedge clk or negedge rst_n)
begin
if(!rst_n)
clk_n <= 1'b0;
else if (cnt_n == (N-1)/2) //计数器到1且在上升沿,时钟信号翻转
clk_n <= ~clk_n;
else if (cnt_n == 0) //计数器到0且在上升沿,时钟信号翻转
clk_n <= ~clk_n;
else
clk_n <= clk_n; //防止latch产生
end
//延时输出,消除亚稳态
assign clk_div3_1 = clk_p; //得到占空比非50%的3分频时钟信号
assign clk_div3_2 = clk_p | clk_n; //或逻辑运算得到占空比50%的3分频时钟信号
endmodule
3.4 Testbench
`timescale 1ns/1ps //时间刻度:单位1ns,精度1ps
module clk_div_odd_tb;
//信号申明
reg clk;
reg r