Use 3-8 MUX instead of Case statement
The most usual way to write a multiplexer in Verilog is with a case statement:

reg mux_out;
always @ (*)
begin : 
    case(sel ) 
        1'b0 : mux_out = din_0;
        1'b1 : mux_out = din_1;
    endcase 
end


For a 2:1 mux like this, it might be just as clear to write it using the ternary operator:

wire mux_out;
assign mux_out = sel ? din_1 : din_0;


But for larger muxes, the case statement is easier to read.

You could of course build one up from gates, but there's no reason to expect this to produce any different result from synthesis. You'd just build it up from the SOP representation. For a 2-1 mux:

wire mux_out;
assign mux_out = ~sel &amp; din_0 | sel &amp; din_1;


I wouldn't recommend to do this, though, because it makes your design harder to understand. Generally you should prefer to code at the highest level of abstraction possible, in order to make your code clearer to whoever has to debug it.