11-26-2016 05:01 AM
Greetings forum,
I recently encountered a strange issue with a multiplexer. This multiplexer drives the input signal of a FIFO, and depending on the value of the select signal, the input of the FIFO either comes from process_0, or from process_1. The write domain of the FIFO, process_0 and process_1, are all synchronous to a 200 Mhz clock, clk_200.
I created a multiplexer in VHDL like this:
MyMux: process(sel) begin case sel is when '0' => data_to_fifo <= data_to_fifo_from_proc_0; wr_en_fifo <= wr_en_fifo_from_proc_0; when '1' => data_to_fifo <= data_to_fifo_from_proc_1; wr_en_fifo <= wr_en_fifo_from_proc_1; when others => data_to_fifo <= (others => '0'); wr_en_fifo <= '0'; end case; end process;
And the result was this in Behavioral Simulation:
As you can see, the output of the MUX never actually changes. In the FPGA implementation of this design, the sel signal was controlled by a VIO. I put ILAs on all signals, and while the MUX was driving the wr_en signal correctly, it was unable to connect the two 18-bit wide data buses correctly, and the data driven to the FIFO had a strange value which remained constant and totally different from the output of proc_1. Unfortunately I don't have a screenshot of the ILA output, but my guess is that you get the picture.
Then I made the MUX synchronous to the clk_200:
MyMux: process(sel, clk_200) begin if(rising_edge(clk_200))then case sel is when '0' => data_to_fifo <= data_to_fifo_from_proc_0; wr_en_fifo <= wr_en_fifo_from_proc_0; when '1' => data_to_fifo <= data_to_fifo_from_proc_1; wr_en_fifo <= wr_en_fifo_from_proc_1; when others => data_to_fifo <= (others => '0'); wr_en_fifo <= '0'; end case; end if; end process;
And it worked. The result in Behavioral Simulation:
I haven't actually tested this in actual hardware yet, but my guess is that it will work now. Can someone explain why this is happening? Are MUXes supposed to be synchronous? Shouldn't a select signal just suffice?
Cheers!
11-26-2016 07:21 AM
Your process sensitivity list is incomplete. Therefore you can change data and write enable signals, but you don't see any effect on the outputs. All signals you are going to read in a combinational process have to be in sensitivity list.
On the other hand only clock and asynchronous signals (reset) are in the sensitivity list of sequential processes. In your case, you have to remove sel from it.
Best Regards,
Stephan
11-26-2016 07:21 AM
Your process sensitivity list is incomplete. Therefore you can change data and write enable signals, but you don't see any effect on the outputs. All signals you are going to read in a combinational process have to be in sensitivity list.
On the other hand only clock and asynchronous signals (reset) are in the sensitivity list of sequential processes. In your case, you have to remove sel from it.
Best Regards,
Stephan
11-26-2016 11:59 AM
11-26-2016 03:31 PM
Thank you for your replies, as they were really enlightening. Now it works fine.
By the way, is there any big difference, low-level-wise and performance-wise, between a correctly working synchronous and an asynchronous MUX?
11-27-2016 12:39 AM
I'm 99% sure that the synchronous multiplexer will just end up being an asynchronous multiplexer with a register stuck on the end of it. Same LUT resources, a few extra flip-flops for the register.
In terms of performance, the effects really depend on what else is connected to the mux output. If there's a whole lot of complex logic on the output then the synchronous one will allow a higher clock speed - because the data goes through the mux on one cycle, then through the complex logic on the next. In the asynchronous one it has to go through both in one cycle. On the other hand, the asynchronous one completes all that in one cycle, whereas the synchronous one takes two cycles.