Palladium 事务级实战 · 03 实现硬件侧 transactor

将接口调用转换为有界握手,用状态机执行 FIFO 操作并处理注册读延迟。

先修知识完成 Palladium FIFO 六章基础课程,理解同步 FIFO、非阻塞赋值与 VALID/READY。

适用环境本地 Python 3 + Icarus Verilog;目标参考 WXE 24.05 ISR5 / Xcelium 配套环境。

验证状态13 项本地 RTL 场景、6 项测量校验测试通过;Cadence 编译、Palladium 映射与设备性能尚未实测。

本文目录两层 transactor 各司其职状态机如何处理 full、empty 与读延迟时钟模型不等于硬件频率故障练习:丢失响应的有界退出

两层 transactor 各司其职

fifo_link 的 exchange 将固定参数转换为请求握手,并等待完整响应;batch_engine 执行 FIFO 引脚级操作。前者是面向官方 interface task 路径的参考,后者是普通可综合 RTL。官方 tb_export 用于导出硬件侧阻塞 task;本地 Icarus 不启用该映射,仅通过层次 task 调用验证逻辑行为。映射是否接受 task 中的循环与等待,仍必须由目标版本编译确认。

一个请求占有 engine,直到响应握手结束。exchange参数 → reqIDLE锁存命令ACTIVEpush / pop / captureRESPONSE保持直到 ready先明确完成条件,再跨越软硬件边界
一个请求占有 engine,直到响应握手结束。(原创示意,非器件引脚图;窄屏可横向滑动)

状态机如何处理 full、empty 与读延迟

pushed 和 popped 只在实际接受写入、读出时增加。rd_en 以固定周期暂停,让小深度 FIFO 真正遇到反压;popped 统计读请求,captured 统计已经采集的返回字节,两者不能混用。pending_read 延迟一拍读取 dout,恰好对应原 FIFO 的非阻塞注册输出。最后一次 capture 后才进入 RESPONSE,避免过早完成。

  1. 对照 course_fifo.sv 的输出更新方式

    预期与判定:dout 在接受读操作的时钟沿更新

  2. 检查 pending_read / captured

    预期与判定:下一拍才消费注册输出

  3. 运行 response-backpressure 场景

    预期与判定:延后接收仍保持响应稳定

  4. 启用 COURSE_BUG 故障

    预期与判定:逐字节 scoreboard 检出 TBA_DATA

实验包中的实际源码;本地 Icarus 已验证。商业工具脚本为待目标环境验证的参考。

systemverilog
// Original synthesizable transaction engine. One command in flight, max 32 bytes.
module batch_engine(input wire clk,rst,
 input wire req_valid,output wire req_ready,input wire [15:0] req_id,
 input wire [5:0] req_len,input wire [255:0] req_data,
 output wire rsp_valid,input wire rsp_ready,output reg [15:0] rsp_id,
 output reg [5:0] rsp_len,output reg [1:0] rsp_status,
 output reg [255:0] rsp_data,output reg [31:0] rsp_cycles);
 localparam IDLE=0,ACTIVE=1,RESPONSE=2;
 reg [1:0] state=IDLE;
 reg [255:0] data;
 reg [5:0] length,pushed,popped,captured;
 reg pending_read;
 wire full,empty;wire [7:0] dout;wire [2:0] count;
 wire wr_en=state==ACTIVE && pushed<length;
 // A fixed, repeatable drain pause exercises FIFO full/backpressure.
 wire rd_en=state==ACTIVE && popped<length && rsp_cycles[2:0]>=3;
 wire [7:0] din=data[8*pushed+:8];
 course_fifo dut_i(clk,rst,wr_en,rd_en,din,dout,full,empty,count);
 assign req_ready=state==IDLE && !rst;
`ifdef DROP_RESPONSE
 assign rsp_valid=1'b0;
`else
 assign rsp_valid=state==RESPONSE && !rst;
`endif
 always @(posedge clk) begin
  if(rst)begin
   state<=IDLE;data<=0;length<=0;pushed<=0;popped<=0;captured<=0;
   pending_read<=0;rsp_id<=0;rsp_len<=0;rsp_status<=0;rsp_data<=0;rsp_cycles<=0;
  end else case(state)
   IDLE:if(req_valid)begin
    data<=req_data;length<=req_len;pushed<=0;popped<=0;captured<=0;pending_read<=0;
`ifdef BAD_TAG
    rsp_id<=req_id^16'h1;
`else
    rsp_id<=req_id;
`endif
    rsp_len<=req_len;rsp_data<=0;rsp_cycles<=0;
    if(req_len==0 || req_len>32)begin rsp_status<=2;state<=RESPONSE;end
    else begin rsp_status<=0;state<=ACTIVE;end
   end
   ACTIVE:begin
    rsp_cycles<=rsp_cycles+1;
    if(wr_en&&!full)pushed<=pushed+1'b1;
    pending_read<=rd_en&&!empty;
    if(rd_en&&!empty)popped<=popped+1'b1;
    // FIFO dout updates on the read edge; consume it on the following edge.
    if(pending_read)begin
     rsp_data[8*captured+:8]<=dout;captured<=captured+1'b1;
     if(captured+1==length)state<=RESPONSE;
    end
   end
   RESPONSE:if(rsp_ready)state<=IDLE;
   default:state<=IDLE;
  endcase
 end
endmodule

时钟模型不等于硬件频率

clk_gen 在语言级仿真里用延时产生时钟,而硬件执行依赖官方流程中的时钟转换选项。把模块移入硬件层次时必须同步修改 +iscDelay 的模块选择,不能仅凭本地波形的 10 ns 周期宣称设备运行在 100 MHz。参考脚本与原始模块一并保留,实际环境应检查时钟转换报告、运行进度和复位退出后的第一次请求。

工程契约与验收证据
项目规定 / 观察结果
时钟没有推进先检查模块层次、转换选项和设备运行状态
req_valid 等待检查 rst、IDLE 和 req_ready
popped 增加但 captured 不对核对 registered dout 与 pending_read
响应消失检查 RESPONSE 是否保持到 ready,而非一拍脉冲

实验包中的实际源码;本地 Icarus 已验证。商业工具脚本为待目标环境验证的参考。

systemverilog
`timescale 1ns/1ps
// Palladium reference flow maps this generator using +iscDelay+clk_gen.
// Do not treat a free-running #delay as ordinary synthesizable RTL.
module clk_gen(output reg clk=0);
 always #5 clk=~clk;
endmodule

故障练习:丢失响应的有界退出

交换函数对请求接受和响应完成分别限制最多 2048 个时钟沿,缺失响应返回 status=3。这是教学工程的周期级保护,不是设备失联时的墙钟 watchdog;若硬件时钟不再推进,循环本身也不会推进。生产运行还应在调度器或站点脚本中设置外部时间限制,并保存首个异常与设备状态后结束作业。

完成检查

  • 读请求数与已收集字节数分开。
  • 响应在反压期间保持稳定。
  • 周期超时与墙钟超时没有混淆。

延伸阅读与来源

本文为黄河电子原创教学说明。产品命令与支持范围请以实际安装版本的官方文档为准。

继续阅读

硬件仿真

首次使用前的工程检查清单

准备版本、输入和模型,减少第一次编译的无效往返。

10 分钟
硬件仿真

如何选择 SA/ICE 及交互方式

根据测试环境所在位置与目标接口要求选择运行流程。

11 分钟
硬件仿真

完成最小设计的编译运行

把第一次平台运行拆为有检查点的五个阶段。

10 分钟