当前位置:首页 > > ZYNQ
		


ZYNQ_PS读写PL资源_base_on_pynqZ2

前言

最近比较系统的学习了zynq,内容还是很多的,不过它的架构我还是很熟悉的,所以一些嵌入式知识很快就过了,我的时间主要花在AXI总线和操作系统;

1、AXI总线:

由于Xilinx是将双核ARM与7系列FPGA集成于一块硅片构成SoC,所以比较重要的一个模块就是硬核处理器(PS)与可编程逻辑(PL)之间的通信,传统的有SPI总线、IFC总线的方式,zynq使用的是ARM和Xilinx共同制定的总线协议AMBA AXI4(Advanced Microcontroller Bus Architec),根据使用场景不同它有三种标准Lite、Stream、Full,Full即总线结构最完整的AXI4,4代表第4代,所以要是想和之前第三代总线模块互联的话,之间必须添加总线转换IP,它的总线结构和时序需要好好看看,《Xilinx AP Z-7000 SoC 设计指南》中有很详细介绍,其中有一段关于交易通道握手信号关系很重要:

2、操作系统:

这里的操作系统主要是指嵌入式linux,需要掌握peta-linux、uboot、内核、设备树、文件系统等,好多,不过幸运的是,在导入硬件文件后Vivado SDK会自动生成一些库,如头文件和BSP,最大的意义在于完成了硬件资源的映射,软件可以通过对地址的调用完成对硬件的操作。

AXI总线寄存器模块

在Tools中选择生成AXI总线接口的模块(IP),然后需求是PS可以读写32个位宽为32的寄存器,所以我选择的深度是32,其实打开代码就会发现,代码中的示例逻辑本身就是一个寄存器模块,PS和PL都可以对这32个寄存器读写操作,它们的W/R属性也是可以修改的

 1//读操作  2assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;  3 always @(*)  4 begin  5 // Address decoding for reading registers  6 case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )  7 5'h00   : reg_data_out <= slv_reg0;  8 5'h01 : reg_data_out <= slv_reg1;  9 5'h02 : reg_data_out <= slv_reg2; 10 5'h03 : reg_data_out <= slv_reg3; 11 5'h04 : reg_data_out <= slv_reg4; 12 5'h05 : reg_data_out <= slv_reg5; 13 5'h06 : reg_data_out <= slv_reg6; 14 5'h07 : reg_data_out <= slv_reg7; 15 5'h08 : reg_data_out <= slv_reg8; 16 5'h09 : reg_data_out <= slv_reg9; 17 5'h0A : reg_data_out <= slv_reg10; 18 5'h0B : reg_data_out <= slv_reg11; 19 5'h0C : reg_data_out <= slv_reg12; 20 5'h0D : reg_data_out <= slv_reg13; 21 5'h0E : reg_data_out <= slv_reg14; 22 5'h0F : reg_data_out <= slv_reg15; 23 5'h10 : reg_data_out <= slv_reg16; 24 5'h11 : reg_data_out <= slv_reg17; 25 5'h12 : reg_data_out <= slv_reg18; 26 5'h13 : reg_data_out <= slv_reg19; 27 5'h14 : reg_data_out <= slv_reg20; 28 5'h15 : reg_data_out <= slv_reg21; 29 5'h16 : reg_data_out <= slv_reg22; 30 5'h17 : reg_data_out <= slv_reg23; 31 5'h18 : reg_data_out <= slv_reg24; 32 5'h19 : reg_data_out <= slv_reg25; 33 5'h1A : reg_data_out <= slv_reg26; 34 5'h1B : reg_data_out <= slv_reg27; 35 5'h1C : reg_data_out <= slv_reg28; 36 5'h1D : reg_data_out <= slv_reg29; 37 5'h1E : reg_data_out <= slv_reg30; 38 5'h1F : reg_data_out <= slv_reg31; 39 default : reg_data_out <= 0; 40 endcase 41 end 42 
 1//写操作片段  2 if (slv_reg_wren)  3 begin  4 case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )  5 5'h00:  6 for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )  7 if ( S_AXI_WSTRB[byte_index] == 1 ) begin  8 // Respective byte enables are asserted as per write strobes  9 // Slave register 0 10 slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; 11 end 12 5'h01: 13 for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) 14 if ( S_AXI_WSTRB[byte_index] == 1 ) begin 15 // Respective byte enables are asserted as per write strobes  16 // Slave register 1 17 slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; 18 end 19 5'h02: 20 for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) 21 if ( S_AXI_WSTRB[byte_index] == 1 ) begin 22 // Respective byte enables are asserted as per write strobes 23 // Slave register 2 24 slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; 25 end 26 5'h03: 27 for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) 28 if ( S_AXI_WSTRB[byte_index] == 1 ) begin 29 // Respective byte enables are asserted as per write strobes  30 // Slave register 3 31 slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; 32 end 

硬件连接

把Zynq PS和上述生成的寄存器IP PL连接起来,其实很简单,两次自动连线就可以了,这里需要强调的是,需要检查DDR的配置、MIO的配置和PL时钟,由于需要串口打印,所以将串口和PS连接起来,具体管脚需要看原理图,可以看到是14 15,点击与之对应的UART0就可以了。

然后是将原理图设计转换成代码,再完成综合、实现和最终的bit文件,烧录进pynq Z2,硬件方面的设计就结束了。

软件设计

在File菜单先Export Hardware,然后 Launch SDK,就进入Xilinx软件开发环境,可以在Hello World模板上直接操作。
源码来源于米联客的教程,我根据自己的工程有改动:

 1#include   2#include "platform.h"  3#include "xil_printf.h"  4#include "xil_io.h" //Xil_In32 Xil_Out32函数的头文件  5#include "xparameters.h" //硬件映射的地址信息,XPAR_MYIP_REGS_0_S00_AXI_BASEADDR 即PL IP核中寄存器的起始偏移地址  6  7int main()  8{  9 init_platform(); 10 print("Hello World\n\r"); 11 12 13 int num; 14 int rev; 15 16 xil_printf("------The test is start...------\n\r"); 17 18 19 for( num=0; num<32; num++ )//写入 20 21 { 22 xil_printf("%x",num); 23 Xil_Out32(XPAR_MYIP_REGS_0_S00_AXI_BASEADDR + num*4, 0x10000000+num); // 24 } 25 26 27 28 for( num=0; num<32; num++ )//读出 29 30 { 31 32 rev = Xil_In32(XPAR_MYIP_REGS_0_S00_AXI_BASEADDR + num*4); 33 xil_printf( "The data at %x is %x \n\r",XPAR_MYIP_REGS_0_S00_AXI_BASEADDR + num*4,rev); 34 35 } 36 37 xil_printf("------The test is end!------\n\r"); 38 39 int test; 40 test = Xil_In32( XPAR_MYIP_REGS_0_S00_AXI_BASEADDR + 4); 41 xil_printf("%x",test); 42 43 //cleanup_platform(); 44 return 0; 45}

总结

调试时遇到一个错误,现象是PL能正常烧录,PS能正常编译但是不能下载RUN,反复一直报错:

AP transaction error, DAP status f0000021
我在网上查找了一下,其他不同厂商的开发板也有遇到类似问题,大致原因是软件通过jtag找不到ARM处理器,我联系了开发板的FAE,他给的解释是可能供电电压不稳,换一种供电方式,但是我并没有适配器,但是我看到开发板上ARM的指示灯(DONE)是亮起的,于是重启了电脑和开发板后就恢复正常了,我觉得这很可能是硬件上的缺陷,也有可能是我笔记本USB接口电压不稳?希望能给有同样遭遇的同学一个思路。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
关闭