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

VHDL 2008 calculate length of vector without leading zeros

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

澄清一下: 如果输入向量看起来像“000100111”,输出向量也应该是(4 到 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,这就是为什么转换如此复杂的原因,因为我只能在密切相关的类型之间进行转换。

首先:你的问题不清楚。你说你想确定一个没有前导零的向量的长度。 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 支持它已有一段时间了。

实例化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

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

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

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