Parameterize the number of I/O ports

L

leon

Guest
I am trying to determine if there is a way in verilog 2k or system
verilog where the number of input or output ports can be parameterized.
One way to do this is to decalre a parameterized bus and use another
parameter to pick chunks off this bus for the various inputs and
outputs.

I was wondering if there is something similart to generate to do
something like this - any ideas??
 
Thanks for the response. However there is a problem when I have to
extract the data from the wires.
I can use a for loop within a always@(*) combinatorial loop and use the
for loop index to extract what I need. Verilog doesnt allow this. I am
looking at generate or some other means to do this.


sharp@cadence.com wrote:
leon wrote:
I am trying to determine if there is a way in verilog 2k or system
verilog where the number of input or output ports can be parameterized.

There is no direct way to do this in Verilog. As you mention, you
could pass a wide vector and then extract pieces from it that represent
different ports.

In SystemVerilog, you could use a packed array to do the same thing
more conveniently. Or you can pass an ordinary unpacked array through
a port. Or you can use the interface construct to pass bundles of
signals through a single port.
 
leon wrote:
Thanks for the response. However there is a problem when I have to
extract the data from the wires.
I can use a for loop within a always@(*) combinatorial loop and use the
for loop index to extract what I need. Verilog doesnt allow this. I am
looking at generate or some other means to do this.
I am not certain what your problem is. I am guessing that you want to
use the loop index to choose a contiguous chunk of bits from the wide
vector, and have found that you cannot do this with a part select. The
range in a part select must be specified with constant expressions.

There are a couple of ways around this. You can use a right-shift
operator to shift the desired bits into the lowest bits, and then
assign that to a narrower vector, truncating all but the lowest bits.

Or you can use a Verilog-2001 indexed part select. This uses a
different syntax from an ordinary part select. Instead of a starting
and ending bit position, it specifies a starting bit position and a
width. Only the width needs to be constant; the starting position can
be a variable. This has the syntax of vector[start+:width], to extract
'width' bits starting with the lowest bit index of 'start'. There is
an alternate syntax of vector[start-:width], which uses a highest bit
index of 'start' instead.

A generate loop could be used instead, since a genvar is a constant
expression and can be used in an ordinary part select. However, I
suspect the code would be less clear and possibly less efficient also.

If you are having a different problem, then you will need to explain it.
 
Thanks for the response. I will try this out and I am trying to
synthesize the code.

Consider the following example where there are parameterized inputs
a_bus, b_bus and bits_sel. The product of a_bus and b_bus produces 8
bits and the bits_sel has 2 of the 4 bits set to 1 but I will not know
which 2. Based on the bit position in bits_sel I will pick 2 sets of 2
bits from w_x_bus and assign it to x_bus(havent implemented this).
Thanks for your advice

module and_bus
#(parameter size = 8,
parameter hsize =4)
(
input [size-1:0] a_bus,
input [size-1:0] b_bus,
input [hsize-1:0] bits_sel,
output [hsize-1:0] x_bus
);
parameter pa = 2;

wire [1:0] w_x_bus;

genvar i;
generate
for (i = 0; i < 4; i = i + 1)
begin
and2 and2
(
.a(a_bus[((i+1)*pa-1) : i*pa]),
.b(b_bus[((i+1)*pa-1) : i*pa]),
.x(x_bus[((i+1)*pa-1) : i*pa])
// .x(w_x_bus)
);
end
endgenerate
endmodule

module and2
(
input [1:0] a,
input [1:0] b,

output [1:0] x

);

assign x = a & b;

endmodule

sharp@cadence.com wrote:
leon wrote:
Thanks for the response. However there is a problem when I have to
extract the data from the wires.
I can use a for loop within a always@(*) combinatorial loop and use the
for loop index to extract what I need. Verilog doesnt allow this. I am
looking at generate or some other means to do this.

I am not certain what your problem is. I am guessing that you want to
use the loop index to choose a contiguous chunk of bits from the wide
vector, and have found that you cannot do this with a part select. The
range in a part select must be specified with constant expressions.

There are a couple of ways around this. You can use a right-shift
operator to shift the desired bits into the lowest bits, and then
assign that to a narrower vector, truncating all but the lowest bits.

Or you can use a Verilog-2001 indexed part select. This uses a
different syntax from an ordinary part select. Instead of a starting
and ending bit position, it specifies a starting bit position and a
width. Only the width needs to be constant; the starting position can
be a variable. This has the syntax of vector[start+:width], to extract
'width' bits starting with the lowest bit index of 'start'. There is
an alternate syntax of vector[start-:width], which uses a highest bit
index of 'start' instead.

A generate loop could be used instead, since a genvar is a constant
expression and can be used in an ordinary part select. However, I
suspect the code would be less clear and possibly less efficient also.

If you are having a different problem, then you will need to explain it.
 
leon wrote:
Consider the following example where there are parameterized inputs
a_bus, b_bus and bits_sel.
The generate looked like it should work. You could do the same thing
more simply by using an instance array instead.
 
I made a mistake in the example. I have reproduced it below with
comments besides the lines that doesnt work.The output of the array of
and2 is size (8 bits) wide and I want to extract hsize (4 bits) bits
out based on the input bits_sel (which is guranteed to have 2 of its 4
bits set to 1 and the other 0 but this is not static) for the output
x_bus. Also array of instances work only if the inputs and outputs of
the module being instantitated is only a single bit wide. This is what
I have seen or am I completely wrong......

module and_bus
#(parameter size = 8,
parameter hsize =4)
(
input [size-1:0] a_bus,
input [size-1:0] b_bus,
input [hsize-1:0] bits_sel,
output [hsize-1:0] x_bus
);
parameter pa = 2;

wire [size-1:0] w_x_bus;

genvar i;
generate
for (i = 0; i < 4; i = i + 1)
begin
and2 and2
(
.a(a_bus[(i*pa+ : pa]),
.b(b_bus[(i*pa+ : pa]),
.x(w_x_bus[(i*pa+ : pa])
// .x(w_x_bus)
);
end
endgenerate

generate
for (i = 0; i < 4; i = i + 1) // This loop doesnt work on the "if
line" even if i used a different index besides i
begin
if (bits_sel)
assign x_bus = w_x_bus[i*pa+:pa]);
end
endgenerate
endmodule

module and2
(
input [1:0] a,
input [1:0] b,

output [1:0] x

);

assign x = a & b;

endmodule
sharp@cadence.com wrote:
leon wrote:

Consider the following example where there are parameterized inputs
a_bus, b_bus and bits_sel.

The generate looked like it should work. You could do the same thing
more simply by using an instance array instead.
 
leon wrote:
I made a mistake in the example. I have reproduced it below with
comments besides the lines that doesnt work.The output of the array of
and2 is size (8 bits) wide and I want to extract hsize (4 bits) bits
out based on the input bits_sel (which is guranteed to have 2 of its 4
bits set to 1 and the other 0 but this is not static) for the output
x_bus. Also array of instances work only if the inputs and outputs of
the module being instantitated is only a single bit wide. This is what
I have seen or am I completely wrong......
Arrays of instances work with vector ports. There are even two ways
that the port can be connected, depending on the widths of the port and
the expression connected. If the port is the same width as the
expression connected, then that expression is connected to each port.
If all the ports in the array total to the same width as the expression
connected, then each port is connected to an appropriate part-select of
the expression.

Now for your generate problem

generate
for (i = 0; i < 4; i = i + 1) // This loop doesnt work on the "if
line" even if i used a different index besides i
begin
if (bits_sel)
assign x_bus = w_x_bus[i*pa+:pa]);
end
endgenerate
endmodule

You need to learn the difference between a generate-for/if and a
procedural for/if. A generate-for/if is executed during compilation,
and essentially decides what code to generate. It can only make
decisions on things that are constant and known at compile time. That
decision is made once during compilation, and then the design is fixed.

A procedural for/if is executed at runtime, and decides how to execute
the code. It can make decisions based on runtime information, but it
cannot change the design itself.

Your generate-for loop above does not run at runtime. It runs at
compile time, and creates 4 copies of the continuous assignment. It is
much like typing in 4 separate continuous assignments yourself. Your
if-statement is syntactically a generate-if. That means that its
condition must be a compile-time constant. It must decide whether the
continuous assignment will be part of the design or not. It cannot
test a runtime value such as bits_sel and make the continuous
assignment appear and disappear at runtime, which is what you seem to
be trying to do. Only a procedural-if can test runtime conditions, and
a procedural-if can only conditionally execute procedural statements;
it cannot conditionally instantiate a continuous assignment.

You need to get these two different things straight in your mind and
rewrite this code. You should probably eliminate the generate
constructs entirely. Instead of a generate-for that creates multiple
continuous assignments, you should have an always block containing a
procedural-for and a procedural-if. Since procedural code cannot
assign to a net, you will need to assign to a variable instead. If you
need the output on a net, you can have a continuous assignment from the
variable to a net.

Procedural code works much like code in typical programming languages.
Generate constructs are quite different, and should only be used if you
understand what they really do.
 
leon wrote:
I am trying to determine if there is a way in verilog 2k or system
verilog where the number of input or output ports can be parameterized.
There is no direct way to do this in Verilog. As you mention, you
could pass a wide vector and then extract pieces from it that represent
different ports.

In SystemVerilog, you could use a packed array to do the same thing
more conveniently. Or you can pass an ordinary unpacked array through
a port. Or you can use the interface construct to pass bundles of
signals through a single port.
 

Welcome to EDABoard.com

Sponsor

Back
Top