I want to reverse and return an array in a function in system verilog, i tried below code and i am getting following error - system-verilog

module rev_array;
initial
begin
int array_in[10]={0,1,2,3,4,5,6,7,8,9};
typedef integer array[9:0];
function array reverse(int array_in[10]);
array reverse;
for(integer i=0;i<$size(array_in)-1;i++)
begin
for(int j=$size(array_in)-1;j>=0;j--)
begin
reverse[j]=array_in[i];
end
end
return reverse;
endfunction:reverse
reverse(array_in);
for(integer k=0;k<$size(array_in)-1;k++)
begin
$display("reverse[%0d]:%0d", k, reverse[k]);
end
end
endmodule
For the above code, I am getting error
Error-[SE] Syntax error
Following verilog source has syntax error :
"testbench.sv", 7: token is 'function'
function array reverse(int array_in[10]);
I want to return an array named reverse(same name as the function ) which has 10 elements, each element being an integer, what am I doing wrong here ?

You cannot define a function in the middle of a procedural block. Move it to the top level of the module. You have many other problems. Note there is a built-in reverse array method.

Related

Converting arrays from signed to integer in VHDL?

I have declared an array
type datastream is array(0 to 10) of signed (5 downto 0);
For simulation, I want to display the array as integer-numbers
So I created
type datastream_int is array(0 to 10) of integer;
and
signal DIN_ARRAY: datastream;
signal DIN_ARRAY_int: datastream_int;
...
DIN_ARRAY_real <= datastream_int(DIN_ARRAY);
But it fails. How to convert it? Dont want to use a for loop
The numeric_std package, that I assume you are using, provides a to_integer function to convert from a single signed value to a single integer object. For an array, you're going to have to use a for loop. Something like this:
for i in DIN_ARRAY'range loop
DIN_ARRAY_int <= to_integer(DIN_ARRAY(i));
end loop;
You could also provide a conversion function (it will also contain a for loop)
function datastream_to_datastream_int( d : datastream ) return datastream_int is
variable r : datastream_int;
begin
for i in d'range loop
r(i) := to_integer(d(i));
end loop;
return r;
end function;
....
--no loop required
DIN_ARRAY_int <= datastream_to_datastream_int(DIN_ARRAY);
So, there will be a for loop somewhere.
Your code fails because you have attempted a type conversion, which is only allowed between similar types - ie. array or record types where the element types match between the two types.
PS. VHDL 2008 provides an integer_vector type in the std.standard library (which is included by default) which may help by allowing you to do this:
signal DIN_ARRAY_int: integer_vector(DIN_ARRAY'range);
If you did decide to keep datastream_int as per your original, you could type convert it to an integer_vector, because the types are similar:
my_iv <= integer_vector(DIN_ARRAY_int);

How to return an array from a function with the same name as that of the function in system verilog?

module rev_array;
int array_in[10]={0,1,2,3,4,5,6,7,8,9};
typedef integer array[9:0];
function array reverse(int array_in[10]);
for(int j=$size(array_in)-1,int i=0;j>=0;j--,i++)
begin
reverse[j]=array_in[i];
end
// working for(integer k=0;k<$size(array_in)-1;k++)
// working $display("reverse[%0d]:%0d", k, reverse[k]);
$display("inside function");
endfunction:reverse
initial
begin
reverse(array_in);
for(integer k=0;k<$size(array_in)-1;k++)
begin
$display("reverse[%0d]:%0d", k, reverse[k]);
end
end
endmodule
Error-[IUS] Illegal use of scope
testbench.sv, 22
rev_array, "rev_array.reverse"
Scope cannot be used in this context
Error-[XMRIBS] Illegal bit select
testbench.sv, 22
Error is found in following cross-module reference, illegal bit select on
the target.
Source info: $display("reverse[%0d]:%0d", k, rev_array.reverse[k]);
I am trying to reverse an array and return it in system verilog function, I am able to see the reversed array inside the function by printing it but
when I try to print it using $display outside the function, I think it is
not being returned properly somehow, in the 4th line from end, getting
errorError-[IUS]
your both issues are related to the line where you use reverse function name as an array within $display.
$display("reverse[%0d]:%0d", k, reverse[k]);
--------------------------------^^^^^^^^^^
this is an illegal syntax causing both messages.
your initial block should look like the following.
initial
begin
array result;
result = reverse(array_in);
//^^^^^^^^^^^^^^^^^^^^^^^^^//
for(integer k=0;k<$size(array_in)-1;k++)
begin
$display("reverse[%0d]:%0d", k, result[k]);
// ^^^^^^ //
end
end
call the function and use returned results for display.

Error (10686): SystemVerilog error at file.sv(8): InstAddress has an aggregate value

I am trying to compile the following SystemVerilog, and I get the following error "Error (10686): SystemVerilog error at InstRom.sv(8): InstAddress has an aggregate value."
module InstRom#(parameter A = 16, parameter W = 9)
(
input InstAddress[A-1:0],
output logic InstOut[W-1:0]
);
logic[W-1:0] instr_rom[2**(A)];
always_comb InstOut = instr_rom[InstAddress];
initial begin
$readmemb("cordic.txt", instr_rom);
end
endmodule
What am I doing wrong?
InstAddress is an unpacked array of bit, not a bit vector (i.e. a packed array). The same applies to InstOut. Change the declaration to
input logic [A-1:0] InstAddress,
output logic [W-1:0] InstOut
and your code should work.

How to assign an unpacked array of real?

While updating Modelsim from 10.3c to 10.6a, I encountered an error on this piece of code that used to not work without warning:
module test(
input bit clk,
input bit signed[31:0] data
);
real rdata_dl[19:0] = '{20{0}};
real rdata = 0;
always #(posedge clk) begin
rdata_dl = {rdata_dl[18:0], rdata};
rdata = data;
end
endmodule
-- Compiling module test
** Note: test.sv(10): (vlog-13177) Promoting concatenation '{rdata_dl[18:0],rdata}' to an assignment pattern: Assigning to a real/wreal array.
** Error (suppressible): (vlog-13215) test.sv(10): Assignment pattern element 'rdata_dl[18:0]': Cannot assign an unpacked type 'real $[18:0]' to a packed type 'real'.
** Error (suppressible): test.sv(10): (vlog-13174) Illegal assignment pattern. The number of elements (2) doesn't match with the type's width (20).
I managed to fix it by using this line instead: rdata_dl = {rdata_dl[18:0], real'(rdata)};.
However, I fail to understand why it failed and why the new version would work. Can anyone explain?
not sure what you are trying to do with this code. real type is 64-bit. When concatenating it with 19-bits, you're getting a 83-bit bus, where the rdata is in the LSBs.
Now, when assigning this 83-bit vector to a 20-bit bus, it will take the 20 LSBs, meaning that it is equivalent to writing the following assignment:
always #(posedge clk) begin
rdata_dl = rdata[19:0];
rdata = data;
end

How can we define a 3-dimensional array of geometry?

I want to write a code for postgis in pgAdmin that is based on postgresql. It defines a 3-dimensional array of geometry.
I used this code for it:
DECLARE
G geometry[9][9][9];
BEGIN
for i IN 1..9 LOOP
for j IN 1..9 LOOP
for k IN 1..9 LOOP
G[i][j][k] := [value that I want];
END LOOP;
END LOOP;
END LOOP;
But it returned this error:
"array subscript out of range"
I used this instead:
DECLARE
G geometry[9][9][9];
BEGIN
for i IN array_lower(G, 1)..array_upper(G, 1) LOOP
for j IN array_lower(G, 1)..array_upper(G, 1) LOOP
for k IN array_lower(G, 1)..array_upper(G, 1) LOOP
G[i][j][k] := [value that I want];
END LOOP;
END LOOP;
END LOOP;
I have a different error this time:
"lower bound of FOR loop cannot be null"
I used this in BEGIN Part and solved all the errors:
G[1][1][1] := '01010000200400000000000000000000000000000000000000';
But I think this is not true and doesn't calculate all of the iterations for loops. I think this takes in account only the G[1][1][1]. What should I do now?
In PostgreSQL, simply declaring the array dimensions does not initialize or pre-allocate anything. The array is dynamic in all its dimensions. That differs significantly from the multi-dimensional array implementations found in general programming language like C.
To mimic the logic of these languages, you may first initialize the 9x9x9 array with a statement like this:
G:=array_fill('point(0 0)'::geometry, array[9,9,9]);
Then the rest of the code will just work when refering to G[i][j][k] either as source or destination of assignments.