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?
Best Answer
You can do this quite elegantly with the new
fixed_pkg
:As a side note I want to comment on the common misuse of types in VHDL:
std_logic_vector
is an arraystd_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 onstd_logic_vector
you need to convert it to the correct type in one of the numerical libraries provided by the IEEE:ieee.fixed_pkg
andieee.numeric_std
; only you know which one. Since bothstd_logic_vector
and(un)signed
are defined as arrays ofstd_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 handlenumeric_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: