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

VHDL generate语句内记录类型数组赋值异常(信号恒为U)

VHDL generate语句中记录数组使用异常排查

问题现象

  • 相关代码在Vivado 2021.1中可正常通过综合、实现全流程,但仿真时关联的记录信号始终保持"U"未定义态,无法被正确赋值
  • 公开可查资料中几乎没有generate语句端口映射直接使用记录字段的参考示例

初始实现代码

记录类型与数组信号定义

type record_a_t is record
    a : std_logic;
    b : std_logic_vector(7 downto 0);
    c : std_logic_vector(3 downto 0);
    d : std_logic;
    e : std_logic;
end record record_a_t;
type record_a_array_t is array (0 to 3) of record_a_t;

signal record_a_array  : record_a_array_t;

generate循环例化映射

GEN_MODULES : for i in 0 to 3 generate
    modules : entity work.module
    port map(    
        clk     => clk,
        rst_n   => rst_n,
        a       => record_a_array(i).a,
        b       => record_a_array(i).b,
        c       => record_a_array(i).c,
        d       => record_a_array(i).d,
        e       => record_a_array(i).e
    );
end generate GEN_MODULES;

上述代码可通过Vivado全流程语法检查与构建,但在RivPro 2018仿真、实际实现验证时信号均无法正常赋值跳变:即使模块内部对输出端口做了复位初始化,对应连接的record_a_array(i).c等信号始终为"U"态,模块输出端口自身也显示为未定义,仿佛内部初始化逻辑被忽略,仅测试台直接驱动的a信号可正常工作。

问题复现用例

被测模块代码

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity module is
    port(    
        clk     : in std_logic;
        rst_n   : in std_logic;
        a       : in std_logic;
        b       : out std_logic_vector(7 downto 0);
        c       : out std_logic_vector(3 downto 0);
        d       : out std_logic;
        e       : out std_logic
    );
end module;
    
architecture rtl of module is
begin

process(clk, rst_n)
begin
    if(rst_n = '0') then
        b <= (others=> '0');
        c <= (others=> '0');
        d <= '0';
        e <= '0';
    elsif(rising_edge(clk)) then        
        if(a = '1') then
            b <= b + '1';
            c <= c + '1';
            d <= not d;
            e <= not e;
        end if;        
    end if;
end process;

end rtl;

测试台代码

library ieee;
use ieee.std_logic_1164.all;

entity testbench is
end entity testbench;    
---------------------------------------------------    
architecture arch of testbench is    
---------------------------------------------------  

type record_a_t is record
a : std_logic;
b : std_logic_vector(7 downto 0);
c : std_logic_vector(3 downto 0);
d : std_logic;
e : std_logic;
end record record_a_t;

type record_a_array_t is array (0 to 3) of record_a_t;

signal record_a_array  : record_a_array_t;
signal clk : std_logic := '1';
signal rst_n : std_logic := '0';    
---------------------------------------------------
begin

clk  <= not clk  after 5 ns;
rst_n  <= '1' after 20 ns;

GEN_MODULES : for i in 0 to 3 generate
    modules : entity work.module
    port map(    
        clk     => clk,
        rst_n   => rst_n,
        a       => record_a_array(i).a,
        b       => record_a_array(i).b,
        c       => record_a_array(i).c,
        d       => record_a_array(i).d,
        e       => record_a_array(i).e
    );
end generate GEN_MODULES;

process(clk, rst_n)
begin    
    if(rst_n = '0') then
        for i in 0 to 3 loop
            record_a_array(i).a <= '0';
        end loop;
    elsif(rising_edge(clk)) then
        for i in 0 to 3 loop
            record_a_array(i).a <= not record_a_array(i).a;
        end loop;
    end if;    
end process;

end arch;

仿真异常表现

  • 测试台层级连接至模块输出的记录字段信号始终为未定义态
  • 循环生成的模块实例输出端无有效驱动,复位阶段置零逻辑未生效
  • 仅测试台进程直接驱动的record_a_array(i).a信号可正常翻转

根因与正确实现方式

问题根因

VHDL是强类型校验语言,该问题和generate语句语法无关,核心诱因是自定义记录类型的定义位置错误:
示例代码中record_a_t、record_a_array_t类型是在测试台的architecture作用域内局部定义的,若后续其他模块也在自身作用域内定义了结构完全相同的同名类型,仿真器会将二者判定为完全独立的两个类型,端口映射时出现隐式连接断开;部分综合工具会做结构优化跳过严格类型校验,因此会出现"综合能过、仿真全U"的反常现象。

正确操作步骤

  1. 新建独立的VHDL包文件,统一存放所有全局自定义的记录、数组类型定义,禁止在各个模块、测试台的局部作用域重复定义同名同结构的自定义类型。
    示例包代码:
library ieee;
use ieee.std_logic_1164.all;

package common_types_pkg is
    type record_a_t is record
        a : std_logic;
        b : std_logic_vector(7 downto 0);
        c : std_logic_vector(3 downto 0);
        d : std_logic;
        e : std_logic;
    end record record_a_t;
    type record_a_array_t is array (0 to 3) of record_a_t;
end package common_types_pkg;
  1. 所有需要使用该类型的模块、测试台,均在代码头部的库声明区域通过use语句引用全局包,删除原有局部定义的同名类型:
library ieee;
use ieee.std_logic_1164.all;
-- 引用全局定义的类型包
use work.common_types_pkg.all;
  1. 若需要进一步简化代码,可将被例化模块的端口直接定义为记录类型,generate例化时直接映射整个记录元素即可,无需逐字段拆分映射,可大幅降低端口接错的概率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 17:39:18