FPGA奇偶分频参数法
设计介绍
初次创作哈哈 先来一个 使用参数方法的奇偶分频设计吧 通过定义两个参数 来实现奇数分频和偶数分频两个时钟的输出 包含具体代码哈哈
如何产生奇数分频
方法有很多种 在这里介绍一种通过assign 语句将两个信号相或的产生方法吧
奇数分频关键在于如何在奇数过程中产生半个系统时钟,我们在这里就是用negedge吧,通过negedge clk 可以产生下降沿触发的nege_clk 信号,将nege_clk信号和pose_clk信号相或就产生了想要的多出来的半个周期的信号了,我们想要的3分频就出来了,系统时钟三个周期div_3_clk为一个周期,就像下图所示,具体代码见下面,下方有完整的代码。
如何产生偶数分频
偶数分频应该就更简单了,一个计数器就可以解决的,以二分频为例吧
二分频当然需要一个能计到2的计数器了,在计数到一般的时候把信号拉高,然后在技术到结束的时候把信号拉低也就可以了啊。
上代码
//----------------------------------------------------------------------------------------
// Modified by: 橘子FPGA
// Modified date: 2020/12/25 10:19
// Version: V1.1
// Descriptions: 奇偶分频参数法
// Introduction: 利用奇偶分频参数 产生两个奇偶分频时钟
//----------------------------------------------------------------------------------------
//****************************************************************************************//
module o_e_div(
input rest,clk , //时钟和复位
output clk_odd , //3分频时钟
output reg clk_even //2分频时钟
);
parameter odd_div = 3’d2 ; //奇分频系数 (以三分频为例)
//odd_div = 想要的奇分频 — 1
parameter even_div = 3’d1 ; //偶分频系数 (以二分频为例)
//even_div = 想要的偶分频 — 1
reg [2:0] cnt_odd ; // 位宽须大于odd_div即可
reg [2:0] cnt_even ; // 位宽须大于even_div即可
reg pos_o_clk ; //
reg neg_o_clk ; //
//------------------------------------------------------------------------------------------
//产生奇分频
always @ ( posedge clk or negedge rest )begin
if ( !rest )
cnt_odd <= 3’d0 ;
else if (cnt_odd == odd_div)
cnt_odd <= 3’d0 ;
else
cnt_odd <= cnt_odd + 3’d1 ;
end
always @ ( posedge clk or negedge rest )begin
if ( !rest )
pos_o_clk <= 1’d0 ;
else if (cnt_odd == odd_div/2’d2)
pos_o_clk <= 1’d1 ;
else if (cnt_odd == odd_div)
pos_o_clk <= 1 'd0 ;
end
always @ ( negedge clk or negedge rest )begin
if ( !rest )
neg_o_clk <= 1’d0 ;
else if (cnt_odd == odd_div/2’d2)
neg_o_clk <= 1’d1 ;
else if (cnt_odd == odd_div)
neg_o_clk <= 1 'd0 ;
end
assign clk_odd = neg_o_clk || pos_o_clk ;
//------------------------------------------------------------------------------------------
//产生偶分频
always @ ( posedge clk or negedge rest )begin
if ( !rest )
cnt_even <= 3’d0 ;
else if (cnt_even == even_div)
cnt_even <= 3’d0 ;
else
cnt_even <= cnt_even + 3’d1 ;
end
always @ ( posedge clk or negedge rest )begin
if ( !rest )
clk_even <= 1’d0 ;
else if (cnt_even == (even_div - 1’d1)/2’d2 )
clk_even <= ~ clk_even ;
else if (cnt_even == even_div )
clk_even <= ~ clk_even ;
end
endmodule
2 3 分频仿真图
parameter odd_div = 3’d2 ; //奇分频系数 (以3分频为例)
//odd_div = 想要的奇分频 — 1
parameter even_div = 3’d1 ; //偶分频系数 (以2分频为例)
//even_div = 想要的偶分频 — 1
4 5 分频仿真图
parameter odd_div = 3’d4 ; //奇分频系数 (以5分频为例)
//odd_div = 想要的奇分频 — 1
parameter even_div = 3’d3 ; //偶分频系数 (以4分频为例)
//even_div = 想要的偶分频 — 1
6 7 分频仿真图
parameter odd_div = 3’d6 ; //奇分频系数 (以7分频为例)
//odd_div = 想要的奇分频 — 1
parameter even_div = 3’d5 ; //偶分频系数 (以6分频为例)
//even_div = 想要的偶分频 — 1
注意
到此奇偶分频就完成了,需要注意代码中随着参数大小改变奇偶计数器位宽也需要改变,如下所示。
reg [2:0] cnt_odd ; // 位宽须大于odd_div即可
reg [2:0] cnt_even ; // 位宽须大于even_div即可
需要注意在计数器的使用时的问题,何时把信号拉高何时把信号拉低,在实际设计中最好采用PLL产生的分频货倍频时钟,因为PLL产生的时钟最后到达各级寄存器的时间是已经被优化好的了,我们自己设计的分频时钟一般是没有被优化的,所以说以后最好还是用PLL吧。