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

时间:2017-09-19 08:13:58

标签: vhdl

我正在写一个小型的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,这就是转换如此复杂的原因,因为我只能在密切相关的类型之间进行转换。

2 个答案:

答案 0 :(得分:1)

crc_n_par实例化时还需要长度:

Foo

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

经过分析,精心制作并模拟出来:

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

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

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;

请注意,计算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与您的问题标题相匹配:

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

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

答案 1 :(得分:0)

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