题目要求
设计一个module,实现任意奇数分频,要求占空比为50%,如3分频、5分频,要求分频参数可配置。
以3分频为例,表示分频后的时钟周期是原时钟周期的3倍,即高电平和低电平时间各占1.5个周期,波形如下:
解题思路
为了实现目标波形,需要用到一个计数器cnt
来计数基本时钟周期,两个中间变量clk1
、clk2
,分别用上升沿
和下降沿
触发,都是在cnt=1或2
时进行了翻转。那么很清晰,目标out_clk = clk1 | clk2
。
图中:绿色表示输入信号,橙色表示中间变量,红色表示输出信号。
代码实现
module divider_odd_n
#(
parameter N = 3'd5
)
(
input wire clk ,
input wire rst_n ,
output wire out_clk
);
reg [$clog2(N)-1:0] cnt ;
reg clk_1 ;
reg clk_2 ;
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt <= 'd0;
else if(cnt == N-1'b1)
cnt <= 'd0;
else
cnt <= cnt + 'd1;
end
always@(posedge clk or negedge rst_n) begin
if(!rst_n)
clk_1 <= 1'b0;
else if(cnt == N>>1'b1 | cnt == N-1'b1)
clk_1 <= ~clk_1;
else
clk_1 <= clk_1;
end
always@(negedge clk or negedge rst_n) begin
if(!rst_n)
clk_2 <= 1'b0;
else if(cnt == N>>1'b1 | cnt == N-1'b1)
clk_2 <= ~clk_2;
else
clk_2 <= clk_2;
end
assign out_clk = clk_1 | clk_2;
endmodule
代码中需要注意的细节:
①$clog2是系统内置函数,是求出该数转换为二进制需要占的位数;
②翻转的条件为cnt == N>>1'b1 | cnt == N-1'b1
,若N=5,则在2和4时翻转,若N=11,则在5和10时翻转。其中N在右移之前不必减1,因为末尾的1可以直接给移掉了。
RTL视图
Testbench
此题的testbench很简单啦,只需要给好时钟信号和复位信号就可以啦,具体如下:
`timescale 1ns/1ns
module divider_odd_n_tb();
reg clk ;
reg rst_n ;
wire out_clk ;
always #10 clk = ~clk;
initial begin
rst_n <= 1'b0;
clk <= 1'b1;
#10
rst_n <= 1'b1;
end
//实例化前面所写的奇数分频模块
divider_odd_n
#(
.N(3'd7) //7分频
)
divider_odd_n_inst
(
.clk (clk ),
.rst_n (rst_n ),
.out_clk(out_clk)
);
endmodule
仿真波形
三分频的波形图:
七分频的波形图: