本次实验主要带领大家了解智多晶FPGA开发中如何调用IP核,了解基本IP核PLL的简单应用
1、添加并配置PLL
打开HQFPGA,新建一个“PLL_led”工程
点击
进入IP Creator
进入IP Creator后在时钟管理单元,双击选中的 IP 或点击“创建”按钮可以弹出相关 IP 的配置框,然后用户就可以对相关 IP 进行配置
选中时钟管理点击“创建”IP。在IP保存选项中可以设置模块名,文件名,格式及存放的目录,读者可按需求设置,也可以保持默认设置,生成独立子目录
选择好后点击“创建”。
进入PLL频率设置模式,在频率设置模式下我们可以直接输入我们需要的频率完成设置。
PLL的IP核可以提供7路输出,输出的频率与CLKI必须有一定的分数关系, LOCK在锁定后输出高电平,可支持设置输出相移。(注:CLKOP一般取值等于CLKI,这样内部PLL会倍频到一个合适的值,其余的CLKOS端口只要通过分频即可输出。)在IP模块视图可以直观看到我们对IP的设置情况,在启用相应的端口时,IP模块视图中的相应端口会变为深色显示。对于本次实验,我们输出4路不同频率的时钟以控制LED,从而让大家熟悉在进行智多晶FPGA开发时PLL核的使用。
对PLL进行设置,芯片外部晶振输入时钟为25MHz,设置PLL输入时钟CLK1默认为25MHz。
选中”锁定”以引出“LOCK信号”、选中复位信号
设置CLKOP输出为25MHz,再分别输出100MHz、50MHz、12.5MHz时钟信号。
可以发现,我们选中的项在左边框图中对应的名称都变为了深色
并且在下方的”info“界面可以观察到相关参数被设置
设置完成后点击“生成IP”,显示完成IP生成后退出PLL设置。
现在在IP Creator可以检测到生成的IP。
双击生成的IP,可以再次进入IP设置界面。
读者需要注意的是,在更新IP后,IP的默认保存路径不会和我们之前设置的路径一致,如果不设置为相同路径在调用IP时我们还是调用的原来未更新的IP,这里就需要读者手动设置IP的保存路径,确保和之前的路径保持一致。勾选“独立子目录”后,会在我们选择的目录下生成一个以我们设置的模块的名称命名的文件夹来保存IP的“.v”文件,这里需要注意,在更新IP并选择好路径,如果路径是在之前的子目录下,再次勾选“独立子目录”栏会在之前的子目录路下再次生成一个子目录,导致IP保存路径不一致。
所有如果需要更改IP设置,要取消勾选”独立子目录“,自行选择之前创建的目录进行更改
在更改后点击“更新IP..”并保存在原文件夹内(PLL),完成IP设置的修改。
打开
添加“xsIP _PLL.v”文件到工程设计中,
在“工程属性”添加设计文件后才可以在“设计管理”中正确识别文件。
退出工程属性,进入
此时系统自动编译,完成后在设计管理栏的设计层级栏可以查看到IP文件。右键点击,选择打开,就可以查看xsIP _PLL.v文件文件中的内容,也可以选择配置IP对IP核进行重新配置。
选择“配置IP”可以进入IP的配置界面,在设计管理页面更新IP不会重新设置IP的路径,我们推荐在设计管理页面进行IP的更新,避免设置路径的过程,避免出错。
在设计管理器更新IP后会提示是否重新加载程序,选择是进行重新加载。
然后在设计管理器中 新建文件或者打开已有文件
依次创建所需的 .v 文件(本实验实现4个led的分频次亮灭)
参考见工程源码led_counter.v 、PLL_led.v
并在子目录创建“rtl”文件夹以保存.v文件
退出设计管理器进入 工程属性 添加刚才创建的 .v 文件
再次进入 设计管理 会发现系统自动帮我们根据已有代码搭建好了分层
将PLL_led模块设置为顶层
也可以在 中更改顶层
最后进行语法检查,确认无误后关闭
此时可选择进行 2(仿真) 或者 3(上板验证)
2、设计PLL仿真文件并设置Modelsim仿真
依次创建所需的 .v 文件
详情代码参考见工程源码
PLL_led_tb.v 、 pll_tb.v
同上文一样将新建的 ".v" 文件保存至rtl文件夹、并添加至 工程属性 中的源文件中。
进入 设计管理 发现顶层文件更改,重新设置回PLL_led (否则由于tb文件中没有引脚信息不能上板验证)
按照"【智多晶FPGA-033】【开发流程】基于Modelsim仿真验证的流程"一节方法设置好仿真。
注意此次实验中IP文件 xsIP_PLL.v 在ipcore_dir文件夹中,不要忘记添加,不然会报错(说pll没定义)
进入project后添加完已有的rtl文件后再右键单击空白处添加文件(也可以与rtl文件同时选中)
在ipcore_dir文件夹中找到xsIP_PLL.v 文件
添加好后全部编译“compile all” 再添加tb simulation工程(此处我已经添加了)
最后仿真出wave的时候会发现波形出的奇慢无比,这是modelsim软件自身优化的问题 下图为笔者仿真了快一小时才出的不到一秒的图
所以我们在代码上进行调整,回到project界面,右键单击或双击PLL_led,将其中所有的.cnt_time(25'd12_499999)改为.cnt_time(25'd12_499,降低精度以追求速度
然后保存,重新编译进行仿真。
(要注意的是这个操作只能在仿真中使用,上板验证要达到精度的匹配还是得改回原来的数据。)
这样我们就可以快速的得到我们想要的LED波形了
如图所示,每个刻度为100us LED_D0、LED_D1、LED_D2、LED_D3分别以250us、500us、1ms、2ms的速率变化
如果看得不清楚,可以灵活使用
这三个按键,以及调整网格的参数来更好的观看波形
右键点击波形底部的空白处再点击Grid,Timeline&cursor Control...,
modelsim可能有时不兼容一些verilog语法(也有可能是没有例化)只需要找到该行去掉finish(0);语句即可
同理可以通过仿真波形观察到PLL产生了我们所需要的时钟。
回到project界面,右键添加pll_tb.v文件
重新编译后 添加相应的simulation configuration
注意一个工程里只能打开一个simulation,如果之前的led sim没有关闭则需要先关闭先前的
最后我们同样能得到pll中不同时钟的波形图,
- CLKI; //25M
- CLKOP; //25M
- CLKOS; //100M
- CLKOS2; //50M
- CLKOS3; //12.5M
2、设计不同时钟频率控制led亮灭的实验并验证
在PLL的基础上我们设计用不同时钟频率以相同的计数控制led亮灭的实验。继续添加设计文件,右键点击,选择“Add to Project”->“Existing Fire...”
选择需要添加的设计文件,设计文件读者可以使用我们提供的例程。
在“Project”窗口显示新的设计文件已经添加成功
重新“Compile All”
在Modelsim中新建一个仿真配置文件。
以“PLL_led_tb”为仿真配置名设置仿真配置文件。
这样我们就得到了两个仿真配置文件,切换不同的仿真配置文件可以对工程进行不同层级的仿真。
在以“PLL_led_tb”为仿真配置,添加波形进行仿真。
重仿真波形界面,我们可以观察到不同的时钟频率在相同的计数情况下控制led以不同的时间翻转。
打开
读入设计
使用约束编辑器
进行管脚分配,全选启用、io_type统一选择 3.3V 即 “LVCMOS33”
AC208-SA5Z 所对应管脚 端口名 | 引脚信息 | Clk | H13 bank2 | Rst_n(KEY S2) | F5 bank1 | LED3 | E14 bank2 | LED2 | F14 bank2 | LED1 | G15 bank2 | LED0 | D15 bank2 |
AC208-SA5Z 全部引脚信息见如下帖
【智多晶FPGA-002】AC208-SA5Z-30-D1开发板资料 http://www.corecourse.cn/forum.php?mod=viewthread&tid=28766 (出处: 芯路恒电子技术论坛)]
AC208 所对应引脚
端口名 | 引脚信息 | Clk | C12 bank2 | Rst_n | N2 bank1 | LED3 | L6 bank3 | LED2 | K9 bank3 | LED1 | K10 bank3 | LED0 | P8 bank3 |
全部引脚信息见如下帖
【智多晶FPGA】基于智多晶SoC FPGA的AC208-601SA5Z开发板资料 http://www.corecourse.cn/forum.php?mod=viewthread&tid=29172 (出处: 芯路恒电子技术论坛)
保存后 点击
下载程序到开发板,程序设计LED_D0、LED_D1、LED_D2、LED_D3分别以2s、1s、0.5s、0.25s的速率变化(照片看不出)。
AC208-SA5Z案例效果
AC208案例效果
本次实验带领读者体验了进行智多晶FPGA逻辑开发时如何进行IP的调用,并调用验证PLL的功能,在仿真的过程中以设置不同仿真配置文件的方法实现了工程不同层级的仿真。
更多智多晶FPGA相关资料,请查看下述汇总贴
【智多晶FPGA-001】小梅哥智多晶FPGA产品使用自助服务手册
工程源码
AC208-SA5Z案例源码
PLL_led.zip
(453.06 KB, 下载次数: 593)
AC208案例源码
PLL_led.rar
(344.52 KB, 下载次数: 433)
1. pll_tb.v
[C#] 纯文本查看 复制代码 `timescale 1ns/1ps
`define clk_period 40
module pll_tb;
reg RST;
reg CLKI;
wire CLKOP;
wire CLKOS;
wire CLKOS2;
wire CLKOS3;
wire LOCK;
PLL PLL(
.CLKI(CLKI),
.RST(RST),
.CLKOP(CLKOP),
.CLKOS(CLKOS),
.CLKOS2(CLKOS2),
.CLKOS3(CLKOS3),
.LOCK(LOCK)
);
initial CLKI = 1;
always #(`clk_period/2)CLKI = ~CLKI;
initial begin
RST = 1'b1;
#201;
RST = 1'b0;
#10000;
end
endmodule
2. PLL_led.v 、
[C#] 纯文本查看 复制代码 module PLL_led(
Clk,
Rst_n,
LED
);
input Clk;
input Rst_n;
output [3:0]LED;
wire CLKOP; //25M
wire CLKOS; //100M
wire CLKOS2;//50M
wire CLKOS3;//12.5M
wire LOCK;
PLL PLL(
.CLKI(Clk),
.RST(!Rst_n),
.CLKOP(CLKOP),
.CLKOS(CLKOS),
.CLKOS2(CLKOS2),
.CLKOS3(CLKOS3),
.LOCK(LOCK)
);
led_counter
#(
.cnt_time(25'd12_499999)
)
counter0(
.clk(CLKOS),
.rst_n(Rst_n),
.led(LED[0])
);
led_counter
#(
.cnt_time(25'd12_499999)
)
counter1(
.clk(CLKOS2),
.rst_n(Rst_n),
.led(LED[1])
);
led_counter
#(
.cnt_time(25'd12_499999)
)
counter2(
.clk(CLKOP),
.rst_n(Rst_n),
.led(LED[2])
);
led_counter
#(
.cnt_time(25'd12_499999)
)
counter3(
.clk(CLKOS3),
.rst_n(Rst_n),
.led(LED[3])
);
endmodule
3. PLL_led_tb.v 、
[C#] 纯文本查看 复制代码 `timescale 1ns/1ps
`define clk_period 40
module PLL_led_tb;
reg Clk;
reg Rst_n;
wire [3:0]LED;
PLL_led PLL_led(
.Clk(Clk),
.Rst_n(Rst_n),
.LED(LED)
);
initial Clk = 1;
always #(`clk_period/2)Clk = ~Clk;
initial begin
Rst_n = 1'b0;
#(`clk_period * 20 + 1);
Rst_n = 1'b1;
#(`clk_period * 2000);
finish(0);
end
endmodule
4. led_counter.v
[C#] 纯文本查看 复制代码 module led_counter(
clk,
rst_n,
led
);
input clk;
input rst_n;
output reg led;
parameter cnt_time = 12_499_999;
reg [31:0]counter;
//延时计数
always@(posedge clk or negedge rst_n)
if(!rst_n)
counter <= 32'd0;
else begin
if(counter == cnt_time)
counter <= 32'd0;
else
counter <= counter + 1;
end
always@(posedge clk or negedge rst_n)
if(!rst_n)
led <= 1'b0;
else if(counter == cnt_time)
led <= ~led;
else
led <= led;
endmodule
|