2
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use IEEE.STD_LOGIC_ARITH.ALL;
--use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;

entity two_number_split is
    Port ( number  : in  integer range 0 to 99;
           position0 : out  STD_LOGIC_VECTOR (3 downto 0);
           position1 : out  STD_LOGIC_VECTOR (3 downto 0));
end two_number_split;

architecture Behavioral of two_number_split is
    signal pos0, pos1 : STD_LOGIC_VECTOR(3 downto 0);
begin
    convert: process(number, pos0, pos1)
    begin
            pos1 <= number/10;
            pos0 <= number mod 10;
            position0 <= std_logic_vector(pos0);
            position1 <= std_logic_vector(pos1);
    end process convert;

end Behavioral;

errors:

ERROR:HDLCompiler:1638 - "C:\Users\XXX\Documents\SS\ISE_Ex\seven_segment\two_numbers.vhd" Line 19: found '0' definitions of operator "/", cannot determine exact overloaded matching definition for "/"
ERROR:HDLCompiler:1638 - "C:\Users\XXX\Documents\SS\ISE_Ex\seven_segment\two_numbers.vhd" Line 20: found '0' definitions of operator "mod", cannot determine exact overloaded matching definition for "mod"

I think I am just using the wrong libraries. Any suggestions?I have tried all combinations of the libraries listed above and not sure what is going on.

marshmallow
  • 158
  • 1
  • 11

2 Answers2

5

You can modify the declarations of pos0 and pos1 to be an integer type, calculate and then convert them to a BCD representation.

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

entity two_number_split is
    port ( 
        number:     in   integer range 0 to 99;
        position0:  out  std_logic_vector (3 downto 0);
        position1:  out  std_logic_vector (3 downto 0)
    );
end two_number_split;

architecture Behavioral of two_number_split is
    signal pos0, pos1 : natural range 0 to 9; -- std_logic_vector(3 downto 0);
begin
    convert: process(number, pos0, pos1)
    begin
            pos1 <= number/10;
            pos0 <= number mod 10;
            position0 <= std_logic_vector(to_unsigned(pos0,position0'LENGTH)); 
            -- was <= std_logic_vector(pos0);
            position1 <= std_logic_vector(to_unsigned(pos1,position1'LENGTH));
            -- was <= std_logic_vector(pos1);
    end process convert;

end Behavioral;

It uses to_unsigned to convert the decimal digit values pos1 and pos0 to unsignedarray types. The returned unsigned array length is specified by the second argument which could simply be a literal.

You could use unsigned as the type for position0 and position1 and save a type conversions for each assignment.

The idea here is threefold: readability, using operator functions with compatible left and right arguments as well as return value, and the use of integer multiplying operators being faster than unsigned operators. Unsigned operation is implied by the natural range of number.

And this example works:

tb_numb_split.png

But isn't particularly synthesis eligible - having two multiplying operators. Should you need to synthesize something please see Convert 8bit binary number to BCD in VHDL for inspiration on how to avoid the seven bit multiplying operators.

Community
  • 1
  • 1
  • Just to note. While the division is problematic for synthesis in the general case, XST does support synthesis of inferred divmod by non-power-of-two constants for 6 and 7-series families. I was curious to see how it performed and the result fits into 7 LUTs for a 7-bit input, the same as a manually implemented two-digit BCD conversion. Other vendors may have similar support for constant division. – Kevin Thibedeau Sep 11 '14 at 13:07
  • @KevinThibedeau - [UG687](http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_1/xst_v6s6.pdf) P. 77, `mod` supported for constant power of 2, `/` "Supported if the right operand is a constant power of 2, or if both operands are constant". `number` isn't a constant, neither case is true, I'm pleasantly surprised - but it fits in a table, i.e. small enough to espresso. It can take 6 LUTs for add3 with BIN(7) a constant '0' (7 bit input), and is shift and conditional add (division step). add3 U0 in the block diagram not need, input cannot be greater than 4. –  Sep 11 '14 at 14:29
  • I was just as surprised to see it work because that was my recollection of the documentation. It does look like it is synthesizing a full divide or modulus operation in RTL view then merging shared paths and optimizing most of them away since only the lower four bits are retained in this case. – Kevin Thibedeau Sep 11 '14 at 16:45
  • Thank you. This has been very helpful. As you can probably tell, I am a bit of a VHDL noobie! I think I will implement this with BCD. It looks like a way better solution. – marshmallow Sep 12 '14 at 00:06
1

std_logic_vector is traditionally not a numeric type. It is a collection of bits and the numeric operators were intentionally left out to reinforce that interpretation. You should use the unsigned or signed types from numeric_std to get arrays with a suite of arithmetic operators.

Optionally, if your tools support VHDL-2008 you can use ieee.numeric_std_unsigned to add arithmetic semantics to std_logic_vector. It is similar to std_logic_unsigned which despite its name and library mapping is not a standard library.

Kevin Thibedeau
  • 3,299
  • 15
  • 26
  • I know a logic vector is an array of bits. But I'm taking in a decimal number and splitting it into two bit arrays representing each number. Ie. input of 99 would make pos0 1001 and pos1 1001. – marshmallow Sep 10 '14 at 22:56
  • That will happen provided you use a type with divide and mod operators defined. You have two options to accomplish that with the standard libraries as described in my answer. It looks like you're potentially attempting to output this to a seven-segment display in which case you may wish to look into conversion to BCD using the double-dabble algorithm which doesn't require any division. – Kevin Thibedeau Sep 10 '14 at 23:28