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.
-
\$\begingroup\$ What do you mean by "better way"? Better readability? Optimized for speed/power/area? \$\endgroup\$Mitu Raj– Mitu Raj2021年04月09日 17:27:06 +00:00Commented 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\$JC_Onp– JC_Onp2021年04月12日 13:44:22 +00:00Commented Apr 12, 2021 at 13:44
2 Answers 2
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.
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.