You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用流操作符实现字节数组到BFM内存的低位对齐转换

AXI-S BFM内存字节对齐问题解决思路

我有一个字节数组,需要将数据流式传输到AXI-S接口的BFM(总线功能模型)中。该BFM的内存位宽N由总线参数配置决定。尝试用流操作符将字节数组复制到BFM内存时,若BFM内存因位宽差异比字节数组大,数据无法对齐到BFM内存的最低有效字节(LSByte)。

问题示例

基础代码示例

logic [7:0]  byte_array[59:0];   // 60字节数据
logic [31:0] bfm_memory[1:0];    // 64字节数据

执行流操作bfm_memory = {<<8{byte_array}};后,仅能传入60字节数据,但字节数组的第0字节并未落在bfm_memory的第0字节,偏移了4字节。

详细数据示例

字节数组为数据包最大尺寸(可能大于实际有效数据),以下仅列出非零有效数据;因总线位宽限制,bfm_memory为12字节(而非10字节):

原始字节数组:

byte_array[9] = 8'h00;
byte_array[8] = 8'h00;
byte_array[7] = 8'h88;
byte_array[6] = 8'h77;
byte_array[5] = 8'h66;
byte_array[4] = 8'h55;
byte_array[3] = 8'h44;
byte_array[2] = 8'h33;
byte_array[1] = 8'h22;
byte_array[0] = 8'h11;

当前流操作结果:

bfm_memory[2] = 32'h00008877;
bfm_memory[1] = 32'h66554433;
bfm_memory[0] = 32'h22110000;

期望结果:

bfm_memory[2] = 32'h00000000;
bfm_memory[1] = 32'h88776655;
bfm_memory[0] = 32'h44332211;

问题根源

SystemVerilog的流操作符{<<8{...}}会先将数组元素按索引从高到低拼接成大位串,再对整个串按字节反转。当目标数组总比特数大于源数组时,流操作会将源数据填充到高位区域,低位补零,导致数据无法对齐到目标内存的LSByte。

解决方法

方法1:流操作结合数组反转

要让源字节数组的LSByte对齐到目标BFM内存的LSByte,需通过三次反转操作实现:

  1. 反转字节数组的索引顺序,把原数组的MSByte端(高索引)移到新数组的低索引位置;
  2. 对反转后的字节数组执行流操作,填充到BFM内存;
  3. 反转BFM内存的元素顺序,让有效数据从高位区域回到低位区域,高位补零。

代码实现:

// 分步实现
logic [7:0] reversed_byte_array[$];
reversed_byte_array = {>>{byte_array}}; // 反转字节数组索引
bfm_memory = {<<8{reversed_byte_array}}; // 流操作填充
bfm_memory = {>>{bfm_memory}}; // 反转BFM内存元素顺序

// 合并为一行简洁写法
bfm_memory = {>>{ {<<8{ {>>{byte_array}} }} }};

验证逻辑:
用测试数据验证:

  1. 反转byte_array后,顺序变为[8'h00, 8'h00, 8'h88, 8'h77, 8'h66, 8'h55, 8'h44, 8'h33, 8'h22, 8'h11];
  2. 流操作将其拼接为8'h00_00_88_77_66_55_44_33_22_11,按字节反转后得到8'h11_22_33_44_55_66_77_88_00_00;
  3. 按32位分割后得到初始BFM内存:bfm_memory[2] = 32'h11223344; bfm_memory[1] = 32'h55667788; bfm_memory[0] = 32'h00000000;
  4. 反转BFM内存元素顺序后,得到期望结果。

方法2:手动字节映射(更直观)

若对流操作逻辑存疑,可直接手动遍历字节数组,将每个字节映射到BFM内存的对应LSByte位置:

// 先初始化BFM内存为全零
bfm_memory = '{default: '0};

// 逐个字节映射到BFM内存的LSByte端
for (int i=0; i<$size(byte_array); i++) begin
    int word_idx = i / (32/8); // 32为bfm_memory每个元素的位宽,可替换为参数N
    int byte_idx = i % (32/8);
    bfm_memory[word_idx][byte_idx*8 +:8] = byte_array[i];
end

这种方法逻辑清晰,适合对内存布局有明确控制需求的场景。

内容的提问来源于stack exchange,提问作者eliljey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 17:13:15