Forum Discussion
verilog- parameterized mux
For the life of me I cannot figure out how to generate a parameterized mux in verilog...
I understand how to generate, say, a 4:1 MUX of "N" bits wide... But I am trying to generate an N:1 mux, of only 1 bit wide. I've been scouring the googleweb for weeks with no such luck (aside from hit after hit for a variable-width mux)... Have I stumbled upon something impossible? thanks, ..dane7 Replies
- Altera_Forum
Honored Contributor
I hope I'm not doing your homework for you. One of the shortcomings of Verilog is the inability to generate ports. So you have to bring the input in as a bus.
I haven't compiled this so there may be errors:module mux (#parameter WIDTH = 8, # parameter CHANNELS = 4) ( input in_bus, input sel, output out ); genvar ig; wire input_array ; assign out = input_array; generate for(ig=0; ig<CHANNELS; ig=ig+1) begin: array_assignments assign input_array = in_bus; end endgenerate //define the clogb2 function function integer clogb2; input depth; integer i,result; begin for (i = 0; 2 ** i < depth; i = i + 1) result = i + 1; clogb2 = result; end endfunction endmodule - Altera_Forum
Honored Contributor
--- Quote Start --- I hope I'm not doing your homework for you. One of the shortcomings of Verilog is the inability to generate ports. So you have to bring the input in as a bus. --- Quote End --- Hahaha.. no, you're not doing your homework for me. Truth be told it's a project I've been working on for a customer for about three months, and this is the last piece to the puzzle (the rest of the project is all done and working just fine) that I just can't seem to crack. I will admit to only a few years of experience with verilog, so your code snippet has a few curiosities in it that I'll ask below.
I am not familiar with a "+" in the port width. A very quick google indicates maybe it's a polarity indicator, but that doesn't help me much -- can you explain what you're accomplishing by including it and how it would behave if it were excluded? I see what you're doing with your generate statement now, and feel a bit silly for not thinking of that myself. I was trying to go about it a much different (and obviously more difficult) way... I will mess around with your code snip and report back how it goes.. thanks again, ..danegenvar ig; wire input_array +:CHANNELS-1]; assign out = input_array; generate for(ig=0; ig<CHANNELS; ig=ig+1) begin: array_assignments assign input_array = in_bus+:WIDTH]; end endgenerate - Altera_Forum
Honored Contributor
1 - That first "+" sign in the array declaration is a typo. See I told you there might be errors.
:). 2 - The second "+:" sign in the "assign" statement is legitimate and is called a "Variable Vector Part Select" operator. For example, a statement like: assign data1 = data[8+:8] is equivalent to: assign data1 = data[15:8]; Generically: assign data1 = data[x+:y] So the "+:" operator uses "x" as the starting index of the vector and uses "y" to determine how many bits of the vector to index. The "+:" operator adds "y" bits to "x" while the "-:" operand subtracts "y" bits from "x". Jake I will post some equivalent examples shortly. - Altera_Forum
Honored Contributor
Equivalent / alternative examples
1 - The one I already posted with a correction:
2 - Similar to# 1 but without using the "Variable Vector Part Select" operator:module mux (#parameter WIDTH = 8, # parameter CHANNELS = 4) ( input in_bus, input sel, output out ); genvar ig; wire input_array ; assign out = input_array; generate for(ig=0; ig<CHANNELS; ig=ig+1) begin: array_assignments assign input_array = in_bus; end endgenerate //define the clogb2 function function integer clogb2; input depth; integer i,result; begin for (i = 0; 2 ** i < depth; i = i + 1) result = i + 1; clogb2 = result; end endfunction endmodule
3 - Equivalent logic without using a generate statement. I don't recommend this because some simulators don't work well with the "reg" type declaration for the array. Again, you could rewrite this to not use the "+:" operator if you wish.module mux (#parameter WIDTH = 8, # parameter CHANNELS = 4) ( input in_bus, input sel, output out ); genvar ig; wire input_array ; assign out = input_array; generate for(ig=0; ig<CHANNELS; ig=ig+1) begin: array_assignments assign input_array = in_bus; end endgenerate //define the clogb2 function function integer clogb2; input depth; integer i,result; begin for (i = 0; 2 ** i < depth; i = i + 1) result = i + 1; clogb2 = result; end endfunction endmodule
Jakemodule module mux (#parameter WIDTH = 8, # parameter CHANNELS = 4) ( input in_bus, input sel, output out ); integer i; reg input_array ; assign out = input_array; always @* for(i=0; i<CHANNELS; i=i+1) input_array = in_bus; //define the clogb2 function function integer clogb2; input depth; integer i,result; begin for (i = 0; 2 ** i < depth; i = i + 1) result = i + 1; clogb2 = result; end endfunction endmodule - Altera_Forum
Honored Contributor
Thanks again Jake for your help.. While cleaning up some of the project I found an optimization opportunity that greatly simplified the problem and made the mux much simpler. I really do appreciate your help though, I've learned a great deal from this thread!
thank you! ..dane - Altera_Forum
Honored Contributor
Old post, but wondering if this ever synthesized? For me, Quartus synthesis errors out on the line:
input [clogb2(CHANNELS-1)-1:0] sel, Stating: Error (10140): Verilog HDL error at param_mux.sv(6): range index is not constant (I just added another parameter for SEL_WIDTH, and used that, forcing the user to manually enter this value. It's easy enough to do, but not ideal...) - Altera_Forum
Honored Contributor
Hi Rysc,
jakobjones suggested:
but I am implementing slightly differently. To continue jakobjones' example it would be:module mux (#parameter WIDTH = 8, # parameter CHANNELS = 4) ( input in_bus, input sel, output out );
I haven't actually tried to synthesize jakobjones' example, so I cannot comment on its ability to be synthesized. However, my structure above which separates the port list declaration and their width definitions does synthesize. I will report however that I've been in the Xilinx world lately so I cannot comment on how the Quartus tools respond to the above example. good luck, and let us know how it goes. ..danemodule mux ( in_bus, sel, out ); parameter WIDTH = 8; parameter CHANNELS = 4; input in_bus; input sel; output out; //define the clogb2 function function integer clogb2; input depth; integer i,result; begin for (i = 0; 2 ** i < depth; i = i + 1) result = i + 1; clogb2 = result; end endfunction