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 上限并减一的目的。
我正在编写一个小的 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 上限并减一的目的。