使用流操作符实现字节数组到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,需通过三次反转操作实现:
- 反转字节数组的索引顺序,把原数组的MSByte端(高索引)移到新数组的低索引位置;
- 对反转后的字节数组执行流操作,填充到BFM内存;
- 反转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}} }} }};
验证逻辑:
用测试数据验证:
- 反转byte_array后,顺序变为
[8'h00, 8'h00, 8'h88, 8'h77, 8'h66, 8'h55, 8'h44, 8'h33, 8'h22, 8'h11]; - 流操作将其拼接为
8'h00_00_88_77_66_55_44_33_22_11,按字节反转后得到8'h11_22_33_44_55_66_77_88_00_00; - 按32位分割后得到初始BFM内存:
bfm_memory[2] = 32'h11223344; bfm_memory[1] = 32'h55667788; bfm_memory[0] = 32'h00000000; - 反转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
相关产品推荐
相关产品推荐

