zedboard如何从PL端控制DDR读写(五)

本文介绍如何在ZedBoard的PL端通过AXI总线控制DDR内存的读写操作,包括创建AXI Master IP、搭建硬件系统、生成比特流并导入SDK,以及分析写数据停止的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  有了前面的一堆铺垫。现在终于开始正式准备读写DDR了,开发环境:VIVADO2014.2 + SDK。

 

  一、首先要想在PL端通过AXI去控制DDR,我们必须要有一个AXI master,由于是测试,就不自己写了,直接用package IP生成,方法如下:

  1.选择package IP工具

  

  2.创建新的AXI外设

  

  3.接口类型选择Full,模式选择master,如果你不关心里面的详细实现过程,那么直接finish就好了。(后面我们会继续分析里面的过程)

  

  

  二、创建好了IP,自然要加入到IP库里,如图,在IP Catalog空白处右键,设置,把刚刚生成IP的路径放进去:

  

 

  三、接下来创建BD块,把整个硬件系统搭建好:

  

  需要指出的是,由于我们需要用到HP,所以在zynq的配置里面把HP勾选上,任选一个通道就行

  

 

   四、然后校验正确性,产生输出文件,创建BD块顶层,这都是套路,一路走下来就行。如果你想在调试里看到产生的AXI信号,那么需要对AXI标记一下debug

   

 

   五、综合,set up debug,然后生成比特流,并将其导入到SDK;在SDK里跑个hello world 就行,主要目的是用CPU去把DDR控制器初始化。

 

  到这里整个过程基本就结束了,接下来看仿真波形:

  

   放大一点,可以看到每次地址的步进长度是十进制的64,这是因为我们的突发长度设置的是16,位宽为32bit。

   

  但是问题来了,我们在上一节里面说过,有一部分地址是连到了OCM的,那么这一部分地址是多少呢?UG585里给出了如下说明:

  

  我们是从全0地址开始写数据的,然而全0的地址刚好分配到了OCM,这TM就很尴尬了。一开始想让程序运行的时间长一点,这样地址是不是就可以跑到0x0008_0000了?然而并没有什么用,因为地址只跑到00001000就停止了,如图:

  

  还记得前面打包AXI IP时候我们说过要分析其过程吗?其实那里就已经挖了一个坑了,具体见代码:

   

  这是AXI的写数据状态机,(可以看到,官方也是用一段式状态机来实现整个时序的,印证了前面三段式状态机不好实现的说法),从写状态到读状态的跳变是由writes_done信号来控制的,那么这个writes_done又是怎么产生的呢?继续看代码:

  

  writes_done是由write_burst_counter的高位进位来控制的,再继续找write_burst_counter:

  

  在这个计数器里有一个很关键的位C_NO_BURSTS_REQ ,在代码的低179行,它的定义如下:

localparam integer C_NO_BURSTS_REQ = C_MASTER_LENGTH-clogb2((C_M_AXI_BURST_LEN*C_M_AXI_DATA_WIDTH/8)-1);

  

  C_M_AXI_BURST_LEN我们设置的是16,C_M_AXI_DATA_WIDTH是32,clogb2可以理解为计算以2为底的某个数的对数,那么最后得到的C_NO_BURSTS_REQ = 6;也就是说write_burst_counter的位宽是7为,当最高位为1时,写数据停止。也就是只会发生64次写数据,之后计数器和写地址就会归零。那么64次写数据乘以每次突发长度16再乘以位宽4个字节,最后得到的数值是4096,换算成16进制刚好是0x00001000。
  所以要想真正的往DDR里面写数据,我们还需要对代码进行修改。
  到这里离成功就已经不远了

 

posted on 2016-07-20 18:09 christ0127 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/christsong/p/5689283.html

PL实现DDR读写操作需要从硬件设计、接口模块开发到测试验证等多个环节进行系统性设计。以下为实现DDR读写操作的基本方法及流程。 ### 3.1 DDR 控制器配置 在FPGA中实现DDR读写操作的第步是使用Xilinx或Intel(Altera)提供的DDR控制器IP核。例如,在Xilinx平台中可以使用MIG(Memory Interface Generator)工具来生成DDR控制器模块。该模块负责与DDR芯片的物理层进行通信,处理初始化、时序控制、地址映射、数据校验等任务。 - 控制器需配置为特定的DDR标准(如DDR3或DDR4),并设置合适的频率、数据宽度和容量。 - 配置完成后,控制器将提供组用户接口(User Interface),包括读写请求信号、地址、数据输入输出等,便于后续逻辑模块接入[^1]。 ### 3.2 用户逻辑设计 用户逻辑模块负责与DDR控制器交互,实现数据的写入与读取。通常包括以下部分: - **地址生成器**:用于生成写入或读取的起始地址及长度。例如,若需连续写入1024个数据,则地址生成器应从0递增到1023。 - **数据生成器**:在写入操作中,可生成特定模式的数据(如递增序列、固定值等)以便后续验证。 - **控制状态机**:实现读写切换、响应检测、错误处理等功能。例如,在写入完成后触发读取操作,并根据读取结果控制LED状态指示[^2]。 ### 3.3 接口统与模块封装 为了便于复用和集成,建议将DDR控制器与用户逻辑封装为统的接口模块。该模块对外提供以下信号: - `wr_en`:写使能信号 - `rd_en`:读使能信号 - `addr`:地址总线 - `wdata`:写入数据 - `rdata`:读取数据 - `done`:操作完成标志 - `error`:错误标志 通过统接口,可以简化上层逻辑对DDR的访问方式,提高系统的模块化程度。 ### 3.4 板级验证与调试 在实际板卡中进行功能与性能验证是DDR读写实现的关键步骤: - **功能验证**:通过写入预设数据并读回比对,验证数据完整性。例如,写入1024个递增数据后读回,若全部正确则点亮LED1,否则闪烁[^2]。 - **性能测试**:测量读写带宽与延迟,确保满足系统需求。例如,DDR4-3200的理论带宽为25.6 GB/s,应通过实际测试验证是否接近该值[^3]。 - **稳定性测试**:长时间运行读写操作,观察是否出现误码或时序问题,尤其是在高频运行条件下。 ### 3.5 示例代码(Verilog) 以下为个简单的DDR读写控制状态机示例: ```verilog module ddr_rw_ctrl( input clk, input rst_n, output reg wr_en, output reg rd_en, output reg [27:0] addr, input done, output reg [3:0] led ); parameter IDLE = 2'd0, WRITE = 2'd1, READ = 2'd2, CHECK = 2'd3; reg [1:0] state; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin state <= IDLE; wr_en <= 1'b0; rd_en <= 1'b0; addr <= 0; led <= 4'b0000; end else begin case(state) IDLE: begin if(start_write) begin state <= WRITE; wr_en <= 1'b1; addr <= 0; end end WRITE: begin if(addr == 1023) begin wr_en <= 1'b0; state <= READ; rd_en <= 1'b1; addr <= 0; end else begin addr <= addr + 1; end end READ: begin if(addr == 1023) begin rd_en <= 1'b0; state <= CHECK; end else begin addr <= addr + 1; end end CHECK: begin if(data_valid) begin led[0] <= 1'b1; end else begin led[0] <= 1'b0; end state <= IDLE; end endcase end end endmodule ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值