初试高云FPGA
前言
之前一直眼馋Sipeed的Tang系列,正好遇到有工程需要高速控制并行总线,就买了NANO 9K和Primer 20K试试水
买回来先拆的贵的20k,结果发现Sipeed设计师有奇怪的脑回路:
- 核心板没有指示灯,没有集成下载器
- tf卡在核心板与底板中间藏着,JTAG丝印在背面
- JTAG接口和官方下载器需要扭麻花形式连接
- 调整供电bank需要手动拆除0R电阻。
- 板载晶振27MHz,很奇怪的频率
结果就是失去了调试的兴趣,随便写了个分频器输出1pps脉冲了事。
之后拆了NANO 9K,这个就比20K好用多了,板载一串LED,虽然一些板载资源占用了IO,但还是比较方便调试的。
Sipeed还有个问题就是,例程太少,点灯、点屏幕,没了。好在高云的手册比较多,虽然各个功能的手册是分别发布的,没有系统教程,但好在详细。摸索了一天,算是明白了这个工具要怎么用,因此先写一篇博客记录一下。
软件准备
- 前往高云官网下载软件和各种参考手册。推荐使用教育版,不用申请license。
- 安装下载好的云源软件,我安装的1.9.8.09教育版,有的教程说要另外下载programmer,该版本已自带。软件安装问题可以参考SUG501手册。
- 打开软件,界面功能问题可以参考SUG100手册。
- 新建工程,点灯测试,详见Sipeed点灯例程。
- 综合、约束、下载之类的基础操作在例程中已有详解,这里列一下可能用到的手册
- 综合问题在SUG550
- 约束在SUG935和SUG940
- 下载在SUG502
- 其他高级功能样例在SUG918,所有功能有独立说明手册
所以说高云手册虽然不系统,但好在很详细
IP核调用
IP核怎么调用,没有专门教程参考,仅在SUG100中放了个界面。各各IP核手册中也只是用Verilog或VHDL实例化原语,搞得我这Verilog入门菜鸟一头雾水。在此随手记录一下IP核调用方式。
项目目标
点灯教程中系统时钟来自于板载时钟27MHz,这个时钟我猜测是为了保留3M时钟基频,以便精确PLL出如21M、12M、24M等时钟(那为什么不用21M时钟,还包含7M基频)。
但是我看27MHz不顺眼,于是项目目标就是,利用GW1NR-9C自带的可编程时钟,产生一个25MHz频率,再用这个25MHz进PLL产生100MHz时钟,同时把25MHz用缓冲器输出到引脚上,以检测板子的信号完整性。最后固化到内部Flash,完成烧录与脱机运行。
这样,该项目检测了逻辑单元、IO、IO速率、PLL、CLK,只剩下DSP、SRAM和一些PHY没测试了,之后可以写一个DDS工程,测一下DSP和SRAM。
IP核配置
- 首先是打开IP核界面,选择时钟模型,选择OSC,双击
- 可以看到内部可编程时钟的配置是很简单的,只需要填一个分频数就好。该IP核的详细说明见UG286,具体搭载的时钟原频率是多少,不要参考软件中IP核的说明,要参考IC的Datasheet,如GW1NR-9的DS117的晶振时钟章节
- 软件自动生成verilog文件,自己也可以仿照该文件直接在主模型文件中例化原语。
- 在主模型文件中将该OSC模型实例化
- 接着,在IP核管理界面选择rPLL模块,一般使用普通模式即可,填入输入时钟、输出时钟、误差容忍度,点击计算即可自动配置。需注意,有些需求时钟是不能产生的,或者它自动生成参数后综合软件认为不在VCO适用频率内,这时就需要手动凑数计算了。详细参数计算综合报错时会有,UG286也有计算方法。
- 在主文件中将该PLL实例化
- 直接在主文件中将25M时钟连到OBUF上,输出带缓冲的clk_out
- 对点灯例子中的一些计数值稍作修改,即可完成代码
- 综合约束,烧录。烧录选择烧录在内部Flash里,这样可以离线运行
附
代码如下:
module led (
input sys_rst_n, // reset input
output reg [5:0] led, // 6 LEDS pin
output wire clk_out
);
reg [31:0] counter;
wire pll_clk;
wire sys_clk;
Gowin_OSC SYSOSC(sys_clk);
Gowin_rPLL APLL(pll_clk,sys_clk);
OBUF uut(
.O(clk_out),
.I(sys_clk)
);
always @(posedge pll_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
counter <= 32'd0;
else if (counter < 32'd49_999_999) // 0.5s delay
counter <= counter + 1'b1;
else
counter <= 32'd0;
end
always @(posedge pll_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
led <= 6'b111110;
else if (counter == 32'd49_999_999) // 0.5s delay
led[5:0] <= {led[4:0],led[5]};
else
led <= led;
end
endmodule
约束: