`timescale 1ns/1ps module tb_array_rd(); // 时钟和复位信号 reg clk; reg rst_n; // 输入信号(DUT 的输入) reg array_rd_frame_valid; reg [151:0] array_rd_frame_data; reg array_rdata_vld; reg [127:0] array_rdata; reg [7:0] array_inner_tras; reg [7:0] array_inner_trp; reg [7:0] array_inner_trcd_rd; reg [7:0] array_inner_trtp; // 输出信号(DUT 的输出) wire array_rd_frame_ready; wire array_rd_done; wire array_rd_csn; wire [15:0] array_rd_raddr; wire array_caddr_vld_rd; wire [5:0] array_caddr_rd; wire array2axi_rdata_valid; wire [127:0] array2axi_rdata; // 实例化被测试模块(DUT) array_rd u_array_rd( .clk (clk), .rst_n (rst_n), .array_rd_frame_valid(array_rd_frame_valid), .array_rd_frame_data(array_rd_frame_data), .array_rd_frame_ready(array_rd_frame_ready), .array_rd_done (array_rd_done), .array_rd_csn (array_rd_csn), .array_rd_raddr (array_rd_raddr), .array_caddr_vld_rd (array_caddr_vld_rd), .array_caddr_rd (array_caddr_rd), .array_rdata_vld (array_rdata_vld), .array_rdata (array_rdata), .array_inner_tras (array_inner_tras), .array_inner_trp (array_inner_trp), .array_inner_trcd_rd(array_inner_trcd_rd), .array_inner_trtp (array_inner_trtp), .array2axi_rdata_valid(array2axi_rdata_valid), .array2axi_rdata (array2axi_rdata) ); // 生成时钟(50MHz,周期 20ns) initial begin clk = 1'b0; forever #10 clk = ~clk; end // 主测试流程 initial begin // 初始化信号 rst_n = 1'b0; array_rd_frame_valid = 1'b0; array_rd_frame_data = 152'd0; array_rdata_vld = 1'b0; array_rdata = 128'd0; array_inner_tras = 8'd3; // 示例值:TRAS = 3 个时钟周期 array_inner_trp = 8'd2; // 示例值:TRP = 2 个时钟周期 array_inner_trcd_rd = 8'd2; // 示例值:TRCD_RD = 2 个时钟周期 array_inner_trtp = 8'd1; // 示例值:TRTP = 1 个时钟周期 // 复位释放(10 个时钟周期后) #200; rst_n = 1'b1; #20; // 测试场景 1:单帧数据读取(含 SOF 和 EOF) $display("=== 测试场景 1:单帧数据读取 ==="); send_frame( 1'b1, // 起始标志 1'b1, // 结束标志(单帧) 16'h1234,// 读取地址 6'h05, // 列地址 128'h0 // 读取操作的帧数据中数据段无效,填0 ); #20; drive_rdata(128'hA5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5); // 返回读取数据 wait(array_rd_done); // 等待读取完成 #100; // 测试场景 2:多帧数据读取(首帧 SOF,末帧 EOF) $display("=== 测试场景 2:多帧数据读取 ==="); // 第一帧(SOF=1,EOF=0) send_frame( 1'b1, 1'b0, 16'h5678, 6'h0A, 128'h0 // 数据段无效 ); // 模拟返回第一帧数据 drive_rdata(128'h55AA55AA55AA55AA55AA55AA55AA55AA); #10; // 第二帧(SOF=0,EOF=1) send_frame( 1'b0, 1'b1, 16'h5678, // 地址与前一帧相同(连续读取) 6'h0B, 128'h0 // 数据段无效 ); drive_rdata(128'hAA55AA55AA55AA55AA55AA55AA55AA55); wait(array_rd_done); // 等待读取完成 #100; // 测试场景 3:无输入时的空闲状态 $display("=== 测试场景 3:空闲状态验证 ==="); array_rd_frame_valid = 1'b0; #200; // 测试结束 $display("=== 所有测试场景完成 ==="); $finish; end // 任务:发送一帧读取请求 task send_frame; input rsof; // 帧起始标志 input reof; // 帧结束标志 input [15:0] rraddr; // 读取地址 input [5:0] rcaddr; // 列地址 input [127:0] wdata; // 占位(读取操作中无效) begin // 等待模块就绪(ready 信号为高) wait(array_rd_frame_ready); #10; // 延迟一小段时间 // 驱动输入信号 array_rd_frame_valid = 1'b1; array_rd_frame_data = {rsof, reof, rraddr, rcaddr, wdata}; // 拼接帧数据 #20; // 保持一个时钟周期 // 撤销有效信号 array_rd_frame_valid = 1'b0; array_rd_frame_data = 152'd0; end endtask // 任务:驱动读取数据返回 task drive_rdata; input [127:0] data; // 要返回的读取数据 begin array_rdata_vld = 1'b1; array_rdata = data; #20; // 保持一个时钟周期 array_rdata_vld = 1'b0; array_rdata = 128'd0; end endtask initial begin $fsdbDumpfile("tb.fsdb"); $fsdbDumpvars(0,tb_array_rd,"+all"); $vcdpluson; $vcdplusmemon; end // 监控关键信号变化(用于调试) initial begin $monitor( "Time: %0t, State: %h, CSN: %b, Ready: %b, Done: %b, CaddrVld: %b, FIFOValid: %b", $time, u_array_rd.cur_state, array_rd_csn, array_rd_frame_ready, array_rd_done, array_caddr_vld_rd, array2axi_rdata_valid ); end endmodule