基于AHB的四通道DMA控制器设计-dmac.v
dmac.v = DMA 控制器顶层例化/连线模块
作用:把你前面看过的所有子模块例化+接线,拼成完整可用的DMA控制器。
它自己不做逻辑,只负责搭架子、连信号线。
`timescale 1ns/10ps
// ==============================
// 模块:DMA 控制器顶层
// 功能:例化所有子模块,完成信号连接,构成完整DMA系统
// ==============================
module dmac(
// AHB 从机接口(CPU 配置 DMA 用)
input HCLK, // 时钟
input HRESETn, // 低电平复位
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 主机接口(DMA 访问内存/外设用)
output HSEL, // 主机选中从设备
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, // 读数据
// 外部通道请求/应答(外部模块触发DMA)
input req_0,
output ack_0,
input req_1,
output ack_1,
input req_2,
output ack_2,
input req_3,
output ack_3
);
// ==============================
// 内部连线(wire):子模块之间的信号线
// ==============================
wire [9:0] ch_0_size, ch_1_size, ch_2_size, ch_3_size;
wire [31:0] ch_0_sour, ch_0_dest;
wire [31:0] ch_1_sour, ch_1_dest;
wire [31:0] ch_2_sour, ch_2_dest;
wire [31:0] ch_3_sour, ch_3_dest;
wire ch_0_en, ch_1_en, ch_2_en, ch_3_en;
wire ch_0_target, ch_1_target, ch_2_target, ch_3_target;
wire wr, rd;
wire [31:0] addr, wdata, rdata;
wire rd_en;
wire req_done;
wire en_0,en_1,en_2,en_3;
wire ch_0_t0_done,ch_1_t0_done,ch_2_t0_done,ch_3_t0_done;
wire fifo_0_empty,fifo_1_empty,fifo_2_empty,fifo_3_empty;
wire fifo_0_full,fifo_1_full,fifo_2_full,fifo_3_full;
wire wr_fifo_0,wr_fifo_1,wr_fifo_2,wr_fifo_3;
wire rd_fifo_0,rd_fifo_1,rd_fifo_2,rd_fifo_3;
wire [31:0] wr_fifo_data_0,wr_fifo_data_1,wr_fifo_data_2,wr_fifo_data_3;
wire [31:0] rd_fifo_data_0,rd_fifo_data_1,rd_fifo_data_2,rd_fifo_data_3;
// ==============================
// 1. 例化:DMA 配置接口(CPU 配置 DMA)
// ==============================
dmac_intf u_dmac_intf(
.HCLK (HCLK),
.HRESETn (HRESETn),
.HSEL (HSEL_SLV),
.HREADY (HREADYIN_SLV),
.HTRANS (HTRANS_SLV),
.HSIZE (HSIZE_SLV),
.HWRITE (HWRITE_SLV),
.HADDR (HADDR_SLV),
.HWDATA (HWDATA_SLV),
.HREADYOUT (HREADYOUT_SLV),
.HRESP (HRESP_SLV),
.HRDATA (HRDATA_SLV),
.ch_0_en (ch_0_en),
.ch_0_target (ch_0_target),
.ch_0_size (ch_0_size),
.ch_1_en (ch_1_en),
.ch_1_target (ch_1_target),
.ch_1_size (ch_1_size),
.ch_2_en (ch_2_en),
.ch_2_target (ch_2_target),
.ch_2_size (ch_2_size),
.ch_3_en (ch_3_en),
.ch_3_target (ch_3_target),
.ch_3_size (ch_3_size),
.ch_0_sour (ch_0_sour),
.ch_0_dest (ch_0_dest),
.ch_1_sour (ch_1_sour),
.ch_1_dest (ch_1_dest),
.ch_2_sour (ch_2_sour),
.ch_2_dest (ch_2_dest),
.ch_3_sour (ch_3_sour),
.ch_3_dest (ch_3_dest)
);
// ==============================
// 2. 例化:AHB 主机控制器(DMA 发总线时序)
// ==============================
dmac_ahb_ctrl u_dmac_ahb_ctrl(
.clk (HCLK),
.rst (HRESETn),
.wr (wr),
.rd (rd),
.addr (addr),
.wdata (wdata),
.rdata (rdata),
.rd_en (rd_en),
.hsel (HSEL),
.htrans (HTRANS),
.hsize (HSIZE),
.hwrite (HWRITE),
.haddr (HADDR),
.hwdata (HWDATA),
.hreadyin (HREADY_IN),
.hresp (HRESP),
.hrdata (HRDATA)
);
// ==============================
// 3. 例化:DMA 通道控制(4通道读写、FIFO、地址生成)
// ==============================
dmac_channel_ctrl u_dmac_channel_ctrl(
.clk (HCLK),
.rst (HRESETn),
.req_0 (req_0),
.req_1 (req_1),
.req_2 (req_2),
.req_3 (req_3),
.wr (wr),
.rd (rd),
.addr (addr),
.wdata (wdata),
.rdata (rdata),
.rd_en (rd_en),
.en_0 (en_0),
.en_1 (en_1),
.en_2 (en_2),
.en_3 (en_3),
.target_0 (ch_0_target),
.target_1 (ch_1_target),
.target_2 (ch_2_target),
.target_3 (ch_3_target),
.ch_0_size (ch_0_size),
.ch_1_size (ch_1_size),
.ch_2_size (ch_2_size),
.ch_3_size (ch_3_size),
.ch_0_sour (ch_0_sour),
.ch_0_dest (ch_0_dest),
.ch_1_sour (ch_1_sour),
.ch_1_dest (ch_1_dest),
.ch_2_sour (ch_2_sour),
.ch_2_dest (ch_2_dest),
.ch_3_sour (ch_3_sour),
.ch_3_dest (ch_3_dest),
.fifo_0_empty (fifo_0_empty),
.fifo_1_empty (fifo_1_empty),
.fifo_2_empty (fifo_2_empty),
.fifo_3_empty (fifo_3_empty),
.fifo_0_full (fifo_0_full),
.fifo_1_full (fifo_1_full),
.fifo_2_full (fifo_2_full),
.fifo_3_full (fifo_3_full),
.wr_fifo_0 (wr_fifo_0),
.wr_fifo_data_0 (wr_fifo_data_0),
.rd_fifo_0 (rd_fifo_0),
.rd_fifo_data_0 (rd_fifo_data_0),
.wr_fifo_1 (wr_fifo_1),
.wr_fifo_data_1 (wr_fifo_data_1),
.rd_fifo_1 (rd_fifo_1),
.rd_fifo_data_1 (rd_fifo_data_1),
.wr_fifo_2 (wr_fifo_2),
.wr_fifo_data_2 (wr_fifo_data_2),
.rd_fifo_2 (rd_fifo_2),
.rd_fifo_data_2 (rd_fifo_data_2),
.wr_fifo_3 (wr_fifo_3),
.wr_fifo_data_3 (wr_fifo_data_3),
.rd_fifo_3 (rd_fifo_3),
.rd_fifo_data_3 (rd_fifo_data_3),
.hready_in (HREADY_IN),
.req_done (req_done),
.ch_0_t0_done (ch_0_t0_done),
.ch_1_t0_done (ch_1_t0_done),
.ch_2_t0_done (ch_2_t0_done),
.ch_3_t0_done (ch_3_t0_done)
);
// ==============================
// 4. 例化:DMA 仲裁器(4通道抢总线)
// ==============================
dmac_arb u_dmac_arb(
.clk (HCLK),
.rst (HRESETn),
.req_0 (req_0),
.req_1 (req_1),
.req_2 (req_2),
.req_3 (req_3),
.ch_0_en (ch_0_en),
.ch_1_en (ch_1_en),
.ch_2_en (ch_2_en),
.ch_3_en (ch_3_en),
.target_0 (ch_0_target),
.target_1 (ch_1_target),
.target_2 (ch_2_target),
.target_3 (ch_3_target),
.en_0 (en_0),
.en_1 (en_1),
.en_2 (en_2),
.en_3 (en_3),
.ack_0 (ack_0),
.ack_1 (ack_1),
.ack_2 (ack_2),
.ack_3 (ack_3),
.req_done (req_done),
.ch_0_t0_done (ch_0_t0_done),
.ch_1_t0_done (ch_1_t0_done),
.ch_2_t0_done (ch_2_t0_done),
.ch_3_t0_done (ch_3_t0_done),
.fifo_0_empty (fifo_0_empty),
.fifo_1_empty (fifo_1_empty),
.fifo_2_empty (fifo_2_empty),
.fifo_3_empty (fifo_3_empty),
.fifo_0_full (fifo_0_full),
.fifo_1_full (fifo_1_full),
.fifo_2_full (fifo_2_full),
.fifo_3_full (fifo_3_full)
);
// ==============================
// 5. 例化:DMA 通道FIFO(4个独立FIFO)
// ==============================
dmac_channel u_dmac_channel(
.clk (HCLK),
.rst (HRESETn),
.clr_0 (1’b0),
.wr_0 (wr_fifo_0),
.rd_0 (rd_fifo_0),
.wdata_0 (wr_fifo_data_0),
.rdata_0 (rd_fifo_data_0),
.full_0 (fifo_0_full),
.empty_0 (fifo_0_empty),
.clr_1 (1’b0),
.wr_1 (wr_fifo_1),
.rd_1 (rd_fifo_1),
.wdata_1 (wr_fifo_data_1),
.rdata_1 (rd_fifo_data_1),
.full_1 (fifo_1_full),
.empty_1 (fifo_1_empty),
.clr_2 (1’b0),
.wr_2 (wr_fifo_2),
.rd_2 (rd_fifo_2),
.wdata_2 (wr_fifo_data_2),
.rdata_2 (rd_fifo_data_2),
.full_2 (fifo_2_full),
.empty_2 (fifo_2_empty),
.clr_3 (1’b0),
.wr_3 (wr_fifo_3),
.rd_3 (rd_fifo_3),
.wdata_3 (wr_fifo_data_3),
.rdata_3 (rd_fifo_data_3),
.full_3 (fifo_3_full),
.empty_3 (fifo_3_empty)
);
endmodule
三、场景化大白话理解(最容易懂)
把 dmac.v 理解成:
DMA 整栋大楼的总设计师 + 包工头
• dmac_intf:前台(CPU 配置窗口)
• dmac_arb:调度室(分配总线)
• dmac_channel_ctrl:4个作业班组
• dmac_channel:班组的临时仓库(FIFO)
• dmac_ahb_ctrl:运输队(AHB 总线)
完整工作流程:
1. CPU 去前台(intf)填单:通道、地址、长度、方向
2. 调度室(arb) 按优先级选一个班组
3. 班组(channel_ctrl) 从仓库(FIFO)取/存数据
4. 运输队(ahb_ctrl) 按 AHB 规矩搬运数据
5. 完成后回传应答信号