Why doesn't my loop work?

T

Thomas Womack

Guest
This ought to be a polynomial multiplier:

reg [15:0] a;
reg [15:0] b;
reg [30:0] c;

integer i;

always @(negedge Clk)
begin

c[15:0] = a[15:0]& {16{b[0]}};
for (i=1; i<=15; i=i+1)
begin
c[15+i : i] = c[15+i : i] ^ ({16{b}} & a[15:0]);
end
end

I'm expecting it to synthesise to a large blob of LUTs with a rather
long critical path -- IE I'm not expecting it to be an efficient polynomial
multiplier, but I've got a few ideas to get that working better.

But I want to get this one to compile before I go to anything more elaborate.

When I feed it through XST, I get a load of error messages
I just don't understand:

ERROR:HDLCompilers:109 - polymul.v line 132 Most significant bit operand in part-select of vector reg 'c' is illegal
ERROR:HDLCompilers:110 - polymul.v line 132 Least significant bit operand in part-select of vector reg 'c' is illegal
ERROR:HDLCompilers:44 - polymul.v line 132 Illegal left hand side of blocking assignment
ERROR:HDLCompilers:109 - polymul.v line 132 Most significant bit operand in part-select of vector reg 'c' is illegal
ERROR:HDLCompilers:110 - polymul.v line 132 Least significant bit operand in part-select of vector reg 'c' is illegal
ERROR:HDLCompilers:45 - polymul.v line 132 Illegal right hand side of blocking assignment

What confuses me is that lines of the form

c[16:1] = c[16:1] ^ ({16{b[1]}} & a[15:0]);

compile just fine. For the moment I'll expand the loop manually, but
that seems really to defeat the point of writing in a hardware design
language!

Please help an ignorant fool,

Tom
 
"Thomas Womack" <twomack@chiark.greenend.org.uk> wrote in message
news:q8A*D9zwq@news.chiark.greenend.org.uk...
This ought to be a polynomial multiplier:
[snip]

}};
for (i=1; i<=15; i=i+1)
c[15+i : i] = c[15+i : i] ^ ({16{b}} & a[15:0]);

[snip]

The trouble is that Verilog2001 improvements to allow the construct you've
coded to work are slow getting into the tools. The "variable bit select"
wasn't allowed in the 1995 version on either the right or left hand sides.
You could consider using a generate loop or simply recoding to take out the
variable index on the left hand side, such as:

c = ( (c>>i)^({16{b}} & a[15:0]) ) << i
| c & ~({31{1'b1}} << i);

It's a little convoluted but it should work. You keep the c bits [i-1:0]
from the previous iterations and have the operation on the i-shifted 16
bits.
 
Hi all,

Verilog 2000 variable-bit-selects would solve this problem, but they DO require you to specify them as such !
This example does not yet contain any variable bit select, since these are clearly defined with the [ expr +: expr ] and [ expr -:
expr ] ranges.
Normal bit-selects must have compile-time 'constant' bounds. Here that means that 'i' must be a 'parameter'.

Try to re-code the example with variable-bit-selects like this :
Change the ranges [15+i:i] to the Verilog 2000 form : [i+:16]
Then try it again, see what happens on XST.
Most Verilog tools now DO support variable bit-select.

My 2 cts.

Rob


"John_H" <johnhandwork@mail.com> wrote in message news:zGy9d.27$Be6.2625@news-west.eli.net...
"Thomas Womack" <twomack@chiark.greenend.org.uk> wrote in message
news:q8A*D9zwq@news.chiark.greenend.org.uk...
This ought to be a polynomial multiplier:

[snip]

c[15:0] = a[15:0]& {16{b[0]}};
for (i=1; i<=15; i=i+1)
c[15+i : i] = c[15+i : i] ^ ({16{b}} & a[15:0]);

[snip]

The trouble is that Verilog2001 improvements to allow the construct you've
coded to work are slow getting into the tools. The "variable bit select"
wasn't allowed in the 1995 version on either the right or left hand sides.
You could consider using a generate loop or simply recoding to take out the
variable index on the left hand side, such as:

c = ( (c>>i)^({16{b}} & a[15:0]) ) << i
| c & ~({31{1'b1}} << i);

It's a little convoluted but it should work. You keep the c bits [i-1:0]
from the previous iterations and have the operation on the i-shifted 16
bits.


 

Welcome to EDABoard.com

Sponsor

Back
Top