1.分频
分频在 fpga 的设计中一直都担任着很重要的角色,对于分频,我们通常都是利用计算器来计算达到想要的时钟频率,但是我们可以注意到一个问题,我么平时使用的计数器实现的分频只能实现偶数,假如我们需要计数分频呢?本次笔记,我们同样利用计数器来实现任意奇数的分频.我们看一下实现奇数分频的时序图:
从上面的时序图我们可以知道,奇数分频,其实就是通过主时钟信号上沿跟下沿产生一对脉冲信号,然后把两信号相或门就可以得到奇数分频的结果了
下面我们看一下例程:
moduleDiv_clk(clk,rst_n,out_clk);
inputrst_n,clk;
outputout_clk;
parameterN=7;//N定义几分频
regout_clk_1;//由时钟上沿产生的信号
reg[9:0]cnt_1;//上沿时钟信号产生的计数器
always@(posedgeclkornegedgerst_n)
begin
if(!rst_n)begin
cnt_1<=1'd0;
out_clk_1<=1'd0;
end
elsebegin
if(cnt_1<=((N-1)/2)-1)//2
begin
cnt_1<=cnt_1+1'd1;
out_clk_1<=1'd1;
end
elseif(cnt_1<=N-2)
begin
cnt_1<=cnt_1+1'd1;
out_clk_1<=1'd0;
end
elsebegin
cnt_1<=1'd0;
out_clk_1<=1'd0;
end
end
end
regout_clk_0;//由时钟上沿产生的信号
reg[9:0]cnt_0;//上沿时钟信号产生的计数器
always@(negedgeclkornegedgerst_n)
begin
if(!rst_n)begin
cnt_0<=1'd0;
out_clk_0<=1'd0;
end
elsebegin
if(cnt_0<=((N-1)/2)-1)
begin
cnt_0<=cnt_0+1'd1;
out_clk_0<=1'd1;
end
elseif(cnt_0<=N-2)
begin
cnt_0<=cnt_0+1'd1;
out_clk_0<=1'd0;
end
elsebegin
cnt_0<=1'd0;
out_clk_0<=1'd0;
end
end
end
assignout_clk=out_clk_1|out_clk_0;
endmodule
//---------------------`tb
`timescale1ns/1ns
`defineclock_period20
moduleDiv_clk_tb();
regclk,rst_n;
wireout_clk;
initialclk=1;
always#(`clock_period/2)clk=~clk;
initialbegin
rst_n=0;
#20;
rst_n=1;
#(`clock_period*50);
$stop;
end
Div_clk
#(.N(7))
Div_clk(.clk(clk),.rst_n(rst_n),.out_clk(out_clk));
endmodule
仿真波形图:
从波形图可以看到我们实现奇数分频的等分频
对于偶数也能实现分频,但是非等分
备注:有兴趣的可以做一下任意分频的, 即:判断奇偶后进行等分频
2.倍频
接下来我们尝试利用 FPGA 的内部的电路延迟,来搭建一个倍频电路(在后仿真的前提下)
当然我们也可以使用计数器实现倍频
我们看一下例程:
moduleMul_clk(clk,out_clk);
inputclk;
outputout_clk;
regclk_a,clk_b;
wirerst_n;
assignout_clk=clk_a|clk_b;
assignrst_n=~out_clk;
always@(posedgeclkornegedgerst_n)
begin
if(!rst_n)
clk_a<=1'b0;
else
clk_a<=1'b1;
end
always@(negedgeclkornegedgerst_n)
begin
if(!rst_n)
clk_b<=1'b0;
else
clk_b<=1'b1;
end
endmodule
`timescale1ns/1ns
`defineclock_period20
moduleMul_clk_tb();
regclk;
wireout_clk;
initialclk=1;
always#(`clock_period/2)clk=~clk;
initialbegin
#(`clock_period*50);
$stop;
end
Mul_clkMul_clk(.clk(clk),.out_clk(out_clk));
endmodule
\