VHDL - 自定义移位器 - 串联输入(在定义范围内)和剩余的零
VHDL - custom shifter - concatenation input (in defined range) and remaining zeros
我正在尝试编写自己的移位器。换档都无所谓,所以请不要推荐我用不同的方式做换档。变速杆在这里只是为了演示我遇到的问题。
这里是一段变速杆的描述:
1: with operand_b select result <=
2: operand_a when "0000",
3: operand_a(14 downto 0) & '0' when "0001",
4: operand_a(13 downto 0) & "00" when "0010",
5: operand_a(12 downto 0) & "000" when "0011",
6: operand_a(11 downto 0) & "0000" when "0100",
7: operand_a(10 downto 0) & "00000" when "0101",
8: operand_a(9 downto 0) & "000000" when "0110",
9: operand_a(8 downto 0) & "0000000" when "0111",
10: operand_a(7 downto 0) & "00000000" when "1000",
11: operand_a(6 downto 0) & "000000000" when "1001",
12: operand_a(5 downto 0) & "0000000000" when "1010",
13: operand_a(4 downto 0) & "00000000000" when "1011",
14: operand_a(3 downto 0) & "000000000000" when "1100",
15: operand_a(2 downto 0) & "0000000000000" when "1101",
16: operand_a(1 downto 0) & "00000000000000" when "1110",
17: operand_a(0) & "000000000000000" when others;
其中 operand_b
是用于移位的值,result
是移位器的输出。
如您所见,这是相当大的瓶颈。当我们有例如 64 位移位器时会发生什么——很多无用的零。我在网上找到了很多如何更合理地编写它的方法,但是我尝试过的每个解决方案,如 operand_a(13 downto 0) & (others => '0') when "0010"
或 (15 downto 2 => operand_a(13 downto 0), others => '0') when "0010"
或 (operand_a(13 downto 0), others => '0') when "0010"
都不起作用。每次我收到有错误的报告。
有什么解决办法吗?
对不起我的英语。
编辑:
当我将第 4 行的 operand_a(13 downto 0) & "00" when "0010",
替换为:
operand_a(13 downto 0) & (others => '0') when "0010",
这returns
无法确定 "others" 个值的总和。 (<= 也适用于第 17 行)
连接操作的大小与目标的大小不同。
(15 downto 2 => operand_a(13 downto 0), others => '0') when "0010",
这returns
aggregate中的元素类型不对应任何数组类型
(operand_a(13 downto 0), others => '0') when "0010",
这returns
找不到具有与聚合类型匹配的元素的数组或记录类型。
operand_a(13 downto 0) & (1 downto 0 => '0') when "0010",
这个可以用,但是这里没有任何使用方法others
?
(operand_a(13 downto 0), others => '0')
等值表达式应该适用于 IEEE Std 1076-2008。
比较 9.3.3.3 数组聚合,第 1 段和第 2 段:
For an aggregate of a one-dimensional array type, each choice shall specify values of the index type, and the expression of each element association shall be of either the element type or the type of the aggregate. If the type of the expression of an element association is the type of the aggregate, then either the element association shall be positional or the choice shall be a discrete range.
For an element association with a choice that is a discrete range and an expression of the element type of the aggregate, the value of the expression is the element at each index value in the range.
IEEE 标准 1076-1993 数组聚合第 1 段:
For an aggregate of a one-dimensional array type, each choice must specify values of the index type, and the expression of each element association must be of the element type. An aggregate of an n-dimensional array type, where n is greater than 1, is written as a one-dimensional aggregate in which the index subtype of the aggregate is given by the first index position of the array type, and the expression specified for each element association is an (n-1)-dimensional array or array aggregate, which is called a subaggregate. A string or bit string literal is allowed as a subaggregate in the place of any aggregate of a one-dimensional array of a character type.
在-2008年我们允许关联元素是聚合类型(一维数组类型)。这允许关联相同类型的切片名称。
同时-2008 9.3.3.3 para 7允许使用others选择:
e) As a value expression in an assignment statement, where the target is a declared object (or member thereof), and either the subtype of the target is a fully constrained array subtype or the target is a slice name
(目标是切片名称已从以前的修订版中添加。)可以使用 others 选择的规则要求您具有提供子类型约束的上下文.
所以它告诉我们您正在使用的 VHDL 实现不兼容 -2008(或未被用作 -2008 兼容)。
此功能是升级到 -2008 兼容性时实现的优先级通常较低的功能之一。
如果您发现您的 VHDL 工具缺乏支持,可以使用其他方式来表达您的移位器,例如:
SHIFTER:
process (operand_b, operand_a)
variable b: integer range 0 to operand_a'HIGH;
begin
result <= (others => '0');
if not is_x(operand_b) then -- culling meta-values
b := to_integer(unsigned(operand_b));
for i in result'range loop
if i = b then
result(result'high downto i) <=
operand_a (operand_a'high - i downto 0);
end if;
end loop;
end if;
end process;
此过程符合综合条件,因为切片范围取决于包括循环常量在内的静态值,循环展开或并行化以进行综合。 operand_b
的每个二进制值都有一个赋值语句,您依赖于综合优化(对于多路复用器和移位器之类的东西来说效果非常好)。
此方法的工作原理是将所有 result
写入“0”,然后将 operand_a
所需的部分写入 result
。它取决于同一进程内的顺序分配(并且可以在 -2008 兼容实现中与顺序条件信号分配一起使用)以及 if 语句或 case 语句。 (但不是取决于同一左侧目标的选定信号分配)。
在一个进程中执行的两个赋值语句取决于有一个驱动程序并且由综合支持。最后写入的数组元素值会覆盖之前写入的数组元素值,投影输出波形中任何特定模拟时间只有一个时隙。
我正在尝试编写自己的移位器。换档都无所谓,所以请不要推荐我用不同的方式做换档。变速杆在这里只是为了演示我遇到的问题。
这里是一段变速杆的描述:
1: with operand_b select result <=
2: operand_a when "0000",
3: operand_a(14 downto 0) & '0' when "0001",
4: operand_a(13 downto 0) & "00" when "0010",
5: operand_a(12 downto 0) & "000" when "0011",
6: operand_a(11 downto 0) & "0000" when "0100",
7: operand_a(10 downto 0) & "00000" when "0101",
8: operand_a(9 downto 0) & "000000" when "0110",
9: operand_a(8 downto 0) & "0000000" when "0111",
10: operand_a(7 downto 0) & "00000000" when "1000",
11: operand_a(6 downto 0) & "000000000" when "1001",
12: operand_a(5 downto 0) & "0000000000" when "1010",
13: operand_a(4 downto 0) & "00000000000" when "1011",
14: operand_a(3 downto 0) & "000000000000" when "1100",
15: operand_a(2 downto 0) & "0000000000000" when "1101",
16: operand_a(1 downto 0) & "00000000000000" when "1110",
17: operand_a(0) & "000000000000000" when others;
其中 operand_b
是用于移位的值,result
是移位器的输出。
如您所见,这是相当大的瓶颈。当我们有例如 64 位移位器时会发生什么——很多无用的零。我在网上找到了很多如何更合理地编写它的方法,但是我尝试过的每个解决方案,如 operand_a(13 downto 0) & (others => '0') when "0010"
或 (15 downto 2 => operand_a(13 downto 0), others => '0') when "0010"
或 (operand_a(13 downto 0), others => '0') when "0010"
都不起作用。每次我收到有错误的报告。
有什么解决办法吗?
对不起我的英语。
编辑:
当我将第 4 行的 operand_a(13 downto 0) & "00" when "0010",
替换为:
operand_a(13 downto 0) & (others => '0') when "0010",
这returns
无法确定 "others" 个值的总和。 (<= 也适用于第 17 行) 连接操作的大小与目标的大小不同。
(15 downto 2 => operand_a(13 downto 0), others => '0') when "0010",
这returns
aggregate中的元素类型不对应任何数组类型
(operand_a(13 downto 0), others => '0') when "0010",
这returns
找不到具有与聚合类型匹配的元素的数组或记录类型。
operand_a(13 downto 0) & (1 downto 0 => '0') when "0010",
这个可以用,但是这里没有任何使用方法others
?
(operand_a(13 downto 0), others => '0')
等值表达式应该适用于 IEEE Std 1076-2008。
比较 9.3.3.3 数组聚合,第 1 段和第 2 段:
For an aggregate of a one-dimensional array type, each choice shall specify values of the index type, and the expression of each element association shall be of either the element type or the type of the aggregate. If the type of the expression of an element association is the type of the aggregate, then either the element association shall be positional or the choice shall be a discrete range.
For an element association with a choice that is a discrete range and an expression of the element type of the aggregate, the value of the expression is the element at each index value in the range.
IEEE 标准 1076-1993 数组聚合第 1 段:
For an aggregate of a one-dimensional array type, each choice must specify values of the index type, and the expression of each element association must be of the element type. An aggregate of an n-dimensional array type, where n is greater than 1, is written as a one-dimensional aggregate in which the index subtype of the aggregate is given by the first index position of the array type, and the expression specified for each element association is an (n-1)-dimensional array or array aggregate, which is called a subaggregate. A string or bit string literal is allowed as a subaggregate in the place of any aggregate of a one-dimensional array of a character type.
在-2008年我们允许关联元素是聚合类型(一维数组类型)。这允许关联相同类型的切片名称。
同时-2008 9.3.3.3 para 7允许使用others选择:
e) As a value expression in an assignment statement, where the target is a declared object (or member thereof), and either the subtype of the target is a fully constrained array subtype or the target is a slice name
(目标是切片名称已从以前的修订版中添加。)可以使用 others 选择的规则要求您具有提供子类型约束的上下文.
所以它告诉我们您正在使用的 VHDL 实现不兼容 -2008(或未被用作 -2008 兼容)。
此功能是升级到 -2008 兼容性时实现的优先级通常较低的功能之一。
如果您发现您的 VHDL 工具缺乏支持,可以使用其他方式来表达您的移位器,例如:
SHIFTER:
process (operand_b, operand_a)
variable b: integer range 0 to operand_a'HIGH;
begin
result <= (others => '0');
if not is_x(operand_b) then -- culling meta-values
b := to_integer(unsigned(operand_b));
for i in result'range loop
if i = b then
result(result'high downto i) <=
operand_a (operand_a'high - i downto 0);
end if;
end loop;
end if;
end process;
此过程符合综合条件,因为切片范围取决于包括循环常量在内的静态值,循环展开或并行化以进行综合。 operand_b
的每个二进制值都有一个赋值语句,您依赖于综合优化(对于多路复用器和移位器之类的东西来说效果非常好)。
此方法的工作原理是将所有 result
写入“0”,然后将 operand_a
所需的部分写入 result
。它取决于同一进程内的顺序分配(并且可以在 -2008 兼容实现中与顺序条件信号分配一起使用)以及 if 语句或 case 语句。 (但不是取决于同一左侧目标的选定信号分配)。
在一个进程中执行的两个赋值语句取决于有一个驱动程序并且由综合支持。最后写入的数组元素值会覆盖之前写入的数组元素值,投影输出波形中任何特定模拟时间只有一个时隙。