2
\$\begingroup\$

While designing a 3:1 mux we require 2 select lines, but one combination is not useful, say 2'b11. If this combination occurs the output becomes 0 irrespective of the value of input lines. Is not the output of 'x' correct in this case ? So, is an extra condition for making the output 'x' required in this code?

module mux(
  input wire a,
  input wire b,
  input wire c,
  input wire[1:0] sel,
  output wire y
);
  assign y = (a&(sel==2'b00))|(b&(sel==2'b01))|(c&(sel==2'b10))|(1'bx&(sel==2'b11));
  endmodule
\$\endgroup\$
  • \$\begingroup\$ What about this line? assign y = (~sel[1] & ((~sel[0] & a) | (sel[0] & b))) | (sel[1] & c); This line maps input 1- to c. \$\endgroup\$ – Paebbels Jul 18 '15 at 22:02
  • \$\begingroup\$ If you want an output of 0 when the select line is combination 2'b11, then it should be 1'b0. Using x (don't care) makes no sense in an assignment. \$\endgroup\$ – Tom Carpenter Jul 18 '15 at 23:54
4
\$\begingroup\$

There is a far neater way to make a multiplexer, using a vector.

Example:

module mux(
  input wire a,
  input wire b,
  input wire c,
  input wire[1:0] sel,
  output wire y
);
  wire [3:0] mux = {1'b0,c,b,a};
  assign y = mux[sel];
endmodule

In this case you assign your outputs into the variable 'mux' and then the output will be the sel'th element in the vector.

A 3:1 mux doesn't really exist - you will always have a \$2^n\$ inputs where \$n\$ is the number of bits in the select signal. So you have to have some way of handling the extra condition. One option is to pick a fixed constant like 0 or 1 (which depends on what it connects to later - e.g. you might want a 1 if this is driving a bus which is considered 'idle' when high). Alternatively, you can add some form of error checking - e.g. have an additional output bit to signify that there was an error (or have the opposite logic and signify that the output is valid).

Example:

module mux(
  input wire a,
  input wire b,
  input wire c,
  input wire[1:0] sel,
  output wire y,
  output wire valid
);
  wire [3:0] mux = {1'b0,c,b,a};
  assign y = mux[sel];
  assign valid = (sel != 2'b11);
endmodule

In this example, when the sel signal has a value that is not 3, then the output signal valid will be high to indicate that the input was correct. Otherwise, if the input is 3, then the valid signal will be low to indicate that the input was invalid.


It's worth noting the reasons why using a vector in this way is preferable. Firstly it is quite easy to follow - if you compare your code to the example, its much clearer what is going on using a vector compared with having to decode the logic. Secondly, and more crucially, it allows for easier parameterisation - you can add a parameter to your block which will correctly scale the select signal and mux signal based of the parameter - although to do this, you would also have to make the input signals into a vector as well which would even then eliminate the need for the 'mux' variable.

\$\endgroup\$
  • \$\begingroup\$ No "don't care; do whatever you can synthesize most efficiently" option? Would that be a useful feature? \$\endgroup\$ – user253751 Jul 19 '15 at 5:20
  • \$\begingroup\$ @immibis having code with that drives other logic which has an unknown state is a recipe for disaster or at the very least a debugging headache. If you really 'don't care' what the output is, then what is the point in having the output in the first place? \$\endgroup\$ – Tom Carpenter Jul 19 '15 at 12:16
  • \$\begingroup\$ the reason would be that you have to use a power of 2 size. \$\endgroup\$ – user253751 Jul 19 '15 at 22:01
  • \$\begingroup\$ @immibis yes you have an unused input to the mux, but you should either use a 'known' value (which depends on what is connected downstream), or have an '(in)valid' signal to qualify whether the select signal is correct. The reason being is simple, imagine you have the output of this mux connected to something like say a pump, you might have three controllers that send a signal to the pump (e.g. PWM). Now say you accidentally select the fourth input. Do you (a) want the pump in a known state (e.g. off) or (b) don't care what the pump is doing? \$\endgroup\$ – Tom Carpenter Jul 19 '15 at 22:34
3
\$\begingroup\$

While using the x value in a simulation might be used to identify unexpected behavior, such a statement will not make sense if you synthesize your code to a gatelevel representation.

And one-liners might be pretty, but they make the code more difficult to read. Also, the constructs may not be correctly identified by the synthesis tool, resulting in inefficient optimizations. In this specific case I would advise you to use the "standard" case statement:

module mux(
  input wire a,
  input wire b,
  input wire c,
  input wire[1:0] sel,
  output reg y
);  
  always @(*) begin
    case (sel)
      2'b00 : y = a;
      2'b01 : y = b;
      2'b10 : y = c;
      2'b11 : y = 1'b0;
    endcase
  end 
endmodule

This is obviously a matter of opinion, but even though it's not so pretty it will be much easier to read because the relation between sel value and the assignment to y is explicitly declared.

@TomCarpenter already explained in detail the problems related with the invalid selection and also introduced a valid signal that is a very good solution for this problem, so I won't extend myself on that topic.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.