Assigning entire array in verilog - arrays

I am trying to copy a 2d array into another like so:
reg [11:0] input_matrix [0:array_width - 1] [0:array_height - 1];
reg [11:0] output_matrix [0:array_width - 1] [0:array_height - 1];
always #(posedge clk)
begin
if(<some condition>)
output_matrix <= input_matrix;
end
So, we have two 2D arrays of 12-bit values. I'd like to copy one into the other.
This doesn't seem to be possible. Does anyone know the correct way to do this? Or, if not, explain why it's not possible? I can't see any reason why this assignment wouldn't be able to synthesize.
For loops generally don't synthesize well, for obvious reasons. However, is this one of the cases that a for loop can be used, because the loop is statically defined?

for loops are synthesizable. This is the case were it is perfectly fine as it can be statically unrolled.
The inner loop may not be necessary but I find some version of synthesis tools struggled with memory (array) assignments, they worked but renamed the buses badly which can cause issues with ECO's.
reg [11:0] input_matrix [0:array_width - 1] [0:array_height - 1];
reg [11:0] output_matrix [0:array_width - 1] [0:array_height - 1];
integer i;
integer j;
always #(posedge clk) begin
if(<some condition>) begin
for (i=0; i<array_width; i=i+1 ) begin
for (j=0; j<array_height; j=j+1 ) begin
output_matrix[i][j] <= input_matrix[i][j];
end
end
end
end

The code as you wrote it is synthesizable. See section 2.5.2 in this paper:
http://www.lcdm-eng.com/papers/snug13_SNUG-SV-2013_Synthesizable-SystemVerilog_paper.pdf

Related

Array search for 1s and 0s

I want to traverse a logic vector of 32 bits and find the indices which have value of 1 and 0 and store them in two separate arrays.
I will know through a input which will tell number of ones in the array.
The indices array will be two dimensional.
Also I want this to be implemented using combo logic and synthesizable.
I am not able to think of any logic without latch being inferred.
logic [31:0] data ; // Array to be traversed
logic [31:0] [ONES_NUM-1:0] one_index;// One's indices in array
logic [31:0] [32-ONES_NUM-1:0] zero_index;//Zeros indices in array
always #(*)
while(j < ONES_NUM)
while ( i < 32)
if(data[i]==1) begin
one_index[j][31:0] = i;
j++;
i++;
end
else
i++; //Here prob is no else statement so latch inferred.
Similar always#(*) for zero index as well.
Also I have doubts whether while loop is synthesizable.
Kindly help with the logic.
logic [31:0] data ;
logic [31:0][(ONES_NUM-1):0] one_index; // One's indices in array
logic [31:0][(32-ONES_NUM-1):0] zero_index; // Zeros indices in array
bit clk;
int j,k;
always#(posedge clk)
for(i=0;i<32;i++)
begin
if(data[i]==1)
begin
one_index[j]=i;
j++;
end
else
begin
zero_index[k]=i;
k++;
end
end
You have to use a clock to avoid latches.
you can refer to this link https://www.edaplayground.com/x/kZ6 for better understanding.

Making 2D arrays in Verilog

How do I create an 2D array in Verilog? To be precise, I wanted a 32x100 matrix. Then, how do I define the values of each position of this array?
I tried some stuff I found on the web, but my code needs to be synthesised , simulating is not enought.
Thanks
My attempt so far (I'm new to verilog)
module top(
input a
);
integer i;
reg [31:0] arr[0:99];
initial begin
for(i=0;i<100;i=i+1) begin
assign arr[i] = 22;
end
end
endmodule
Don't use assign within an initial block or always bock. It is procedural assign a simulation feature scheduled for depletion (IEEE Std 1800-2012 C.4 Constructs identified for deprecation).
I'm guessing you are targeting FPGA, you can initialize the array with:
initial begin
for(i=0;i<100;i=i+1) begin
arr[i] = 22;
end
end
IC design ignore initial the code would have to go into the reset condition of an always block. Alternatively if it is a ROM you can use a generate block:
genvar i;
generate
for(i=0;i<100;i=i+1) begin
assign arr[i] = 22;
end
endgenerate

Passing in a subset of an array to the mean function in SAS

I have an array of variables and an array of flags, both of length 77. For every observation, the array of flags is made up of consecutive 0's, followed by consecutive 1's (ie, after a flag is a 1, all flags at a later index is a one). I am trying to calculate the mean/std/min/max of the array of variables where its corresponding flag is a 0. This is my macro:
%macro meanof_precancel(input, meanstat);
j = 77;
do i = 1 to 77;
if cancelled_{i} = 1 then do;
j = i - 1;
call symputx('lastactive', j);
leave;
end;
end;
if j = 0 then &meanstat = 0;
else &meanstat = mean(of &input.1-&input.&lastactive);
%mend;
I am having difficulty finding out how to resolve the line:
else &meanstat = mean(of &input.1-&input.&lastactive);
Does anybody have a strategy to resolve it to something like the following, for j = 33:
else mean_stats = mean(of total_1-total_33);
Thanks in advance.
I used another approach in the end, although it requires a creation of 77 new variables. I created a new array which sets each value to missing whenever its corresponding flag is one, and took the mean of this new array. For those interested :
%macro meanof_precancel(input, meanstat);
array &input.temp{77};
do i = 1 to 77;
if not cancelled_{i} then
&input.temp{i} = &input{i};
else &input.temp{i} = .;
end;
&meanstat = mean(of &input.temp{*});
%mend;
as you figured out you can only sum the values of the entire array, and the reason you were having issues with:
else &meanstat = mean(of &input.1-&input.&lastactive);
is because the call symputx earlier in the macro isn't executed until the datastep has finished.
here is the corresponding SAS documentation:
Problem Trying to Reference a SYMPUT-Assigned Value Before It Is
Available
One of the most common problems in using SYMPUT is trying to reference
a macro variable value assigned by SYMPUT before that variable is
created. The failure generally occurs because the statement
referencing the macro variable compiles before execution of the CALL
SYMPUT statement that assigns the variable's value. The most important
fact to remember in using SYMPUT is that it assigns the value of the
macro variable during program execution, but macro variable references
resolve during the compilation of a step, a global statement used
outside a step, or an SCL program.
As a result: • You cannot use a
macro variable reference to retrieve the value of a macro variable in
the same program (or step) in which SYMPUT creates that macro variable
and assigns it a value.
http://support.sas.com/documentation/cdl/en/mcrolref/61885/HTML/default/viewer.htm#a000210266.htm
this would be destructive of the original data so i would be careful, but it will allow for calculation of std/mean/min/max etc from the original array.
%macro precancel_stat(input, statvar, stat);
j = 77;
do i = 1 to 77;
if cancelled_{i} = 1 then do;
j = i - 1;
do k=i to 77;
&input.{k}=.;
end;
i=77;
end;
end;
if j = 0 then &statvar = 0;
else &statvar = &stat.(of &input.{*});
%mend;
/* test datasets*/
data test;
array sum_me{77} sum1 - sum77;
array cancelled_{77} cancelled1 - cancelled77;
do k=1 to 10;
do i =1 to 77;
sum_me{i}=i;
if i lt 33+k then cancelled_{i}=0; else cancelled_{i}=1;
end;
output;
end;
run;
/* test the macro call*/
data testit ;
set test (drop= i k );
array sum_me{77} sum1 - sum77;
array cancelled_{77} cancelled1 - cancelled77;
%precancel_stat(sum_me,meanstat,mean);
%precancel_stat(sum_me,StDev,STD);
%precancel_stat(sum_me,MinVal,Min);
%precancel_stat(sum_me,MarVal,Max);
%precancel_stat(sum_me,SumVal,sum);
run;
proc print data=testit;
run;
You can't use call symput that way, because the timing is wrong; you need to know the value of &lastactive. during compilation, but you don't actually know it until the data has been looked at.
You can certainly do this with a helper array. I would use a temporary array for this purpose, if you're going to do it that way (array &input.temp[77] _temporary_;) as it won't be written out uselessly to the final dataset and resides only in memory.
Honestly, you might be best off just having two variables, the mean-variable and a counter (your j is that already, basically). Instead of putting it in the temporary array, just
meanvar=meanvar+input[i];
And then at the end of the loop
meanvar=meanvar/j;
That seems more efficient.

Verilog Parallel Check and Assignment Across Dissimilar Sized Shift Registers

I'm looking to perform the cross-correlation* operation using an FPGA.
The secific part that I am currently struggling with is the multiplication piece. I want to multiply each 8-bit element of a nx8 shift register that uses excess or offset representation** against a nx1 shift register where I treat 0s as a -1 for the purposes of multiplication.
Now if I was doing that for a single element, I might do something like this for the operation:
input [7:0] dataIn;
input refIn;
output [7:0] dataOut;
wire [7:0] dataOut;
wire [7:0] invertedData;
assign invertedData = 8'd0 - dataIn;
assign dataOut <= refIn ? dataIn : invertedData;
What I'm wondering is how do I scale this to 4, 8, n elements?
My first though was to use a for loop like this:
for(loop=0; loop < n; loop = loop+1)
begin
assign invertedData[loop*8+7:loop*8] = 8'd0 - dataIn[loop*8+7:n*8];
assign dataOut[loop*8+7:loop*8] <= refIn[loop] ? dataIn[loop*8+7:loop*8] : invertedData[loop*8+7:loop*8];
end
This doesn't compile, but that's more or less the idea, and I can't seem to find the right syntax to do what I want.
https://en.wikipedia.org/wiki/Cross-correlation
** http://www.cs.auckland.ac.nz/~patrice/210-2006/210%20LN04_2.pdf
for(loop=0; loop < n; loop = loop+1)
begin
assign invertedData[n*8+7:n*8] = 8'd0 - dataIn[n*8+7:n*8];
assign dataOut[n*8+7:n*8] <= refIn[n] ? dataIn[n*8+7:n*8] : invertedData[n*8+7:n*8];
end
There's a few issues with this, but I think you can make this work.
You can't have 'assign' statements in a for loop. A for loop is meant to be used inside a begin/end block, so you need to change invertedData/dataOut from wire type to reg type, and remove the assign statements.
You generally can't have variable part-selects, unless you use the special constant-width selection operator (verilog-2001 support required). That would look like this: dataIn[n*8 +:8], which means: select 8 bits starting from n*8.
I don't know about your algorithm, but it looks like loop/n are backwards in your statement. You should be incrementing n, not loop variable (or else all statements will be operating on the same part-select).
So considering those points I believe this should compile for you:
always #* begin
for(n=0; n< max_loops ; n=n+1)
begin
invertedData[n*8 +:8] = 8'd0 - dataIn[n*8 +:8];
dataOut[n*8 +:8] <= refIn[n] ? dataIn[n*8 +:8] : invertedData[n*8 +:8];
end
end

Verilog, logic OR-ing an entire array

Suppose I have an array like this:
parameter n=100;
reg array[0:n-1];
How would one get the logic-OR value of each and every bit in the array?
The resulted circuit must be combinatorial.
This is a follow up question from this one.
(see discussion below the answer)
I don't know if this meets your design requirements, but you might have a much easier time with a hundred bit bus reg [n-1:0] array; than by using an array of 1 bit wires. Verilog does not have the greatest syntax to support arrays. If you had a bus instead you could just do assign result = |array;
If you must use an array, than I might consider first turning it into a bus with a generate loop, and then doing the same:
parameter n=100;
reg array[0:n-1];
wire [n-1:0] dummywire;
genvar i;
generate
for (i = 0; i < n; i = i+1) begin
assign dummywire[i] = array[i];
end
endgenerate
assign result = |dummywire;
I'm not aware of a more elegant way to do this on arrays.

Resources