【问题标题】:display 3-bit on 7 segment display在 7 段显示器上显示 3 位
【发布时间】:2018-10-23 15:08:05
【问题描述】:

我想在 4 位 7 段显示器上显示 3 位二进制,并按下适当的开关。 例如:- 如果开关位置为 001(switch2-off switch1-off switch0-on) 然后我想在 7 段显示器上显示 001。 我使用 VHDL 来做这件事。 尝试了多路复用,但仍然无法正常工作。 下面是代码。

    entity test is
    Port(Seg_AN :out std_logic_vector(3 downto 0);
            Seg7    :out std_logic_vector(6 downto 0);
            SWITCH  :in std_logic_vector(2 downto 0);
            CLK :in std_logic
            );
end test;

architecture Behavioral of test is
    signal sel  :natural range 0 to 8;
    signal anode_sel    :std_logic_vector(2 downto 0);
--  signal number   :std_logic_vector(2 downto 0);
    constant c_cnt_200hz    :natural    := 87500;
--  constant c_cnt_1hz  :natural    := 17500000;
    signal r_cnt_200hz  :natural range 0 to c_cnt_200hz;
--  signal r_cnt_1hz    :natural range 0 to c_cnt_1hz;
    signal anode    :std_logic_vector(2 downto 0);
    signal segment  :std_logic_vector(6 downto 0);
--  signal digit    :std_logic;
begin
    process(CLK)
    begin
        if rising_edge(CLK) then
            if r_cnt_200hz = c_cnt_200hz - 1 then
                r_cnt_200hz <= 0;
                if sel = 8 then
                    sel <= 0;
                else
                    sel <= sel + 1;
                end if;
            else
                r_cnt_200hz <= r_cnt_200hz + 1;
            end if;
        end if;
    end process;

    process(sel)
    begin
        case sel is
            when 1 => anode_sel <= "001";
            when 2 => anode_sel <= "010";
            when 3 => anode_sel <= "100";
            when 4 => anode_sel <= "011";
            when 5 => anode_sel <= "101";
            when 6 => anode_sel <= "110";
            when others => anode_sel <= "111";
        end case;
        anode <= not anode_sel;
    end process;

    process(anode)
    begin
        if SWITCH(0)='1' or SWITCH(1)='1' or SWITCH(2)='1' then
            segment <= "1111001";
        else 
            segment <= "1000000";
        end if;
    end process;

    Seg_AN <= '1' & anode;
    Seg7 <= segment;
end Behavioral;

【问题讨论】:

  • 您只需要在显示 0 和 1 之间切换即可控制 4 个段:0= 段打开,1= 段关闭。除了三位的所有 VHDL 头文件、库实体等之外,您可以使用三行代码来完成。
  • @Oldfart 请你说清楚。
  • 使用 4 Khz 时钟(c_cnt_200hz = 20,用于更快的仿真)。 Note more than one anode (Seg_AN) is on at a time。显示 0 还是 1 取决于启用的阳极和相应的开关。 still not working 不是一个明确的问题陈述。你在问什么?

标签: vhdl fpga seven-segment-display


【解决方案1】:

参考下图:

  • 要显示 ONE,您需要打开 B 和 C。

  • 要显示零,您需要打开 A、B、C、D、E、F。

因此实际上您只需打开或关闭 A、D、E、F。 对于 ONE,他们需要关闭,对于 ZERO,他们需要开启。

您的代码需要:

  • 始终保持 B 和 C 开启。 (两个不变的输出)

  • 始终保持 G 关闭。 (第三个输出不变)

  • 根据您的位开关位置同时打开或关闭所有 A、D、E、F。那是四个输出都具有相同的值。

唯一的问题是您是否需要逆变器。这取决于开关和/或 LED 是连接到高电平有效还是低电平有效。

【讨论】:

  • 优化对阳极敏感的过程中的 if 语句将产生没有语义复杂性的等效逻辑,并且该论述并不能解决 OP 的未指定问题。 (这个答案是评论)。
  • 我同意,它从评论开始,但 OP 询问“请您说清楚”,仅使用评论中可用的功能非常困难。 (例如没有图片)
  • 当我的 fpga 通电时,我会在三位数字上显示 0。但是如果一个开关打开,那么所有数字都会显示为 1,而我希望它在与按下的开关对应的数字上显示 1,并且剩余的数字需要显示为 0。如果按下 switch0,那么我想显示为 001 而不是只显示 1 并且剩余的数字为 OFF。
  • 在您的端口声明中看到一个端口用于 one 段,但用于 three 开关。在我看来,您缺少对另外两个细分的控制。
  • Seg_AN 端口处理 4 位数字,其中第 4 位数字始终为 OFF,其他 3 位数字由 3 个开关控制。
【解决方案2】:

我建议通过纯组合逻辑来实现解决方案,您实际上并不需要寄存器(在使用时钟的上升/下降沿时合成)。

你可以在时钟之外给它计时(通过一些寄存器)。

LIBRARY     ieee;
    USE     ieee.std_logic_1164.all;

Entity SEG7_LUT is
port(   oSEG  : out std_logic_vector (6 downto 0); 
        iDIG  : in std_logic_vector  (3 downto 0));
end entity SEG7_LUT;

Architecture RTL of SEG7_LUT is
begin

logic : process (iDIG) begin 
    case iDIG is 
        when x"1" => oSEG <= "1111001";
        when x"2" => oSEG <= "0100100";     -- |--rt--|
        when x"3" => oSEG <= "0110000";     -- lt    rt
        when x"4" => oSEG <= "0011001";     -- |      |
        when x"5" => oSEG <= "0010010";     -- ---m----
        when x"6" => oSEG <= "0000010";     -- |      |
        when x"7" => oSEG <= "1111000";     -- lb    rb
        when x"8" => oSEG <= "0000000";     -- |      |
        when x"9" => oSEG <= "0011000";     -- ---b----
        when x"a" => oSEG <= "0001000";
        when x"b" => oSEG <= "0000011";
        when x"c" => oSEG <= "1000110";
        when x"d" => oSEG <= "0100001";
        when x"e" => oSEG <= "0000110";
        when x"f" => oSEG <= "0001110";
        when x"0" => oSEG <= "1000000";
    end case; 
end process logic; 

end;

下面的代码给出了一个在八个 7 段显示器上以十六进制格式表示 32 位数字的示例。

LIBRARY     ieee;
    USE     ieee.std_logic_1164.all;

Entity SEG7_LUT_8 is
    port( oSEG0 : out std_logic_vector (6 downto 0); 
          oSEG1 : out std_logic_vector (6 downto 0); 
          oSEG2 : out std_logic_vector (6 downto 0); 
          oSEG3 : out std_logic_vector (6 downto 0); 
          oSEG4 : out std_logic_vector (6 downto 0); 
          oSEG5 : out std_logic_vector (6 downto 0); 
          oSEG6 : out std_logic_vector (6 downto 0); 
          oSEG7 : out std_logic_vector (6 downto 0);
          iDIG  : in std_logic_vector (31 downto 0));
end;

Architecture RTL of SEG7_LUT_8 is 
begin 
u0  : entity work.SEG7_LUT port map(    oSEG0,iDIG(3  downto 0)     );
u1  : entity work.SEG7_LUT port map(oSEG1,iDIG(7  downto 4)     );
u2  : entity work.SEG7_LUT port map(oSEG2,iDIG(11 downto 8)     );
u3  : entity work.SEG7_LUT port map(oSEG3,iDIG(15 downto 12)    );
u4  : entity work.SEG7_LUT port map(oSEG4,iDIG(19 downto 16)    );
u5  : entity work.SEG7_LUT port map(oSEG5,iDIG(23 downto 20)    );
u6  : entity work.SEG7_LUT port map(oSEG6,iDIG(27 downto 24)    );
u7  : entity work.SEG7_LUT port map(oSEG7,iDIG(31 downto 28)    );

end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    • 1970-01-01
    • 2012-03-10
    • 2018-02-05
    • 2019-05-28
    • 1970-01-01
    相关资源
    最近更新 更多