verilog multi-dimensional reg error - verilog

This statement:
reg [7:0] register_file [3:0] = 0;
Produces this error:
Error (10673): SystemVerilog error at simpleprocessor.v(27): assignments to unpacked arrays must be aggregate expressions
First of all I am using Verilog, not SystemVerilog, so why is it giving me a SystemVerilog error?
Second of all, what is the cause of this error, and how can I fix it? I am using it in my desgin of a very rudementary processor to represent the internal working registers as a multidemmnsional array of memory.
It would be such that my registers are accessible directly from the instructions. For example this line:
register_file[instruction[5:4]] <= register_file[instruction[3:2]] + register_file[instruction[1:0]];
But it's not working. Any ideas?

From the SystemVerilog LRM:
The term packed array is used to refer to the dimensions declared before the data identifier name. The term unpacked array is used to refer to the dimensions declared after the data identifier name.
bit [7:0] c1; // packed array of scalar bit types
real u [7:0]; // unpacked array of real types
You have declared an unpacked array, therefore you cannot assign it to a value, hence the error message. With an unpacked array you have to use an aggregate expression to assign the entire array:
logic [7:0] register_file [3:0] = {8'b0, 8'b0, 8'b0, 8'b0};
If you declare a packed array you can then assign as though it was a flat vector:
logic [7:0][3:0] register_file = '0;

You have implied a memory but not specified the location to be set to 0.
You can use an aggregate expressions to define all the values in one line:
reg [7:0] register_file [3:0] = {8'b0, 8'b0, 8'b0, 8'b0};
If it is for an fpga you could also use initial:
reg [7:0] register_file [3:0];
initial begin
for(int i=0; i<4; i++) begin
register_file[i] = 8'b0
end
end
In this instant the loop can be statically unrolled, and therefore is synthesisable.
NB Verilog is depreciated. The Verilog standard has been merged with SystemVerilog in 2009, SystemVerilog 2012 being the latest version.

Related

System Verilog Illegal assignment: Cannot assign an unpacked type to a packed type

In System Verilog I wrote:
module mult32x32_arith (
input logic clk, // Clock
input logic reset, // Reset
output logic [63:0] product // Miltiplication product
);
logic left_decoder, right_decoder, product_FF[63:0]={64{1'b0}};
always_ff #(posedge clk, posedge reset) begin
if (reset==1'b1)begin
product <= product_FF;
end
else begin
end
end
But, I'm getting errors on this line:
product <= product_FF;
It says:
Error: mult32x32_arith.sv(19): Illegal assignment to type 'reg[63:0]' from type 'reg $[63:0]': Cannot assign an unpacked type to
a packed type.
But, I don't understand what the problem is.
You declared product as packed and product_FF as unpacked. Refer to IEEE Std 1800-2017, section 7.4 Packed and unpacked arrays:
The term packed array is used to refer to the dimensions declared
before the data identifier name. The term unpacked array is used to
refer to the dimensions declared after the data identifier name
You need to declare them as the same data type. For example, to make them both packed, change:
logic left_decoder, right_decoder, product_FF[63:0]={64{1'b0}};
to:
logic left_decoder, right_decoder;
logic [63:0] product_FF = {64{1'b0}};

Output is in undefined state

Image. I am trying to solve a problem that was written below. I confused why my output was in undefined state.
A "population count" circuit counts the number of '1's in an input vector. Build a population count circuit for a 255-bit input vector.
module top_module(
input [254:0] in,
output [7:0] out );
reg [7:0] counter=8'b0;
reg [7:0] counter_next=8'b0;
always # (*)
begin
counter=counter_next;
end
always # (*)
begin
for (int i=0; i<$bits(in);i++)
counter_next=counter+in[i];
end
assign out=counter;
endmodule
confused why my output was in undefined state.
All HDL variables are undefined ('X' or 'U') until you give them a value.
Then, you add a value to that undefined value counter_next=counter+in[i]; which still gives undefined. So it stays that way.
Also you are using 'counter=counter_next' which suggest you have seen some existing HDL code and you are trying to copy it, but you do not understand why it is implemented that way. The 'next' system is used when there is a clock. You do not have a clock and as such it is superfluous here.
The code you are looking for is probably something like this:
output reg [7:0] out
always #( * )
begin
out = 0;
for (int i=0; i<$bits(in);i++)
out =out+in[i];
end
Note that I am not using an extra variable counter here. All I do is make 'out' a reg type so I can use it directly.

How do you manipulate input arrays in an always block (verilog)?

I'm very new to verilog and i'm just starting to understand how it works.
I want to manipulate an input to a module mant[22:0], in an always block but I am not sure how to go about it.
module normalize(mant,exp,mant_norm,exp_norm);
input [22:0]mant;
input [7:0]exp;
output [22:0]mant_norm;
output [7:0]exp_norm;
reg mantreg[22:0];
reg count=0;
always#(mant or exp)
begin
mantreg<=mant; //this gives an error
if(mant[22]==0)
begin
mant<={mant[21:0],1'b0};//this also gives an error
count<=count+1;
end
end
endmodule
so i have to shift the mant register if the bit22 is zero and count the number of shifts. I am so confused about when to use reg and when to use wire and how to do the manipulation. please help let me know how to go about it.
As you can see in your code you are assigning vector value (mant) to array of 23(mantreg). Instead you should declare mantreg as reg [22:0] mantreg (which is vector of 23 bit).
Wire type variable can not be assigned procedurally. They are used only in continues assignment. Other way around reg varible can only be procedural assigned.
For that try to read out LRM of Verilog .

How to write to "wire" and passing parameters to arrays of instances in Verilog

I have the following code:
module X;
wire [11:0] mga [0:15];
// other code omitted here for clarity
reg [11:0] globalStartAddresses [0:15];
reg [11:0] globalEndAddresses [0:15];
localMMU mmu[0:15](clock, globalStartAddresses, globalEndAddresses, mrw, mdi, mdo, mga);
task dispatcher;
// parameters
output reg dataReady;
input readWrite;
input [7:0] dataIn;
output reg [7:0] dataOut;
input [11:0] globalAddress;
// local variables
integer x, selected;
begin
for(x=0; x<16; x=x+1) begin
if(globalAddress >= globalStartAddresses[x] && globalAddress <= globalEndAddresses[x]) selected=x;
end
mrw[selected]=readWrite;
mdi[selected]=dataIn;
assign mga[selected]=globalAddress;
if(readWrite==1)
wait(mdo[selected]!=0);
else
wait(mdo[selected]!=dataIn);
dataOut=mdo[selected];
end
endtask
endmodule
I get 2 errors in the code:
In the array instance declaration of "localMMU", it states that "globalStartAddress[ ] should be present", but I have declared it just above as is evident.
In the assign statement inside the task, it states that only variables are allowed on LHS.
(I am using VeritakWin 3.84F) Please tell me how can I rectify these 2 problems. Thanks.
globalStartAddresses and globalEndAddresses are both of type array but array can not be passed directly between two modules. You must flatten the array into a vector and then pass it to a module. The problem is answered here :
How to pass array structure between two verilog modules
Left hand side of procedural continuous assignment can not be of type wire while in continuous assignment, left hand side must be just of type wire. As a solution, change mga type to reg. The same problem answered here:
Continuous assignment verilog

Is this code structure going in the right direction?

I am trying to utilize a 7 segment display. I have written a module which I want to take 4 inputs and change the hex output. There seems to be an issue with unpacked/packed arrays and I really don't know what on earth I'm doing. Any help much appreciated.
module hexDisplay(hex, c0, c1, c2, c3);
input c0;
input c1;
input c2;
input c3;
output hex[6:0];
reg out[6:0];
always#(*)
begin
case({c3, c2, c1, c0})
4'b0000:out [5:0] = 1;
// 0001-1111 go here
//...
default:out [6:0] = 0;
endcase
assign hex = out;
end
endmodule
Errors:
Error (10773): Verilog HDL error at lab2pre.v(55): declaring module ports or function arguments with unpacked array types requires SystemVerilog extensions
Error (10133): Verilog HDL Expression error at lab2pre.v(61): illegal part select of unpacked array "out"
Error (10133): Verilog HDL Expression error at lab2pre.v(62): illegal part select of unpacked array "out"
Error (10048): Verilog HDL error at lab2pre.v(64): values cannot be assigned directly to all or part of array "hex" - assignments must be made to individual elements only
Error (10137): Verilog HDL Procedural Assignment error at lab2pre.v(64): object "hex" on left-hand side of assignment must have a variable data type
Error (10044): Verilog HDL error at lab2pre.v(64): expression cannot reference entire array "out"
Error: Quartus II 64-Bit Analysis & Synthesis was unsuccessful. 6 errors, 1 warning
Error: Peak virtual memory: 959 megabytes
Error: Processing ended: Tue Feb 2 17:33:35 2016
Error: Elapsed time: 00:00:15
Error: Total CPU time (on all processors): 00:00:46
Error (293001): Quartus II Full Compilation was unsuccessful. 8 errors, 1 warning
2 Errors :
You need to have "packed" array rather than an "unpacked" array for
"out" & "hex" nets.
SystemVerilog supports both packed arrays and unpacked arrays of data.
The term packed array is used to refer to the dimensions declared
before the data identifier name. The term unpacked array is used to
refer to the dimensions declared after the data identifier name.
bit [7:0] c1; // packed array of scalar bit types
real u [7:0]; // unpacked array of real types
A packed array is a mechanism for subdividing a vector into subfields,
which can be conveniently accessed as array elements. Consequently, a
packed array is guaranteed to be represented as a contiguous set of
bits.
An unpacked array may or may not be so represented. A packed array
differs from an unpacked array in that, when a packed array appears as
a primary, it is treated as a single vector.
So in the code, you require, out & hex to be used as a continuous
bit vector, then it should be packed array, instead of unpacked
array.
Refer to topic 7.4 of the Systemverilog LRM.
assign statement to hex, cannot be with in always block. Because an
assign statement is used for modeling only combinational logic and it
is executed continuously. So the assign statement is called
'continuous assignment statement' as there is no sensitive list.
So it can't be within always block, which is executed as per
sensitivity list.
So your final working code is as below:
module hexDisplay(hex, c0, c1, c2, c3);
input c0;
input c1;
input c2;
input c3;
output [6:0] hex;
reg [6:0] out;
always#(*)
begin
case({c3, c2, c1, c0})
4'b0000:out [5:0] = 1;
// 0001-1111 go here
//...
default:out [6:0] = 0;
endcase
end
assign hex = out;
endmodule
Try something like this. Move the range specifiers ([6:0]) to the left of the signal names, and move the assign outside of the always block.
module hexDisplay(hex, c0, c1, c2, c3);
input c0;
input c1;
input c2;
input c3;
output [6:0] hex;
reg [6:0] out;
always#(*)
begin
case({c3, c2, c1, c0})
4'b0000:out [5:0] = 1;
// 0001-1111 go here
//...
default:out [6:0] = 0;
endcase
end
assign hex = out;
endmodule
whatever variable in always block must be reg , here you assign hex in always which is by default wire so if you assign hex at out side of always u will get compile free code.

Resources