4
\$\begingroup\$

I am trying to find a way to conditionally assign values to a signal in verilog similar to the with/select in VHDL. So far I found two ways https://www.chipverify.com/verilog/verilog-4to1-mux.

This is the first one:

module mux_4to1_assign ( input [3:0] a, // 4-bit input called a
 input [3:0] b, // 4-bit input called b
 input [3:0] c, // 4-bit input called c
 input [3:0] d, // 4-bit input called d
 input [1:0] sel, // input sel used to select between a,b,c,d
 output [3:0] out); // 4-bit output based on input sel
 // When sel[1] is 0, (sel[0]? b:a) is selected and when sel[1] is 1, (sel[0] ? d:c) is taken
 // When sel[0] is 0, a is sent to output, else b and when sel[0] is 0, c is sent to output, else d
 assign out = sel[1] ? (sel[0] ? d : c) : (sel[0] ? b : a);
endmodule

Second one:

module mux_4to1_case ( input [3:0] a, // 4-bit input called a
 input [3:0] b, // 4-bit input called b
 input [3:0] c, // 4-bit input called c
 input [3:0] d, // 4-bit input called d
 input [1:0] sel, // input sel used to select between a,b,c,d
 output reg [3:0] out); // 4-bit output based on input sel
 
 // This always block gets executed whenever a/b/c/d/sel changes value
 // When that happens, based on value in sel, output is assigned to either a/b/c/d
 always @ (a or b or c or d or sel) begin
 case (sel)
 2'b00 : out <= a;
 2'b01 : out <= b;
 2'b10 : out <= c;
 2'b11 : out <= d;
 endcase
 end
endmodule

Both examples were taken from the link I shared before, my QUESTION IS if there is something in Verilog, similar to VHDL using the with/select, that is easy to understand without using procedural blocks?.

The first verilog example does the job but it takes a bit to understand the logic. Please keep in mind I am not complaining about or criticizing any language, I just want to know how to improve code readability for this particular case.

asked Apr 9, 2021 at 17:11
\$\endgroup\$
2
  • \$\begingroup\$ What do you mean by "better way"? Better readability? Optimized for speed/power/area? \$\endgroup\$ Commented Apr 9, 2021 at 17:27
  • 1
    \$\begingroup\$ @MituRaj, you got it, I meant better readability, I will try to edit my post. Thanks \$\endgroup\$ Commented Apr 12, 2021 at 13:44

2 Answers 2

1
\$\begingroup\$

If you really want something based on an assign statement, your version can be improved:

// yours is below
assign out = sel[1] ? (sel[0] ? d : c) : (sel[0] ? b : a);
// but you can decode two bits at a time:
assign out = (sel==2'b00) ? a :
 (sel==2'b01) ? b :
 (sel==2'b10) ? c :
 (sel==2'b11) ? d :
 2'bx; // should never hit this case, but you need an else

It's much more readable your version. If you're not used to the ternary conditional operator, well you just have to get used to it. It's part of C and many C-like languages (including Perl) but it's very widely used in Verilog since it's a natural multiplex operator, and it can be used in the middle of complex expressions. Very helpful, and something I miss a lot now that I'm at a VHDL company.

answered Apr 9, 2021 at 18:55
\$\endgroup\$
4
\$\begingroup\$

You can simplify the procedural block by using an implicit sensitivity list, always @* in Verilog and preferably always_comb in SystemVerilog. And you should not be using non-blocking assignments in combinational logic.

always_comb case (sel)
 2'b00 : out = a;
 2'b01 : out = b;
 2'b10 : out = c;
 2'b11 : out = d;
endcase

Almost the same amount of typing as the VHDL with/select.

answered Apr 9, 2021 at 17:28
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.