关于如何搭建基本FPGA软核系统,在极术社区上第五届集创赛ARM杯的前三个公开课视频中已经有很详细的讲解,建议先看看。我个人在工程初步搭建完毕到跑通并调试的过程中,仍遇到不少问题,写下这边博文是为了记录它们。
开发环境:
开发板:黑金AX7a200
软件工具:vivado2017.4 keil5
1.Cortex-m3软核建议使用50M时钟
笔者曾经使用开发板上给的200M晶振时钟直接与CPU内核时钟pin相连,综合实现后时序出现大量时序违规,下载FPGA后CPU没有执行main函数。
通过使用PLL得到50M时钟,给到CPU,时序违规消失,问题解决。
2.关于仿真器
黑金的FPGA只提供了用于下载bitstream的下载器,但我们都知道ARM核也是需要仿真器用于调试的,这就需要额外购买,笔者购买的是正点原子的ATK-DAP仿真器,需要将CPU的调试接口引出到开发板的扩展IO口上,再与仿真器相连。
3.关于ARM调试接口
M3软核貌似不提供jtag接口,只有一个sw接口,核对外引出SWDITMS,SWCLKTCK,SWDO,SWDOEN,分别是SWDI,SW_CLK,SWDO,以及SWDOEN,但仿真器的sw接口只有SWDIO以及SWCLK这两个引脚,因此需要在FPGA内部例化一个三态门。
XILINX的三态门叫做IBUF,连接方式如图:
IOBUF #
(
.DRIVE(12), // Specify the output drive strength
.IBUF_LOW_PWR("TRUE"), // Low Power - "TRUE", High Performance = "FALSE"
.IOSTANDARD("DEFAULT"), // Specify the I/O standard
.SLEW("SLOW") // Specify the output slew rate
)SWIOBUF(
.I (SWDO),
.T (!SWDOEN),
.O (SWDI),
.IO (SWDIO)
与CPU的连接如下:
.SWDITMS (SWDI),
.SWCLKTCK (swck),
.SWDO (SWDO),
.SWDOEN (SWDOEN),
请注意IOBUF的,I,O,其方向都是对于IOBUF本身而言的。SWDIO与FPGA管脚相连,最终与仿真器的DIO相连,ARM核输出给仿真器的SWDO信号,首先通过I脚输入给IOBUF,并通过IO输出;仿真器给ARM核的SWDI信号先通过SWDIO输入,再从IOBUF的O输出。T是三态使能,T=1时,输出为高阻,亦即此时SWDIO为输入,T=0时SWDIO为输出,因此 SWDOEN需要反向后再给T。
至于调试时钟SW_CLK,则是仿真器输入给ARM核,FPGA的时钟一般是需要接入专用时钟管脚的,但因为笔者为调试时钟分配了一个普通IO管脚,所以需要使用一个BUFG资源提升该时钟信号的性能
BUFG BUFG_inst(
.I (SWCLK),
.O (swck)
);
此时,在布局布线时会报错:
ERROR:[Place 30-574] Poor placement for routing between an IO pin and BUFG. If this sub optimal condition is acceptable for this design, you may use the CLOCK_DEDICATED_ROUTE constraint in the .xdc file to demote this message to a WARNING. However, the use of this override is highly discouraged. These examples can be used directly in the .xdc file to override this clock rule.
< set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF] >
clk_IBUF_inst (IBUF.O) is locked to IOB_X0Y248
and BUFG_inst (BUFG.I) is locked to BUFGCTRL_X0Y31
这个报错的意思是:分配的时钟的pin,和用到的BUFG资源,两者在FPGA中的位置离得太远了,因为本来这个pin也不是为了让你输入时钟的所以是一个poor placement。那么我们可以通过它的提示,来写一个xdc约束,从而忽略掉这个问题,实践表明在10M频率下完全没有问题。
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets SWCLK_IBUF]
打开keil5,点击debug栏的setting,
如果显示仿真器型号,则说明仿真器没有问题,如果显示CPU 的IDCODE,则说明仿真器与核已经建立连接,可以单步调试了。
4.关于仿真
ARM核在执行到main函数之前,需要数万个时钟周期用于执行启动程序(建立堆栈,程序搬移等等,我也不是很懂),这在仿真时是很慢的,好久没出结果也不一定是工程有问题,耐心等待几分钟再看。