基于 PYNQ 的 AXI 总线主从控制编写(ddr3的读写)

菜鸟一枚,最近也学习了关于 AXI 总线的相关知识。基于 PYNQ 编写了一个简单的 AXI 主从控制(牵涉到 DDR3 的读写)。

设计目的

设计出以下一个通过 AXI 总线连接的简单片上系统。包含以下部分:

PL 端逻辑

PL 端实现四个模块包括:

  • 寄存器堆
    寄存器堆主要是对指令等控制信息进行片上存储。具体的指令将由 PS 端写入。对于寄存器堆来说,其相当于 slave,而 PS 端的 jupyter 服务器相当于 master。使用的总线是 AXI Lite 总线棕色的大箭头)。

  • 控制端
    控制端主要做的是将寄存器堆送来的指令进行译码,进而从寄存器堆中取得各种配置信息,产生控制信号(主要是对 DRAM 的访存操作,相当于是 SDRAM 控制器)。

寄存器堆与控制端要进行连线。

  • 内存读处理(read)
    该模块主要负责处理对DRAM的读请求与接收到数据的处理。主要负责实现 AXI FULL 总线的相关逻辑。内部有一个读请求的 FIFO 队列。

  • 内存写处理(write)
    该模块主要负责处理对DRAM的写请求与写数据的处理。主要负责实现 AXI FULL 总线的相关逻辑。内部有一个写数据请求的FIFO队列。

控制端与读写请求处理模块(DRAM)是 master 与 slave 的关系。即控制端通过产生相应的访存请求信号,进而令读写请求模块进行访存的相应操作。简而言之,读写请求模块其实就是 AXI 总线的访存接口,其内部实现了 AXI 总线相应的握手机制,我们可以通过这两个模块在片上进行 ddr 的读写控制。故读写请求模块要挂在 AXI 总线上(绿色大箭头)。

下图中红色的框即为上面所说的 PL 端逻辑模块的系统框图。我们可以用 HDL 把模块实现好之后封装成 IP 核,写好输入输出端口,就可以挂在 AXI_Interconect 和 AXI register slice IP 核上并且连接到 ZYNQ 硬核上。进而编写 PS 端程序。
在这里插入图片描述
可能有人要问,为什么绿色的箭头有5条,而棕色有2条?其实这就是 AXI 总线的内部机制,下图记录了 AXI 读写的时序图。可以很清楚地看到读数据时,只需要两个通道即可,而写数据则需要三条通道,所以说对于访存请求处理的两个模块共需要5条导线。而寄存器堆其实也是需要3条线,只是图中省去了,因为在 pynq 里我们可以很方便的对寄存器地址进行判断(4的倍数)。
在这里插入图片描述

PS 端程序设计

接下来是软件方面的设计。我们知道,为了发挥 zynq 系列的优势,我们将通讯密集型的应用放在 CPU 上——即指令相关的控制信息的写入或预先对 ddr 数据的写入。

由于本篇博文是基于 pynq 的,故不牵涉到 sdk 编程(其实两者原理相同)。

  • 对 DDR 的读写
    由于我们使用的是 pynq,其中已经封装好了我们需要用到的相应 API,只需调用即可!在这一步里我们主要调用以下 API:
from pynq import Xlnk
xlnk.cma_array(shape=(),dtype=np.float16)

该函数返回一个 numpy 数组,相当于在 DRAM 里申请了一段大小为 shape 的空间,然后可以自由地对这一段空间进行读写操作。

  • 对寄存器堆的写入
    我们在 jupyter 服务器下可以很方便的对寄存器堆进行读写!只需提前定义好相应的寄存器地址即可。在这一步里我们主要调用以下 API:
from pynq import MMIO
ctrl = MMIO(0x40000000, 0x1000)# 开辟一块区域可供用户读写,主要是对寄存器(slave)的读写
ctrl.write(reg_addr, data) # 写寄存器
ctrl.read(reg_addr) # 读寄存器

我们封装一个 FPGA 类,将上面的操作完整写下来:

from pynq import Xlnk
from pynq import MMIO

# 寄存器地址
RESET_REG           = 0
PHY_ADDR_REG        = 4
START_REG           = 8
DONE_REG            = 12

class FPGA(object):
    initdone = False
    memalloc = False
    xlnk = None
    ctrl = None
    mem = None
    im_wh_q = None
    bb_list = list()
    cmdidx = 0
    
    def __init__(self, xlnk):
        self.xlnk = xlnk
        self.ctrl = MMIO(0x40000000, 0x1000) # 开辟一块区域可供用户读写,主要是对寄存器(slave)的读写
        self.im_wh_q = deque()
        try:
            self.mem = xlnk.cma_array(shape=(0x800000,4), dtype=np.float16) #分配buff内存区域,返回的是numpy数组
            self.memalloc = True           
        except:
            print("CMA array allocation failed (64MB)")
            print("Please call xlnk.xlnk_reset() or Restart notebook")
            xlnk.xlnk_reset()   
        
    def configure(self, weight_file, padding_file):
        if (self.memalloc == False):
            return False
        
        self.ctrl.write(PHY_ADDR_REG, self.mem.physical_address)  # 将内存偏移(起始地址)写入寄存器中
        self.ctrl.write(RESET_REG, 1)
        self.ctrl.write(RESET_REG, 0)
        rd = self.ctrl.read(PHY_ADDR_REG) # 读寄存器,看是否成功写入信息
        if (rd != self.mem.physical_address):
            xlnk.xlnk_reset()
            print("Error: Memory mapped IO failed")
            return False
        
        if (os.path.isfile(weight_file)):  # 打开一个本地的文件
            W = np.load(weight_file)
            woff = 0
			# 写权重到DRAM里面去
            for i in range(len(W)):
                self.mem[woff:(woff + W[i].shape[0]),:] = W[i]
                woff += W[i].shape[0]
        else:
            print("Error: Weight file not found")
            self.xlnk.xlnk_reset()
            return False
        # 写padding项到DRAM里面去
        if (os.path.isfile(padding_file)):
            W = np.load(padding_file)
            membase = 7 << 20  # 写pading项的起始地址,这个地址是如何得到的??? 7340032
			# 11100000000000000000000
            self.mem[membase: (membase | W.shape[0]), :] = W
        else:
            print("Error: Padding file not found")
            self.xlnk.xlnk_reset()
            return False
        
        membase = 4 << 20  # 4194304
		# 10000000000000000000000
        self.mem[membase:(membase | 106496), 3] = np.zeros((106496), dtype=np.float16) 

未完待更。。。。

<think>嗯,用户之前问过FIFO,现在又问了APB和AHB。看来他们可能是在学习嵌入式系统或者SoC设计相关的知识,尤其是总线协议。我需要先确认APB和AHB的全称,以及它们在ARM体系中的位置。 首先,APB是Advanced Peripheral Bus,而AHB是Advanced High-performance Bus。这两个都是ARM公司推出的AMBA总线协议的一部分。用户可能对AMBA不太了解,所以需要简要介绍一下AMBA,这样他们能理解这两个总线的关系。 然后,APB通常用于连接低速外设,比如UART、GPIO等,而AHB用于高速组件,比如CPU、内存控制器。需要解释两者的主要区别,比如性能、结构复杂度、应用场景。可能用户想知道为什么会有不同的总线类型,以及它们各自的应用场景。 还要注意用户可能的背景。如果他们是学生或刚入行的工程师,可能需要更基础的解释,避免使用过多术语。但问题直接问APB和AHB,可能他们已经有一定基础,所以需要详细但清晰的说明。 另外,用户之前的FIFO问题涉及数据结构,而这次转向总线协议,可能他们在学习系统设计中的不同组件。需要确保回答的结构清晰,分点说明每个总线的特点、结构、应用,以及它们之间的关系,比如APB通常作为AHB的次级总线。 还要检查是否有常见的混淆点,比如APB和AHB的版本差异,比如AHB有AHB-Lite,APB有APB3、APB4等,但可能不需要深入版本细节,除非用户特别询问。重点放在核心概念上。 可能用户需要知道如何选择使用哪种总线,或者在实际项目中如何应用。因此,在回答中可以加入典型应用示例,帮助理解。 最后,确保语言简洁,符合中文表达习惯,避免直译英文术语。比如用“主设备”和“从设备”而不是“master”和“slave”,但需要确认当前术语是否有更新,比如现在有些文档可能用其他词替代,但ARM官方文档可能仍沿用主从,所以保持一致性。 总结,回答需要涵盖:AMBA简介,APB和AHB各自的定义、特点、结构、应用场景,以及两者的关系和区别。可能还需要对比它们与其他总线AXI的不同,但用户没问,所以点到为止即可。</think>APB(**Advanced Peripheral Bus**)和 AHB(**Advanced High-performance Bus**)是 ARM 公司提出的两种总线协议,属于 **AMBA(Advanced Microcontroller Bus Architecture)** 标准的一部分,主要用于片上系统(SoC)中不同功能模块之间的通信。 --- ### **1. APB(Advanced Peripheral Bus)** - **定位**: APB 是 AMBA 总线家族中的 **低速、低功耗总线**,专为连接 **外设模块**(如 GPIO、UART、定时器等)设计。 - **特点**: - **简单性**:协议简单,信号线少,适合低带宽、低复杂度的外设。 - **低功耗**:通过时钟门控(Clock Gating)技术减少能耗。 - **同步传输**:所有操作与时钟同步,时序易控制。 - **典型结构**:通常作为 AHB/AXI 的次级总线,通过桥接器连接高性能总线。 - **应用场景**: 控制寄存器读写、状态查询等对实时性要求不高的操作。 --- ### **2. AHB(Advanced High-performance Bus)** - **定位**: AHB 是 AMBA 总线家族中的 **高性能总线**,适用于高带宽、低延迟的核心模块(如 CPU、DMA、内存控制器等)。 - **特点**: - **高性能**:支持单周期传输、突发传输(Burst Transfer)和流水线操作。 - **灵活性**:支持多主设备(Master)和仲裁机制,允许多个主设备竞争总线使用权。 - **复杂时序**:需要处理地址/数据相位分离、等待状态(Wait State)等。 - **典型结构**:作为系统主总线,连接处理器、高速内存和外设桥接器。 - **应用场景**: 高速数据传输(如 CPU 与内存交换数据)、DMA 控制器操作等。 --- ### **3. APB 与 AHB 的关系** - **层级结构**: AHB 负责高速核心模块的通信,而 APB 通过 **AHB-to-APB 桥接器** 连接低速外设,形成分层总线架构。 **示例**: `CPU(AHB主设备) → AHB总线 → 内存控制器(AHB从设备)` `AHB-to-APB桥接器 → APB总线 → UART/GPIO(APB从设备)` - **性能对比**: | | **带宽** | **延迟** | **复杂度** | **功耗** | |----------|----------|----------|------------|----------| | **AHB** | 高 | 低 | 高 | 较高 | | **APB** | 低 | 较高 | 低 | 低 | --- ### **4. 扩展:AMBA 总线家族** - **AXI(Advanced eXtensible Interface)**: 新一代高性能总线,支持乱序传输、多路并行操作,适用于多核处理器和复杂 SoC。 - **ASB(Advanced System Bus)**: 旧版总线,已逐渐被 AHB/AXI 替代。 --- ### **典型应用示例** - **APB**:配置传感器寄存器、读取温度传感器的状态值。 - **AHB**:CPU 从 DDR 内存加载程序、DMA 控制器搬运大量数据。 如果需要更深入的细节(如时序图或协议字段),可以进一步探讨!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wangbowj123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值