VHDL - 如何有效地将整数转换为ascii或8位slv

时间:2016-04-24 14:48:23

标签: serial-port vhdl uart usart

我正在尝试通过串行输出不同的(非常量)值。串行通信工作正常,但似乎没有一种优雅的,可综合的方法将任何大小和值的任何整数/自然/ std_logic_vector / unsigned / signed类型转换为基于ASCII表的8位std_logic_vectors数组。这是非常奇怪的,因为我想要做的事并不罕见。

我能做到这一点的一种方法是使用大型查找表或if-elsif-else语句的长嵌套链,但这看起来非常低效且不优雅。

这不是sysnthesize:

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

说出你对这个函数的看法,但请记住,当我需要它时会产生正确的结果,而不是几个周期之后,并且简单明了。我可以轻松扩展它以覆盖负数和更大的数字。

2 个答案:

答案 0 :(得分:0)

以十进制输出是绝对必要的吗? 如果你想要效率,十六进制输出是你要走的路。 要克隆十六进制输出,只需将整数分成4位组,然后将每个组转换为ASCII字符0-F。

将int转换为十进制ASCII表示是一项计算繁重的操作,因为它需要很多分区。

但如果这是你需要的,那么更有效的方法之一就是创建一个状态机,每个时钟周期计算一个数字。状态机需要在每个时钟周期执行以下操作:

  • 将整数X除以10并将结果存储回X.
  • 计算余数。
  • 通过向其余部分添加x'30'来生成ASCII数字。

状态机必须运行10个时钟周期才能将32位整数转换为ASCII十进制。

答案 1 :(得分:0)

您需要设计一个如本文所述的小电路,并将其用于BCD转换器的内插器,请参阅第2页上的值0到9999的示例,这将满足您的需求。

微米。 Benedek,“开发大型二进制到BCD转换结构”,第三届IEEE计算机算术研讨会论文集,南卫理公会大学,德克萨斯州达拉斯,1975年11月19日至20日 http://www.acsel-lab.com/arithmetic/arith3/papers/ARITH3_Benedek.pdf