• FPGA----ZCU106基于axi-hp通道的pl与ps数据交互(全网唯一最详)


    1、大家好,今天给大家带来的内容是,基于AXI4协议的采用AXI-HP通道完成PL侧数据发送至PS侧(PS侧数据发送至PL侧并没有实现,但是保留了PL读取PS测数据的接口)

    2、如果大家用到SoC这种高级功能,那大家应该对于AXI4协议已经很熟悉了,但本文侧重点为初学者直接提供可以上手的硬件实验,大佬请忽略。

    3、AXI4协议的基础内容:

    之前对于AXI4协议已经做过一些总结,但是总结的不好,下面重新进行总结。

    (1)关于AXI4协议的视频课以及博客

    FPGA-ZCU106-PL侧读写ddr4(全网唯一)_发光的沙子的博客-CSDN博客本次给大带来了ZCU106的PL侧读写ddr4的教程,本教程是全网唯一ZCU106教程。本教程采用的是xilinx的ddr4的IP核的AXI4接口开发的,因此需要先了解AXI4总线协议。https://blog.csdn.net/qq_37912811/article/details/125952512?spm=1001.2014.3001.5502这是我之前对AXI4协议的总结nullSDK篇_58~62_AXI接口简介【Xilinx】+【Vivado】+【AXI4总线】+【FPGA】共计5条视频,包括:58_AXI接口简介(第一讲)、59_AXI接口简介(第二讲)、60_AXI接口简介(第三讲)等,UP主更多精彩视频,请关注UP账号。https://www.bilibili.com/video/BV1gy4y1Y7zr/?spm_id_from=333.337.search-card.all.click&vd_source=6b401d1c7af4d19ac1a956340ac80699这是b站的课程,看完之后会对AXI4有更深的了解。

    (2)AXI4协议的总结

    ①写时序

     写时序,主机向从机写入数据。

    一:aw开头的信号是写地址协议。主机告诉从机,我要向awaddr这个地址写数据。

    二:w开头的信号是写数据协议。主机告诉从机,我要向awaddr这个地址写入wdata这个数据。

    三:b开头的写响应协议。从机高速主机,你写的操作是否成功。

    以上三个步骤,均需要ready以及valid双握手,这两个信号同时高电平时,协议才能正常传输。

    注意:M_AXI_WR_awlen这个信号代表了每组数据需要传输的次数,在最后一次传输时,M_AXI_WR_wlas信号置为高电平。M_AXI_WR_awsize代表每次传输的字节数大小。例如,1024bit数据传输,通道最大传输为128bit;则需要传输1024bit/128bit=8次,128bit/8=16byte。

    ②读时序

     读时序,从机向主机请求数据。

    一:ar开头的信号是读地址协议。从机告诉主机,我要向araddr这个地址读数据。

    二:r开头的信号是读数据协议。从机告诉主机,我要读取araddr这个地址对应的rdata这个数据。

    三:没有读数据相应,rresp信号被包含在读数据协议中,用以指示读响应,表明读传输的状态。

    4、PL侧向PS侧通过AXI-HP通道写入数据实验

    (1)实验任务:PL侧生成数据,通过AXI-HP通道写入PS侧的ddr中。PS侧完成软件设计,完成对PL侧写来的数据处理。

    (2)实验软硬件:Vivado 2019.1、ZCU106

    (3)实验过程:

    ①建立工程:embedded_axi_hp,选择ZCU106器件

    ②进行PS侧设计:仅针对ZCU106

    一、搜索ZYNQ添加器件后,点击红框自动布线

     二、设置ddr,经本人亲测,我的ddr只能用这个设置,大家自己多调一下看看吧,这儿挺坑的。

    FPGA学习之路-ZCU106板子点亮PS侧LED_发光的沙子的博客-CSDN博客_zcu1061、本文章借鉴了ZCU106--PL+PS点灯_Junluoyu的博客-CSDN博客_zcu106、ZCU106开发之PS侧MIO闪灯_lixiaolin126的博客-CSDN博客https://blog.csdn.net/qq_37912811/article/details/121953910?spm=1001.2014.3001.5502三、去掉无用端口

    四、添加HP0端口,位宽选择128位(HP支持32/64/128位,PG201) 。右键各个端口,点击Make External,变成下面这样。

    五、添加地址,容量自己设定,我直接用的就是系统直接给分配好的。

     六、添加debug,等待一会,点击左上角的即可。

     

     七、设置复位模块,并点击右上角的自动布线按钮。最终变成下图。

     

     点击红框,弹出成功表示设计无误。

     

     八、输出产品,生成HDL

     九,编写PL侧数据生成代码以及AXI4读写协议,整个项目目录如下所示。

    这里给出data_gen.v代码,其余代码请联系作者

    1. `timescale 1ns / 1ps
    2. //
    3. // Company: 东北电力大学
    4. // Engineer: Yang Zheng
    5. //
    6. // Create Date: 2022/11/27 14:18:57
    7. // Design Name:
    8. // Module Name: data_gen
    9. // Project Name:
    10. // Target Devices:
    11. // Tool Versions:
    12. // Description:
    13. //
    14. // Dependencies:
    15. //
    16. // Revision:
    17. // Revision 0.01 - File Created
    18. // Additional Comments:
    19. //
    20. //
    21. module data_gen(
    22. input sys_clk, //系统时钟
    23. input sys_rst_n, //系统复位,低电平有效
    24. //写
    25. output reg wr_en, //写使能
    26. output reg [1023:0] wr_data, //写数据
    27. output read_enable, //写完成,开始读
    28. //读
    29. output reg rd_en, //读使能
    30. input [1023:0] rd_data, //读数据
    31. input rd_fifo_valid, //读出数据时为高电平,由于ddr是512位的,因此我们需要计数4次,即每次读回4条数据;512/128=4
    32. input rd_fifo_wr_ack, //写入数据为高电平
    33. //开始写入数据物理按钮
    34. input start_bnt
    35. );
    36. //********************************************************************//
    37. //****************** Parameter and Internal Signal *******************//
    38. //********************************************************************//
    39. //parameter define
    40. parameter COUTER_MAX = 30'd5_000_000;//0.2s的时间计数器
    41. reg [29:0] time_counter = 'd0;
    42. //reg define
    43. reg [29:0] count = 'd0; //写入计数器
    44. reg wr_flag = 'd0; //写标志
    45. //********************************************************************//
    46. //***************************** Main Code ****************************//
    47. //********************************************************************//
    48. assign read_enable = wr_flag;
    49. //生成64个32位的数据并且写入PS侧
    50. //这里的 wr_data是输入到ddr的数据,wr_en是使能端口
    51. //这里的 wr_flag是可以ddr存有数据,因此可读标志
    52. always@(posedge sys_clk or negedge sys_rst_n) begin
    53. if (sys_rst_n == 1'b0) begin
    54. wr_data <= 1024'd0;
    55. wr_en <= 1'd0;
    56. wr_flag <= 1'b0;
    57. count <= 'd0;
    58. end
    59. else begin
    60. if (wr_flag == 1'b0 && count < 'd4 && start_bnt == 1'b0) begin
    61. //wr_en <= 1'd1;
    62. count <= count + 1'b1;// 1
    63. end
    64. else if(start_bnt == 1'b1) begin
    65. if (wr_flag == 1'b0 && count == 'd4) begin
    66. wr_data <= {
    67. 32'd1 ,32'd2 ,32'd3 ,32'd4 ,32'd5 ,32'd6 ,32'd7 ,32'd8 ,
    68. 32'd9 ,32'd10,32'd11,32'd12,32'd13,32'd14,32'd15,32'd15,
    69. 32'd17,32'd18,32'd19,32'd20,32'd21,32'd22,32'd23,32'd24,
    70. 32'd25,32'd26,32'd27,32'd28,32'd29,32'd30,32'd31,32'd32
    71. };
    72. wr_en <= 1'd1;
    73. count <= count + 1'b1;// 2
    74. end
    75. else if (wr_flag == 1'b0 && count == 'd5) begin
    76. wr_data <= {
    77. 32'd33,32'd34,32'd35,32'd36,32'd37,32'd38,32'd39,32'd40,
    78. 32'd41,32'd42,32'd43,32'd44,32'd45,32'd46,32'd47,32'd48,
    79. 32'd49,32'd50,32'd51,32'd52,32'd53,32'd54,32'd55,32'd56,
    80. 32'd57,32'd58,32'd59,32'd60,32'd61,32'd62,32'd63,32'd64
    81. };
    82. wr_en <= 1'd1;
    83. count <= count + 1'b1;// 3
    84. end
    85. else if (wr_flag == 1'b0 && count == 'd6) begin
    86. wr_data <= {
    87. 32'd1 ,32'd2 ,32'd3 ,32'd4 ,32'd5 ,32'd6 ,32'd7 ,32'd8 ,
    88. 32'd9 ,32'd10,32'd11,32'd12,32'd13,32'd14,32'd15,32'd15,
    89. 32'd17,32'd18,32'd19,32'd20,32'd21,32'd22,32'd23,32'd24,
    90. 32'd25,32'd26,32'd27,32'd28,32'd29,32'd30,32'd31,32'd32
    91. };
    92. wr_en <= 1'd1;
    93. count <= count + 1'b1;// 3
    94. end
    95. else if (wr_flag == 1'b0 && count == 'd7) begin
    96. wr_flag <= 1'b1;
    97. wr_en <= 1'd0;
    98. end
    99. end
    100. end
    101. end
    102. always@(posedge sys_clk or negedge sys_rst_n) begin
    103. if(~sys_rst_n) begin
    104. time_counter <= 30'd0;
    105. end
    106. else begin
    107. if (wr_flag) begin
    108. time_counter <= time_counter + 1;
    109. if(time_counter == COUTER_MAX) begin
    110. time_counter <= 30'd0;
    111. end
    112. end
    113. end
    114. end
    115. //根据写完成拉高读使能数据
    116. //这里的rd_en可以控制是否读取ddr,因此每次读取给出一个周期的高电平即可
    117. //一直读取
    118. always@(posedge sys_clk or negedge sys_rst_n) begin
    119. if (~sys_rst_n) begin
    120. rd_en <= 1'd0;
    121. end
    122. //写完后等待0.2s开始读取数据
    123. else begin
    124. if(wr_flag == 1'b1 && time_counter == COUTER_MAX) begin//写完后等待0.2s
    125. rd_en<=1'd1;
    126. end
    127. else begin
    128. rd_en<=1'd0;
    129. end
    130. end
    131. end
    132. endmodule

    (4)实验结果:

    一、仿真结果

    可以看到数据已经写入到wdata信号,bresp响应0且bvalid为高电平说明已经将数据写入到PS侧。

    二、硬件结果

    这里给出helloword.c代码,由于传输数据量小,因此需要将缓存屏蔽掉。

    1. #include
    2. #include "platform.h"
    3. #include "xil_printf.h"
    4. #include "xil_cache.h"
    5. int main()
    6. {
    7. //init_platform();
    8. Xil_DCacheDisable();
    9. print("Hello World\n\r");
    10. //cleanup_platform();
    11. return 0;
    12. }

    基于axi-hp通道的pl与ps数据交互

     5、结论及展望

    以上就是本实验的全部内容。本实验完成了,PL侧自定义数据传输到PS侧,并在PS侧写加软件,完成了PL侧传入数据的求和功能,发挥了整个SoC的功能,为后续PL侧加速计算,PS侧数据分析奠定了基础。

  • 相关阅读:
    面向云时代的龙蜥操作系统,是 CentOS 替代的最佳选择
    【慕课C#学习笔记】第一章: 走进C#
    【深入设计模式】迭代器模式模式—什么是迭代器模式?
    Flink Icerberg 离线输仓-维度建模过程(二)
    debian/ubuntu/windows配置wiregurad内网服务器(包含掉线自启动)
    40度高温,如何通过SOLIDWORKS找到室内最凉快的地方?
    【JAVASE】带你了解面向对象三大特性之一(继承)
    P8973 『GROI-R1』 继续深潜,为了同一个梦想
    一种基于端到端结构化网络的高效火灾和烟雾检测算法
    强化学习-DDPG算法
  • 原文地址:https://blog.csdn.net/qq_37912811/article/details/128097813