0

I want to display 3-bit binary on 4-digit 7 segment display with appropriate switch pressed. For eg :- if switch positon is 001(switch2-off switch1-off switch0-on) then i want to display 001 on 7 segment display. Im doing this using VHDL. Tried multiplexing but still not working. Below is the code.

    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;
RobyJacob
  • 1
  • 5
  • All you need to switch between displaying 0 and 1 is to control 4 segments: 0= segments on, 1= segments off. Apart from all the VHDL header, libraries entities etc. for three bits, you can do that with three lines of code. – Oldfart Oct 21 '18 at 17:10
  • @Oldfart pls could you make it clear. – RobyJacob Oct 21 '18 at 18:12
  • With a 4 Khz clock (c_cnt_200hz = 20, for faster simulation). [Note more than one anode (Seg_AN) is on at a time](https://i.stack.imgur.com/XcZvu.jpg). Whether you display a 0 or a 1 should depend on which anode is enabled and a corresponding switch. *still not working* isn't a clear problem statement. What are you asking? –  Oct 21 '18 at 20:22

2 Answers2

1

Referring to the picture below:

  • To show a ONE you need B and C on.

  • To show a ZERO you need A, B, C, D, E, F on.

So in effect you only need to switch A,D,E,F on or off. For ONE they need to be off, for a ZERO they need to be on.

Typical & segment

Your code needs to:

  • Keep B and C on all the time. (Two outputs which do not change)

  • Keep G off all the time. (A third outputs which does not change)

  • Switch all of A,D,E,F simultaneous on or off depending on your bit switch position. That is four outputs which all have the same value.

The only problem is if you need an inverter or not. That depends on if the switch and/or the LEDS are connected for active high or active low operation.

Oldfart
  • 6,104
  • 2
  • 13
  • 15
  • Optimization of the if statement in the process sensitive to anode would produce the equivalent logic without the semantic rigmarole and this discourse doesn't cure the OP's unspecified problem. (This answer is a comment). –  Oct 21 '18 at 20:22
  • I agree, it started as a comment but the OP asked "pls could you make it clear" which is very difficult using only features available in a comment. (e.g. no picture) – Oldfart Oct 22 '18 at 03:59
  • when my fpga is powered i get 0's displayed on three digits.But if one switch is ON then all digits get displayed as 1's whereas i want it to display 1 on the digit corresponding to the switch pressed and the remaining digits need to be displayed as 0.If switch0 is pressed then i want to display as 001 instead of just displaying 1 and the remaining digits being OFF. – RobyJacob Oct 22 '18 at 05:31
  • In your port declaration is see a port for *one* segment but for *three* switches. It looks to me your are missing control for two more segments. – Oldfart Oct 22 '18 at 06:04
  • Seg_AN port handles 4-digits where the 4th digit is always OFF and the other 3 digits are controlled by 3 switches. – RobyJacob Oct 22 '18 at 06:50
  • In that case you need to add a 3-bit counter to mux the three switches to the display and control the enable with the counter too. – Oldfart Oct 22 '18 at 07:04
0

I recommend to implement the solution by pure combinational logic, you don't really need the registers (synthesized when you use rising/falling edge of clock).

You can clock it(put it through some registers) outside the clock.

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;

The code below gives an example of representing 32 bit number in hexadecimal format on eight 7 segment displays.

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;
CJC
  • 795
  • 8
  • 25