i have been told to use 'when' statement to make multiplexer but not use 'if' statement as it will cause timing errors... i don't understand this ... so what is the difference between 'if' and 'when' ? and do they map to the same thing in hardware ?
OK, lets discuss some points at first on the difference between if and when statements:
- Both are called Dataflow Design Elements.
when statement
- concurrent statement
- not used in process, used only in architecture as process is sequential execution
if statement
- sequential statement
- used in process as it is sequential statement, and not used outside the process
And you know multiplexer is a component don't need process block, as its behavior doesn't change with changing its input, so it will be outside process, so you have to write it using when statement as it is concurrent statement.. And if you wrote it with if statement, timing errors may occur. Also all the references and also Xilinx help (if you are using Xilinx) are writing the Multiplexer block using when statement not if statement
Reference: Digital Design Priciples & Practices, John F. Wakerly, 3rd Edition
Both coding styles are totally valid.
Let's recall some elements. Starting from HDL, synthesis is done in two main steps :
- first, the VHDL is analyzed in order to detect RTL templates (consisting in RTL elements : flip-flops, arithmetic expressions, multiplexers , control logic ). We say that these elements are "infered" (i.e you must code using the right template to get what you wanted initially. You must imagine how these elements are connected, before coding ).
- The second step is real logic synthesis, that takes a particular target technology parameters into account (types of gates available, timing, area, power).
These two steps clearly separates RTL functional needs (steering logic, computations) from technology contingencies (timing etc).
Let's come back to the first step (RTL) :
Concerning multiplexers, several coding styles are possible :
using concurrent assignement :
y<= a1 when cond1 else a2 when cond2 else cond3;
using if statement within a process :
process(a1,a2,a3,cond1,cond2) begin if(cond1) then y<=a1; elsif(cond2) then y<=a2; else y<=a3; end if; end;
using another concurrent assignment form, suitable for generic descriptions : if sel is an integer and muxin an array of signals, then :
muxout <= muxin(sel); --will infer a mux
Note that the 3 coding styles always work. Note also that they are "a bit more" than simple multiplexer as the coding style force the presence of a priority encoding (if elsif, when else), which is not the case of a simple equation-based multiplexer, really symmetric.
using a case statement
process(a1,a2,a3,cond1,cond2) variable cond : std_logic(1 downto 0); begin cond := cond2 & cond1; case cond is when "01" => y<= a1; when "10" => y<= a2; when others => y<=a3; end case; end;
using a select statement (in our example, two concurrent assignements needed) :
sel <= cond2 & cond1; WITH sel SELECT y <= a1 WHEN "01", a2 WHEN "10", a3 WHEN OTHERS;
A final remark is about the rising of abstraction, even for RTL design : the synthesizers are now really mature. Have a look at Jiri Gaisler coding styles for LEON2 open source processor for example, as well as his coding styles (see here). He prones a very different approach, yet perfectly valid, from classical books.
You should always understand what the RTL synthesizer will infer.
In the contrary, behavioral synthesis allows you to forget (partially) what the synthesizer will infer. But that's another story.