# Sum of switch-triggered integers in VHDL

I've implemented a VHDL program that sums up the positions of switches and shows it on a 7-segment LED, but I've had to use lots of temporaries and a division. Is there a better way?

library ieee;
use ieee.std_logic_1164.all;

entity light is
port(
LEDR : out std_logic_vector(0 to 9);
LEDG : out std_logic_vector(0 to 7);
SW : in std_logic_vector(0 to 9);
KEY : in std_logic_vector(0 to 3);
HEX0 : out std_logic_vector(0 to 6);
HEX1 : out std_logic_vector(0 to 6);
HEX2 : out std_logic_vector(0 to 6);
HEX3 : out std_logic_vector(0 to 6)
);
end light;

architecture arch of light is

signal sum, sum2 : integer := 0;
signal x1,x2,x3,x4,x5,x6,x7,x8,x9 : integer := 0;

function led_value(x:integer)
return std_logic_vector is
begin
case x is
when 0 => return "0000001";
when 1 => return "1001111";
when 2 => return "0010010";
when 3 => return "0000110";
when 4 => return "1001100";
when 5 => return "0100100";
when 6 => return "0100000";
when 7 => return "0001111";
when 8 => return "0000000";
when 9 => return "0000100";
when others => return "1111111";
end case;
end led_value;

begin
x1 <= 1 when sw(1) = '1' else 0;
x2 <= 2 when sw(2) = '1' else 0;
x3 <= 3 when sw(3) = '1' else 0;
x4 <= 4 when sw(4) = '1' else 0;
x5 <= 5 when sw(5) = '1' else 0;
x6 <= 6 when sw(6) = '1' else 0;
x7 <= 7 when sw(7) = '1' else 0;
x8 <= 8 when sw(8) = '1' else 0;
x9 <= 9 when sw(9) = '1' else 0;

sum <= x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9;
sum2 <= (sum - sum mod 10) / 10;

hex0 <= led_value(sum mod 10);
hex1 <= led_value(sum2);
hex2 <= led_value(11);
hex3 <= led_value(11);
end arch;

• Do you have a preference in which base the switches should be counted? – Mast Aug 31 '16 at 13:39
• @Mast well the idea was to count them in Base 10, so SW(1) contributes a 1 if switched, SW(8) an 8, and so on. – Dmitri Nesteruk Aug 31 '16 at 15:06

This is some old question, but lets answer it.

Synthesis software is not that dumb. It will evaluate the potential outcomes of a function and generate reduced logic from that. Often you have to aid the synthesis software somewhat. You could do that by writing a function which internally resolves the things you want.

N.B. constraining the range of your integers keep the resource usage low. Else everything will be implemented as a 32-bit value

library ieee;
use ieee.std_logic_1164.all;

entity light is
port(
SW : in std_logic_vector(0 to 9); -- why 'to' and not 'downto'??
KEY : in std_logic_vector(0 to 3); -- downto is normally used
HEX0 : out std_logic_vector(0 to 6);
HEX1 : out std_logic_vector(0 to 6);
HEX2 : out std_logic_vector(0 to 6);
HEX3 : out std_logic_vector(0 to 6);
LEDR : out std_logic_vector(0 to 9);
LEDG : out std_logic_vector(0 to 7)
);
end light;

architecture arch of light is
function hex_decode(x:integer)
return std_logic_vector is
begin
case x is
when 0 => return "0000001";
when 1 => return "1001111";
when 2 => return "0010010";
when 3 => return "0000110";
when 4 => return "1001100";
when 5 => return "0100100";
when 6 => return "0100000";
when 7 => return "0001111";
when 8 => return "0000000";
when 9 => return "0000100";
when others => return "1111111";
end case;
end hex_decode;

function add_input(input : std_logic_vector(0 to 9))
return natural is
variable sum : natural range 0 to 45 := 0;
begin
for i in 1 to 9 loop
if input(i)='1' then
sum := sum + i;
end if;
end loop;
return sum;

function select_decimal(input : natural; sel: natural)
return natural is
variable output : natural range 0 to 9;
begin
output := (input / (10**sel)) mod 10;
return output;
end function select_decimal;

signal switch_value : natural range 0 to 45;
begin

hex0 <= hex_decode(select_decimal(switch_value, 0));
hex1 <= hex_decode(select_decimal(switch_value, 1));
hex2 <= hex_decode(select_decimal(switch_value, 2));
hex3 <= hex_decode(select_decimal(switch_value, 3));
end arch;


---------------------------------------------------------------------------------
Start RTL Component Statistics
---------------------------------------------------------------------------------
Detailed RTL Component Info :
8 Input      6 Bit       Adders := 1
+---Muxes :
11 Input      7 Bit        Muxes := 2
2 Input      6 Bit        Muxes := 1
---------------------------------------------------------------------------------
Finished RTL Component Statistics
---------------------------------------------------------------------------------
Report Cell Usage:
+------+-------+------+
|      |Cell   |Count |
+------+-------+------+
|1     |CARRY4 |     2|
|2     |LUT2   |     2|
|3     |LUT3   |     1|
|4     |LUT4   |     4|
|5     |LUT5   |     7|
|6     |LUT6   |    15|
|7     |IBUF   |     9|
|8     |OBUF   |    28|
|9     |OBUFT  |    18|
+------+-------+------+

Report Instance Areas:
+------+---------+-------+------+
|      |Instance |Module |Cells |
+------+---------+-------+------+
|1     |top      |       |    86|
+------+---------+-------+------+

• You should avoid the division by using the double dabble algorithm to convert binary to decimal numbers. The binary to 7-segment encoder is low-active. That not a good design choice. Low-active conversation should be performed at the top-level VHDL file. – Paebbels Apr 1 '17 at 3:16
• -1. Your function doesn't include bit 0 of the input switches. The range of the integer makes no sense. A) so sum will never exceed 10, B) synthesis will strip off​ unused bits anyhow regardless of 32 or 6 bit. Moreover, 0..45 is not a power of two range. Initialization of variables does not work in Quartus. Note the original design uses only 2 digits. – Paebbels Apr 1 '17 at 3:23
• @paebbels you can either complain, or write your own, better answer. This question was asked six months ago, so you've had enough time to answer it. But nobody did, so I figured, I'd give it a try. – JHBonarius Apr 1 '17 at 7:13
• But @paebbels, I don't understand your second complaint about the range of sum. sum+0 is still sum, isn't it? And 1+2+3+4+5+6+7+8+9=45? Did you misread the question? I myself never had an issue with variable initialization, even in Quartus. – JHBonarius Apr 1 '17 at 7:20
• And I tried with no constraint on the integer, but vivado synthesis did not drop unused bits. I would show you if you tell me how to contract you. – JHBonarius Apr 1 '17 at 7:24