【问题标题】:How to write std_logic_vector assignment with input-dependent range in VHDL?如何在 VHDL 中编写具有输入相关范围的 std_logic_vector 赋值?
【发布时间】:2018-11-28 03:59:28
【问题描述】:

我正在尝试将 std_logic_vector 的某些部分复制到另一个位置(索引),具体取决于输入。这可以在 Vivado 中合成,但我想使用另一个工具(SymbiYosys,https://github.com/YosysHQ/SymbiYosys)进行形式验证。 SymbiYosys 可以使用 Verific 作为前端来处理 VHDL,但 Verific 不接受这一点。这是重现问题的一小段代码。 Verific 抱怨“左范围界限不是恒定的”。那么,有没有办法让 Verific 接受这样的变量范围分配?

我已经找到了这篇文章VHDL: slice a various part of an array,它建议使用循环并按位分配值,但我宁愿不更改我的代码,因为它适用于 Vivado。此外,我认为这样的循环会损害代码的可读性,可能还会损害实现效率。因此,我正在寻找一种不同的方法(也许是一种将这个错误变成警告的方法,或者是不那么激烈的代码修改)。

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;

entity test is

port(
    clk         : in std_logic;
    prefix      : in std_logic_vector(  8*8 -1 downto 0);
    msgIn       : in std_logic_vector(128*8 -1 downto 0);
    msgLength   : in integer range 1 to 128;

    test_out    : out std_logic_vector((128+8)*8 -1 downto 0)
);

end test;

architecture behav of test is
begin

process (clk)
begin
    if rising_edge(clk) then

        test_out <= (others => '0');
        test_out((msgLength+8)*8 -1 downto msgLength*8) <= prefix;
        test_out( msgLength   *8 -1 downto           0) <= msgIn(msgLength*8 -1 downto 0);

    end if;
end process;

end behav;

【问题讨论】:

  • 你能把msgLength 设为通用吗?即在您的系统正常运行期间是否会发生变化?
  • 很遗憾,是的,msgLength 是可变的。
  • 有时将它放在一个函数中然后从进程中调用该函数会有所帮助。过去赛灵思 ISE 也需要此功能。
  • 看来 Yosys 是基于 verilog 的。您使用的是哪个 VHDL 前端?这些似乎都是实验性的。所以不要指望奇迹。
  • 我刚刚读到:“因此,我正在寻找一种不同的方法。也许是一种将这个错误变成警告的方法,或者是不那么激烈的代码修改。”你可能想要不可能的事。我会考虑接受。按位选择可能是最好的。而且您应该考虑设计的复杂性。这不会是高速的。

标签: vhdl yosys


【解决方案1】:

应该做一些改变(如果您的工具支持srlsll 运算符)。首先左对齐你的消息(左移),用你的前缀向左填充,最后右移:

process (clk)
    variable tmp1: std_logic_vector(128*8 -1 downto 0);
    variable tmp2: std_logic_vector((128+8)*8 -1 downto 0);
begin
    if rising_edge(clk) then
        tmp1 := msgIn sll (8 * (128 - msgLength));    -- left-align
        tmp2 := prefix & tmp1;                        -- left-pad
        test_out <= tmp2 srl (8 * (128 - msgLength)); -- right-shift
    end if;
end process;

备注:

  1. 如果您的工具不支持std_logic_vector 上的srlsll 运算符,请尝试使用bit_vectorsrlsll 已于 1993 年在标准中引入。示例:

    process (clk)
        variable tmp1: bit_vector(128*8 -1 downto 0);
        variable tmp2: bit_vector((128+8)*8 -1 downto 0);
    begin
        if rising_edge(clk) then
            tmp1 := to_bitvector(msgIn) sll (8 * (128 - msgLength));
            tmp2 := to_bitvector(prefix) & tmp1;
            test_out <= to_stdlogicvector(tmp2 srl (8 * (128 - msgLength)));
        end if;
    end process;
    
  2. 合成结果可能是巨大而缓慢的,因为这个 1088 位桶形移位器具有 128 种可能的不同移位是一种怪物。

  3. 如果您有时间(我的意思是几个时钟周期)来做这件事,可能有更小更高效的解决方案。

【讨论】:

  • @JHBonarius 我不知道std_vector_1164 包(你的意思是std_logic_1164?)。无论如何,他们自 2008 年以来就在std_logic_1164 中(甚至可能在此之前,我不保留所有版本)。如果 OP 的工具不支持它们,它们自 1993 年以来在 bit_vector 上定义。我将此添加到我的答案中。
  • 删除了我的评论。正在阅读旧图书馆。在 2008 年之前,它们仅在已弃用的 std_logic_arith 中为 std_logic_vector 定义。我的错。我个人会使用shift_leftshift_right 并顺便转换为unsigned
  • 我也会使用 SHIFT_LEFT/RIGHT,在 IEEE Std 1076.3-1997 .73.2 NUMERIC_STD 的包声明中定义,在 1995 年普遍使用。这个答案可以使用 std_logic_vector 进行类型转换,用 unsigned 代替过程中的位向量。 (这些移位距离应该是 8 倍,消息长度以八位字节为单位。) Verific 支持 VHDL 修订标志。如果不进行实验或了解 Verific 并阅读完整的 SymbiYosys 源代码,则无法保证支持 sll、srl、shfit_left 或 shift_right。当您可以使用一加二调整大小时,两个班次似乎很尴尬。
  • 我认为this process 可能会提供与 Vivado 相同的逻辑。 test_out &lt;= std_logic_vector ( resize ( unsigned(prefix) &amp; resize( unsigned(msgin), msglength * 8 ) , test_out'length ) );(我模拟了原版并与此进行了比较。)
  • @user1155120:“当你可以使用一加二调整大小时,两个班次看起来很尴尬”合成比你想象的要聪明。并不是因为您在描述中使用了两个班次,所以您最终得到了两个桶式移位器。在这种情况下,将只有一个。但是是的,你是对的,shift_right/shift_left 也可以使用。还有resize。您使用 resize 的解决方案有一个优点:它避免了减法 (128-msglength)。
猜你喜欢
  • 2021-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多