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)beginif(!rst_n)begincnt_1<=1'd0;out_clk_1<=1'd0;endelsebeginif(cnt_1<=((N-1)/2)-1)//2begincnt_1<=cnt_1+1'd1;out_clk_1<=1'd1;endelseif(cnt_1<=N-2)begincnt_1<=cnt_1+1'd1;out_clk_1<=1'd0;endelsebegincnt_1<=1'd0;out_clk_1<=1'd0;endendendregout_clk_0;//由时钟上沿产生的信号reg[9:0]cnt_0;//上沿时钟信号产生的计数器always@(negedgeclkornegedgerst_n)beginif(!rst_n)begincnt_0<=1'd0;out_clk_0<=1'd0;endelsebeginif(cnt_0<=((N-1)/2)-1)begincnt_0<=cnt_0+1'd1;out_clk_0<=1'd1;endelseif(cnt_0<=N-2)begincnt_0<=cnt_0+1'd1;out_clk_0<=1'd0;endelsebegincnt_0<=1'd0;out_clk_0<=1'd0;endendendassignout_clk=out_clk_1|out_clk_0;endmodule//---------------------`tb`timescale1ns/1ns`defineclock_period20moduleDiv_clk_tb();regclk,rst_n;wireout_clk;initialclk=1;always#(`clock_period/2)clk=~clk;initialbeginrst_n=0;#20;rst_n=1;#(`clock_period*50);$stop;endDiv_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)beginif(!rst_n)clk_a<=1'b0;elseclk_a<=1'b1;endalways@(negedgeclkornegedgerst_n)beginif(!rst_n)clk_b<=1'b0;elseclk_b<=1'b1;endendmodule`timescale1ns/1ns`defineclock_period20moduleMul_clk_tb();regclk;wireout_clk;initialclk=1;always#(`clock_period/2)clk=~clk;initialbegin#(`clock_period*50);$stop;endMul_clkMul_clk(.clk(clk),.out_clk(out_clk));endmodule