Search code examples
vhdlmultiplexing

How to Write A Mux With Several Inputs Without Creating a New Input Signal?


If this can't be done, just leave me with a simple "no" plus perhaps a short answer as to why, but I'd just like to double check this can't be done.

I have this process:

process(clk_p)
begin
    if rising_edge(clk_p) then
        if rst_i = '1' then
            stored_events <= (others => '0');
        else
            if mode_triggered = '1' and ptr = 0 and read_state = ST_ENABLE then
                stored_events <= stored_events;
            elsif mode_triggered = '1' then
                stored_events <= stored_events + 1;
            elsif ptr = 0 and read_state = ST_ENABLE then
                stored_events <= stored_events - 1;
            end if;
        end if;
    end if;
end process;

Yup, it's not great which us why I'm going to help the synthesis by turning it into a proper case mux.

You could do something like this:

sel(0) <= '1' when mode_triggered= = '1' else '0';
sel(1) <= '1' when ptr = 1 else '0'; 
sel(2) <= '1' when read_state = ST_ENABLE else '0';

case sel is 
    when "111" => 
        stored_events <= stored_events; -- and so on...

Though since I'm going to be changing several processes, I cba to make make even more signal names. So...

I was wondering if there was some way I could so like (though not entirely sure how the final when others would work out ):

case mode_triggered, ptr, read_state is 
    when '1', 0, ST_ENABLE =>
        stored_events <= stored_events;

Solution

  • You can probably achieve what you seek using records and/or VHDL-2008 syntax, but I recommend against it.

    Not only will you lose in readability, I seriously doubt you would get any synthesis gain.

    When I look at your code, I don't see any mux. Instead, I see an up/down counter with synchronous reset and clock enable port. You could write it like this if you want:

    clk_en <= '0' when mode_triggered = '1' and ptr = 0 and read_state = ST_ENABLE else
              '1' when mode_triggered = '1' or (ptr = 0 and read_state = ST_ENABLE) else
              '0';
    up <= '1' when mode_triggered = '1' else '0';
    
    process(clk_p)
    begin
        if rising_edge(clk_p) then
            if rst_i = '1' then
                stored_events <= (others => '0');
            elsif clk_en = '1' then
                if up = '1' then
                    stored_events <= stored_events + 1;
                else
                    stored_events <= stored_events - 1;
                end if;
            end if;
        end if;
    end process;
    

    All three way to write the code should lead to the same netlist (hopefully), they only differ in readability. Personally, I prefer your first attempt, as it comes from the function you are achieving, but it all come to preference. I also dislike the mux approach (for this case).

    As a rule of thumb, don't write to help the synthesizer unless you have too. Look at synthesis reports and generated netlist and adjust only if you don't like what you see. The synthesizer is better at extracting the circuit from code like your first attempt than we human are at understanding the function of a code full of muxes and logic gates.