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

Vivado混合仿真报错:无法将打包类型分配给非打包类型

Vivado混合仿真中VHDL数组与SystemVerilog打包类型赋值问题

问题场景

使用Vivado 2022.1进行混合语言仿真,涉及以下文件:

不可修改的VHDL包(mytypes.vhd)

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package mytypes is

  type std_logic_vector_array is array(natural range <>) of std_logic_vector;

  type my_record is record
    rxdata      : std_logic_vector_array(3 downto 0)(7 downto 0);
  end record;
end package mytypes;

SystemVerilog测试台(mytest.sv)

import mytypes::*;

class MyPacket;
  rand bit[31:0] _header;
endclass 

module simu(
    output mytypes::my_record recdata
   );

  logic CLK100;
  MyPacket pckt;
  const int increment = 2;
  
  initial
  begin
    CLK100 = 0;
    forever #(5) CLK100 = ~CLK100;
  end

  initial
  begin
    pckt = new();
    pckt.randomize();
    @(posedge CLK100); 
  
    for (int i = 0; i < 4; i+= increment) begin
      recdata.rxdata[0][7:0] = pckt._header[i*8 +: 8];
      @(posedge CLK100);
    end    
  end
endmodule

仿真时触发错误:

[VRFC 10-395] cannot assign a packed type to an unpacked type

存在以下限制条件:

  • 必须使用混合源仿真
  • 无法修改VHDL包,且VHDL无打包/非打包数据类型的概念
  • MyPacket._header作为单一逻辑元素,声明为非打包类型不符合业务逻辑

需要找到无需修改原有数据模型的解决方案,比如让仿真器将VHDL数组解释为打包类型,或通过宏等方式规避赋值错误。


解决方案

1. 逐位赋值规避类型差异

由于Vivado将VHDL的二维数组映射为SystemVerilog的完全非打包数组,直接将打包的bit[7:0]切片赋值给非打包数组会触发错误。可以通过逐位赋值的方式绕过这个限制:

// 修改测试台内的赋值循环
for (int i = 0; i < 4; i+= increment) begin
    bit [7:0] temp_slice = pckt._header[i*8 +: 8];
    // 逐位将打包切片赋值给非打包的VHDL数组元素
    for (int j = 0; j < 8; j++) begin
        recdata.rxdata[i][j] = temp_slice[j];
    end
    @(posedge CLK100);
end

这种方式无需修改原有数据模型,完全适配现有类型映射规则。

2. 用宏封装逐位赋值逻辑

如果需要多次进行此类赋值,可以用宏封装重复代码,提升可读性:

// 在测试台开头定义宏
`define PACKED_TO_UNPACKED(dst_unpacked, src_packed) \
    for (int __idx = 0; __idx < $bits(src_packed); __idx++) begin \
        dst_unpacked[__idx] = src_packed[__idx]; \
    end

// 赋值时直接调用宏
for (int i = 0; i < 4; i+= increment) begin
    bit [7:0] temp_slice = pckt._header[i*8 +: 8];
    `PACKED_TO_UNPACKED(recdata.rxdata[i], temp_slice);
    @(posedge CLK100);
end

宏内部使用双下划线前缀的变量名,避免与用户代码中的变量冲突。

3. 利用$cast进行类型强制转换

可以在SystemVerilog中定义与VHDL数组位宽匹配的打包类型,再通过$cast完成打包到非打包的转换:

// 定义与VHDL rxdata位宽匹配的打包类型
typedef bit [3:0][7:0] packed_rxdata_t;

// 修改赋值逻辑
initial
begin
    pckt = new();
    pckt.randomize();
    @(posedge CLK100); 

    packed_rxdata_t temp_packed = pckt._header;
    // 强制将打包类型转换为VHDL导出的非打包类型
    $cast(recdata.rxdata, temp_packed);
    
    // 若需要分时钟周期输出,可拆分赋值
    for (int i = 0; i < 4; i+= increment) begin
        packed_rxdata_t temp = '0;
        temp[i] = pckt._header[i*8 +: 8];
        $cast(recdata.rxdata, temp);
        @(posedge CLK100);
    end    
end

$cast会在运行时检查位宽兼容性,确保转换安全,且无需修改原有数据结构。


内容的提问来源于stack exchange,提问作者G. B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 19:07:19