Palladium 事务级实战 · 02 定义批事务、完成和复位协议
固定 256 位载荷、单事务在途、显式状态与事务编号,避免把提交误认为完成。
先修知识完成 Palladium FIFO 六章基础课程,理解同步 FIFO、非阻塞赋值与 VALID/READY。
适用环境本地 Python 3 + Icarus Verilog;目标参考 WXE 24.05 ISR5 / Xcelium 配套环境。
验证状态13 项本地 RTL 场景、6 项测量校验测试通过;Cadence 编译、Palladium 映射与设备性能尚未实测。
先冻结协议,再编写驱动
本例最大一次交换 32 字节,payload 为固定 256 位向量,最低八位装第一个字节,未使用字节补零。len 表示有效字节数而不是向量位数。固定参数便于检查映射边界,但 BATCH=1 依然携带固定宽度参数,因此调用次数降低不等于传输字节按同样比例降低。接口使用静态 task,仅允许一个调用者和一个在途事务。
| 项目 | 规定 / 观察结果 |
|---|---|
| id / len | 16 位编号;6 位长度,正常范围 1…32 |
| data | 256 位;第 i 字节位于 [8*i +: 8] |
| status | 0 成功;2 非法长度;3 接口等待超时 |
| 复位 | 启动或事务之间;不支持在途取消与自动重试 |
用可执行 host 检查协议的每一层
host 先检查 status,再比较返回 id 和长度,最后逐字节验证数据。任何一层失败立即终止本次运行,不能继续将后续结果混入性能样本。N=65、BATCH=16 的最后一批长度为 1,能够检查尾批处理;id 在当前 N 上限下不会回绕。跨运行重试或多个客户端需要 epoch 和更严格的关联规则,当前接口没有声称提供这些能力。
- 运行 python3 test.py
预期与判定:batch1 / 4 / 16 / 32 全部对照通过
- 检查 partial-tail 场景
预期与判定:65 字节、5 次 exchange、121 个 ACTIVE 周期
- 检查 bad-tag 故障
预期与判定:TBA_TAG 被测试脚本识别为预期失败
- 检查 invalid-length 故障
预期与判定:TBA_STATUS status=2,不能记录成功样本
实验包中的实际源码;本地 Icarus 已验证。商业工具脚本为待目标环境验证的参考。
module tb_host;
integer n=64,batch=16,seq=0,j,len,calls=0,cycles=0,fd,meta,unused;
reg [15:0] id=0,returned_id;
reg [5:0] returned_len;
reg [1:0] status;
reg [255:0] request,result;
reg [31:0] active_cycles;
reg [7:0] expected;
initial begin
unused=$value$plusargs("N=%d",n);unused=$value$plusargs("BATCH=%d",batch);
if(n<8||n>100000||batch<1||batch>32)$fatal(1,"TBA_CONFIG");
fd=$fopen("transactions.csv","w");if(!fd)$fatal(1,"TBA_IO");
$fdisplay(fd,"seq,data");
hw_top.link.reset_hw();
while(seq<n)begin
len=(n-seq<batch)?n-seq:batch;request=0;
for(j=0;j<len;j=j+1)request[8*j+:8]=((seq+j)*17+3)%256;
if($test$plusargs("BAD_REQUEST")&&seq==0)len=0;
hw_top.link.exchange(id,len,request,returned_id,returned_len,status,result,active_cycles);
if(status!==2'b00)$fatal(1,"TBA_STATUS status=%0d id=%0d (2=length,3=timeout)",status,id);
if(returned_id!==id)$fatal(1,"TBA_TAG expected=%0d actual=%0d",id,returned_id);
if(returned_len!==len)$fatal(1,"TBA_LENGTH");
for(j=0;j<len;j=j+1)begin
expected=((seq+j)*17+3)%256;
if(result[8*j+:8]!==expected)$fatal(1,"TBA_DATA seq=%0d expected=%0d actual=%0d",seq+j,expected,result[8*j+:8]);
$fdisplay(fd,"%0d,%0d",seq+j,result[8*j+:8]);
end
calls=calls+1;cycles=cycles+active_cycles;id=id+1'b1;seq=seq+len;
if($test$plusargs("RESET_BETWEEN"))hw_top.link.reset_hw();
end
$fclose(fd);meta=$fopen("result.json","w");if(!meta)$fatal(1,"TBA_IO");
$fwrite(meta,"{\"status\":\"PASS\",\"transactions\":%0d,\"batch\":%0d,\"calls\":%0d,\"engine_cycles\":%0d}\n",n,batch,calls,cycles);
$fclose(meta);$display("TBA_PASS transactions=%0d batch=%0d calls=%0d engine_cycles=%0d",n,batch,calls,cycles);$finish;
end
`ifndef PALLADIUM_HOST
// Local-only monitor. Excluded from the hardware migration reference TB.
reg was_stalled=0;reg [279:0] held;
always @(posedge hw_top.clk)begin
if(hw_top.link.rst)was_stalled=0;
else begin
if(was_stalled && (!hw_top.link.rsp_valid || {hw_top.link.rsp_id,hw_top.link.rsp_len,hw_top.link.rsp_status,hw_top.link.rsp_data}!==held))$fatal(1,"TBA_RESPONSE_UNSTABLE");
was_stalled=hw_top.link.rsp_valid&&!hw_top.link.rsp_ready;
held={hw_top.link.rsp_id,hw_top.link.rsp_len,hw_top.link.rsp_status,hw_top.link.rsp_data};
end
end
initial begin #10000000;$fatal(1,"TBA_GLOBAL_TIMEOUT");end
`endif
endmodule
响应必须保持,复位必须有边界
engine 进入 RESPONSE 后保持数据、状态、长度和编号,直到 rsp_valid 与 rsp_ready 同时成立。HOLD=9 场景刻意延后接收,让稳定性检查暴露“响应脉冲只保持一拍”的实现错误。reset_hw 只驱动 rst,避免多个 task 同时驱动握手寄存器;调用者只在初始状态或一个 exchange 完成后复位,超时后的恢复应重新初始化整个运行。
实验包中的实际源码;本地 Icarus 已验证。商业工具脚本为待目标环境验证的参考。
// Fixed packed arguments; single caller only. Reference blocking TBA interface.
interface fifo_link #(parameter HOLD=0)(input wire clk);
reg rst=1,req_valid=0,rsp_ready=0;
reg [15:0] req_id=0;reg [5:0] req_len=0;reg [255:0] req_data=0;
wire req_ready,rsp_valid;wire [15:0] rsp_id;wire [5:0] rsp_len;
wire [1:0] rsp_status;wire [255:0] rsp_data;wire [31:0] rsp_cycles;
`ifdef IXCOM_UXE
initial begin
$ixc_ctrl("tb_export", "reset_hw");
$ixc_ctrl("tb_export", "exchange");
end
`endif
task reset_hw;
begin
@(posedge clk);rst<=1;
repeat(4)@(posedge clk);
rst<=0;
repeat(2)@(posedge clk);
end
endtask
task exchange(input [15:0] id,input [5:0] len,input [255:0] payload,
output [15:0] returned_id,output [5:0] returned_len,
output [1:0] status,output [255:0] result,output [31:0] active_cycles);
integer guard;reg accepted,completed;
begin
accepted=0;completed=0;status=3;result=0;returned_id=0;returned_len=0;active_cycles=0;
@(posedge clk);req_id<=id;req_len<=len;req_data<=payload;req_valid<=1;
for(guard=0;guard<2048&&!accepted;guard=guard+1)begin
@(posedge clk);if(req_ready)accepted=1;
end
req_valid<=0;
if(accepted)begin
for(guard=0;guard<2048&&!completed;guard=guard+1)begin
@(posedge clk);if(rsp_valid)completed=1;
end
if(completed)begin
repeat(HOLD)@(posedge clk);
returned_id=rsp_id;returned_len=rsp_len;status=rsp_status;result=rsp_data;active_cycles=rsp_cycles;
rsp_ready<=1;@(posedge clk);rsp_ready<=0;
end
end
end
endtask
endinterface
故障练习:编号正确不代表结果完整
只返回请求编号并不足以证明一次交换完成。错误实现可能在最后一次 rd_en 接受的当拍就发送响应,而 FIFO 的注册输出尚未进入结果向量;这通常表现为最后一个字节沿用旧值。先以 len=1 和尾批测试定位完成条件,再扩大批大小,不要用重复延时掩盖协议错误。
完成检查
- 长度、字节顺序、状态码和在途数都有明确定义。
- 尾批、响应保持和错误编号均有测试。
- 超时不被自动重试或当作成功。
延伸阅读与来源
本文为黄河电子原创教学说明。产品命令与支持范围请以实际安装版本的官方文档为准。
- Cadence Palladium 官方入口;WXE 24.05 TBA Tutorial
TBA Tutorial 第 36–42 页;compileIXCOM 第 269 页。页码指用户提供的本地安装文档印刷页;公开链接为产品入口,并非受限手册下载。
继续阅读
硬件仿真首次使用前的工程检查清单
准备版本、输入和模型,减少第一次编译的无效往返。
如何选择 SA/ICE 及交互方式
根据测试环境所在位置与目标接口要求选择运行流程。
完成最小设计的编译运行
把第一次平台运行拆为有检查点的五个阶段。
黄河电子