Take the 2-minute tour ×
Electrical Engineering Stack Exchange is a question and answer site for electronics and electrical engineering professionals, students, and enthusiasts. It's 100% free, no registration required.

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?

share|improve this question
1  
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
1  
Why not make temp signed also, then you don't have to cast it? –  Martin Thompson May 25 '12 at 14:07

1 Answer 1

You can do this quite elegantly with the new fixed_pkg:

pr_scale : process is    
    constant b : s_fixed(0 downto -15) := to_sfixed(0.8, 0, -15);
    variable x, y : s_fixed(0 downto -15);
begin
    x        := to_sfixed(data_in, x);
    y        := resize( b * x, y);
    incoming <= to_slv(y);
end process;

As a side note I want to comment on the common misuse of types in VHDL: 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 need to convert it to the correct type in one of the numerical libraries provided by the IEEE: ieee.fixed_pkgand 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:

The dogmas of the quiet past are inadequate to the stormy present.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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