【问题标题】:VHDL 2008 calculate length of vector without leading zerosVHDL 2008 计算不带前导零的向量长度
【发布时间】:2017-09-21 15:43:29
【问题描述】:

我正在编写一个小型 vhdl 模块,但我对这种语言还很陌生。 我的实体的输出向量的长度是可变的,取决于我的多项式的 msb。例如,如果我有一个像 100111 这样的多项式,len 应该是 4。所以输出向量有 5 位。 比输入向量少一。

为了澄清: 如果输入向量看起来像“000100111”,那么输出向量也应该是(4 downto 0)。这就是为什么我不能使用 'length

entity CRC_n_par is
generic(
    polynom     : std_logic_vector
    );
port(
    clk     : in    std_logic;
    input   : in    std_logic;
    reset   : in    std_logic;
    output  : out   std_logic_vector(integer(ceil(log2(real(to_integer(unsigned(polynom))))))-2 downto 0) );
end entity;
architecture Behavioral of CRC_n_par is

    constant len : integer := integer(ceil(log2(real(to_integer(unsigned(polynom))))))-2;

有什么方法可以让这个更优雅。 Here's 一个类似的问题,但我不能在端口声明中使用函数。端口声明后,我再次使用常量 len。 有没有办法在 vhdl 中使用类似 c 的宏? 我使用的是 vhdl 2008,这就是转换如此复杂的原因,因为我只能在密切相关的类型之间进行转换。

【问题讨论】:

  • 您的两个声明涉及全局静态值,这意味着计算是在设计层次结构的详细说明中完成的。为什么不将常量 len 设为泛型?在通用接口中只计算一次,并将 len 用于端口数组绑定。您还可以在函数调用中隐藏 len 计算,该函数声明在一个方便的包中,就像 ceil 或 log2 一样。
  • 我只想给一个通用值,所以上层不必计算长度,这会导致错误。还是您的意思是在多项式泛型下方定义常数? GHDL 给我一个错误,“多项式”在这里不可见
  • polynomlen 的算法还不清楚。你能更具体地描述一下吗?
  • 使用 ghdl 的 -08 标志 (ghdl -a --std=08 crc_par_n.vhdl) 使多项式在通用中可见。这是一个 -2008 功能,需要在需要进行详细说明的地方使用(命令 -e 用于 gcc/llvm 或 -r 用于 mcode)。您也可以将 len 作为自然参数传递,并在 crc_n_par 被实例化的地方进行计算,这将在 -1993 年及以后工作。问问你自己,实例化 crc_n_par 的地方如何知道输出端口的长度,需要声明一个实际信号,在详细说明关联实际信号和正式端口时使用。
  • @JHBonarius log2 需要一个实数输入,这就是为什么我将多项式转换为无符号数,然后再转换为实数。 log2(0b000100111) = 5,28,ceil 增加到 6(位)我的输出长度应该少 1,所以 5 位。定义向量范围时,我必须指定 (4 downto 0)

标签: vhdl


【解决方案1】:

如果 crc_n_par 被实例化,也需要长度:

library ieee;
use ieee.std_logic_1164.all;

entity crc_n_par is
    generic (
        len:           natural
    );
    port (
        clk:      in    std_logic;
        input:    in    std_logic;
        reset:    in    std_logic;
        output:   out   std_logic_vector (len - 1 downto 0) 
    );
end entity;
architecture Behavioral of crc_n_par is
begin
MONITOR:
    process
    begin
        report "crc_n_par output len = " & integer'image(len);
        wait;
    end process;
end architecture;

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

entity some_top_level is
end entity;

architecture foo of some_top_level is
    -- For -2002 and earlier, present in -2008:
    function to_string (inp: std_logic_vector) return string is
        variable image_str: string (1 to inp'length);
        alias input_str:  std_logic_vector (1 to inp'length) is inp;
    begin
        for i in input_str'range loop
            image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
        end loop;
        return image_str;
    end function;
    constant polynom: std_logic_vector := "000100111";
    constant crc_inst_len : natural := 
        integer(ceil(log2(real(to_integer(unsigned(polynom))))))-1;
    signal clk:     std_logic;
    signal input:   std_logic;
    signal reset:   std_logic;
    signal output:  std_logic_vector (crc_inst_len - 1 downto 0);
begin
MONITOR:
    process
    begin
        report LF & "polynom len = " & integer'image(polynom'length) &
               " crc_inst_len = " & integer'image(crc_inst_len) & LF &
               " output length = " & integer'image(output'length) & 
               " polynom = " & to_string(polynom);
        wait;
    end process;
CRC_INSTANCE:
    entity work.crc_n_par 
        generic map (
            len => crc_inst_len
        )
        port map (
            clk => clk,
            input => input,
            reset => reset,
            output => output
        );

end architecture;

这会将长度计算移到设计层次结构中的更高点,从而允许端口输出的实际使用也以适当的长度声明。

当分析、阐述和模拟时,它会产生:

ghdl -a some_top_level.vhdl
ghdl -e some_top_level
ghdl -r some_top_level
some_top_level.vhdl:20:9:@0ms:(report note): crc_n_par output len = 5
some_top_level.vhdl:55:9:@0ms:(report note):
polynom len = 9 crc_inst_len = 5
 output length = 5 polynom = 000100111

你可以独立计算两个地方的长度:

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

entity crc_n_par is
    generic (
        polynom:       std_logic_vector;
        len:           natural :=  -- requires -2008 to access polynom
            integer(ceil(log2(real(to_integer(unsigned(polynom)))))) - 1
        );
    port (
        clk:      in    std_logic;
        input:    in    std_logic;
        reset:    in    std_logic;
        output:   out   std_logic_vector (len - 1 downto 0) 
    );
end entity;
architecture Behavioral of crc_n_par is
begin
MONITOR:
    process
    begin
        report "len = " & integer'image(len);
        wait;
    end process;
end architecture;

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

entity some_top_level is
end entity;

architecture foo of some_top_level is
    constant polynom: std_logic_vector := "000100111";
    constant crc_inst_len : natural := 
        integer(ceil(log2(real(to_integer(unsigned(polynom))))))-1;
    signal clk:     std_logic;
    signal input:   std_logic;
    signal reset:   std_logic;
    signal output:  std_logic_vector (crc_inst_len - 1 downto 0);
begin
MONITOR:
    process
    begin
        report LF & "polynom len = " & integer'image(polynom'length) &
               " crc_inst_len = " & integer'image(crc_inst_len) & LF &
               " output length = " & integer'image(output'length) & 
               " polynom = " & to_string(polynom);
        wait;
    end process;
CRC_INSTANCE:
    entity work.crc_n_par 
        generic map (
            polynom => polynom
            -- don't pass len
        )
        port map (
            clk => clk,
            input => input,
            reset => reset,
            output => output
        );
end architecture;

但你可以看到这是不必要的重复,需要-2008来分析和阐述:

ghdl -a --std=08 crc_n_par.vhdl
ghdl -e --std=08 crc_n_par
ghdl -r --std=08 some_top_level
some_top_level.vhdl:20:9:@0ms:(report note): crc_n_par output len = 5
some_top_level.vhdl:55:9:@0ms:(report note):
polynom len = 9 crc_inst_len = 5
 output length = 5 polynom = 000100111

注意- 1 在计算polynom 长度时与您的问题标题匹配:

VHDL 2008 计算不带前导零的向量长度

这就是使用将数组值转换为整数并确定它的 log2 上限并减一的目的。

【讨论】:

  • 非常感谢,但即使使用 --std=08,我的 ghdl 也会抛出错误(“这里看不到多项式”)。你用什么版本?我有 ghdl-0.33 我想使用 --std=08 作为默认值,因为它是一个新项目,我们不必维护旧部件。或者您认为 vhdl2008 有什么不好的地方吗?但是,我认为,最好将长度作为通用常量给出,因为正如您所提到的,我会在更高的层次结构中定义它。
  • 在您的第一个示例中,polynom 不包含在泛型中。我假设提问者希望能够在每次实例化时更改它(否则它不会是通用的,而只是架构中的常量)。在 cmets 中,提问者特别要求他只想给出一个通用值......
  • 泛型可以通过架构向下传播。多项式从何而来?
【解决方案2】:

首先:您的问题不清楚。你说你想确定一个没有前导零的向量的长度。 100111 没有前导零,因此长度为 6。而且还不清楚如何从 4 字节长度变为 5 字节。

嗯,最佳方法取决于您的具体实施。我会在包中使用一个函数。即

library ieee;
use ieee.std_logic_1164.all;

package my_functions is
    function det_output_len(polynom:std_logic_vector) return positive;
end package;

library ieee;
use ieee.numeric_std.all;
use ieee.math_real.all;

package body my_functions is
    function det_output_len(polynom:std_logic_vector) return positive is
    begin
        return integer(ceil(log2(real(to_integer(unsigned(polynom))))))-1;
    end function;
end package body;

然后在你的实体中:

use work.my_functions.all;

entity CRC_n_par is
    [...]
port(
    [...]
    output  : out   std_logic_vector(det_output_len(polynom)-1 downto 0) );
end entity;

对于常量'len',你不需要重新计算函数。如果已经为输出向量设置了长度,则可以使用VHDL attributes(旧站点,在 VHDL-2008 上不是最新的)。即

constant len : positive := output'length;

顺便说一句,这不是 VHDL-2008 特定的东西,因为它在 VHDL 中得到了一段时间的支持。

【讨论】:

  • 抱歉造成误会。如果我在“100111”上使用我的公式,结果是 4。(检查结尾的 -2)。同样的结果应该是“000100111”。
  • 那么在设计层次结构中实例化 crc_n_par 的架构如何知道声明一个正确长度的实际信号以与端口输出相关联?
  • @user1155120 该架构也设置了多项式,也必须调用该函数来确定长度。当我给更多时间时,我会将其添加到答案中。就像我在回答中所说:这只是一个可能的解决方案。这完全取决于您选择的实施方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 2014-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多