news 2026/5/20 11:01:02

DDR学习之基于AXI4接口的MIG核读写控制逻辑简单实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DDR学习之基于AXI4接口的MIG核读写控制逻辑简单实现

前言

上次我们学习了使用MIG核的native接口实现DDR内存的读写功能,这一次我们使用AXI4接口也做一个简单实现。由于我的开发板还没有到,暂时使用MIG example design进行仿真观察一下。通过这个小实验,我们能够学习AXI4接口协议,MIG IP核生成及配置,以及如何通过AXI4总线去读写DDR芯片。

AXI4总线信号总览

我们这一次,要用到AXI4接口,所以不得不了解一下AXI4的总线协议。AXI4总线协议包括,AXI4-lite、AXI4-Stream和AXI4-full,我们要了解的是AXI4-full。我后面准备单独写一个专题讲解AXI4接口协议,如果你想成为一个FGPA高手,AXI4的学习必不可少。

全局信号


全局信号,主要有时钟和复位信号,其中,复位信号低有效。

写地址通道


写地址通道信号数量有点多,这一次我们不需要都了解,只需要知道其中几个信号即可,包括,AWDDR、AWLEN、AWSIZE、AWBURST、AWVALID和AWREADY。下面详细介绍这6个信号。

AWDDR信号

AWDDR是写地址信号,在AXI4协议中,一个地址对应8位数据,也就是说如果你一次写入一个128位的数据,那么下一个连续写入的地址应该要在现有的地址上加128/8=16。也就是说,一个数据对应16个地址。如果是进行递增的突发传输,那么在一次完整的突发传输的过程中,只需要写入一个首地址即可。等待突发传输完成,再写入下一个地址。这里的地址间隔是由一次突发的传输个数和一个传输的数据Byte数的乘积决定的。

AWLEN信号

AWLEN信号就是前面提到的,一次突发的传输个数。实际的传输个数应该等于AWLEN的设置值加一,最高支持256笔传输。

AWSIZE信号

AWSIZE信号就是我们前面提到的,一次传输的数据字节数。我们这次实验设置是16字节,即128位。详细配置列表,可以查看用户手册《IHI0022E_amba_axi_and_ace_protocol_spec》第A3-47页。

AWBURST信号

AWBURST信号是用来配置突发传输的类型,比如设置2’b01表示递增突发,常用的一种突发方式,也是我们这次实验使用的突发方式。详细配置列表,可以查看用户手册《IHI0022E_amba_axi_and_ace_protocol_spec》第A3-48页。

AWVALID信号和AWREADY信号

AWVALID信号是主设备给从设备的地址有效信号,只有AWVALID信号和AWREADY信号都有效时, AWDDR信号才算是成功从主机传输给从机。

写数据通道


写数据通道的信号也不需要全部了解,只需要知道其中几个信号即可,包括,WDATA、WLAST、WVALID和WREADY。下面详细介绍这4个信号。

WDATA信号

WDATA信号是主机发送给从机的数据信号,其位宽由数据通道中的AWSIZE信号决定。

WLAST信号

WLAST信号在突发的最后一笔传输拉高,表示此次突发传输结束。

WVLAID信号和WREADY信号

WVLAID信号和WREADY信号同时为高时,表示当前这笔传输有效。

写响应通道


写响应通道的信号,我们这里需要了解BRESP、BVALID和BREADY。

BRESP信号

BRESP信号由从机传输给主机的表示此次传输的状态,如返回的值为2‘b00,表示传输成功。

BVALID信号和BREADY信号

BVALID信号和BREADY信号同时有效,表示BRESP信号有效。一般主机BREADY信号设置为长高,随时接受从机发来的响应信号。本次实验,使用写响应信号作为写通道传输完成的标志,接着开始执行读操作。

读地址通道


同写地址通道一样,我们也只需了解对应的信号即可,包括,ARADDR、ARLEN、ARSIZE、ARBURST、ARVALID和ARREADY。这6个信号同写地址通道对应的信号,只是名字不同而已,含义是一样的,不再赘述。

读数据通道


读数据通道的信号除了RREADY,都是由从机发给主机的。这里我们需要了解的信号,包括RDATA、RRESP、RLAST、RVALID和RREADY。

RDATA信号

RDATA信号是从机由指定地址读取,并返回给主机的数据,其位宽由ARSIZE信号配置。

RRESP信号

RRESP信号之所以没有单独放在一个通道,而是和数据放在一起,是因为RRESP的传输方向和RDATA方向是一致的。具体含义同BRESP信号一致。

RLAST信号

RLAST信号是由从机发给主机的表示此次突发读传输的结束信号,需要在传输最后一个有效的RDATA时拉高。

RVALID信号和READY信号

RVALID信号和READY信号同时有效,才表示此次数据读取有效。READY信号有效,通常表示主机的缓冲区未满或接受的数据来得及处理,没有形成阻塞。

关于VALID和READY信号的一点感悟

VALID和READY信号是一对握手信号,可以说是AXI接口的一组关键信号。在实际的代码编写的过程中,往往存在谁先拉高的问题。对于这一点,我有一点小小的看法。那就是,“谁有需求,谁主动。谁主动,谁先拉高”。具体来说,对于写通道来说,如果主机有强烈的写需求,比如FIFO已经快满了,再不取出来就要溢出了。这个时候,主机的VALID信号就先拉高,等待从机握手。如果从机有强烈的需求,如FIFO已经快空了,再不写入,就要没有数据可以用了。这个时候,从机的READY信号就先拉高,等待主机握手。对于读通道来说,亦然。这里举个现实生活中的例子。

餐馆和食客

对于一家餐馆来说,当他迫切的需要赚取利润,再不赚钱就要倒闭情况下,这个时候他就有强烈的需求,他会到店门口招揽顾客(拉高VALID),等待食客进店消费(READY拉高)。对食客来说,他已经几天没吃发了,现在已经饿的不行,迫切需要大吃一顿,就会主动去找餐馆(拉高READY),等待餐馆安排他落座(拉高VALID)。当餐馆和食客刚好都有需求的时候,这笔生意就是好生意。如果有一方没有需求,比如食客已经饥肠辘辘,但是餐馆生意爆满。如果食客想要在这家餐馆就餐,就需要排队等候,等到餐馆有空闲的时候再接待他。对于餐馆来说也是这样,餐馆已经很久没有营业了,在店门口主动拉客,但是顾客都刚吃过,根本不饿。这个时候餐馆就需要等待一段时间,等客人饥饿的时候再来店里就餐。

实验方案

本次实验并不复杂,主要是为了理解如何通过AXI4接口控制MIG核,实现DDR的读写功能。步骤如下:1)生成一个MIG IP核,并进行相关的配置。后面会提供生成MIG IP核的步骤,如果你是老手,可以直接跳过此步骤;2)生成example design,example design是我们学习IP核的一个很好的工具,生成的example design可以直接仿真,方便我们学习接口时序;后面会提供生成example design的步骤,如果你是老手,可以直接跳过此步骤;3)编写AXI4读写代码,然后替换掉example design中对应的代码;4)仿真波形对比写入和读取结果。

步骤一:生成MIG IP核

我相信你们应该都能使用VIVADO创建一个新项目,这里就不再赘述。

点击IP Catalog。

在对话框中,输入MIG,可以看到有显示Memory Interface Generator IP,双击IP核会弹出如下窗口。

点击Next。

勾选AXI4 Interface,然后点击Next。

点击Next。

勾选DDR3 SDRAM,然后点击Next。


配置完成后,点击Next。

默认就行,点击Next。

默认就行,点击Next。

System Clock和Reference Clock配置完成后,其余选项保持默认即可。点击Next。
后面一直点击Next,仿真不需要配配置引脚。直到下面页面。

先勾选Accept,再点击Next。来到下面页面。

点击Generate,至此IP核配置完成,等待生成。

等待右上角综合跑完。跑完后会显示Ready。生成IP核如下。

步骤二:生成example design

鼠标右键点击生成的mig_7_series_0的IP核,会弹出下拉菜单。


点击Open IP Example Design选项,弹出下面窗口。

选择一个新的路径放置新的工程,然后点击OK。

等待新工程生成,也就是example design,工程会自动打开。如下。

到此,生成example design结束。

步骤三:代码编写

全部代码如下。AXI4的配置,突发传输的长度16(一次突发连续传输16个数据),每次传输的尺寸128(读写数据的位宽为128位),突发类型为2‘b01(递增)。代码结构很简单,主要由两个状态机构成,一个写通道状态机,一个读通道状态机。
写通道状态机,默认是处于S0_IDLE状态,DDR初始化完成(init_cmptd拉高)后,跳到写地址状态(S0_WR_WADDR),等待axi_wready信号有效,写入地址,并拉高wvalid,跳到写数据状态(S0_WR_WDATA);在写数据状态,写数据从0加到15,在最后一个数据时,同时拉高wd_valid和wd_last信号。
读通道状态机,默认是处于S1_IDLE状态,检测到从设备的响应信号(axi_wd_bvalid && (axi_wd_bid == 4’d0)),即写入数据成功,开始读数据,跳转到写地址状态(S1_WR_RADDR)。和写地址一样,等待axi_rready信号拉高,然后写入地址raddr和拉高rvalid,跳转到读数据状态S1_RD_RDATA;在读数据状态,一直检测axi_rd_rvalid信号,有效时,将读数据赋值给rd_data,同时获取到rd_rresp,等到axi_rd_last信号拉高,说明此为突发传输的最后一个数据,跳转到S0_FINISH状态。

`timescale 1ps/1ps module axi4_tg ( input aclk, // AXI input clock input aresetn, // Active low AXI reset signal // Input control signals input init_cmptd, // Initialization completed // AXI write address channel signals input axi_wready, // Indicates slave is ready to accept a output [ 3:0] axi_wid, // Write ID output [31:0] axi_waddr, // Write address output [ 7:0] axi_wlen, // Write Burst Length output [ 2:0] axi_wsize, // Write Burst size output [ 1:0] axi_wburst, // Write Burst type output [ 1:0] axi_wlock, // Write lock type output [ 3:0] axi_wcache, // Write Cache type output [ 2:0] axi_wprot, // Write Protection type output axi_wvalid, // Write address valid // AXI write data channel signals input axi_wd_wready, // Write data ready // output [ 3:0] axi_wd_wid, // Write ID tag output [127:0] axi_wd_data, // Write data output [15:0] axi_wd_strb, // Write strobes output axi_wd_last, // Last write transaction output axi_wd_valid, // Write valid // AXI write response channel signals input [ 3:0] axi_wd_bid, // Response ID input [ 1:0] axi_wd_bresp, // Write response input axi_wd_bvalid, // Write reponse valid output axi_wd_bready, // Response ready // AXI read address channel signals input axi_rready, // Read address ready output [ 3:0] axi_rid, // Read ID output [31:0] axi_raddr, // Read address output [ 7:0] axi_rlen, // Read Burst Length output [ 2:0] axi_rsize, // Read Burst size output [ 1:0] axi_rburst, // Read Burst type output [ 1:0] axi_rlock, // Read lock type output [ 3:0] axi_rcache, // Read Cache type output [ 2:0] axi_rprot, // Read Protection type output axi_rvalid, // Read address valid // AXI read data channel signals input [ 3:0] axi_rd_bid, // Response ID input [ 1:0] axi_rd_rresp, // Read response input axi_rd_rvalid, // Read reponse valid input [127:0] axi_rd_data, // Read data input axi_rd_last, // Read last output axi_rd_rready // Read Response ready ); localparam PARAM_AWLEN = 4; localparam PARAM_AWSIZE = 4; localparam PARAM_AWBURST = 4; reg [ 1:0] state0 ; reg [31:0] waddr ; reg [ 7:0] wd_data ; reg wd_valid ; reg [ 7:0] wd_data_next; reg valid ; reg wd_last ; reg wvalid ; assign axi_wid = 0; assign axi_rid = 0; assign axi_wlen = 8'd15; //16 transfers in a burst; assign axi_rlen = 8'd15; //16 transfers in a burst; assign axi_wsize = 3'd4 ; //16 bytes in a transfer; assign axi_rsize = 3'd4 ; assign axi_wburst = 2'd1 ; //16 bytes in a transfer; assign axi_rburst = 2'd1 ; assign axi_wlock = 0; assign axi_rlock = 0; assign axi_wd_strb = 16'hFFFF; assign axi_waddr = waddr; assign axi_wd_bready = 1; assign axi_wvalid = wvalid; assign axi_wd_data = {16{wd_data}}; assign axi_wd_valid = wd_valid; assign axi_wcache = 4'b0; assign axi_rcache = 4'b0; assign axi_wprot = 0; assign axi_rprot = 0; assign axi_wd_last = wd_last; //######################-WRITE CMD START-###################### localparam S0_IDLE = 3'd0; localparam S0_WR_WADDR = 3'd1; localparam S0_WR_WDATA = 3'd2; localparam S0_FINISH = 3'd3; always@(posedge aclk) begin if(!aresetn) begin state0 <= S0_IDLE; waddr <= 0; wd_data<= 0; wd_data_next<= 0; wvalid<= 0; wd_valid<= 0; wd_last<= 0; end else begin case(state0) S0_IDLE: begin if(init_cmptd) begin state0 <= S0_WR_WADDR; end else begin state0 <= S0_IDLE; end end S0_WR_WADDR: begin waddr <= 32'd0; if(axi_wready) begin waddr <= 32'd0; wvalid <= 1; state0 <= S0_WR_WDATA; end else begin state0 <= S0_WR_WADDR; end end S0_WR_WDATA: begin wvalid <= 0; if(wd_data < 8'd15) begin if(axi_wd_wready) begin wd_data_next <= wd_data_next + 8'd1; wd_data <= wd_data_next; wd_valid <= 1; wd_last <= 0; end state0 <= S0_WR_WDATA; end else begin if(axi_wd_wready) begin wd_valid <= 1; wd_last <= 1; state0 <= S0_FINISH; end end end S0_FINISH: begin state0 <= S0_FINISH; waddr <= 0; wd_data<= 0; wd_data_next<= 0; wvalid<= 0; wd_valid<= 0; wd_last<= 0; end endcase end end //######################-WRITE CMD END-###################### //++++ //++++ //######################-READ CMD START-###################### localparam S1_IDLE = 3'd0; localparam S1_WR_RADDR = 3'd1; localparam S1_RD_RDATA = 3'd2; localparam S1_FINISH = 3'd3; reg [ 1:0] state1 ; reg [ 1:0] rd_rresp ; reg [31:0] raddr ; reg [127:0] rd_data ; reg rvalid ; assign axi_raddr = raddr; assign axi_rvalid = rvalid; assign axi_rd_rready = 1'b1; always@(posedge aclk) begin if(!aresetn) begin state1 <= S1_IDLE; raddr <= 0; rd_data<= 0; rvalid<= 0; wd_last<= 0; end else begin case(state1) S1_IDLE: begin if(axi_wd_bvalid && (axi_wd_bid == 4'd0) && init_cmptd) begin state1 <= S1_WR_RADDR; end else begin state1 <= S1_IDLE; end end S1_WR_RADDR: begin raddr <= 32'd0; if(axi_rready) begin raddr <= 32'd0; rvalid <= 1; state1 <= S1_RD_RDATA; end else begin state1 <= S1_WR_RADDR; end end S1_RD_RDATA: begin rvalid <= 0; if(axi_rd_rvalid) begin rd_rresp <= axi_rd_rresp; rd_data <= axi_rd_data; if(axi_rd_last) begin state1 <= S0_FINISH; end end end S0_FINISH: begin state1 <= S0_FINISH; raddr <= 0; rd_data <= 0; rvalid <= 0; wd_last <= 0; end endcase end end //######################-READ CMD END-###################### endmodule

将上面的代码,替换掉红色方框处的代码,即可点击左侧菜单栏的Run Simulation,开始仿真,分析波形,查看写入和读取结果。

步骤四:仿真波形分析

写通道波形分析

写地址

从波形中可以看出,初始化完成信号拉高后,在从机axi_wready信号拉高时,主机写入地址,并拉高valid。

写数据

在从机axi_wd_wready信号有效时,主机写入从0-15,共16笔数据,每一笔数据128位,在最后一笔数据0x0F时,拉高last信号,数据发送完毕。

写响应

写数据完毕后,等待axi_wd_bvalid拉高,获取从机响应信号。

读通道波形分析

写地址

当响应信号的axi_wd_bvalid拉高时,主机开始等待axi_rready拉高,然后写入地址。

读数据



可以看出,写完地址后,需要等待一段时间,主机才能收到数据。从机输出数据,并伴有axi_rd_rvalid信号拉高,可以看出这些数据和我们写入的数据一致,在最后读出最后一个数据时,axi_rd_last信号拉高。至此,实验完成。

总结

通过这个简单的小实验,我们能够学习如何控制MIG IP的AXI4接口写入数据到DDR芯片和从DDR芯片中读取数据。希望大家学习顺利!

参考文献

  1. 《AMBA AXI and ACE ProtocolSpecification》
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 10:59:47

收藏!小白程序员也能抓住的AI红利:AI大模型应用开发入门指南

文章指出AI正成为行业风口&#xff0c;引发大众焦虑&#xff0c;但真正可怕的不是AI本身&#xff0c;而是拒绝学习的“被落下”。AI已渗透各领域&#xff0c;催生新岗位&#xff0c;如AI大模型应用开发&#xff0c;门槛低、薪资高、就业广。普通人通过学习AI工具或入门该岗位&a…

作者头像 李华
网站建设 2026/5/20 10:50:30

方差分析(ANOVA)入门——比较三组或更多组均值的利器

如果你做科研、读论文、写方法部分&#xff0c;迟早会遇到一个非常经典的问题&#xff1a; 当我想比较三组或更多组的均值时&#xff0c;该用什么方法&#xff1f; 如果你第一反应是做很多次 t 检验&#xff0c;那要先停一下。 因为当组数超过两组时&#xff0c;简单地一组一组…

作者头像 李华