Zedboard的体系中,ZYQN的外设资源已经很丰富,Xilinx提供大量的基于AXI总线和PLB总线的外设,推荐大家优先Xilinx官方IP,不仅经历过测试和验证,还有完善的文档和驱动。
- 为了进一步丰富ZYQN的生态系统,Xilinx的ZYQN系列的PS部分,开放内部互连,提供一系列接口,便于挂接各类符合总线要求的外设;
- 也为了进一步搭建异构系统,实现三分天下。
- 此外,ALTERA也推出了飓风V的SOPC系列,配置类似ZYQN
三部曲大致如下:
- AXI-LITE基本建立流程和XMD测试方法(协处理加法器的实现)
- AXI-LITE实用外设开发---AXI-LITE串口开发 (待定)
- AXI 互连多主机开发---读写DDR3
注:才疏学浅,不擅于绘图,更加不擅于贴图教程。操作贴图步骤有很多很不错的帖子,如“Zedboard 一步一步系列,Zedboard学习手记,玩转Zedboard开发板”等,望大家参考!
感谢老部长BW的支持,提供珍贵的Zedboard!
AXI-LITE外设基本建立流程和XMD测试方法
注:很多例程从Planahead开始,因为参考ug873-zynq-ctt.pdf。本文为了简便,直接从XPS启动(XPS是建立以软MCU或者硬MCU为主体的SOPC硬件开发平台)
1.直接从XPS启动,建立基于BSB的系统
- Step1:选择AXI系统,ARM-A9的使用AXI接口与内部互连相接,而且开发的外设也基本基于AXI。
- 若大家建立基于Microblaze的系统,可以选择PLB。
- AXI是ARM的总线,越来越成为主流。不仅仅在Xilinx上有用,在ALTERA同样行的通。
- Step2:选择基于基于开发板的配置,选择avent的zedboard配置
- 建议大家如此操作,省略设置DDR控制器时序参数的操作;而且UCF文件自动生成,免去配置错误的情况发生(引脚配错,导致无法生成bitsteam)
- 如果大家以后自己绘制PCB,那么建议采用custom的选择,满足自主化的要求
思 考:如果大家从ISE开始,启动XPS后,有可能会发现没有avent的选项,
- 此时,可以先建立个同类型芯片的自主的配置,然后进入XPS主界面后,选择import,导入zedboard的xml格式的配置信息
- 此处,反过来看,如果作为项目开发,可以建立自己的XML文件,便于项目间传递,通过export导出。如下图
2.通过向导建立AXI-Lite的外设
- step1: 从hardware选项里的create or import 建立,具体参考edk_ctt.pdf(来自官网)
- 选择相应的接口
- 选择合适的寄存器数量
- 如果是verilog HDL使用者,建议勾选用verilog hdl 实现user logic的temple
思 考: 如何Import 外设?如何从.hdl全自主书写开发?如何开发内部包含xilinx ip的外设?
- 在导入的过程中,有此3个复选框
- 至少要选择第一个选项,作为顶层TOP使用
- 关于第二个和第三个,根据个人需要选择。
- 关于.ngc.edif格式的文件,基本是综合后的文件,意味着可以直接综合完成,然后采用black box的方式调用,确保IP的安全性
- 关于pfd,doc等文档,建议大家参考官方的IP文档书写,至少画个框架图,功能摘要,寄存器列表及简单的驱动演示
- step2: 互连AXI-LITE外设
- 如果外设只有AXI-LITE从机接口,直接选择连接processor7即可
- 如果外设包含主机口等其他接口,建议选择手动连接
- 添加axi interconnect IP
- 设定相应的参数值
插入自己写的DEMO,基于AXI lite 的32bit加法器
0x0 写读
|
加数1 寄存器1
|
0x4 写读
|
加数2 寄存器2
|
0x8 只读
|
和 寄存器3
|
user loigc片段 // implement slave model register(s)
always @( posedge Bus2IP_Clk )
begin
if ( Bus2IP_Resetn == 1'b0 )
begin
slv_reg0 <= 0;
slv_reg1 <= 0;
// slv_reg2 <= 0;
end
else
case ( slv_reg_write_sel )
3'b100 :
for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
if ( Bus2IP_BE[byte_index] == 1 )
slv_reg0[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
3'b010 :
for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
if ( Bus2IP_BE[byte_index] == 1 )
slv_reg1[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];
/* 3'b001 :
for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 )
if ( Bus2IP_BE[byte_index] == 1 )
slv_reg2[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8];*/
default : begin
slv_reg0 <= slv_reg0;
slv_reg1 <= slv_reg1;
// slv_reg2 <= slv_reg2;
end
endcase
end // SLAVE_REG_WRITE_PROC
// implement slave model register read mux
always @( slv_reg_read_sel or slv_reg0 or slv_reg1 or slv_reg2 )
begin
case ( slv_reg_read_sel )
3'b100 : slv_ip2bus_data <= slv_reg0;
3'b010 : slv_ip2bus_data <= slv_reg1;
3'b001 : slv_ip2bus_data <= slv_reg2;
default : slv_ip2bus_data <= 0;
endcase
end // SLAVE_REG_READ_PROC
// ------------------------------------------------------------
// User Logic adder:
// ------------------------------------------------------------
always @ (slv_reg0 or slv_reg1 )
slv_reg2 = slv_reg0 + slv_reg1;
helloworld.c/*
* Copyright (c) 2009 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
/*
* helloworld.c: simple test application
*/
#include <stdio.h>
#include "summator.h"
//void print(char *str);
int main()
{
unsigned int sum;
int op1,op2;
init_platform();
printf("======summator design======\n\r");
printf("Please input the first operand ADD1:\n\r");
scanf("%d", &op1);
printf("Please input the second operand ADD2:\n\r");
scanf("%d", &op2);
sum = add(op1, op2);
printf("Output the result ADD1 + ADD2:\n\r");
printf("SUM = ADD1 + ADD2 = %d\n\r",sum);
cleanup_platform();
return 0;
}
summator.c/*
* summator.h
*
* Created on: 2013-7-9
* Author: szy
*/
#ifndef SUMMATOR_H_
#define SUMMATOR_H_
#include "platform.h"
#define ADD1 (* (volatile unsigned int *) 0x7aa00000) // 第一个寄存器地址---加数一
#define ADD2 (* (volatile unsigned int *) 0x7aa00004) // 第二个寄存器地址---加数二
#define SUM (* (volatile unsigned int *) 0x7aa00008) // 第三个寄存器地址---和
int add(int a, int b)
{
int sum;
ADD1 = a;
ADD2 = b;
sum = SUM;
return sum;
}
#endif /* SUMMATOR_H_ */
XMD流程简介
XMD是Xilinx® Microprocessor Debugger 的含义,采用命令行的形式,使用TCL语言及Xilinx扩展的一些TCL命令。
- 作为调试PS系统的调试工具,
- 作为GNU Debug 和目标板的连接(软件开发时,即可作为后台任务的执行者,也可可以调出命令行界面)
思 考: XMD如何工作?如何充分利用XMD
- XMD通过JTAG接口连接到PS的互连结构上
- 连接MCU的调试口来控制MCU(复位,停止,读取寄存器等)
- XMD作为互连结构的主机,可以控制外设即访问外设的寄存器(采用地址方式)
- 参考EDK的文档,充分学习使用XMD。
- 基本使用,建议在命令行输入help running,会列出一些常见命令
XMD简单演示
- 从XPS里启动SDK (复选框:Include .bitstream .bmm 选上)
- 在SDK—xilinx tool—launch XMD
- 在SDK—xilinx tool—programme FPGA
- 此处,可以看到XMD打印出SDK软件的一些操作语句------精彩马上到来!!
- 在XMD下,依次输入一下指令:
- connect arm hw ----连接ARM硬件
- stop ----
- mwr 0x7aa00000 0x1 ---向 0x7aa00000 写入0x1
- mwr 0x7aa00004 0x5 ---向 0x7aa00004 写入0x5
- mrd 0x7aa00000 --- 从 0x7aa00000 读出数
注: 此流程配合着上一段写的加法器的demo,请大家对比以前用软件操作外设的方法,类比理解
- 针对大家通常看的DEMO,zedboard的Helloworld DEMO,可以尝试做一下小测试
- connect arm hw ----连接ARM硬件
- stop ----
- mwr 0x41220000 0x3 ---此时,对应的 LD0和LD1亮了 (0x后面的值,对应着二进制0000_0011,所以低位两个led亮)
- mrd 0x41200000 ---此时,读出数据为8个拨码开关的二进制组合数,望大家验证