基于AHB的四通道DMA控制器设计-sim_ahb_task.v

sim_ahb_task.v = 仿真用AHB主机任务库
作用:在Testbench里模拟CPU,通过AHB总线对DMA进行单次写、单次读、空闲操作。
它不是RTL,是仿真测试代码(Verilog Task)。

// ==============================
// 功能:仿真AHB主机任务
// 用于Testbench中模拟CPU,配置/读取DMA寄存器
// 包含:单次写、单次读、空闲
// ==============================

// ==============================
// Task 1:AHB 单次写操作(CPU → DMA 写寄存器)
// 输入:地址AHB_HADDR、数据AHB_HWDATA
// ==============================
task AHB_SIGNLE_WR;
input [31:0] AHB_HADDR; // 要写的地址
input [31:0] AHB_HWDATA; // 要写的数据

begin
// 1. 地址周期:发送地址+控制信号
repeat(1) @ (posedge hclk) // 等待1个时钟沿
begin
cpu_s_hsel <= 1’b1; // 选中从机(DMA)
cpu_s_htrans <= 2’b10; // 非序列传输(NONSEQ)
cpu_s_haddr <= AHB_HADDR; // 发地址
cpu_s_hburst <= 0; // 单次传输
cpu_s_hwrite <= 1; // 写操作
cpu_s_hsize <= 3’b010; // 32位传输
cpu_s_hprot <= 4’b1111; // 权限标记
end
$display ($time,”<WRITE START>”); // 打印:写开始

// 2. 数据周期:等待从机就绪,发送写数据
repeat (1) @ (posedge hclk)
begin
wait (hreadyout_from_dmaslv == 1’b1); // 等待DMA返回就绪

cpu_s_hwdata <= AHB_HWDATA; // 发送数据
cpu_s_hsel <= 1’b0 ; // 取消选中
cpu_s_htrans <= 2’b00 ; // 回到IDLE
cpu_s_haddr <= 32’h0 ; // 地址清零
cpu_s_hburst <= 3’b000 ;
cpu_s_hwrite <= 1’b0 ;
cpu_s_hsize <= 3’b010 ;
cpu_s_hprot <= 4’b1111;
cpu_s_hbusreq <= 1’b0 ;
end

// 3. 数据清零
repeat (1) @ (posedge hclk)
cpu_s_hwdata <= 32’h0;

$display($time,” <write done >”); // 打印:写完成
end
endtask

// ==============================
// Task 2:AHB 空闲状态(总线空闲)
// ==============================
task AHB_IDLE ;
begin
cpu_s_hlock <= 1’b0 ;
cpu_s_htrans <= 2’b00 ; // IDLE 无传输
cpu_s_haddr <= 32’h0000;
cpu_s_hburst <= 3’b000 ;
cpu_s_hwrite <= 1’b0 ;
cpu_s_hbusreq <= 1’b0 ;
cpu_s_hsize <= 3’b010 ; // 32位
cpu_s_hprot <= 4’b1111 ;
cpu_s_hwdata <= 32’h0000 ;
end
endtask

// ==============================
// Task 3:AHB 单次读操作(CPU ← DMA 读寄存器)
// 输入:地址AHB_HADDR
// 输出:读到的数据AHB_HRDATA
// ==============================
task AHB_SIGNLE_RD ;
input [31:0] AHB_HADDR ; // 读地址
output [31:0] AHB_HRDATA ; // 读出的数据

begin
// 1. 地址周期:发地址+读控制
repeat (1) @ (posedge hclk);
begin
cpu_s_hsel <= 1’b1 ; // 选中DMA
cpu_s_htrans <= 2’b10 ; // NONSEQ
cpu_s_haddr <= AHB_HADDR ; // 地址
cpu_s_hburst <= 3’b000 ; // 单次
cpu_s_hwrite <= 1’b0 ; // 读操作
cpu_s_hsize <= 3’b010 ; // 32位
cpu_s_hprot <= 4’b1111 ;
end

// 2. 等待传输
repeat (1) @ (posedge hclk);
$display(” < read start >”);

// 3. 数据周期:等待就绪,读取数据
repeat (1) @ (posedge hclk);
begin
wait (hreadyout_from_dmaslv == 1’b1); // 等DMA就绪

AHB_HRDATA = hrdata ; // 把总线上的数据读出来

// 总线回到空闲
cpu_s_hsel <= 1’b0 ;
cpu_s_htrans <= 2’b00 ;
cpu_s_haddr <= 32’h0000 ;
cpu_s_hburst <= 3’b000 ;
cpu_s_hwrite <= 1’b0 ;
cpu_s_hsize <= 3’b010 ;
cpu_s_hprot <= 4’b1111 ;
cpu_s_hwdata <= 32’h0000 ;
cpu_s_hbusreq <= 1’b0 ;

$display($time, “< read done >”);
// 注:原代码写错成write done,应为read done
end
end
endtask

七、和你整套DMA的关系
1. sim_ahb_task(假CPU)
2. → 通过AHB写 dmac_intf(配置接口)
3. → dmac_arb 仲裁
4. → dmac_ahb_ctrl 发总线传输
5. → 完成DMA搬运
它是你仿真验证DMA的必备工具!

留言

您的邮箱地址不会被公开。 必填项已用 * 标注