【问题标题】:Decimal number on 7 segment display7 段显示器上的十进制数
【发布时间】:2014-01-01 08:07:15
【问题描述】:

我对一个项目的 VHDL 有一个大问题。我想在 7 段显示上看到用户用开关设置的数字。例如,如果低位 5 个开关打开,那么它们将代表二进制数“11111”,即十进制的 31。所以我想在 7 段显示器上看到 31。

为此,我计划了以下步骤:

  • 将开关的5值插入数组
  • 将数组转换为整数
  • 将整数看成7段显示

第 1 点)插入数组

     signal first: std_logic_vector (0 to 4);
     signal temp: integer range 0 to 9999:=0;
     for i in 0 to 4 loop
           first(i)<=SW(i);
     end loop;
     temp<=VEC_TOINT(first);
     HEX0<=INT_TO7SEG(temp);

第 2 点)向量到整数

     Function VEC_TOINT(Vector: in std_logic_vector) return integer is
     variable temp: bit_vector(Vector'range);
     variable result: integer :=0;
     Begin
          for index in Vector'range loop
               result:=result * 2 + bit'pos(temp(index));
          end loop;
          if Vector(Vector'left) = '1' then 
               result:=(-result)-1;
          end if;
          return result;
     End VEC_TOINT;

关于第三点,目前我不知道。

【问题讨论】:

  • 如果你真的不知道第三部分,那么你应该考虑另一条职业道路。另一方面,如果您确实有一些想法,那么您应该告诉我们您对该问题的理解。因为你只是要求我们为你做功课。
  • 您的 7 段显示器要么具有内置编码器,要么更可能接受每个字符 7 位,每个位代表一个段。显示器应该附带一些文档(或者可能在连接器上编号),指示哪个位对应于哪个段。如果它们从上到下按左右行编号,则 1,2,4,6,7 将是字符“5”,而 1,3,6 将是字符“7”。 (画出来。)一个简单的 10 字节转换表会将数字转换为它们的段编码。
  • 数字 A-F 有点棘手。 A、C、E、F 很简单,B 通常呈现为“b”,D 通常呈现为“d”。

标签: arrays vhdl


【解决方案1】:

我写了一个小包,可以满足你的需求。给定一个无符号输入值,它将这个值分解为一系列十进制数字,并生成可以驱动任意数量的七段显示器的信号。

以下是您如何使用它的示例:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.seven_segment_pkg.all;

entity switches_to_7seg_displays is
    port (
        switches: in std_logic_vector(4 downto 0);
        seven_segments_display_1: out std_logic_vector(6 downto 0);
        seven_segments_display_2: out std_logic_vector(6 downto 0)
    );
end entity switches_to_7seg_displays;

architecture behavior of switches_to_7seg_displays is
    signal segments: std_logic_vector(13 downto 0);
    signal input: integer;
begin

    input <= to_integer(unsigned(switches));

    segments <= unsigned_to_seven_segment(
        value => unsigned(switches),
        number_of_digits => 2,
        value_is_bcd => false          
    );

    seven_segments_display_1 <= segments(13 downto 7);
    seven_segments_display_2 <= segments(6 downto 0);

end;

请注意,输入值是无符号的。要将 std_logic_vector 转换(实际上是“类型转换”)为无符号,只需使用:

switches_uns <= unsigned(switches_slv);

如果出于某种原因您决定将开关中的值转换为整数,ieee.numeric_std 中有一个函数可以执行此操作。使用它而不是自己编写是个好主意。您可以将其用作:

switches_int <= to_integer(unsigned(switches_slv));

最后,这是包的代码。欢迎您使用或研究它并提出自己的解决方案。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

package seven_segment_pkg is

    -- Return a std_logic_vector ready for driving a number of 7-segment displays.
    function unsigned_to_seven_segment(
        value: unsigned;
        number_of_digits: integer;
        value_is_bcd: boolean
    ) return std_logic_vector;

end;

package body seven_segment_pkg is

    function seven_seg_from_bcd_digit(bcd_digit: std_logic_vector(3 downto 0)) 
        return std_logic_vector 
    is begin
        case bcd_digit is
            --                   abcdefg
            when x"0" => return "0111111";
            when x"1" => return "0000110";
            when x"2" => return "1011011";
            when x"3" => return "1001111";
            when x"4" => return "1100110";
            when x"5" => return "1101101";
            when x"6" => return "1111101";
            when x"7" => return "0000111";
            when x"8" => return "1111111";
            when x"9" => return "1101111";
            when x"a" => return "1110111";
            when x"b" => return "1111100";
            when x"c" => return "0111001";
            when x"d" => return "1011110";
            when x"e" => return "1111001";
            when x"f" => return "1110001";
            when others => return "0000000";
        end case;
    end;

    -- Return a vector ready for driving a series of 7-segment displays.
    function unsigned_to_seven_segment(
        value: unsigned;
        -- Number of 7-segment displays (determines output vector width: W = 7*N)
        number_of_digits: integer;
        -- When true, treat the input value as a BCD number where every 4 bits hold one
        -- digit from 0 to A. When false, treat the input number as an unsigned integer.       
        value_is_bcd: boolean
    ) return std_logic_vector is

        variable segments: std_logic_vector(number_of_digits*7-1 downto 0);
        variable bcd_quotient: unsigned(value'range);
        variable bcd_remainder: unsigned(3 downto 0);
    begin

        if value_is_bcd then
            for i in 0 to number_of_digits-1 loop
                segments(i*7+6 downto i*7) := seven_seg_from_bcd_digit(
                    std_logic_vector(value(i*4+3 downto i*4))
                );
            end loop;
        else
            bcd_quotient := value;
            for i in 0 to number_of_digits-1 loop
                bcd_remainder := resize(bcd_quotient mod 10, 4);
                bcd_quotient := bcd_quotient / 10;
                segments(i*7+6 downto i*7) := seven_seg_from_bcd_digit(
                    std_logic_vector(bcd_remainder)
                );
            end loop;

        end if;

        return segments;
    end;

end;

【讨论】:

  • 嗨瑞克!首先,新年快乐,谢谢。最后我开始明白一些东西,对不起我的愚蠢问题,但我刚刚开始学习 VHDL,这并不像我一开始想的那样容易。另一个问题,如果可能的话,我的老师给我们一些幻灯片和一本书,里面什么都不写!你能告诉我一本我可以学习VHDL的好书吗?非常感谢您的合作,您非常但非常友善
  • 我喜欢 Pedroni 的 Cicuit Design with VHDL 的示例和 Ashenden 的 Designer's Guide to VHDL 的彻底性。如果您受限于免费在线资源,您可以查看Free Range VHDL
  • @rick 感谢您的工作。但我认为提供完整代码并不是学习的正确方法,它可能会误导在不理解的情况下复制和粘贴。
  • 我也有同样的担忧,@Sebastian,但我也觉得 VHDL 缺乏正确编写代码的示例。甚至教科书和课堂幻灯片也提供了糟糕的例子、草率的建议和不明智的指导方针。我相信编程不能通过泛泛而谈来教,而培养优秀程序员的最好方法就是向他们展示优秀的例子。我并不是说我编写的代码总是堪称典范,但宣传它是获得建设性 cmets 的好方法。此外,OP 的问题是许多人真正需要的,这就是我首先编写库的原因
  • +1 @Sebastian,也就是说,我认为您的评论非常恰当,值得点赞
【解决方案2】:

我保证的最后一个问题:)

我开始研究您的代码并考虑工作,因此我决定插入另一个输入,其中包含我拥有的最后两个十六进制显示并将它们相加

所以我创建广告插入这部分代码

      -- insert into entity         
      key: in std_logic_vector(3 downto 0);
      clock_50: in std_logic;

      signal input2: integer;
      signal result: integer;
      signal result1: unsigned;
      .............. -- the declaration of the 2° input is the same of the first

      Process(Clock_50)
      Begin
      if(CLOCK_50' EVENT AND CLOCK_50='1' AND KEY(0)='1') THEN
             result <= input1 + input2;
             result1 <=to_unsigned(integer((result), result1'length));
             segmentsR <= unsigned_to_seven_segment(Value => unsigned(result1), number_of_digits =>2, value_is_bcd =>false);
      HEX1 <= segmentsR(13 downto 7);
      HEX0 <= segmentsR(6 downto 0);
  End if;
  End Process;

有一个错误,我找不到“Near text”:”;期待“)”或“,”......据我所知,合成器是正确的,因为在 input1 上,input2 我已经使用了该功能to_integer....

最好的问候

米歇尔

【讨论】:

  • 嗨@Michele,在 Stackoverflow 中,使用 aswer 提供有关您自己问题的其他信息是一种不好的形式;您可能应该创建一个新问题,或编辑原始问题。
【解决方案3】:

要解决 3),您必须了解 7 段显示的工作原理,特别是字符显示。基本上,您必须实现从整数到显示的十六进制编码的编码器。显示器的数据表中提供了十六进制编码,例如this datasheet 显示哪些显示引脚连接到哪个段。 wikipedia 提供了一个示例性的十六进制代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    • 2020-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多