- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
8 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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) );- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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!- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page