# Scaling an input in VHDL

I want to attenuate an incoming signal (16 bit signed number between -1 and 1) by a certain amount (let's say 0.8), i.e.,

incoming = incoming * 0.8


Where incoming is a signal:

signal incoming : std_logic_vector(15 downto 0);


But I'm having trouble getting this to work. Inside a process block:

variable temp : std_logic_vector(31 downto 0);
variable scale_factor : std_logic_vector(15 downto 0) := x"6666";

begin

incoming_raw <= data_in;
temp := incoming_raw * scale_factor;
incoming <= temp(31 downto 16);

end process;


ModelSim doesn't like this and gives me:

# ** Error: /home/blah/blah.vhd(254): No feasible entries for infix operator "*".
# ** Error: /home/blah/blah.vhd(254): Bad right hand side (infix expression) in variable assignment.


Why can't the * operator do this when both operands are 16 bit std_logic_vectors?

-
Aha! My mistake, the * operator needed the operands to be cast to signed. It should have been: temp := std_logic_vector(signed(incoming) * signed(scale_factor)); – benjwy May 24 '12 at 22:58
Had to post in comments because I'm not allowed to answer my own question yet. – benjwy May 24 '12 at 22:58
Or it should allow to do the same with unsigned. TBH I don't use variables. I like unsigned type more, since it is easy to cast it to any type later. – Socrates May 25 '12 at 8:30
You can have unsigned variables just fine – Martin Thompson May 25 '12 at 14:07
Why not make temp signed also, then you don't have to cast it? – Martin Thompson May 25 '12 at 14:07

I think you have already answered the question yourself in the comments, but just to emphasize the important part here: std_logic_vector is an array std_logic, which is a set of variables, signals or constants frequently used to model digital signals. std_logic_vector has no numerical interpretation by default, and therefore has no associated * operator. To do math on std_logic_vector you have to cast it to signed or unsigned from the library ieee.numeric_std; only you know which one. Since both std_logic_vector and(un)signed are defined as arrays of std_logic they are closely-related types and can be converted with a simple cast. But due to the strong typing nature they are still different types and cannot me mixed.
As a closing remark I want to mention that there seem to be a widespread misunderstanding that you need to convert everything to std_logic_(vector). Most synthesis tools will handle numeric_std types, integers and booleans just fine, so there is no need to discard this valuable tool of abstraction because software twenty years ago didn't support it. To quote Abraham Lincoln: