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
