FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6519 Discussions

verilog- parameterized mux

Altera_Forum
Honored Contributor II
14,933 Views

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, 

..dane
0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
11,407 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
11,407 Views

 

--- 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. 

 

genvar 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  

 

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, 

..dane
0 Kudos
Altera_Forum
Honored Contributor II
11,407 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
11,407 Views

Equivalent / alternative examples 

1 - The one I already posted with a correction: 

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 

 

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 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  

 

Jake
0 Kudos
Altera_Forum
Honored Contributor II
11,407 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
11,407 Views

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...)
0 Kudos
Altera_Forum
Honored Contributor II
11,407 Views

Hi Rysc, 

 

jakobjones suggested: 

 

module mux (#parameter WIDTH = 8, # parameter CHANNELS = 4) ( input in_bus, input sel, output out );  

 

but I am implementing slightly differently. To continue jakobjones' example it would be: 

 

module 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  

 

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. 

..dane
0 Kudos
Reply