Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16592 Discussions

Implement mux using for loop

Altera_Forum
Honored Contributor II
3,981 Views

Hi 

I think it is possible to implement a mux using a for loop like in the following example: 

 

type array_type is array (7 downto 0) of std_logic_vector(15 downto 0); signal mux_in: array_type; signal mux_slct: unsigned(2 downto 0); signal mux_out: std_logic_vector(15 downto 0); ... p_mux : process(mux_slct,mux_in) begin mux_out <= (others=>'0'); for i in 0 to 7 loop if i=mux_slct then mux_out <= mux_in(i); end if; end loop; end process p_mux;  

 

My problem is that Quartus seems (based on RTL viewer) to synthesise it as a priority circuit which is not efficient at all.  

Does anyone knows if: 

-> something is missing in my code? 

-> Quartus doesn't support this construction? 

-> Some config of the synthesis tool could solve this? 

 

I'm using Quartus II 32-bit Version 12.1 Build 243 01/31/2013 SJ Web Edition 

 

Thanks in advance, 

 

Jean
0 Kudos
8 Replies
Altera_Forum
Honored Contributor II
2,710 Views

It has to be implemented as a priority encoder because i has to keep being compared to mux_slct. Why not just use a case statement?

0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

Hi sstrell, 

 

Thank you for your reply. I saw this construction working elsewhere and it is much better than a case statement aspecially when your mux start to be huge. 

It's already big just for MUX8 so imagine for MUX16 or MUX32: 

 

type array_type is array (7 downto 0) of std_logic_vector(15 downto 0); signal mux_in: array_type; signal mux_slct: unsigned(2 downto 0); signal mux_out: std_logic_vector(15 downto 0); ... p_mux : process(mux_slct,mux_in) begin case mux_slct is when 0 => mux_out <= mux_in(0); when 1 => mux_out <= mux_in(1); when 2 => mux_out <= mux_in(2); when 3 => mux_out <= mux_in(3); when 4 => mux_out <= mux_in(4); when 5 => mux_out <= mux_in(5); when 6 => mux_out <= mux_in(6); when 7 => mux_out <= mux_in(7); when others => mux_out <= (others=>'0'); end case; end process p_mux;  

 

The first version contains less redundancy and is I think much more readable and code is better for maintenance. 

 

No idea why Quartus deosn't want to synthesise it as I want? 

 

Cheers
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

This is because it fits the template for a priority encoder. Multiple ifs, with a default if one isnt hit, even though they are mutually exclusive. The technology view may have worked properly, but wont look nice. 

 

This will give you a mux, as you expect, and work on any size: 

 

mux_out <= mux_in( to_integer( mux_slct) );
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

Hi Tricky, 

Thank you for your reply. It's probably the best to do. 

Do you know what happend if you don't have a quantity of input equal to a power of 2 (= size of mux_in array size) because you can't specify any default value. 

So if 

type array_type is array (5 downto 0) of std_logic_vector(15 downto 0); signal mux_in: array_type; signal mux_slct: unsigned(2 downto 0); signal mux_out: std_logic_vector(15 downto 0); ... -- no problem with that mux_slct <= "011"; mux_out1 <= mux_in(to_integer(mux_slct); -- what about this situation mux_slct <= "111"; mux_out2 <= mux_in(to_integer(mux_slct);  

 

So maybe the best would be: 

p_mux : process(mux_slct,mux_in) begin if(mux_slct < mux_in'length) then mux_out <= mux_in(to_integer(mux_slct)); else mux_out <= (others<='0'); end if; end process p_mux; 

 

Is it the most robust way to do it? 

Cheers, 

 

Jean
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

When building (having just tried it) it fills the non-existing entries with 0's without modifying my code (other than the array size) 

In simulation, it would throw an error. This is probably the best situation, as you wouldnt want control logic selecting a non-existing connection. 

 

code I synthed: 

 

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; package test_pkg is type array_type is array (5 downto 0) of std_logic_vector(15 downto 0); end package test_pkg; library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.test_pkg.all; entity mux_test is port ( mux_in : in array_type; mux_slct : in unsigned(2 downto 0); mux_out : out std_logic_vector(15 downto 0) ); end entity mux_test; architecture rtl of mux_test is begin mux_out <= mux_in( to_integer( mux_slct) ); end architecture rtl;  

 

Synthed with Quartus Lite 17
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

You said 

 

--- Quote Start ---  

This is probably the best situation, as you wouldnt want control logic selecting a non-existing connection. 

--- Quote End ---  

 

 

The mux_out can be invalid for some mux_slct values if further in the pipeline this mux_out signal is not propagated in situation where mux_slct was "out of bounds". You still want to be able to test your circuit so you need a default value or the simulation will fail. 

 

So yeah, I'll opt for a robust solution ;-) 

 

It's just desapointing Quartus (maybe just my student version?) can't manage with the for...loop statement. I'm sure some other synthesis tools can. 

 

Thank you for your help Tricky!
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

 

--- Quote Start ---  

 

The mux_out can be invalid for some mux_slct values if further in the pipeline this mux_out signal is not propagated in situation where mux_slct was "out of bounds". You still want to be able to test your circuit so you need a default value or the simulation will fail. 

 

--- Quote End ---  

 

 

You can use this to your advantage in simulation. The test fails, therefore there is an error in the generation of mux_slct.
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

 

--- Quote Start ---  

My problem is that Quartus seems (based on RTL viewer) to synthesise it as a priority circuit which is not efficient at all.  

--- Quote End ---  

 

I couldn't believe the assumption of "inefficient" synthesis of the code in the first post. A test compilation shows that it's actually wrong. 

 

All three variants discussed in the thread (loop, case, direct mux) end up with the same logic cell utilization and combinational delay of three LEs (with Cyclone III/IV 4-input LUT). 

 

The only "problem" is that the RTL schematics are quite different, but the gate level isn't.  

 

I know that it's not guaranteed to get identical gate level output for functionally equivalent logic, but it seems to work in this case.
0 Kudos
Reply