[ZCU111折腾笔记] 00 简介&用PL点亮流水灯
00 简介&用PL点亮流水灯
0x00 项目背景
任务描述
设计一个卫星上的一个载荷, 载荷功能: 采用高分辨率广角相机采集卫星当前方向的大视场高分图像, 并识别指定物体, 并返回该物体所在的区域, 将这个裁剪的小像素图片通过RF发送回地面站.
方案简介
采用 Zynq UltraScale+ RFSoC ZCU111 Evaluation Kit, 进行设计, 功能验证. 系统框图如下:
项目需要确定一个CMOS的连接方式, 可以考虑 Camera Link 或者其他方式, 有待研究,
Zynq RFSoC 中PL部分负责读取CMOS(实现某种总线), 由Zynq RFSoC中的PS部分负责图像的识别(运行识别算法, 可用PL进行加速), 最后将目标从高分辨率的图像中分割出来, 通过RF部分传输到地面站.
本节内容
本节将通过Zynq RFSoC上的PL部分进行点亮流水灯.
如果只用PL部分, 就相当于一个普通的FPGA, 与使用Xilinx其他系列的FPGA的流程类似, 但是由于ZCU111的设计, 带来一些小麻烦, 比如差分时钟信号的处理.
0x01 Zynq UltraScale+ RFSoC ZCU111 Evaluation Kit 简介
启动选项(BOOT)
Zynq UltraScale+ XCZU28DR-2E RFSoC devices use a multi-stage boot process as described in the “Boot and Configuration” chapter of the Zynq UltraScale+ Device Technical Reference Manual (UG1085)
ZCU111 所板载的 XCZU28DR-2E SoC拥有三种启动模式: JTAG, Quad SPI, SD
而三种模式的选定在ZCU111板子上通过拨码开关SW6进行选定, 参见下表
Boot Mode | Mode Pin[3:0] | Mode SW6[3:0] |
---|---|---|
JTAG | 0000 | ON,ON,ON,ON |
QSPI32 | 0010 | ON,ON,OFF,ON |
SD | 1110 | OFF,OFF,OFF,ON |
时钟简介
ZCU111板载提供一些可编程的时钟芯片, 为系统产生时钟, 下表介绍了SoC 需要的时钟信号, 以及其所使用的时钟源
下表参考 UG1271 Chapter3: Clock Generation 一节
由上表可知, 系统的板载时钟芯片有四个, 一个为固定频率时钟芯片 SI5341B(U46), 另三个为可编程时钟芯片, 其中有两个SI570(U47, U49), 一个为SI5382A.
时钟芯片与板子的连接方式见下表
由上表可以看出, 除了PS的参考时钟之外, 所有时钟均采用的是差分输入模式, 因此,在编写Verilog文件的时候需要特殊处理, 才能正常使用时钟.
0x02 实现PL点亮流水灯
如果只用PL的部分的话, 和普通的FPGA并没有什么区别, 通过这个步骤只是希望对FPGA的设计步骤有一个初步的认识, 下面不是很详细, 但是希望能解决一些问题.
2.1 我遇到的问题
参照UG1271 Chapter3: Clock Generation 一节, 我们知道板载的时钟, 大多数都是采用LVDS差分输入的(事实上只有PS_REF_CLK采用了单端输入). 这种差分输入时钟或者差分输入信号在FPGA中如何处理?
参考文章:
在XILINX中差分输入信号到单端信号的转换
2.2 Verilog源码
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2019/10/30 11:10:58
// Design Name:
// Module Name: led
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module led(
input sys_clk_p,
input sys_clk_n,
input rst,
output reg[3:0] led
);
reg[31:0] timer_cnt;
wire sys_clk;
clk cl(sys_clk_p, sys_clk_n, sys_clk);
always@(posedge sys_clk or negedge rst)
begin
if(rst)
begin
led <= 4'd0;
timer_cnt <= 32'd0;
end
else if(timer_cnt >= 32'd49_999_999)
begin
led <= ~led;
timer_cnt <= 32'd0;
end
else
begin
led <= led;
timer_cnt <= timer_cnt + 32'd1;
end
end
endmodule
module clk(
input clk_p,
input clk_n,
wire clk
);
begin
IBUFGDS CLK_U(
.I(clk_p),
.IB(clk_n),
.O(clk)
);
end
endmodule
module led是创建的普通流水灯工程, 代码十分简单, 因此不再赘述, 而clk模块就是将差分信号输入改为单端输入的模块. 引用了IBUFGDS
IP核, 在led模块中简单调用以后, 就可以使用了. 同样的, 如果输入的信号为差分信号, 我们则需要用IBUFDS
模块来把差分输入信号转为单端输入信号.
有上图可见实例模块cl将差分的时钟信号输出转为单端输入信号.
2.3 时钟约束
在参考的某些教程中, 需要在综合之前首先进行时钟约束, 据老司机(某FPGA高手)所说, 时钟约束就是保证一个片内的两个或多个模块的之间不会因为长线的连接而造成时钟信号的延迟(所带来的同步问题), 所以要采用时钟约束, 来保证模块的综合的时候使用了附近的门阵列资源, 以保证时钟同步性.
时钟约束的添加需要在综合之前完成, 在 SYNTHESIS -> Open Synthesized Design -> Constrains Wizards
2.4 约束文件
顶层模块中, 就已经有clk_p 和clk_n 这对差分引脚了, 而 IBUFGDS模块的描述, 也让vivado自动的识别了这对差分引脚.
LED的设置不再赘述. rst信号为板载的一个微动开关充当. 注意这个微动开关不应该时标有RST标志的引脚, 原因是该引脚被PS端所使用
Vivado自动的将sys_clk_p, sys_clk_n识别为差分输入引脚, 并使用DIFF_HSTL_I_18电平协议自动处理
系统生成的约束文件(xdc文件)如下
set_property PACKAGE_PIN AW5 [get_ports rst]
set_property PACKAGE_PIN AR13 [get_ports {led[0]}]
set_property PACKAGE_PIN AP13 [get_ports {led[1]}]
set_property PACKAGE_PIN AR16 [get_ports {led[2]}]
set_property PACKAGE_PIN AP16 [get_ports {led[3]}]
set_property PACKAGE_PIN J19 [get_ports sys_clk_p]
create_clock -period 20.000 -name sys_clk_p -waveform {0.000 10.000} [get_ports sys_clk_p]
set_property IOSTANDARD LVCMOS18 [get_ports {led[3]}]
set_property IOSTANDARD LVCMOS18 [get_ports {led[2]}]
set_property IOSTANDARD LVCMOS18 [get_ports {led[1]}]
set_property IOSTANDARD LVCMOS18 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports rst]
set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports sys_clk_p]
2.5 JTAG调试
首先要保证SoC的启动模式为JTAG模式, 在vivaod进行 SYNTHESIS -> IMPLEMENTATION -> Generate Bitstream 之后, 启动Open Hardware Manger, 连接ZCU111的USB, 然后进行烧录. 完成实验.