DMA学习笔记

目录

1.1 DMA的基本原理

1.1.1 DMA 的概念

1.1.2 DMA 的特性

1.1.3 DMA的作用举例

1.1.4 DMA的基本配置流程

1.1.5 DMA的工作流程

1.2 DMA的系统构成

DMA的系统构成

1.3 DMA的传输方式

1.3.1 存储器到存储器

1.3.2 存储器到外设

1.3.3 外设到存储器

1.3.4 外设到外设

1.4 DMA的工作模式

1.4.1 正常传输模式

1.4.2 循环传输模式

1.4.3 双缓冲模式

1.5 DMA的流控制

1.5.1 DMA的流控制

1.5.2 DMA 的流控制方式

①软件流控制

②外设流控制

③DMA 流控制

2 DMA设计——DMA设计规格详解

2.1 DMA的设计规格介绍

2.2 DMA的寄存器功能

2.3 DMA的总体结构

总结:dmac顶层模块的端口

2.4 DMA的总线接口

总结

2.5 DMA的寄存器模块

总结

2.6 DMA的仲裁器

总结

2.7 DMA的channel控制器

总结

3 DMA的RTL部分

3.1 dmac 顶层模块

代码实现

3.2 dmac_ahb_ctrl 模块

代码实现

3.3 dmac_intf 模块

代码实现

3.4 dmac_arb 模块

代码实现

3.5 dmac_channel 模块

代码实现

3.6 dmac_fifo 模块

代码实现

3.7 dmac_channel_ctrl 模块

代码实现


1.1 DMA的基本原理

1.1.1 DMA 的概念

DMA(direct memory access,直接内存访问),是一种避开CPU,可以直接对外设和内存进行访问的技术,可以实现外设与内存、内存之间、外设之间的数据的访问和搬移。

1.1.2 DMA 的特性

①作为外设:DMA是CPU的slave,类似于一般的性的外设,DMA配置好之后,不需要CPU的干预就能直接服务外设,让CPU可以去处理别的事物,提高系统的性能。

②作为控制器: DMA在对内存的操作上是独立于CPU的,是外设和内存的master,DMA具有一般CPU没有的高效操作,能提高系统的吞吐率。

1.1.3 DMA的作用举例

①两块内存的数据拷贝,将SDRAM的数据读入到SRAM,或者SRAM的数据写入到FLASH;

②外设数据的定时自动采集,每完成一次ADC的数据采集,就将ADC采集结果存储到指定的SRAM空间;

③外设数据的定时自动发送,将SRAM存储的数据依次写入到USART进行发送;

1.1.4 DMA的基本配置流程

①配置通道请求源;

②配置传输方式(存储器到存储器或者其他);

③配置源、目的地址、传输数量;

④配置工作模式;

⑤每组通道之间的工作方式都是独立的。

1.1.5 DMA的工作流程

①从外设数据寄存器或者内存中取出数据;

②将取出的数据进行存储;

③传输数量寄存器的自减,直到为0,传输完成;

1.2 DMA的系统构成

这是一个基于cortexM3的soc的系统架构。

DMA是和CPU平级;

DMA可以通过ahb2apb桥直接连接外设;

DMA的系统构成

①理论上DMA和CPU一样,访问趋于可以做到全地址覆盖;

②实际的soc系统中,可能同时存在多个DMA,根据应用需求,DMA访问的地址空间会不同;

③同一个DMA会有多个master接口,master功能不同,所映射的地址范围不同;

④有的master接口还会绕开总线矩阵的仲裁,而直接连接到外设的ahb2apb桥,加快对外设的访问速度;

1.3 DMA的传输方式

1.3.1 存储器到存储器

特定存储区内容拷贝到另一个存储区空间,比如:两块地址空间的数据拷贝,或者不同类型存储器之间的数据搬移,SDRAM数据搬移到SRAM;

配置完成后,数据流会马上由源地址存储到FIFO中,达到FIFO的门限之后,再向目的地址传递;

1.3.2 存储器到外设

特定存储区内容转移至外设的数据寄存器中,比如:内容中存储的表格数据,连续发送到外设,将SIN表格值输出到DAC;

配置完成后,数据流会马上由源地址存储到FIFO中,达到FIFO的门限之后,如果由外设的请求,数据会一次一次的像外设寄存器传递;

1.3.3 外设到存储器

外设数据寄存器内容转移到特定存储区,比如:连续的usart数据接收;

一旦由外设的DMA请求,DMA就从外设取数据放到FIFO,达到FIFO门限,则从FIFO连续往memory发送数据;

1.3.4 外设到外设

外设数据寄存器之间的转移,比如:ADC采样的值通过USART发送出去;

一旦由外设的DMA请求,DMA就从源地址外设取数据,发送到目的地址外设的数据寄存器;

1.4 DMA的工作模式

1.4.1 正常传输模式

通道配置好后,DMA只按照配置传输一次,当传输完成后,DMA通道被自动关闭,需要重新配置DMA通道才能继续新的传输;

1.4.2 循环传输模式

当传输完成一次之后,会按照上一次的配置,重新接着传送,除非关闭DMA通道,射处理连续的数据流;

1.4.3 双缓冲模式

设置有两片存储区,当第一片存储器传输完成后,自动切换到第二片继续传输,并不停切换;

双缓冲一般应用于:外设到存储器或者存储器到外设的传输。在信号的编解码数据、视频、音频的连续输出方面非常高效;

1.5 DMA的流控制

1.5.1 DMA的流控制

控制DMA批量数据(数据流)的传输。

1.5.2 DMA 的流控制方式

①软件流控制

通过软件配置,来结束传输;

②外设流控制

在传输之前无法确定传输数目,DMA不知道数据的传输数量时,从而无法自己结束传输。需要外设产生特定的传输结束信号,比如SDIO。一般的外设不具备流控制能力。

③DMA 流控制

固定数量的传输,DMA知道传输的数量,那么DMA可以控制传输的完成。比如memory到memory的传输,只能用DMA做流控制。

2 DMA设计——DMA设计规格详解

2.1 DMA的设计规格介绍

①1个32位ahb slave interface;

②1个32位ahb master interface;

③4个独立可配置的通道,固定优先级仲裁;

④支持外设与存储器之间的传输(外设到存储器、存储器到外设);

⑤可编程的数据传输数目:最大为1024;

*ahb interface只支持基本的单次传输;

2.2 DMA的寄存器功能

12个寄存器,分为四组,一个通道一组寄存器;

名称 偏移地址 位宽
ch_0_ctrl 0X00 [0] :ch_0_en, 通道0使能;[4]:che_0_target,0为memory到外设,1为外设到memory;[17~8]:ch_0_size,传输大小,单位为4B
ch_0_sour 0X04 31~0:通道0源地址
ch_0_dest 0X08 31~0:通道0目的地址
ch_1_ctrl 0X0C [0] :ch_0_en, 通道0使能;[4]:che_0_target,0为memory到外设,1为外设到memory;[17~8]:ch_0_size,传输大小,单位为4B
ch_1_sour 0X10 31~0:通道0源地址
ch_1_dest 0X14 31~0:通道0目的地址
ch_2_ctrl 0X18 [0] :ch_0_en, 通道0使能;[4]:che_0_target,0为memory到外设,1为外设到memory;[17~8]:ch_0_size,传输大小,单位为4B
ch_2_sour 0X1C 31~0:通道0源地址
ch_2_dest 0X20 31~0:通道0目的地址
ch_3_ctrl 0X24 [0] :ch_0_en, 通道0使能;[4]:che_0_target,0为memory到外设,1为外设到memory;[17~8]:ch_0_size,传输大小,单位为4B
ch_3_sour 0X28 31~0:通道0源地址
ch_3_dest 0X2C 31~0:通道0目的地址

2.3 DMA的总体结构

总共分为五个模块,其中channel模块包含四路同步FIFO。

总结:dmac顶层模块的端口

①ahb_slave :作为CPU外设,供CPU配置DMA;

②ahb_master :读写存储器和外设;

③req[3:0] :外设输入的dma_req 信号;

④ack[3:0] :输出给外设的dma_ack信号;

2.4 DMA的总线接口

ahb_master接口(amba 2.0)

名称 输入/输出 位宽(bit) 描述
HSEL Output 1
HADDR Output 32
HSIZE Output 3
HTRANS Output 2
HWRITE Output 1 1:写;0:读;
HWDATA Output 32
HREADY Output 1
HRDATA Input 32
HREADYOUT Input 1
HRESP Input 2

内部的读写时序类似于一个SRAM。

名称 输入/输出 位宽(bit) 描述
clk Input 1 时钟
rst Input 1 复位
wr Input 1 写信号
rd Input 1 读信号
addr Input 32 内部地址
wdata Input 32 写数据
rdata Output 32 读数据
rd_en Output 1 读使能
总结

将内部产生的读、写信号,地址,数据,转换成AHB的时序接口

①总线接口时一个AHB的master接口;

②channel_ctrl 发出读、写操作,由ahb_ctrl转换为AHB的时序;

③wr为高,表示需要向AHB的addr写数据;

④rd为高,表示需要向AHB的addr读数据;

简要示意图如下:

2.5 DMA的寄存器模块

AHB_SLAVE接口

名称 输入/输出 位宽(bit) 描述
HCLK
HRESETn
HSEL_SLV Input
HADDR_SLV Input
HSIZE_SLV Input
HTRANS_SLV Input
HWRITE_SLV Input
HWDATA_SLV Input
HREADY_SLV Input
HRDATA_SLV Output
HREADYOUT_SLV Output
HRESP_SLV Output

在CPU内部进行dma进行配置之后,对寄存器需要进行输出;

名称 输入/输出 位宽(bit) 描述
ch_0_en/1/2/3 Output 1 通道使能
ch_0_target/1/2/3 Output 1 传输方向【M2P,P2M】
ch__0_size/1/2/3 Output 10 传输大小
ch_0_sour Output 32 源地址
ch_0_dest Output 32 目的地址
总结

将内部产生的读写信号,地址,数据,转换成AHB的时序接口

①寄存器模块时接在AHB的slave模块,挂接在AHB总线上

②接收来自AHB的配置,并解析出4个通道的配置信息,宫其他模块使用

2.6 DMA的仲裁器

名称 输入/输出 位宽(bit) 描述
clk Input 1 时钟
rst Input 1 复位
req_0 Input 1 外设0的请求信号
req_1 Input 1 外设1的请求信号
req_2 Input 1 外设2的请求信号
req_3 Input 1 外设3的请求信号
ack_0 Output 1 外设0的应答信号
ack_1 Output 1 外设1的应答信号
ack_2 Output 1 外设2的应答信号
ack_3 Output 1 外设3的应答信号
ch_0/1/2/3en Input 1 来自配置寄存器,1表示通道打开
target_0/1/2/3 Input 1 来自配置寄存器,0:数据从memory到外设;1:数据从外设到memory;
en_0 Output 1 1:通道0正在工作,其他通道等待;
en_1 Output 1 1:通道1正在工作,其他通道等待;
en_2 Output 1 1:通道2正在工作,其他通道等待;
en_3 Output 1 1:通道3正在工作,其他通道等待;
req_done Input 1 表示当前req被处理完
ch_0/1/2/3_t0_done Input 1 表示t0方向传输结束
fifo_0_empty Input 1 FIFO0空标志
fifo_1_empty Input 1 FIFO1空标志
fifo_2_empty Input 1 FIFO2空标志
fifo_3_empty Input 1 FIFO3空标志
fifo_0_full Input 1 FIFO0满标志
fifo_1_full Input 1 FIFO1满标志
fifo_2_full Input 1 FIFO2满标志
fifo_3_full Input 1 FIFO3满标志
总结

仲裁器根据输入的req信号,仲裁出当前优先级最高的通道并进行操作

①采用固定优先级算法对4个通道进行仲裁(req0>req1>req2>req3);

②多个通道req同时来到时,会先处理优先级高的,再处理优先级低的;

③通道req处理完成后会回ack握手信号;

2.7 DMA的channel控制器

通道控制器包含3个模块

①dmac_fifo,同步fifo,用于数据的存储;

②dmac_channel ,例化4个通道的fifo;

③dmac_channel_ctrl,对通道进行传输控制;

总结

通道控制器需要根据仲裁结果,对通道进行管理

①接收arbiter仲裁后的使能信号

②发起对FIFO的操作

③发起对ahb_ctrl模块的读写;

3 DMA的RTL部分

3.1 dmac 顶层模块

声明了输入输出端口;

例化了内部的所有模块;

整个顶层除了例化模块,没有多余的逻辑;

编写顶层代码,除了例化模块外,尽量减少其他的逻辑;

代码实现
`timescale 1ns / 1ns
/*--------------------------------------------------------------------------------
--  Module      :  dmac_top
--  Description :  
------------------------------------------------------------------------------*/
  module dmac_top(
  /*-------------------------- Interface definitation ------------------------*/
  input                        HCLK,
  input                        HRESETn,
  //AHB SLAVE PORTS
  input                        HSEL_SLV,
  input                        HREADYIN_SLV,
  input [1:0]                  HTRANS_SLV,
  input [2:0]                  HSIZE_SLV,
  input                        HWRITE_SLV,
  input [31:0]                 HADDR_SLV,
  input [31:0]                 HWDATA_SLV,
  output                       HREADYOUT_SLV,
  output                       HRESP_SLV,
  output [31:0]                HRDATA_SLV,
  //AHB MASTER PORTS
  output                       HSEL,
  output                       HREADY,
  output [1:0]                 HTRANS,
  output [2:0]                 HSIZE,
  output                       HWRITE,
  output [31:0]                HADDR,
  output [31:0]                HWDATA,
  input                        HREADY_IN,
  input                        HRESP,
  input [31:0]                 HRDATA,
  //handshake signal
  input                        req_0,
  input                        req_1,
  input                        req_2,
  input                        req_3,
  output                       ack_0,
  output                       ack_1,
  output                       ack_2,
  output                       ack_3
  /*-----------------------------------------------------------*/
  );
  
  /*------------- Parameter and Internal Signal ---------------*/
  /*------------- Internal Interface definitation -------------*/
  //
  wire                         ch_0_en;
  wire                         ch_1_en;
  wire                         ch_2_en;
  wire                         ch_3_en;
  //
  wire                         ch_0_target;
  wire                         ch_1_target;
  wire                         ch_2_target;
  wire                         ch_3_target;
  //
  wire [9:0]                   ch_0_size;
  wire [9:0]                   ch_1_size;
  wire [9:0]                   ch_2_size;
  wire [9:0]                   ch_3_size;
  //
  wire [31:0]                  ch_0_sour;
  wire [31:0]                  ch_1_sour;
  wire [31:0]                  ch_2_sour;
  wire [31:0]                  ch_3_sour;
  //
  wire [31:0]                  ch_0_dest;
  wire [31:0]                  ch_1_dest;
  wire [31:0]                  ch_2_dest;
  wire [31:0]                  ch_3_dest;
  //
  wire                         en_0;
  wire                         en_1;
  wire                         en_2;
  wire                         en_3;
  //
  wire                         ch_0_t0_done;
  wire                         ch_1_t0_done;
  wire                         ch_2_t0_done;
  wire                         ch_3_t0_done;
  //
  wire                         wr;
  wire                         rd;
  wire [31:0]                  addr;
  wire [31:0]                  wdata;
  wire [31:0]                  rdata;
  wire                         rd_en;
  
  wire [31:0]                  wr_fifo_data_0;
  wire [31:0]                  wr_fifo_data_1;
  wire [31:0]                  wr_fifo_data_2;
  wire [31:0]                  wr_fifo_data_3;
  
  wire [31:0]                  rd_fifo_data_0;
  wire [31:0]                  rd_fifo_data_1;
  wire [31:0]                  rd_fifo_data_2;
  wire [31:0]                  rd_fifo_data_3;
  
  wire                         wr_fifo_0;
  wire                         wr_fifo_1;
  wire                         wr_fifo_2;
  wire                         wr_fifo_3;
  
  wire                         rd_fifo_0;
  wire                         rd_fifo_1;
  wire                         rd_fifo_2;
  wire                         rd_fifo_3;
  
  wire                         fifo_0_full;
  wire                         fifo_1_full;
  wire                         fifo_2_full;
  wire                         fifo_3_full;
  
  wire                         fifo_0_empty;
  wire                         fifo_1_empty;
  wire                         fifo_2_empty;
  wire                         fifo_3_empty;
  
  wire                         req_done;
  /*------------------------Main Code--------------------------*/
  dmac_intf Inst_dmac_intf(.HCLK(HCLK),
                          
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

炎龙铠甲会合体

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

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

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

打赏作者

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

抵扣说明:

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

余额充值