首页 文章

在VHDL中使用数组切片

提问于
浏览
1

我正在尝试设计一个可合成的VHDL代码,它使用了一些多维数组特征 . RTL有一个64字深的数组(称为 big_array_s ,64×16位),用于存储一些初始LUT值 . 此外,还有一个4字深的数组( small_array_s ,4 x 16位),用于设计 . 需要将大数组的切片分配到小数组中 . 它在下面的代码片段中进行了说明 .

type small_array is array (0 to 3) of bit_vector(15 downto 0);
type big_array is array (0 to 64) of bit_vector(15 downto 0);

signal small_array_s : small_array;
signal big_array_s : big_array := init_array_func("test.dat");

init_array_func() 是一个VHDL函数,它使用"test.dat" ascii文件中的数据初始化big_array_s . 我遇到的部分是将big_array_s的一部分分配给small_array_s . 例如,像,

small_array_s  <= big_array_s(0 to 3);

是我需要用RTL实现的 . 但是这种直接分配是不可能的,因为LHS和RHS具有不同的阵列类型 . My question is how do I achieve this kind of array slicing in VHDL?


我可以使用的另一种方法是将big_array类型声明为small_array数组 . 例如,

type small_array is array (0 to 3) of bit_vector(15 downto 0);
type big_array is array (0 to 15) of small_array;

signal small_array_s : small_array;
signal big_array_s : big_array;

在这种情况下,声明

small_array_s  <= big_array_s(0);

会很顺利的 . 但考虑到综合支持,我怀疑如何初始化3D阵列 big_array_s .

2 回答

  • 3

    您的问题中没有声明多维(3D)数组类型 . 你的第二个big_array声明有一个索引 .

    IEEE Std 1976-2008

    5.3.2数组类型
    5.3.2.1概述

    数组对象的特征在于索引的数量(数组的维数);每个指数的类型,位置和范围;以及元素的类型和可能的约束 . 指数的顺序很重要 . 一维数组对于每个可能的索引值具有不同的元素 . 多维数组对于每个可能的索引值序列具有不同的元素,可以通过为每个索引选择一个值(按给定顺序)来形成 . 给定索引的可能值是属于相应范围的所有值;这个值范围称为索引范围 .

    对于第一种方法,您可以声明子类型而不是独立类型 . 结果是它们是相同的类型 .

    这样做不是风险,在VHDL分配中,左手侧目标中每个元素的右 Watch 达式都需要匹配元素 . 具有不匹配元素数量的代码可以进行分析和详细说明,但会导致运行时错误报告边界不匹配(并且需要合成以遵守VHDL语义) .

    创建一个工作Minimal, Complete and Verifiable example对于你的第一个片段看起来像这样:

    entity some_array is
    end entity;
    
    architecture fuu of some_array is
        -- type small_array is array (0 to 3) of bit_vector(15 downto 0);
        -- type big_array is array (0 to 64) of bit_vector(15 downto 0);
        type some_array is array (natural range <>) of bit_vector(15 downto 0);
        subtype small_array is some_array(0 to 3);
        subtype big_array is some_array (0 to 64);
    
        impure function init_array_func (init_file:  in string) return 
                 big_array is
            use std.textio.all;
            file big_array_file: text is in init_file;
            variable file_line:         line;
            variable big_array_val:     big_array;
        begin
            for i in big_array'range  loop
                readline (big_array_file, file_line);
                read (file_line, big_array_val(i));
            end loop;
            return big_array_val;
        end function;
    
        function to_string (inp: bit_vector) return string is
            variable image_str: string (1 to inp'length);
            alias input_str:  bit_vector (1 to inp'length) is inp;
            begin
            for i in input_str'range loop
                image_str(i) := character'VALUE(bit'IMAGE(input_str(i)));
            end loop;
            return image_str;
        end function;
    
        signal small_array_s : small_array;
        signal big_array_s : big_array := init_array_func("test.dat");
    
    begin
        small_array_s  <= big_array_s(0 to 3);
    
    MONITOR:
        process
        begin
            wait on small_array_s;
            wait for 0 ns; -- not the default value;
            for i in small_array_s'range loop
                report "small_array_s(" & integer'image(i) & ") = " &
                        to_string(small_array_s(i));
            end loop;
        end process;
    
    end architecture;
    

    这给了:

    ghdl -r some_array some_array.vhdl:47:13:@ 0ms :(报告说明):small_array_s(0)= 0000000000000000 some_array.vhdl:47:13:@ 0ms :(报告说明):small_array_s(1)= 0000000000000001 some_array .vhdl:47:13:@ 0ms :(报告说明):small_array_s(2)= 0000000000000010 some_array.vhdl:47:13:@ 0ms :(报告说明):small_array_s(3)= 0000000000000011

    其中正确显示了初始化的前四个值,以便为已知的test.dat内容发出big_array_s信号 .

    这些函数与早于2008年的VHDL标准版本兼容,并从其他示例中进行剪切,粘贴和编辑 .

    请注意,init_array_func函数需要一个test.dat文件,其中包含至少65行big_array元素的有效值,并且这样的函数也可以通过传递big_array元素的数量(长度)来推广,返回任意子类型的值some_array .

    您还可以在具有相同维度(索引数)的数组类型之间进行显式类型转换,其中元素类型密切相关:

    9.3.6类型转换

    密切相关的类型之间允许显式类型转换 . 特别是,一种类型与自身密切相关 . 其他类型仅在以下条件下密切相关:... - 数组类型 - 当且仅当类型具有相同维度且元素类型密切相关时,两种数组类型密切相关

    请注意,作为数组类型的元素类型必须遵循相同的要求,因为它的元素(子元素,此处为类型位) .

    使用没有子类型声明的原始类型声明,唯一的其他更改将是赋值:

    small_array_s  <= small_array(big_array_s(0 to 3));
    

    其中类型转换操作数表达式big_array_s(0到3)与small_array_s具有相同的维度,并且元素类型密切相关(bit_vector(15 downto 0)) .

    通过这些更改,上面的代码分析,详细说明并模拟了相同的结果 .

    请注意类型转换还依赖于赋值语义,确保赋值目标和右侧表达式的匹配元素:

    14.7.3.4信号更新

    为了在给定的模拟周期内更新信号,内核过程首先确定该信号的驱动和有效值 . 然后,内核进程使用新确定的驱动值更新包含驱动值的变量 . 内核还使用新确定的有效值更新包含信号当前值的变量,如下所示:... b)如果S是复合信号(包括数组的片),则S的有效值是隐式的转换为S的子类型 . 子类型转换检查对于S的每个元素,在有效值中存在匹配元素,反之亦然 . 如果此检查失败,则会发生错误 . 然后将此子类型转换的结果分配给表示S的当前值的变量 .

    关于子类型转换的一点意味着索引范围不必匹配,表达式和目标必须具有匹配的元素 .

  • 0

    要进行数组切片,您可以使用一次复制一个bit_vector(15 downto 0)的generate语句 .

    关于3D阵列,我使用Xilinx Vivado进行综合的经验不佳 . Vivado将其识别为3D阵列,告诉您它不受支持并实现了一堆寄存器 .

相关问题