SystemVerilog中利用AXI-Stream的tkeep信号实现tdata字节掩码的优雅方法咨询
SystemVerilog中利用AXI-Stream的tkeep信号实现tdata字节掩码的优雅方法咨询
嗨,我来帮你搞定这个问题!你现在的困扰是AXI-Stream里的tkeep标记的是有效字节,不是无效字节,所以直接拿tdata和tkeep按位与肯定达不到预期——毕竟tkeep的每一位对应一个字节的有效性,可不是对应tdata的单个比特位。
给你两种优雅的实现方式,都是testbench里能用的,不用考虑综合问题:
方法1:位复制生成全宽掩码
先把窄位宽的tkeep扩展成和tdata同宽的掩码,让tkeep的每一位对应tdata里对应字节的8个全1或全0,再和tdata按位与就行。比如你给的32位tdata+4位tkeep的例子:
logic[31:0] tdata = 32'hC1FF; // 修正位宽,原写法4'hC1FF为16位值,适配32位tdata更合理 logic[3:0] tkeep = 4'b0001; logic[31:0] masked_tdata; // 把tkeep的每一位复制8次,生成32位掩码 logic[31:0] tkeep_mask; assign tkeep_mask = { {8{tkeep[3]}}, {8{tkeep[2]}}, {8{tkeep[1]}}, {8{tkeep[0]}} }; assign masked_tdata = tdata & tkeep_mask;
当tkeep是4'b0001时,tkeep_mask会变成32'b00000000_00000000_00000000_11111111,和tdata与之后就能保留最后一个字节的所有有效位,把其他无效字节清零。
方法2:foreach循环实现通用掩码
如果你的tdata位宽可能变化(比如有时候32位,有时候64位),用foreach循环会更通用,可读性也更好:
logic[31:0] tdata = 32'hC1FF; logic[3:0] tkeep = 4'b0001; logic[31:0] masked_tdata; always_comb begin masked_tdata = '0; // 先把结果清零 foreach(tkeep[i]) begin if(tkeep[i]) begin // 把tdata中对应i的字节赋值给结果 masked_tdata[i*8 +: 8] = tdata[i*8 +: 8]; end end end
这种方式不用硬编码位宽,只要tkeep的位宽是tdata位宽除以8,就能自动适配,非常灵活。
这两种方法都能优雅地实现你要的字节掩码效果,完全满足testbench的需求~
备注:内容来源于stack exchange,提问作者Guilty
相关产品推荐
相关产品推荐

