Verilog实现倍频
这篇博客讲怎么用D触发器和异或门组成的倍频器,并用Verilog实现验证;
1. 原理:
- CLK时钟要想实现倍频,那么CLK每变化一次,对应的CLK_out就必须变化两次;因此采用D触发器,且CLK的上升沿,下降沿均有效,且均会引起CLK_out两次的变化;因此,需要在加入一个组合逻辑电路,CLK变化时,时序逻辑引起CLK_out从0->1,时序逻辑部分的输出作为输入,通过组合逻辑使CLK_out从1->0, 这样每次CLK变化时,CLK_out都会出现一个短时间的脉冲变化,从而达到倍频效果。
- 如图,手画了一下,我们将~Q与D相连,那么每次输入时钟信号时, Q都会翻转, Q和CLK通过一个异或门,输出到D触发器的时钟信号上,那么此时CLK的每次变化,都会使D触发器收到一个上升沿,而 Q翻转后又会将异或门的输出变回0,导致CLK每次变化都会在异或门的输出端产生一个脉冲信号,该脉冲信号是CLK的两倍。(也不知道这种电路设计出自哪儿,没找到出处)
2. 代码实现
module double_f(
input clk,
input rst,
output clk_out
);
reg Q;
wire NOR_clk;
always@(posedge NOR_clk or negedge rst)
begin
if(!rst)
Q <= 0;
else
Q <= ~Q; // #0.3 Q <= ~Q,通过加延时可以显示出来波形
end
assign NOR_clk = Q^clk;
assign clk_out = NOR_clk; //clk_out的频率是clk的两倍
endmodule
3.测试(testbench)
module test(
);
reg rst;
reg clk;
wire clk_out;
wire clk_;
wire rst_;
reg Q;
initial
begin
rst = 1;
clk = 0;
#5
rst = 0;
#20
rst = 1;
end
assign clk_ = clk;
assign rst_ = rst;
always #5 clk = ~clk;
double_f f(
.clk(clk_),
.rst(rst_),
.clk_out(clk_out)
);
always@(posedge clk_out or negedge rst) #由于clk_out的脉冲宽度特别小,所以我们用Q来捕获它的上升沿
begin
if(!rst)
Q <= 0;
else
Q <= ~Q;
end
endmodule
仿真波形如图所示:
由于clk_out的脉冲是延时导致的,而一般FPGA的延时很短,因此clk_out的脉冲长度很短,Xilinx仿真结果不显示这么短的脉冲,为了方便观看,clk_out每经历一次上升沿,Q就改变一次,因此Q的频率是clk_out的1/2, 因此由图可知clk_out的频率是clk的两倍.