VHDL - AND 可变位数
VHDL - AND variable number of bits
我有一个名为 matrix
的 w*y 位宽 std_logic_vector
,其中 w 和 y 是整数。我想将 y 位宽度 std_logic_vector
称为 output
,它的位同时分配给 matrix
元素的 w 位的 AND。
例如,w=5 y=3:
output(2) <= matrix(14) and matrix(13) and matrix(12) and matrix(11) and matrix(10);
output(1) <= matrix(9) and matrix(8) and matrix(7) and matrix(6) and matrix(5);
output(0) <= matrix(4) and matrix(3) and matrix(2) and matrix(1) and matrix(0);
在这个例子中,你可以看到output
是y位长,也就是3,output
的每一位被分配给[=13=的w位的AND ] 即 5.
现在,我想用泛型来写。我试图在两个 for..generate
循环中编写它,但我无法处理它。 output(i)
的右边应该是什么?也可以换个方式实现,非常欢迎换个思路。不一定是我想的那样。
library ieee;
use ieee.std_logic_1164.all;
entity module is
generic (
w : integer := 5; -- input width
y : integer := 3 -- output width
);
port (
matrix : in std_logic_vector(w * y - 1 downto 0); -- matrix
output : out std_logic_vector(y - 1 downto 0) -- output
);
end entity module;
architecture rtl of module is
begin -- architecture rtl
AND_FOR: for i in y - 1 downto 0 generate
AND_FOR2: for j in w - 1 downto 0 generate
output(i) <= ????;
end generate AND_FOR2;
end generate AND_FOR;
end architecture rtl;
这里的目标是找到一种方法来描述切片,将分配中的元素范围作为归约的输入,并在尽可能少的生成语句中使用详尽的边界。
生成语句在提供静态索引名称或保留综合资格的切片名称方面很有吸引力。我们没有办法在 VHDL 中详细说明不同的复杂性(这里是长度)表达式,这使得 AND 简化具有吸引力。根据综合工具,您可能 'encouraged' 使用预先存在的函数,例如 Synopsys 包 std_logic_misc.
中的 AND_REDUCE
在 -2008 中,我们可以使用单一的 AND(保留字,后跟一个操作数。在符合 VHDL 标准早期修订版的工具中,我们可以使用函数调用:
architecture rtl of module is
-- -2008 use unitary AND without parameter instead of call:
function reduce_and (inp: std_logic_vector) return std_logic is
variable retval: std_logic := '1';
begin
for i in inp'range loop
retval := retval and inp(i);
end loop;
return retval;
end function;
begin
AND_FOR:
for i in y - 1 downto 0 generate
output(i) <= reduce_and(matrix((i + 1) * w - 1 downto i * w));
end generate;
describe_outputs:
process
begin
report "matrix'range is (" & integer'image(matrix'left) &
" downto " & integer'image(matrix'right) & ")";
for i in y - 1 downto 0 loop
report "output(" & integer'image(i) & ") <= reduce_and(matrix(" &
integer'image((i + 1) * w - 1 ) & " downto " &
integer'image (i * w) & ")";
end loop;
wait;
end process;
end architecture;
for generate 语句将为生成参数(这里是 i)的每个值详细说明一个块。它在块声明区域中被声明为常量。 w 和 y 都是全局静态泛型常量,因此矩阵的范围也是全局静态的。这主要意味着使用像这样的生成语句会产生符合条件的综合赋值语句。
添加标记为 describe_outputs
的过程语句是为了证明与您之前的赋值语句的等效性(通过算法描述被 AND 运算的元素的能力),因为您没有证明矩阵的值和预期结果连同一个测试台。可以去掉进程。
只要您使用 w
和 x
的值不会导致空范围或空切片,此方法应该适用于硬编码方向(downto
).
报告语句依赖于实现(需要 'header' 信息)。这里显示的是 ghdl:
%: ghdl -a module.vhdl
%: ghdl -e module
%: ghdl -r module
module.vhdl:35:9:@0ms:(report note): matrix'range is (14 downto 0)
module.vhdl:38:13:@0ms:(report note): output(2) <= reduce_and(matrix(14 downto 10)
module.vhdl:38:13:@0ms:(report note): output(1) <= reduce_and(matrix(9 downto 5)
module.vhdl:38:13:@0ms:(report note): output(0) <= reduce_and(matrix(4 downto 0)
%:
您确实可以使用 2 维生成对其进行建模,但您需要一个与 2 输入与门的输出相对应的中间信号。
让我们将您的输入视为 y
行乘以 w
列的矩阵。为了便于解释,我们将矩阵 m
的行 i
、列 j
中的元素表示为 m(i,j)
。所以你的 matrix(i*w+j)
表示为 matrix(i,j)
.
您希望 output(i)
,其中 0 <= i <= y-1
成为 matrix
的 bit-wise 和第 i
行。您可以使用 y
行乘以 w-1
列 tmp
矩阵来接收 2 输入 AND 的结果。 tmp(i,0)
将是 matrix(i,0)
和 matrix(i,1)
的 AND。然后,tmp(i,1)
将是 tmp(i,0)
和 matrix(i,2)
的 AND... 最后,tmp(i,w-2)
将是 tmp(i,w-3)
和 matrix(i,w-1)
的 AND,也会是你想要的output(i)
VHDL编码:
library ieee;
use ieee.std_logic_1164.all;
entity module is
generic(
w: integer := 5;
y: integer := 3
);
port(
matrix: in std_logic_vector(w * y - 1 downto 0);
output: out std_logic_vector(y - 1 downto 0)
);
end entity module;
architecture rtl of module is
type matrix_t is array(natural range <>, natural range <>) of std_logic;
signal tmp: matrix_t(0 to y - 1, 0 to w - 2);
begin
and_for: for i in 0 to y - 1 generate
tmp(i, 0) <= matrix(i * w) and matrix(i * w + 1);
and_for2: for j in 1 to w - 2 generate
tmp(i, j) <= tmp(i, j - 1) and matrix(i * w + j + 1);
end generate and_for2;
output(i) <= tmp(i, w - 2);
end generate and_for;
end architecture rtl;
演示:
library ieee;
use ieee.std_logic_1164.all;
entity module_sim is
end entity module_sim;
architecture sim of module_sim is
constant w: natural := 5;
constant y: natural := 3;
signal matrix: std_logic_vector(w * y - 1 downto 0);
signal output: std_logic_vector(y - 1 downto 0);
begin
u0: entity work.module(rtl)
port map(
matrix => matrix,
output => output
);
process
begin
matrix <= (others => '1');
wait for 1 ns;
report to_string(output);
for i in 0 to y - 1 loop
matrix(i * w) <= '0';
end loop;
wait for 1 ns;
report to_string(output);
matrix <= (others => '1');
wait for 1 ns;
report to_string(output);
wait;
end process;
end architecture sim;
$ ghdl -a --std=08 module_sim.vhd
$ ghdl -r --std=08 module_sim
module_sim.vhd:50:5:@1ns:(report note): 111
module_sim.vhd:55:5:@2ns:(report note): 000
module_sim.vhd:58:5:@3ns:(report note): 111
但是,正如另一个答案中所建议的那样,使用 AND 缩减函数而不是最内层的 generate 语句更简单且不易出错。
我有一个名为 matrix
的 w*y 位宽 std_logic_vector
,其中 w 和 y 是整数。我想将 y 位宽度 std_logic_vector
称为 output
,它的位同时分配给 matrix
元素的 w 位的 AND。
例如,w=5 y=3:
output(2) <= matrix(14) and matrix(13) and matrix(12) and matrix(11) and matrix(10);
output(1) <= matrix(9) and matrix(8) and matrix(7) and matrix(6) and matrix(5);
output(0) <= matrix(4) and matrix(3) and matrix(2) and matrix(1) and matrix(0);
在这个例子中,你可以看到output
是y位长,也就是3,output
的每一位被分配给[=13=的w位的AND ] 即 5.
现在,我想用泛型来写。我试图在两个 for..generate
循环中编写它,但我无法处理它。 output(i)
的右边应该是什么?也可以换个方式实现,非常欢迎换个思路。不一定是我想的那样。
library ieee;
use ieee.std_logic_1164.all;
entity module is
generic (
w : integer := 5; -- input width
y : integer := 3 -- output width
);
port (
matrix : in std_logic_vector(w * y - 1 downto 0); -- matrix
output : out std_logic_vector(y - 1 downto 0) -- output
);
end entity module;
architecture rtl of module is
begin -- architecture rtl
AND_FOR: for i in y - 1 downto 0 generate
AND_FOR2: for j in w - 1 downto 0 generate
output(i) <= ????;
end generate AND_FOR2;
end generate AND_FOR;
end architecture rtl;
这里的目标是找到一种方法来描述切片,将分配中的元素范围作为归约的输入,并在尽可能少的生成语句中使用详尽的边界。
生成语句在提供静态索引名称或保留综合资格的切片名称方面很有吸引力。我们没有办法在 VHDL 中详细说明不同的复杂性(这里是长度)表达式,这使得 AND 简化具有吸引力。根据综合工具,您可能 'encouraged' 使用预先存在的函数,例如 Synopsys 包 std_logic_misc.
中的AND_REDUCE
在 -2008 中,我们可以使用单一的 AND(保留字,后跟一个操作数。在符合 VHDL 标准早期修订版的工具中,我们可以使用函数调用:
architecture rtl of module is
-- -2008 use unitary AND without parameter instead of call:
function reduce_and (inp: std_logic_vector) return std_logic is
variable retval: std_logic := '1';
begin
for i in inp'range loop
retval := retval and inp(i);
end loop;
return retval;
end function;
begin
AND_FOR:
for i in y - 1 downto 0 generate
output(i) <= reduce_and(matrix((i + 1) * w - 1 downto i * w));
end generate;
describe_outputs:
process
begin
report "matrix'range is (" & integer'image(matrix'left) &
" downto " & integer'image(matrix'right) & ")";
for i in y - 1 downto 0 loop
report "output(" & integer'image(i) & ") <= reduce_and(matrix(" &
integer'image((i + 1) * w - 1 ) & " downto " &
integer'image (i * w) & ")";
end loop;
wait;
end process;
end architecture;
for generate 语句将为生成参数(这里是 i)的每个值详细说明一个块。它在块声明区域中被声明为常量。 w 和 y 都是全局静态泛型常量,因此矩阵的范围也是全局静态的。这主要意味着使用像这样的生成语句会产生符合条件的综合赋值语句。
添加标记为 describe_outputs
的过程语句是为了证明与您之前的赋值语句的等效性(通过算法描述被 AND 运算的元素的能力),因为您没有证明矩阵的值和预期结果连同一个测试台。可以去掉进程。
只要您使用 w
和 x
的值不会导致空范围或空切片,此方法应该适用于硬编码方向(downto
).
报告语句依赖于实现(需要 'header' 信息)。这里显示的是 ghdl:
%: ghdl -a module.vhdl
%: ghdl -e module
%: ghdl -r module
module.vhdl:35:9:@0ms:(report note): matrix'range is (14 downto 0)
module.vhdl:38:13:@0ms:(report note): output(2) <= reduce_and(matrix(14 downto 10)
module.vhdl:38:13:@0ms:(report note): output(1) <= reduce_and(matrix(9 downto 5)
module.vhdl:38:13:@0ms:(report note): output(0) <= reduce_and(matrix(4 downto 0)
%:
您确实可以使用 2 维生成对其进行建模,但您需要一个与 2 输入与门的输出相对应的中间信号。
让我们将您的输入视为 y
行乘以 w
列的矩阵。为了便于解释,我们将矩阵 m
的行 i
、列 j
中的元素表示为 m(i,j)
。所以你的 matrix(i*w+j)
表示为 matrix(i,j)
.
您希望 output(i)
,其中 0 <= i <= y-1
成为 matrix
的 bit-wise 和第 i
行。您可以使用 y
行乘以 w-1
列 tmp
矩阵来接收 2 输入 AND 的结果。 tmp(i,0)
将是 matrix(i,0)
和 matrix(i,1)
的 AND。然后,tmp(i,1)
将是 tmp(i,0)
和 matrix(i,2)
的 AND... 最后,tmp(i,w-2)
将是 tmp(i,w-3)
和 matrix(i,w-1)
的 AND,也会是你想要的output(i)
VHDL编码:
library ieee;
use ieee.std_logic_1164.all;
entity module is
generic(
w: integer := 5;
y: integer := 3
);
port(
matrix: in std_logic_vector(w * y - 1 downto 0);
output: out std_logic_vector(y - 1 downto 0)
);
end entity module;
architecture rtl of module is
type matrix_t is array(natural range <>, natural range <>) of std_logic;
signal tmp: matrix_t(0 to y - 1, 0 to w - 2);
begin
and_for: for i in 0 to y - 1 generate
tmp(i, 0) <= matrix(i * w) and matrix(i * w + 1);
and_for2: for j in 1 to w - 2 generate
tmp(i, j) <= tmp(i, j - 1) and matrix(i * w + j + 1);
end generate and_for2;
output(i) <= tmp(i, w - 2);
end generate and_for;
end architecture rtl;
演示:
library ieee;
use ieee.std_logic_1164.all;
entity module_sim is
end entity module_sim;
architecture sim of module_sim is
constant w: natural := 5;
constant y: natural := 3;
signal matrix: std_logic_vector(w * y - 1 downto 0);
signal output: std_logic_vector(y - 1 downto 0);
begin
u0: entity work.module(rtl)
port map(
matrix => matrix,
output => output
);
process
begin
matrix <= (others => '1');
wait for 1 ns;
report to_string(output);
for i in 0 to y - 1 loop
matrix(i * w) <= '0';
end loop;
wait for 1 ns;
report to_string(output);
matrix <= (others => '1');
wait for 1 ns;
report to_string(output);
wait;
end process;
end architecture sim;
$ ghdl -a --std=08 module_sim.vhd
$ ghdl -r --std=08 module_sim
module_sim.vhd:50:5:@1ns:(report note): 111
module_sim.vhd:55:5:@2ns:(report note): 000
module_sim.vhd:58:5:@3ns:(report note): 111
但是,正如另一个答案中所建议的那样,使用 AND 缩减函数而不是最内层的 generate 语句更简单且不易出错。