VHDL测试平台中创建可变长度字符串数组的方法问询
在VHDL Testbench中创建可变长度字符串列表的可行方案
嘿,这个问题我太有共鸣了!VHDL里处理不同长度的字符串数组确实容易踩坑,你试过的两种方案的痛点我都懂——固定长度数组逼你把所有字符串补成一样长(实在没必要),访问类型又没法直接声明成常量,确实头疼。其实你没遗漏核心逻辑,只是VHDL的类型系统对可变长度字符串的数组支持需要点小技巧,下面给你几个可行的方案:
方案1:使用VHDL-2008的非限定字符串数组(推荐)
如果你的模拟器支持VHDL-2008(现在主流的Modelsim、Vivado都支持),直接定义一个非限定的字符串数组类型,就能轻松容纳不同长度的字符串,完全不用填充:
-- 定义非限定的字符串数组类型 type t_string_list is array(natural range <>) of string; -- 直接声明常量,每个字符串长度可以不一样 constant FILENAMES : t_string_list := ( "file.txt", "anotherfile.txt", "yetanotherfile.txt" );
这个方案简单直接,完全符合你要的“常量+可变长度”需求,代码可读性还高。如果需要和你的iADCCount_C绑定,只需要把数组范围改成0 to iADCCount_C-1就行:
constant FILENAMES : t_string_list(0 to iADCCount_C-1) := ( "file.txt", "anotherfile.txt", "yetanotherfile.txt" );
方案2:用包函数初始化访问类型数组(兼容旧版本)
如果你的环境不支持VHDL-2008,那可以用访问类型+包函数的组合绕开“访问类型不能直接声明常量”的限制。思路是在包里面写一个函数,初始化访问类型数组,然后在Testbench里用这个函数初始化信号或变量:
-- 先定义一个包来封装类型和初始化函数 package file_utils is type tp_string is access string; type t_string_array is array(natural range <>) of tp_string; -- 初始化函数,返回填充好的字符串数组 function get_filenames return t_string_array; end package file_utils; package body file_utils is function get_filenames return t_string_array is variable temp_array : t_string_array(0 to iADCCount_C-1); begin temp_array(0) := new string'("file.txt"); temp_array(1) := new string'("anotherfile.txt"); temp_array(2) := new string'("yetanotherfile.txt"); -- 如果iADCCount_C更大,继续补充剩下的元素 return temp_array; end function; end package body file_utils; -- 在Testbench里使用 use work.file_utils.all; entity tb_mydesign is end entity; architecture sim of tb_mydesign is -- 用函数初始化信号,仿真开始时就会赋值完成 signal filenames : t_string_array(0 to iADCCount_C-1) := get_filenames; begin -- 这里就可以正常使用filenames里的字符串了,比如读取文件: -- file_open(my_file, filenames(0).all, READ_MODE); end architecture;
这个方案虽然不能直接用常量,但信号在仿真初始化阶段就会被赋值,效果和常量差不多,而且完美支持可变长度字符串。需要注意的是,访问类型指向的字符串需要用.all来引用,比如filenames(0).all就是第一个字符串的内容。
方案3:用std.textio的line类型替代自定义访问类型
其实VHDL标准库std.textio里的line类型本质就是指向字符串的访问类型,你可以直接用它来创建字符串列表,省去自定义访问类型的步骤:
use std.textio.all; architecture sim of tb_mydesign is type t_line_array is array(natural range <>) of line; signal filenames : t_line_array(0 to iADCCount_C-1); begin -- 在初始化进程里给每个line赋值 init_proc : process begin filenames(0) := new string'("file.txt"); filenames(1) := new string'("anotherfile.txt"); filenames(2) := new string'("yetanotherfile.txt"); wait; -- 只执行一次 end process; end architecture;
这个方案和方案2原理一样,只是用了标准库的类型,适合不想自定义类型的场景。
为什么你之前的方案不行?
- 方案1的问题:你定义的
tastring是限定长度的字符串数组,VHDL要求数组的所有元素必须是相同类型——而字符串的长度是类型的一部分(比如string(1 to 7)和string(1 to 13)是不同类型),所以固定长度的数组没法容纳不同长度的字符串。 - 方案2的问题:VHDL的常量要求初始化值是静态表达式,而
new string'(...)是动态分配内存的操作,不属于静态表达式,所以没法直接声明成常量。
内容的提问来源于stack exchange,提问作者pknoe3lh
相关产品推荐
相关产品推荐

