[X]关闭

[米联客-XILINX-H3_CZ08_7100] FPGA_PL-DDR篇连载-06 uifdma_dbuf+fdma实现数据流

文档创建者:FPGA课程
浏览次数:327
最后更新:2024-09-10
文档课程分类-AMD-ZYNQ
AMD-ZYNQ: ZYNQ-FPGA部分 » 2_FPGA实验篇(仅旗舰) » 2-FPGA PL DDR使用
​ 软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!
目录



1概述
uifdma_dbuf3.1开始支持了full和empty信号, ud_wfull信号为0代表FIFO未满,写通道可以写入数据,uifdma_dbuf的ud_rempty信号为0代表读通道的FIFO中有数据可以读出。
当uifdma_dbuf设置非视频模式的时候,ud_vs信号仅仅用于uifdma_dbuf内部的传输状态机的启动和停止。当ud_vs为高电平,数据传输开始后,通过de控制数据的读或者写。本方案在实际的应用中需要注意,ud_rvs有效的时候,只要uifdma_dbuf中读控制部分的FIFO准备好,就会从DDR读数据写入到uifdma_dbuf的读控制部分的fifo,这样就存在一个问题,必须确保读出该地址空间的内存数据都是有效的。
所以在本方案中设计的测试环境是写入数据流速度,和读出数据流速度是一致的,并且读操作会晚于写操作一段时间,这样可以确保读的内存地址空间里面的数据都是有效的。
2系统框图
d2b034337a8b4834bccada9aaa306c47.jpg
3基于图形化逻辑设计部分
基于图形化的编程思想主要是把所有的开发都进行标准化的IP化,通过可视化的绘制IP之间的连线即可完成逻辑部分的设计工作。基于这套思想,我们可以把所有一切可以标准化的代码制作为IP,这样以后需要使用的时候只需要通过调用图形化的IP即可完成编程设计。实现FPGA所见即所得的可视化编程。
以下代码中,我们把数据的输入,输出接口引出到顶层模块,由用户自由控制。
b60a54cb5b924b1081fb8be154ad377b.jpg
1:uifdma_dbuf设置
通过把uifdma_dbuf配置为非视频模式,可以无需vs进行帧同步,即可进行数据的传输。当uifdma_dbuf配置为非视频模式的时候,vs信号高电平时候,可以进行fdma数据搬运传输。如下图所示,写通道和读通道,我们都设置了3个缓存地址,每个缓存的大小为1024*1024*32bit=4MB。ud写数据端接口数据位宽为32,ud读数据接口数据位宽为32。
缓存1的起始地址为:0x01000000+2^24*0
缓存2的起始地址为:0x01000000+2^24*1
缓存3的起始地址为:0x01000000+2^24*2
fca35bd58bb444b4a3344a0f08456225.jpg
2:uifdma设置
我们这里演示的demo输入输出的数据时钟为100M,数据速度为100M*32bit,而MIG出来的时钟远高于100M并且这里配置AXI4总线位宽是128bit所以总线带宽非常充裕,我们可以设置每次burst的长度为合理值,无需太大,我们这里设置64
169bff30fcbe475daffc259a159df580.jpg
3:编写测试代码
本方案中,演示从DDR中连续写入数据,之后连续读出,并且写入的速度和读出的速度一致。
  1. `timescale 1ns / 1ps

  2. module fdma_ddr_test(
  3. output [14:0]DDR3_0_addr,
  4. output [2 :0]DDR3_0_ba,
  5. output DDR3_0_cas_n,
  6. output [0 :0]DDR3_0_ck_n,
  7. output [0 :0]DDR3_0_ck_p,
  8. output [0 :0]DDR3_0_cke,
  9. output [0 :0]DDR3_0_cs_n,
  10. output [7 :0]DDR3_0_dm,
  11. inout  [63:0]DDR3_0_dq,
  12. inout  [7 :0]DDR3_0_dqs_n,
  13. inout  [7 :0]DDR3_0_dqs_p,
  14. output [0 :0]DDR3_0_odt,
  15. output DDR3_0_ras_n,
  16. output DDR3_0_reset_n,
  17. output DDR3_0_we_n,
  18. input sysclk_p,
  19. input sysclk_n
  20. );
  21. wire resetn,init_calib_complete_0;
  22. wire wr_rd_clk;
  23. wire ud_rempty_0,error;
  24. reg ud_wvs_0, ud_wde_0 ,ud_rvs_0 ;
  25. wire [31:0]ud_wdata_0 , ud_rdata_0;
  26. reg [15:0]wr_cnt , rd_cnt, delay_cnt;
  27. wire sysclk;
  28. IBUFGDS CLK_U(
  29. .I(sysclk_p),
  30. .IB(sysclk_n),
  31. .O(sysclk)
  32. );

  33. assign ud_rde_0 = !ud_rempty_0;
  34. assign ud_wdata_0 = {16'd0,wr_cnt};

  35. assign resetn = init_calib_complete_0;

  36. always @(posedge wr_rd_clk)begin
  37.     if(resetn == 1'b0)begin
  38.         delay_cnt <= 0;
  39.         ud_rvs_0 <= 1'b0;
  40.     end
  41.     else if(delay_cnt[13:12] == 2'b11) begin //read start delay write 32768 data
  42.         delay_cnt <= delay_cnt;
  43.         ud_rvs_0 <= 1'b1;
  44.     end
  45.     else begin
  46.         delay_cnt <= delay_cnt + 1'b1;
  47.     end
  48. end

  49. always @(posedge wr_rd_clk)begin
  50.     if(delay_cnt[13] == 1'b0)begin
  51.         ud_wvs_0 <= 1'b0;
  52.         ud_wde_0 <= 1'b0;
  53.     end
  54.     else begin
  55.         ud_wvs_0 <= 1'b1;
  56.         ud_wde_0 <= 1'b1;
  57.     end
  58. end

  59. always @(posedge wr_rd_clk)begin
  60.     if(resetn == 1'b0)begin
  61.         wr_cnt <= 0;
  62.     end
  63.     else begin
  64.         if(ud_wde_0)
  65.             wr_cnt <= wr_cnt + 1'b1;
  66.     end
  67. end

  68. always @(posedge wr_rd_clk)begin
  69.     if(resetn == 1'b0)begin
  70.         rd_cnt <= 0;
  71.     end
  72.     else begin
  73.         if(ud_rde_0)
  74.             rd_cnt <= rd_cnt + 1'b1;
  75.         else
  76.             rd_cnt <= rd_cnt;
  77.     end
  78. end

  79. assign error = ud_rde_0&&(rd_cnt != ud_rdata_0[15:0]);

  80. ila_0 ila_wdg (
  81.     .clk(wr_rd_clk), // input wire clk
  82.     .probe0({ud_rde_0,rd_cnt[15:0],ud_rdata_0[15:0],ud_wde_0,ud_wdata_0[15:0],ud_rempty_0, error})// input wire [17:0]  probe0  
  83. );

  84.   system system_i
  85.        (.DDR3_0_addr(DDR3_0_addr),
  86.         .DDR3_0_ba(DDR3_0_ba),
  87.         .DDR3_0_cas_n(DDR3_0_cas_n),
  88.         .DDR3_0_ck_n(DDR3_0_ck_n),
  89.         .DDR3_0_ck_p(DDR3_0_ck_p),
  90.         .DDR3_0_cke(DDR3_0_cke),
  91.         .DDR3_0_cs_n(DDR3_0_cs_n),
  92.         .DDR3_0_dm(DDR3_0_dm),
  93.         .DDR3_0_dq(DDR3_0_dq),
  94.         .DDR3_0_dqs_n(DDR3_0_dqs_n),
  95.         .DDR3_0_dqs_p(DDR3_0_dqs_p),
  96.         .DDR3_0_odt(DDR3_0_odt),
  97.         .DDR3_0_ras_n(DDR3_0_ras_n),
  98.         .DDR3_0_reset_n(DDR3_0_reset_n),
  99.         .DDR3_0_we_n(DDR3_0_we_n),

  100.         .ud_rdata_0(ud_rdata_0),
  101.         .ud_rde_0(ud_rde_0),
  102.         .ud_rempty_0(ud_rempty_0),
  103.         .ud_rvs_0(ud_rvs_0),

  104.         .ud_wdata_0(ud_wdata_0),
  105.         .ud_wde_0(ud_wde_0),
  106.         .ud_wvs_0(ud_wvs_0),

  107.         .init_calib_complete_0(init_calib_complete_0),
  108.         .wr_rd_clk(wr_rd_clk),
  109.         .sysclk(sysclk)
  110.                 );
  111. endmodule
复制代码

4实验结果
1:RTL仿真结果
仿真需要的时间比较长,大概在180us处可以看到读出的数据部分,我们可以看到,error一直为0,代表没有错误。
5725b5d802e44592ac3e50627bfac9ca.jpg
观察FDMA部分的数据传输
d0b34a09a276466d8c1cd950d23ceda5.jpg
观察读出的数据是否正确
4ef2ca4cdf3847c28e64dc5e5d51b934.jpg
2:上板验证
编译下载,后通过在线逻辑分析仪观察结果
d8de94a38bdc4deeb7a2f193871da3fe.jpg




您需要登录后才可以回帖 登录 | 立即注册

本版积分规则