Augus

9.菜鸟初入FPGA之任意等分频和倍频

0
阅读(16130)

1.分频

分频在 fpga 的设计中一直都担任着很重要的角色,对于分频,我们通常都是利用计算器来计算达到想要的时钟频率,但是我们可以注意到一个问题,我么平时使用的计数器实现的分频只能实现偶数,假如我们需要计数分频呢?本次笔记,我们同样利用计数器来实现任意奇数的分频.我们看一下实现奇数分频的时序图:

2016-03-30_161326.jpg

从上面的时序图我们可以知道,奇数分频,其实就是通过主时钟信号上沿跟下沿产生一对脉冲信号,然后把两信号相或门就可以得到奇数分频的结果了


下面我们看一下例程:

module Div_clk(clk,rst_n,out_clk); input rst_n,clk; output out_clk; parameter N = 7;//N定义几分频 reg out_clk_1; //由时钟上沿产生的信号 reg [9:0]cnt_1;//上沿时钟信号产生的计数器 always @(posedge clk or negedge rst_n) begin if(!rst_n)begin cnt_1 <= 1'd0; out_clk_1 <= 1'd0; end else begin if(cnt_1 <= (( N-1 )/2)-1)//2 begin cnt_1 <= cnt_1 + 1'd1; out_clk_1 <= 1'd1; end else if(cnt_1 <= N-2) begin cnt_1 <= cnt_1 + 1'd1; out_clk_1 <= 1'd0; end else begin cnt_1 <= 1'd0; out_clk_1 <= 1'd0; end end end reg out_clk_0; //由时钟上沿产生的信号 reg [9:0]cnt_0;//上沿时钟信号产生的计数器 always @(negedge clk or negedge rst_n) begin if(!rst_n)begin cnt_0 <= 1'd0; out_clk_0 <= 1'd0; end else begin if(cnt_0 <= (( N-1 )/2)-1) begin cnt_0 <= cnt_0 + 1'd1; out_clk_0 <= 1'd1; end else if(cnt_0 <= N-2 ) begin cnt_0 <= cnt_0 + 1'd1; out_clk_0 <= 1'd0; end else begin cnt_0 <= 1'd0; out_clk_0 <= 1'd0; end end end assign out_clk = out_clk_1 | out_clk_0 ; endmodule //--------------------- `tb `timescale 1ns/1ns `define clock_period 20 module Div_clk_tb(); reg clk,rst_n; wire out_clk; initial clk = 1; always #(`clock_period/2)clk = ~clk; initial begin 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

仿真波形图:

2016-03-30_162825.jpg

从波形图可以看到我们实现奇数分频的等分频

对于偶数也能实现分频,但是非等分

2016-03-30_163304.jpg


备注:有兴趣的可以做一下任意分频的, 即:判断奇偶后进行等分频

2.倍频

接下来我们尝试利用 FPGA 的内部的电路延迟,来搭建一个倍频电路(在后仿真的前提下)

当然我们也可以使用计数器实现倍频

2016-03-30_165324.jpg

我们看一下例程:

module Mul_clk(clk,out_clk); input clk; output out_clk; reg clk_a,clk_b; wire rst_n; assign out_clk = clk_a | clk_b; assign rst_n = ~out_clk; always @(posedge clk or negedge rst_n) begin if(!rst_n) clk_a <= 1'b0; else clk_a <= 1'b1; end always @(negedge clk or negedge rst_n) begin if(!rst_n) clk_b <= 1'b0; else clk_b <= 1'b1; end endmodule `timescale 1ns/1ns `define clock_period 20 module Mul_clk_tb(); reg clk; wire out_clk; initial clk = 1; always #(`clock_period/2)clk = ~clk; initial begin #(`clock_period*50); $stop; end Mul_clk Mul_clk(.clk(clk),.out_clk(out_clk)); endmodule


2016-03-30_172010.jpg\








Baidu
map