Is there a way in Verilog to refer to a slice of an array?

Nov 05, 2020 10 Replies

I've got two Verilog modules that look like this:



module queue ( output [ 64:0] dataOut , input reset , input shift , input [ 64:0] dataIn); ... endmodule



and



module lessThan ( output lssThn , input [ 48:0] leftOp , input [ 48:0] rightOp); ... endmodule



I've got six instances of module (queue) and need to pipe the forty-nine mo st significant bits of the output of each of two (queue)s to the two inputs of (lessThan). Is there a way to refer to that forty-nine-bit slice? Or do I have to do something like this:



module hmm ();



wire rs, shLf, shRg; wire lfOut [ 64:0], lfIn [ 64:0]; wire rgOut [ 64:0], rgIn [ 64:0]; wire rgMsbs [ 48:0], lfMsbs [ 48:0];



queue lfq( lfOut, rs, shLf, lfIn); queue rgq( rgOut, rs, shRg, rgIn);



lessThan lfLtRg( result, lfMsbs, rgMsbs);



generate for (bit = 0; bit


I've got two Verilog modules that look like this:

module queue ( output [ 64:0] dataOut , input reset , input shift , input [ 64:0] dataIn); ... endmodule

and

module lessThan ( output lssThn , input [ 48:0] leftOp , input [ 48:0] rightOp); ... endmodule

I've got six instances of module (queue) and need to pipe the forty-nine mo st significant bits of the output of each of two (queue)s to the two inputs of (lessThan). Is there a way to refer to that forty-nine-bit slice? Or do I have to do something like this:

module hmm ();

wire rs, shLf, shRg; wire lfOut [ 64:0], lfIn [ 64:0]; wire rgOut [ 64:0], rgIn [ 64:0]; wire rgMsbs [ 48:0], lfMsbs [ 48:0];

queue lfq( lfOut, rs, shLf, lfIn); queue rgq( rgOut, rs, shRg, rgIn);

lessThan lfLtRg( result, lfMsbs, rgMsbs);

generate for (bit = 0; bit

lesssThan lrLtRg(results, lfOut[64:16], rgOut[64:16))

I tried this out with a pair of simpler modules, namely: [code] module lessThan ( output lssThn , input [ 4:0] leftOp , input [ 4:0] rightOp);

assign lssThn = leftOp < rightOp;

endmodule [/code] and [code] module check ();

reg left [ 8:0], right [ 8:0]; wire result;

lessThan ltc( result, left[ 8:4], right[ 8:4]);

initial begin left = 9'd287; right = 9'd449; #5 $display( "left: %d, right: %d, result: %d.", left, right, result); #5 $finish; end

endmodule [/code] When I tried to get Icarus to simulate it I got:

  D:\Hf\Verilog\Unpacked\Src>\HdlTools\Icarus\bin\iverilog -g2009 -o check.vvp lessThan.sv check.sv  check.sv:6: error: Array cannot be indexed by a range.  check.sv:6: warning: Port 2 (leftOp) of lessThan expects 5 bits, got 1.  check.sv:6:        : Padding 4 high bits of the port.  check.sv:6: error: Array cannot be indexed by a range.  check.sv:6: warning: Port 3 (rightOp) of lessThan expects 5 bits, got 1.  check.sv:6:        : Padding 4 high bits of the port.  check.sv:10: error: Cannot assign to array left. Did you forget a word index?  check.sv:11: error: Cannot assign to array right. Did you forget a word index?

4 error(s) during elaboration.

D:\Hf\Verilog\Unpacked\Src>

Can anyone tell me what I'm doing wrong? Do I have the syntax wrong for expressing a slice of arguments (left) and (right)?

Yes--you have declared 'left' and 'right' with "unpacked" dimensions instead of "packed". Try this declaration:

reg [8:0] left, [8:0] right;

That should work.

...

Kevin Neilson, I copied your line of code into my code, giving me: [code] module neilson ();

reg [8:0] left, [8:0] right; wire result;

lessThan ltc( result, left[ 8:4], right[ 8:4]);

initial begin left = 9'd287; right = 9'd449; #5 $display( "left: %d, right: %d, result: %d.", left, right, result); #5 $finish; end

endmodule [/code] Then I tried simulating, and got the following error messages: [demo] D:\Hf\Verilog\Unpacked\Src>\HdlTools\Icarus\bin\iverilog -g2009 -o neilson.vvp lessThan.sv neilson.sv neilson.sv:3: syntax error neilson.sv:3: error: invalid module item.

D:\Hf\Verilog\Unpacked\Src> [/demo] Do you have any idea what Icarus means by "syntax error" or "invalid module item"? It looks like I've still got problems with my code.

Sorry; I guess you can't redeclare the bus width on the same lane. It's probably best to just use two lines:

reg [8:0] left; reg [8:0] right;

robably best to just use two lines:

Thanks, Kevin Neilson! That did the trick. Now one post prior to that last one you said, "Yes--you have declared 'left' and 'right' with 'unpacked' di mensions instead of 'packed'." So it would appear in order to refer to a sl ice of an array the array has to be packed. Is that right? When I began wri ting the project I'm working on right now, all my arrays were packed, but s omehow along the way I understood that would cause me problems, so I made a ll my arrays unpacked. But it's going to be pretty vital to my project to b e able to specify that slice. So can you tell me what exactly the rules are about packed and unpacked arrays, and when I'll want to have them packed a nd when I'll want to have them unpacked?

:

te:

for expressing a slice of arguments (left) and (right)?

instead of "packed". Try this declaration:

son.vvp lessThan.sv neilson.sv

dule item"? It looks like I've still got problems with my code.

robably best to just use two lines:

robably best to just use two lines:

Thanks, Kevin Neilson! That did the trick. Now one post prior to that last one you said, "Yes--you have declared 'left' and 'right' with 'unpacked' di mensions instead of 'packed'." So it would appear in order to refer to a sl ice of an array the array has to be packed. Is that right? When I began wri ting the project I'm working on right now, all my arrays were packed, but s omehow along the way I understood that would cause me problems, so I made a ll my arrays unpacked. But it's going to be pretty vital to my project to b e able to specify that slice. So can you tell me what exactly the rules are about packed and unpacked arrays, and when I'll want to have them packed a nd when I'll want to have them unpacked?

I guess I could just convert every array in my project back to being packed and then see if the compiler likes that, but I'm not sure that's the best way to do it.

te:

rote:

ng for expressing a slice of arguments (left) and (right)?

s instead of "packed". Try this declaration:

;

ilson.vvp lessThan.sv neilson.sv

module item"? It looks like I've still got problems with my code.

probably best to just use two lines:

probably best to just use two lines:

t one you said, "Yes--you have declared 'left' and 'right' with 'unpacked' dimensions instead of 'packed'." So it would appear in order to refer to a slice of an array the array has to be packed. Is that right? When I began w riting the project I'm working on right now, all my arrays were packed, but somehow along the way I understood that would cause me problems, so I made all my arrays unpacked. But it's going to be pretty vital to my project to be able to specify that slice. So can you tell me what exactly the rules a re about packed and unpacked arrays, and when I'll want to have them packed and when I'll want to have them unpacked?

ed and then see if the compiler likes that, but I'm not sure that's the bes t way to do it.

Packed/unpacked is probably a whole topic, but in general, if you just have one dimension, you almost always want packed:

reg [7:0] one_byte;

and to model something like a RAM, use one dimension of each type:

reg [7:0] ram [0:31]; // 32-byte RAM

In the above case, ram[31][7:4] would be the most-significant 4 bits of the last byte in the RAM.

:

te:

for expressing a slice of arguments (left) and (right)?

instead of "packed". Try this declaration:

son.vvp lessThan.sv neilson.sv

dule item"? It looks like I've still got problems with my code.

robably best to just use two lines:

reg [8:0] left = 0, right = 0; You could just make it as above, which creates two 9-bit arrays with proper data init...

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required