1 PLL IP核配置步骤
(Vivado 赛灵思)
我看的教程里面,那个兄弟是选的下面这个。 看来还是比较注重开发效率。
下面按照截图路径打开这个veo文件,学习如何在FPGA程序中例化IP核(有点像C++你创建了一个类,然后你实例化一个)。
2 测试代码
现在咱们有3个不同频率的时钟了,我们用这三个时钟计数到同样的值,然后点灯。 就能看出时钟频率的区别。由于灯只有两个,所以实验分成了两次,一次是50MHz时钟和100MHz时钟的对比,一次是50MHz时钟和25MHz时钟的对比。
`timescale 1ns / 1ps
module pll(
input wire clk ,
input wire rst_n ,
output wire [1:0] led
);
//==================================================================
// Parameter define
//==================================================================
localparam CNT_MAX = 50_000_000 - 1;
//==================================================================
// Internal Signals
//==================================================================
// IP_PLL 输出信号引出
wire clk_out1 ; // 注意,这里用的wire类型
wire clk_out2 ;
wire clk_out3 ;
wire locked ;
reg [31:0] timer1cnt ;
reg [31:0] timer2cnt ;
reg [31:0] timer3cnt ;
reg [1:0] led_r ;
assign led = ~led_r;
IP_PLL inst_pll
(
.clk_out1(clk_out1), // output clk_out1 50MHz 0
.clk_out2(clk_out2), // output clk_out2 100MHz 90
.clk_out3(clk_out3), // output clk_out3 25MHz 0
.reset(~rst_n), // input reset 默认高有效,我们的复位信号是低有效,遂取反
.locked(locked), // output locked
.clk_in1(clk) // input clk_in1 我们的输入时钟信号是clk
);
//----------------------------- clk_out1 and timer1cnt and locked -----------------------------
always @(posedge clk_out1 or negedge rst_n) begin
if (rst_n == 1'b0) begin
timer1cnt <= 'd0;
end
else if (locked == 1'b1) begin
if (timer1cnt == CNT_MAX) begin
timer1cnt <= 'd0;
end
else begin
timer1cnt <= timer1cnt + 1'b1;
end
end
else begin
timer1cnt <= 'd0;
end
end
//----------------------------- clk_out2 and timer2cnt and locked -----------------------------
always @(posedge clk_out2 or negedge rst_n) begin
if (rst_n == 1'b0) begin
timer2cnt <= 'd0;
end
else if (locked == 1'b1) begin
if (timer2cnt == CNT_MAX) begin
timer2cnt <= 'd0;
end
else begin
timer2cnt <= timer2cnt + 1'b1;
end
end
else begin
timer2cnt <= 'd0;
end
end
//----------------------------- clk_out3 and timer3cnt and locked -----------------------------
always @(posedge clk_out3 or negedge rst_n) begin
if (rst_n == 1'b0) begin
timer3cnt <= 'd0;
end
else if (locked == 1'b1) begin
if (timer3cnt == CNT_MAX) begin
timer3cnt <= 'd0;
end
else begin
timer3cnt <= timer3cnt + 1'b1;
end
end
else begin
timer3cnt <= 'd0;
end
end
//----------------------------- clk_out1 led -----------------------------
always @(posedge clk_out1 or negedge rst_n) begin
if (rst_n == 1'b0) begin
led_r[0] <= 1'b0;
end
else if (timer1cnt == CNT_MAX) begin
led_r[0] <= ~led_r[0];
end
else begin
led_r[0] <= led_r[0];
end
end
// //----------------------------- clk_out2 led -----------------------------
// always @(posedge clk_out2 or negedge rst_n) begin
// if (rst_n == 1'b0) begin
// led_r[1] <= 1'b0;
// end
// else if (timer2cnt == CNT_MAX) begin
// led_r[1] <= ~led_r[1];
// end
// else begin
// led_r[1] <= led_r[1];
// end
// end
//----------------------------- clk_out3 led -----------------------------
always @(posedge clk_out3 or negedge rst_n) begin
if (rst_n == 1'b0) begin
led_r[1] <= 1'b0;
end
else if (timer3cnt == CNT_MAX) begin
led_r[1] <= ~led_r[1];
end
else begin
led_r[1] <= led_r[1];
end
end
endmodule
在代码中,应该重点关注IP核是如何被调用(例化)的,同时注意例化时,填写的输入输出。 另外,在使用IP核输出的时钟信号计数时,我们同时使用了locked信号,这一点请不要忽略。
3 约束文件
create_clock -period 20.000 [ get_ports clk ]
set_property PACKAGE_PIN N18 [ get_ports clk ]
set_property PACKAGE_PIN P15 [ get_ports {led[0]} ]
set_property PACKAGE_PIN U12 [ get_ports {led[1]} ]
set_property PACKAGE_PIN T12 [ get_ports rst_n ]
set_property IOSTANDARD LVCMOS33 [ get_ports clk ]
set_property IOSTANDARD LVCMOS33 [ get_ports {led[*]} ]
set_property IOSTANDARD LVCMOS33 [ get_ports rst_n ]
4 运行结果
PLL_RUN1
左边的灯闪1次,右边的灯闪2次。 左边灯用的是50MHz时钟,右边灯用的100MHz时钟
PLL_RUN2
左边的灯闪2次,右边的灯闪1次。 左边灯用的是50MHz时钟,右边灯用的25MHz时钟