Mux versus internal high impledance
Started by 6 years ago●5 replies●latest reply 6 years ago●140 viewsHi,
I have been an FPGA designer for more than a decade now and tutor a class on FPGA design at University presently. In all these years, I have had two ways of implementing a multiplexer functionality.
The first one is the conventional
module mux ( input [9:0] din, input [3:0] sel1, input [3:0] sel2, output dout ); reg op1, op2; always @(*) begin case(sel1) 4'd0 : op1 = din[0]; 4'd1 : op1 = din[1]; 4'd2 : op1 = din[2]; 4'd3 : op1 = din[3]; 4'd4 : op1 = din[4]; 4'd5 : op1 = din[5]; 4'd6 : op1 = din[6]; 4'd7 : op1 = din[7]; 4'd8 : op1 = din[8]; 4'd9 : op1 = din[9]; default op1 = 1'd0; endcase end always @(*) begin case(sel2) 4'd0 : op2 = din[0]; 4'd1 : op2 = din[1]; 4'd2 : op2 = din[2]; 4'd3 : op2 = din[3]; 4'd4 : op2 = din[4]; 4'd5 : op2 = din[5]; 4'd6 : op2 = din[6]; 4'd7 : op2 = din[7]; 4'd8 : op2 = din[8]; 4'd9 : op2 = din[9]; default op2 = 1'd0; endcase end assign dout = op1 ^ op2; endmodule
while the other one is a bit quirky and uses internal tri states. Now before you draw the big guns, I know FPGAs do not have internal tristates (the last ones which had them are probably Virtex II Pro, but I learned Verilog on a Virtex II Pro). The code follows.
module hiz #( parameter DW = 10, parameter SW = 4 )(
input [DW-1:0] din,
input [SW-1:0] sel1,
input [SW-1:0] sel2,
output dout
);
reg op1, op2;
generate
genvar i;
for (i=0;i<=DW-1;i=i+1)
begin : SEL1
always @(*)
if(sel1 == i)
op1 = din[i];
else
op1 = 1'bz;
always @(*)
if(sel2 == i)
op2 = din[i];
else
op2 = 1'bz;
end
endgenerate
assign dout = op1 ^ op2;
endmodule
The advantage I saw of this code is that my module is parametrizable. In my experience, the design works correctly.
Any comments on the design style
Either ASIC/FPGA, Tristate is not permitted within the fabric. The only place to implement tristate are the IOs. Parameterisation is a matter of coding style, does not fit in the context of tristate. Mux has been implemented using for loops decades ago, must be conventional too. The synthesis tool just rolls out the loop and implements the correct structure.
Hello Rajkeerthy18,
Thank you for your reply.
However, I do not agree with your statement that either ASIC/FPGA do not permit Tristate within the fabric. As I have mentioned in my original post, in the Virtex II Pro FPGA, each CLB had access to an "internal" tri-state buffer https://media.digikey.com/pdf/Data%20Sheets/Xilinx... (page 43). These were used to drive tristate buses inside the FPGA fabric. Yes they were not true tristates, but were implemented using AND-OR logic. The pseudo tri-states were a nice way to implement a bus-like functionality within modules inside the FPGA.
Having said that however, I agree that whenever the the synthesis tool sees the generate for loop, it just rolls out and implements the correct structure.
I am wanting to know if there is a situation that can arise where the generate loop with the tristate will not work correctly.
In a tri-state the totem pole output transistors are not driven meaning they are off. If such a structure could be inferred from an HDL model then we are sure that tri-state is permitted inside the fabric. Then multiple drivers could exist for that signal. Mux structure achieves many to one driver and logically equivalent. The Virtex II pro internal tristate buffer emulated a tri-state, which is not exactly a tri-state logic. The AND-OR logic is a mux structure.
With generate statement one could generate any structure/instances including IOs which have tristate. A situation where a generate loop does not work correctly with tristate - I am curious to know the design intent because generate is an HDL statement to describe logic in a compact way, Whereas tristate is a logic state. Generate statement is not related to logic state.
I'm a VHDLer, but can you not do something like:
op1 = d[sel1]; op2=d[sel2]; dout = op1^op2;
?
I'd hope the synthesier would do just the same, but I don't have one to hand!
Or is the default case something critical? In which case I would do
op1 <= d(sel1) when sel1 < 10 else 0;
etc.
Should also be perfectly parameterisable...
Perhaps I'm missing something (perhaps verilog-fu!)?
Regarding your question about design-style - I personally don't like using Zs to make muxes on principle - the principle being that I don't like to use design-patterns that are unlikely to be recognised, and I'm not sure many/most will, given that it is so long since tristate buses actually existed in the FPGA.
But I think it's a personal preference thing!
Cheers,
Martin
Hello Martin,
Thank you for your reply.
I agree with your design principle that it is inadvisable to use design patterns that are unlikely to be recognised. Will keep that in mind the next time I am writing code.
Cheers,
Prashant