奇数分频和偶数分频在FPGA中可以使用PLL很容易实现,也可以用Verilog实现奇数分频和偶数分频,偶数分频相对来说比较简单,奇数分频需要利用系统时钟的上升沿和下降沿来进行分频。奇数分频和偶数分频都是以系统时钟为基准,然后进行计数,具体什么时间翻转电平是有公式的,只要把公式记住,实现分频轻而易举:
偶数分频(50%占空比):
上升沿N/2-1翻转
奇数分频(50%占空比):
上升沿:上升沿(N-1)/2-1翻转
下降沿:下降沿(N-1)翻转
偶数分频Verilog代码:
module clk_div_even(
input clk,
input rst_n,
output reg clk_div
);
parameter N = 8;
reg [7:0]cnt;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 'd0;
else if(cnt == (N/2-1))
cnt <= 'd0;
else
cnt <= cnt + 1'b1;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
clk_div <= 1'b0;
else if(cnt == (N/2-1))
clk_div <= ~clk_div;
else
clk_div <= clk_div;
end
endmodule
仿真代码(奇数分频和偶数分频共用一个,例化时候注意模块即可):
`timescale 1ns/1ns
module clk_div_tb;
reg clk;
reg rst_n;
wire div_clk;
clk_div clk_div_inst(
.clk (clk ),
.rst_n (rst_n ),
.div_clk (div_clk )
);
// clk_div_even clk_div_even_inst(
// .clk (clk ),
// .rst_n (rst_n ),
// .clk_div (div_clk )
//);
initial clk = 0;
always#10 clk = ~clk;
initial begin
rst_n = 0;
#200;
rst_n = 1;
#2000;
$stop;
end
endmodule
波形仿真:
奇数分频Verilog代码:
module clk_div(
input clk,
input rst_n,
output div_clk
);
parameter N = 9;
reg [3:0] cnt;
reg div_clk1;
reg div_clk2;
//--------------------cnt计数-------------------//
always @(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
cnt <= 0;
end
else if(cnt == (N-1)) //N-1
cnt <= 0;
else begin
cnt <= cnt + 1;
end
end
//---------------上升沿(N-1)/2-1翻转-------------//
always @(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
div_clk1 <= 0;
end
else if(cnt == ((N-1)/2-1))begin //(N-1)/2-1
div_clk1 <= ~div_clk1;
end
else
div_clk1 <= div_clk1;
end
//----------------下降沿(N-1)翻转-----------------//
always @(negedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
div_clk2 <= 0;
end
else if(cnt == (N-1))begin //N-1
div_clk2 <= ~div_clk2;
end
else
div_clk2 <= div_clk2;
end
//----------------两个时钟做异或-----------------//
assign div_clk = div_clk2 ^ div_clk1;
endmodule
波形仿真: