VHDL - 如何有效地将整数转换为 ascii 或 8 位 slv
VHDL - How to efficiently convert integer to ascii or 8-bit slv
我正在尝试通过串行输出不同的(非常量)值。串行通信工作正常,但似乎没有一种优雅的、可综合的方法来将任何大小和值的任何 integer/natural/std_logic_vector/unsigned/signed 类型转换为基于 ASCII [=] 的 8 位 std_logic_vectors 数组33=]。这太奇怪了,因为我正在尝试做的事情并不少见。
我可以做到这一点的一种方法是使用大查找 table 或 if-elsif-else 语句的长嵌套链,但这似乎非常低效且不优雅。
这不综合:
eight_bit_result <= std_logic_vector(to_unsigned(character'pos(some_integer), 8));
ISE 14.7 因某些头文件引起的模糊错误而中断。即使它确实有效,它也不适用于 0-255 之外的值。正确的做法是什么?
编辑:
我写了一个快速而肮脏的函数来覆盖整数值 0-9999。它不需要时钟进程,不需要额外的实体等。目前提出的答案似乎过于复杂。
function get_ascii_array_from_int(i : integer range 0 to 9999) return char_array is
variable result : char_array(0 to 3) := (x"30", x"30", x"30", x"30"); -- 0000
begin
if i >= 0 then
if i < 1000 then
result(0) := x"30"; -- 0
result(1 to 3) := get_ascii_array_from_int_hundreds(i);
elsif i < 2000 then
result(0) := x"31"; -- 1
result(1 to 3) := get_ascii_array_from_int_hundreds(i-1000);
elsif i < 3000 then
result(0) := x"32"; -- 2
result(1 to 3) := get_ascii_array_from_int_hundreds(i-2000);
elsif i < 4000 then
result(0) := x"33"; -- 3
result(1 to 3) := get_ascii_array_from_int_hundreds(i-3000);
elsif i < 5000 then
result(0) := x"34"; -- 4
result(1 to 3) := get_ascii_array_from_int_hundreds(i-4000);
elsif i < 6000 then
result(0) := x"35"; -- 5
result(1 to 3) := get_ascii_array_from_int_hundreds(i-5000);
elsif i < 7000 then
result(0) := x"36"; -- 6
result(1 to 3) := get_ascii_array_from_int_hundreds(i-6000);
elsif i < 8000 then
result(0) := x"37"; -- 7
result(1 to 3) := get_ascii_array_from_int_hundreds(i-7000);
elsif i < 9000 then
result(0) := x"38"; -- 8
result(1 to 3) := get_ascii_array_from_int_hundreds(i-8000);
else
result(0) := x"39"; -- 9
result(1 to 3) := get_ascii_array_from_int_hundreds(i-9000);
end if;
else
result := (x"6e", x"65", x"67", x"23"); -- "neg#"
end if;
return result;
end get_ascii_array_from_int;
您可能已经猜到了,还有其他三种方法:get_ascii_array_from_int_hundreds
get_ascii_array_from_int_tens
get_ascii_array_from_int_ones
说说你对这个函数的看法,但请记住,它会在我需要时产生正确的结果,而不是在几个周期之后,而且简单明了。我可以轻松地扩展它以涵盖负数和更大的数字。
是否绝对要求以十进制输出?
如果您想要提高效率,十六进制输出是您的不二之选。
要创建十六进制输出,您只需将整数分成 4 位组,并将每组转换为 ASCII 字符 0-F。
将 int 转换为十进制 ASCII 表示是一项计算量很大的操作,因为它需要很多除法。
但如果这是您需要的,更有效的方法之一是创建一个状态机,每个时钟周期计算一个数字。状态机每个时钟周期需要执行以下操作:
- 将整数 X 除以 10 并将结果存储回 X。
- 计算余数。
- 通过将 x'30' 加到余数来生成 ASCII 数字。
状态机必须 运行 10 个时钟周期才能将 32 位整数转换为 ASCII 十进制数。
您需要按照本文所述设计一个小电路,并将其用于整数到 BCD 转换器,请参见第 2 页上值 0 到 9999 的示例,这将满足您的需要。
米。 Benedek,"Developing Large Binary to BCD Conversion Structures",第三届 IEEE 计算机算术研讨会论文集,南卫理公会大学,德克萨斯州达拉斯,1975 年 11 月 19 日至 20 日
http://www.acsel-lab.com/arithmetic/arith3/papers/ARITH3_Benedek.pdf
我正在尝试通过串行输出不同的(非常量)值。串行通信工作正常,但似乎没有一种优雅的、可综合的方法来将任何大小和值的任何 integer/natural/std_logic_vector/unsigned/signed 类型转换为基于 ASCII [=] 的 8 位 std_logic_vectors 数组33=]。这太奇怪了,因为我正在尝试做的事情并不少见。
我可以做到这一点的一种方法是使用大查找 table 或 if-elsif-else 语句的长嵌套链,但这似乎非常低效且不优雅。
这不综合:
eight_bit_result <= std_logic_vector(to_unsigned(character'pos(some_integer), 8));
ISE 14.7 因某些头文件引起的模糊错误而中断。即使它确实有效,它也不适用于 0-255 之外的值。正确的做法是什么?
编辑:
我写了一个快速而肮脏的函数来覆盖整数值 0-9999。它不需要时钟进程,不需要额外的实体等。目前提出的答案似乎过于复杂。
function get_ascii_array_from_int(i : integer range 0 to 9999) return char_array is
variable result : char_array(0 to 3) := (x"30", x"30", x"30", x"30"); -- 0000
begin
if i >= 0 then
if i < 1000 then
result(0) := x"30"; -- 0
result(1 to 3) := get_ascii_array_from_int_hundreds(i);
elsif i < 2000 then
result(0) := x"31"; -- 1
result(1 to 3) := get_ascii_array_from_int_hundreds(i-1000);
elsif i < 3000 then
result(0) := x"32"; -- 2
result(1 to 3) := get_ascii_array_from_int_hundreds(i-2000);
elsif i < 4000 then
result(0) := x"33"; -- 3
result(1 to 3) := get_ascii_array_from_int_hundreds(i-3000);
elsif i < 5000 then
result(0) := x"34"; -- 4
result(1 to 3) := get_ascii_array_from_int_hundreds(i-4000);
elsif i < 6000 then
result(0) := x"35"; -- 5
result(1 to 3) := get_ascii_array_from_int_hundreds(i-5000);
elsif i < 7000 then
result(0) := x"36"; -- 6
result(1 to 3) := get_ascii_array_from_int_hundreds(i-6000);
elsif i < 8000 then
result(0) := x"37"; -- 7
result(1 to 3) := get_ascii_array_from_int_hundreds(i-7000);
elsif i < 9000 then
result(0) := x"38"; -- 8
result(1 to 3) := get_ascii_array_from_int_hundreds(i-8000);
else
result(0) := x"39"; -- 9
result(1 to 3) := get_ascii_array_from_int_hundreds(i-9000);
end if;
else
result := (x"6e", x"65", x"67", x"23"); -- "neg#"
end if;
return result;
end get_ascii_array_from_int;
您可能已经猜到了,还有其他三种方法:get_ascii_array_from_int_hundreds get_ascii_array_from_int_tens get_ascii_array_from_int_ones
说说你对这个函数的看法,但请记住,它会在我需要时产生正确的结果,而不是在几个周期之后,而且简单明了。我可以轻松地扩展它以涵盖负数和更大的数字。
是否绝对要求以十进制输出? 如果您想要提高效率,十六进制输出是您的不二之选。 要创建十六进制输出,您只需将整数分成 4 位组,并将每组转换为 ASCII 字符 0-F。
将 int 转换为十进制 ASCII 表示是一项计算量很大的操作,因为它需要很多除法。
但如果这是您需要的,更有效的方法之一是创建一个状态机,每个时钟周期计算一个数字。状态机每个时钟周期需要执行以下操作:
- 将整数 X 除以 10 并将结果存储回 X。
- 计算余数。
- 通过将 x'30' 加到余数来生成 ASCII 数字。
状态机必须 运行 10 个时钟周期才能将 32 位整数转换为 ASCII 十进制数。
您需要按照本文所述设计一个小电路,并将其用于整数到 BCD 转换器,请参见第 2 页上值 0 到 9999 的示例,这将满足您的需要。
米。 Benedek,"Developing Large Binary to BCD Conversion Structures",第三届 IEEE 计算机算术研讨会论文集,南卫理公会大学,德克萨斯州达拉斯,1975 年 11 月 19 日至 20 日 http://www.acsel-lab.com/arithmetic/arith3/papers/ARITH3_Benedek.pdf