我有一个像这样的std_logic_vector作为输入:v1 =“10001010”,我想创建另一个像这样的向量:v2 = X“00000731”,其中X“7”,X“3”和X“1”代表第一个向量 (v1) 的索引,其中值为“1”。
v1(1) = '1'、v1(2) = '0'、v1(3) = '1' 等。
请帮助我提供一些可以创建 v2 的编码示例。
我们过去也遇到过类似的问题。我们找到的最佳解决方案是对 v2 使用移位寄存器:循环遍历 v1 的元素,每当在 v1 中找到“1”时,就在循环索引中移动。
这是一个可以满足您需要的功能:
type output_type is array (7 downto 0) of unsigned(2 downto 0);
function find_ones(v1: std_logic_vector(7 downto 0)) return output_type is
variable v2: output_type := (others => "000");
begin
for i in v1'range loop
if v1(i) = '1' then
v2 := v2(6 downto 0) & to_unsigned(i, 3);
end if;
end loop;
return v2;
end;
-- results:
-- find_ones("00000000") --> "000_000_000_000_000_000_000_000"
-- find_ones("11111111") --> "111_110_101_100_011_010_001_000"
-- find_ones("10001010") --> "000_000_000_000_000_111_011_001"
由于此解决方案基于移位寄存器,因此很容易以时钟方式实现并根据需要一次处理一个元素,甚至可以流水线化整个过程。
就像是:
variable base : natural := 0;
....
v2 <= (others => '0');
for i in v1'right to v1'left loop
if v1(i) = '1' then
v2(base+3 downto base) = to_unsigned(i,4);
base := base + 4;
end if;
end for;
可以使用此函数生成 v2,其中 v1 为 std_logic_vector(8 - 1 downto 0):
library ieee;
use ieee.numeric_std.all;
...
function v1_to_v2(v1 : std_logic_vector) return std_logic_vector is
variable v2_v : std_logic_vector(4 * v1'length - 1 downto 0);
variable ones_v : natural;
begin
ones_v := 0;
v2_v := (others => '0');
for idx in 0 to v1'left loop
if v1(idx) = '1' then
v2_v(4 * ones_v + 3 downto 4 * ones_v) := std_logic_vector(to_unsigned(idx, 4));
ones_v := ones_v + 1;
end if;
end loop;
return v2_v;
end function;
当 v1 和 v2 上有触发器时,该函数可以在 Altera Cyclone IV E (EP4CE6E22A7) FPGA 中关闭约 220 MHz 的时序。
这是否是一个可接受的解决方案取决于您尝试解决的详细问题。
此外,当 v1 =“00000000”时,您为 v2 选择的格式不会像“00000001”一样导致 v2 = X“00000000”。这可能没问题,具体取决于问题的详细信息。