I've got a big problem with VHDL for a project. I want to see on 7 segment display a number that user sets with switches. For example if the low-order 5 switches are turned on then they will represent the binary number "11111" that is 31 in decimal. So I want to see 31 on 7 segment display.
To do that I plan these steps:
- Insert the 5 value of the switch into an array
- Convert the array into an integer number
- See the integer number into 7 segment display
Point 1) insert into an array
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);
Point 2) Vector to Integer
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;
For the third point at the moment I don't have any idea.
I've written a small package that does what you want. Given an unsigned input value, it breaks down this value into a series of decimal digits, and generates signals that can drive any number of seven-segments displays.
Here's an example of how you'd use it:
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;
Note that the input value is an unsigned. To convert (actually, "type cast") an std_logic_vector to an unsigned, just use:
switches_uns <= unsigned(switches_slv);
If for some reason you decide to convert the value from the switches to an integer, there's a function in ieee.numeric_std that does that. It's a good idea to use it rather than writing your own. You can use it as:
switches_int <= to_integer(unsigned(switches_slv));
Finally, here's the code for the package. You are welcome to use it or study it and come up with your own solution.
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;
Last questions i promise :)
I start to study your code and think about work, and so i decide to insert another input with the last two hex display that i have and sum them
so i create ad insert this part of code
-- 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;
There is a mistake that i can't find "Near text ":"; expecting ")", or "," .....according me the synthax is correct because on input1, input2 i already use the function to_integer....
Best Regards
Michele
To solve 3) you'll have to understand how a 7 segment display works, specifically character display. Basically you'll have to implement an encoder from integer to the hexadecimal encoding of the display. The hexadecimal encoding is provided in the data sheet of the display, e.g. this datasheet shows you which display pins are connected to which segment. An exemplary hexadecimal code is provided at wikipedia.