3
\$\begingroup\$

I am preparing a program in VHDL and I got stuck in type-conversion. I tryed google-search and also here at stack exchange, but I am quite confused since one answer contradicts other and neither one I can get to work. But finally to the question of mine: I have to display ordinary digital clocks. I have got from my professor decoder for 7 segment display which takes as input std_logic_vector(3 downto 0). And my part is to provide data (more specifically set of digits) to display. Most of work is already done but I am struggling to convert from my variables e.g. minutes (it is std_logic_vector(4 downto 0)) to two decimal digits. I have done separation this way:

if (min >= 50) then
  d3 <= 5;
  d4 <= min - 50;
elsif (min >= 40) then
  d3 <= 4;
  d4 <= min - 40;
elsif 
...
end if;

(Maximal value of min is 59 and if it get this high, it resets to 0 and hours counter get +1, just like ordinary clocks). Thus d3 should display tens of minutes and d4 unites of minutes. As you probably had already guessed, since min has length of 5, I can not compile it (d4 accepts length of 4 tops). Thus my idea is to convert min to integer, subtract number (e.g. 50) and convert back to std_logic_vector with right length (actual value would be in range 0 to 9, thus no problem with length of four bits). I tried to preform something like this:

d4 <= std_logic_vector(unsigned(integer(unsigned(min)) - 50));

but without success. I had always ended with errors like unknown function, type mismatch or no matching overload for method, no matter what combination I tried. Apparently I got somewhere some trivial error, but I fail to see it. I use those:

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

Please can you point me to the right direction? I am running out of ideas.

Thank you very much for your time, Michal

EDIT: Inputs, outputs, variables declarations as requested are:

port (sw2, sw1, sw0: in std_logic;  -- input switches
        clock:       in std_logic;
        reset:       in std_logic;
        d0, d1, d2, d3, d4, d5, d6, d7: out std_logic_vector(3 downto 0);  -- outputs for eight units of 7segment display decoders
        dp0, dp1, dp2, dp3, dp4, dp5, dp6, dp7: out std_logic);  -- outputs for decimal points

  attribute loc : string; 
  attribute loc of sw0   : signal is "P7";
  attribute loc of sw1   : signal is "P9";
  attribute loc of sw2   : signal is "P10";
  attribute loc of clock : signal is "P2"; 
  attribute loc of reset : signal is "P11"; 

end main_1048;

architecture main_1048arch of main_1048 is
begin
process(sw2, sw1, sw0, clock, reset)
variable yrs: std_logic_vector(11 downto 0);
variable min, sec: std_logic_vector(4 downto 0);
variable hrs, day, mth: std_logic_vector(3 downto 0);
begin

EDIT2: After deleting libs std_logic_arith a std_logic_unsigned as sugested by Brian Drummond and redefining variables so they are now naturals. New errors were No matching overload for "-". According to the specifications I found, "-" should work:

function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED;
  -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0).
  -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L.

Thus final edit was to d4 <= std_logic_vector(min - to_unsigned(50,4)); (with declaration variable min: natural range 0 to 59;) and this (concerning typecast) works.

Thank you all for your help!

\$\endgroup\$
  • \$\begingroup\$ Please post the declarations of all your signals, otherwise we have to assume what type min/d3/d4 etc. have. \$\endgroup\$ – damage Sep 2 '15 at 15:42
  • \$\begingroup\$ @damage: Added then as requested along with a few others, but not all. \$\endgroup\$ – Rao Sep 3 '15 at 7:38
3
\$\begingroup\$

First delete the non-standard std_logic_arith and std_logic_unsigned libraries, leaving std_logic and numeric_std.

As well as being non-standard, they cause problems through a VHDL rule that - if two definitions of a type (or procedure or operator or whatever) are visible - like unsigned or <= - VHDL will try to discover which you intended (e.g. by the parameter types of the operator, because overloaded operators are legal).

But if two definitions are visible and indistinguishable - both are considered to be hidden. This makes you FIX the problem instead of allowing the compiler to pick one - probably wrong - at random.

So with only the standard libraries, things get a lot simpler.


Now another basic rule is that if you are fighting with lots of type conversions, something is declared the wrong type, which points to a design error.

I'm going to guess the mistake : min should be declared as unsigned but isn't. (Ditto d3 etc). It represents an unsigned number in bit (std_logic) form. So declare it as such.

Fix that and see what happens. But first, find the source for the numeric_std package (the package spec, don't bother with the package body). You will see a lot of operators that allow unsigned and integer to interact directly.

Then I would expect your code snippet to work directly, without any type conversions.

If you don't actually need the bits of min, go further and declare it as a subtype of natural with range 0 to 59. There is no reason not to do so, even for synthesis, and for ports on a component.

It is usually appropriate to use unsigned (or even std_logic_vector if you must) for ports at the very top level, where you need to connect each bit to an FPGA pin. But internally, convert to the types most appropriate to the design as soon as you can.

\$\endgroup\$
  • \$\begingroup\$ Thank you very much for your ideas. I had done redefining all internal variables as natural since I am not interested in their exact bit interpretation, and removed those two non-standard libs. And results are such that ` d4 <= min - 50 ` keeps complaining that it doesn't have matching overload for minus: @E: CD371 :"E:\main_1048.vhd":197:17:197:24|No matching overload for "-" ?"-"(variable:min, 20) @E: CD308 :"E:\main_1048.vhd":197:17:197:24|Unable to evaluate expression type I will now go to fetch package specs and see if some idea will strike me. Anyway, thanks! \$\endgroup\$ – Rao Sep 3 '15 at 7:58
  • \$\begingroup\$ Thanks to your ideas and help I made this part of code working, see original post EDIT2. Thank you very much. \$\endgroup\$ – Rao Sep 3 '15 at 8:54
  • \$\begingroup\$ Good! Now you are using that library instead of blindly coding and hoping it works. The overload failure occurs because "-"(natural,natural) returns natural. You could apply to_unsigned to that result, and it might be cleaner for the reader (less "tricky"), but both versions should generate the same hardware. \$\endgroup\$ – Brian Drummond Sep 3 '15 at 9:34
  • \$\begingroup\$ I have to admit that you are totally right :-) \$\endgroup\$ – Rao Sep 3 '15 at 9:44
  • 1
    \$\begingroup\$ Also using code style of other peoples isn´t allways the best practice. This was the basic problem, since I copied a style of declarations and libraries, thus here comes problems... :-) \$\endgroup\$ – Rao Sep 3 '15 at 10:30
1
\$\begingroup\$

Using the information you have given, I assume you are using incorrect type conversion functions.
Assuming min and d4 are std_logic_vectors the line to calculate d4 should look like:

d4 <= std_logic_vector(to_unsigned(to_integer(unsigned(min)) - 50, d4'length));

When converting between the types unsigned and integer the functions to_unsigned() and to_integer() are your friends. The second argument to to_unsigned() is the length of the resulting unsigned value.

\$\endgroup\$
  • \$\begingroup\$ Thank you for your idea, but it doesn´t work. I already tryed it, but it fails with message "Cast of incompatible types" and highlighting the unsigned(min). P.S. min is of type natural. \$\endgroup\$ – Rao Sep 3 '15 at 8:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.