内核创建
首先根据自己的板子型号创建好一个工程,然后点击 IP Catalog 再点击图片高亮处:
在最上面给创建的内核起个名字,然后最下面根据自己板子上的晶振填写,其余默认即可。比如以下图片:命名:ip_pll 晶振:50MHz
点击 Output Clocks 进行输出时钟的配置,在此我配置了两个时钟信号,二倍频(100MHz)和二分频(25MHz):
右边还有相位,占空比的配置,在此不做配置,直接点击ok即可。
随后IP就已经创建完毕了,位置在此处:
点击如下文件:
此处就是我们需要在自己的.v文件里调用的:
注意:蓝色字体处也是需要改动的,详细请看下面介绍的.v文件
代码
.v文件:
`timescale 1ns / 1ps
module pll(
input wire sys_clk , // 系统时钟输入
input wire rst_n , // 复位信号
output reg [1:0] led // led输出信号
);
// 计数器计数最大值
parameter CNT_MAX = 50_000_000 - 1;
// 定义两个28位的计数器 可用计数器算出计数最大值对应的二进制位数
reg [27:0] timer1;
reg [27:0] timer2;
// 二倍频(100M) 二分频(25M) 输出时钟信号
wire clk_mul_2 ;
wire clk_div_2 ;
wire locked ;
// 二倍频计数器
always @( posedge clk_mul_2 or negedge rst_n )begin
if( rst_n == 1'b0 )begin
timer1 <= 1'd0;
end
else if( locked == 1'b1 )begin
if( timer1 == CNT_MAX )
timer1 <= 1'd0;
else
timer1 <= timer1 + 1'b1;
end
else begin
timer1 <= 1'd0;
end
end
// 二分频计数器
always @( posedge clk_div_2 or negedge rst_n )begin
if( rst_n == 1'b0 )begin
timer2 <= 1'd0;
end
else if( locked == 1'b1 )begin
if( timer2 == CNT_MAX )
timer2 <= 1'd0;
else
timer2 <= timer2 + 1'b1;
end
else begin
timer2 <= 1'd0;
end
end
// led0状态设置
always @( posedge clk_mul_2 or negedge rst_n )begin
if( rst_n == 1'b0 )begin
led[0] <= 1'b1;
end
else if( timer1 == CNT_MAX )begin
led[0] <= ~led[0];
end
else begin
led[0] <= led[0];
end
end
// led1状态设置
always @( posedge clk_div_2 or negedge rst_n )begin
if( rst_n == 1'b0 )begin
led[1] <= 1'b1;
end
else if( timer2 == CNT_MAX )begin
led[1] <= ~led[1];
end
else begin
led[1] <= led[1];
end
end
// 调用创建的ip_pll
ip_pll ip_pll_inst(
.clk_in1(sys_clk),
.clk_out1(clk_mul_2),
.clk_out2(clk_div_2),
.locked(locked),
.reset(~rst_n)
);
endmodule
约束文件:
############## clock define##################
create_clock -period 20.000 [get_ports sys_clk]
set_property PACKAGE_PIN N18 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
############## key define##################
set_property PACKAGE_PIN P16 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
##############LED define##################
set_property PACKAGE_PIN P15 [get_ports {led[0]}]
set_property PACKAGE_PIN U12 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led[*]}]
有这两个文件就可以生成bit文件了,实验结果为两个led灯以不同的频率进行闪烁。
仿真验证
以下进行仿真验证,仿真文件如下:
`timescale 1ns / 1ps
module tb_pll();
reg sys_clk ;
reg rst_n ;
wire [1:0] led ;
initial begin
rst_n = 1'b0;
#10
rst_n = 1'b1;
end
initial sys_clk = 1'b1;
always #10 sys_clk = ~sys_clk;
pll #( .CNT_MAX(10) ) t_pll(
.sys_clk (sys_clk ),
.rst_n (rst_n ),
.led (led )
);
endmodule
仿真结果:
两个led闪烁周期差了四倍,验证成功。