- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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, ..daneLink Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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...)- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page