Incrementing a variable in for-generate in verilog - arrays

I need to generate the following assignments in a for-generate block in verilog. This is a part of an signed number multiplication process for a given bit size n=8 bits.
assign p[1]=pp[1][1];
assign p[2]=pp[2][1];
assign p[3]=pp[3][1];
assign p[4]=pp[4][1];
assign p[5]=pp[5][1];
assign p[6]=pp[6][1];
assign p[7]=pp[7][1];
assign p[8]=pp[8][2];
assign p[9]=pp[9][3];
assign p[10]=pp[10][4];
assign p[11]=pp[11][5];
assign p[12]=pp[12][6];
assign p[13]=pp[13][7];
assign p[14]=pp[14][8];
assign p[15]=pp[15][9];
I could write the first part in first conditional statement within the for loop. For the second if block I am not able to run the second index variable of the pp[][] array. How to do this?
genvar k;
generate
for(k=1; k<=2*size-1; k=k+1)
begin:product
if (k<=size-2) begin
assign p[k] = pp[k][1];
end
else if (k>size-2) begin
assign p[k] = ??????????????????; //How to assign p[7] to p[15]
end
end
endgenerate

According to the pattern:
assign p[k] = pp[k][k-6];
(The loop is like a preprocessor anyway, no substraction will happen in hardware of course.)

Related

Updating golang array while iterating it

When iterating an array with range, if the array is updated the updated positions do not make it into the future loop runs. The following prints "1 2" instead of "1 0"
package main
import (
"fmt"
)
func main() {
var A = &[2]int{1, 2}
for i, v := range A {
if i == 0 {
A[1] = 0
}
fmt.Print(v, " ")
}
fmt.Println()
var B = [2]int{1, 2}
for i, v := range B {
if i == 0 {
B[1] = 0
}
fmt.Print(v, " ")
}
}
https://play.golang.org/p/0zZY6vjxwut
It looks like the array is copied before it's iterated.
What part of the spec describes this behavior?
See "For statements with range clause" at https://golang.org/ref/spec#For_range
TLDR; Whatever you range over, a copy is made of it (this is the general "rule", but there is an exception, see below). Arrays are rare in Go, usually slices are used. Slice values (slice headers) contain a pointer to an underlying array, so copying a slice header is fast, efficient, and it does not copy the slice elements, not like arrays. Ranging over a pointer to array is similar to ranging over a slice in this regard.
Spec: For statements:
The range expression x is evaluated once before beginning the loop, with one exception: if at most one iteration variable is present and len(x) is constant, the range expression is not evaluated.
Arrays are values, they do not contain pointers to data located outside of the array's memory (unlike slices). The Go Blog: Go Slices: usage and internals:
Go's arrays are values. An array variable denotes the entire array; it is not a pointer to the first array element (as would be the case in C). This means that when you assign or pass around an array value you will make a copy of its contents. (To avoid the copy you could pass a pointer to the array, but then that's a pointer to an array, not an array.) One way to think about arrays is as a sort of struct but with indexed rather than named fields: a fixed-size composite value.
Evaluating an array is a copy of the entire array, it is a copy of all the elements. Spec: Variables:
A variable's value is retrieved by referring to the variable in an expression; it is the most recent value assigned to the variable.
In your first example the range expression is just a pointer to the array, so only this pointer is copied (but not the pointed array), so when you do A[1] = 0 (which is a shorthand for (*A)[1] = 0), you modify the original array, and the iteration variable gets elements from the pointed array.
In your second example the range expression is the array, so the array (with all its elements) is copied, and inside it B[1] = 0 still modifies the original array (B is a variable, not the result of the evaluation of the range expression), but v is an element of the copy (v is populated from the copied array in each iteration).
Under the hood
So how is this "copy" realized? The compiler generates code for the for range that copies (assigns) the result of the range expression to a temporary variable (if needed, because it might not always be needed: "if at most one iteration variable is present and len(x) is constant, the range expression is not evaluated").
This code can be inspected in the cmd/compile/internal/gc/range.go file.
See related article: Go Range Loop Internals
The spec says
The range expression x is evaluated once before beginning the loop, with one exception: if at most one iteration variable is present and len(x) is constant, the range expression is not evaluated.
Function calls on the left are evaluated once per iteration. For each iteration, iteration values are produced as follows if the respective iteration variables are present
The thing here is that given your loop takes more than one variable, the range expression is evaluated only once at the beginning of the iteration. Thus the value of the B[1] assigned to the v won't change.
In the case with reference, you see the modified value since the expression evaluates the reference to the B[1], which is not modified and prints the value of that referenced variable, which is actually modified.

Systemverilog localparam array with configurable size

I want to create and define a localparam array in SystemVerilog. The size of the array should be configurable, and the value of each localparam array cell calculated based on its location. Essentially this code:
localparam [7:0] [ADDR_BITS-1:0] ADDR_OFFSET = '{
7*PAGE_SIZE,
6*PAGE_SIZE,
5*PAGE_SIZE,
4*PAGE_SIZE,
3*PAGE_SIZE,
2*PAGE_SIZE,
1*PAGE_SIZE,
0
};
but where the first '7' is replaced with a parameter, and where the parameter initialization is extended to the generic case. So I need a way to loop from 0 to (N-1) and set ADDR_OFFSET(loop) = loop*PAGE_SIZE.
The "obvious" option in SystemVerilog would be generate, but I read that placing a parameter definition inside a generate block generates a new local parameter relative to the hierarchical scope within the generate block (source).
Any suggestions?
For background reference: I need to calculate an actual address based on a base address and a number. The calculation is simple:
real_address = base_address + number*PAGE_SIZE
However, I don't want to have the "*" in my code since I am afraid the synt tool will generate a multiplier, that it will then try to simplify since PAGE_SIZE is a constant value. I am guessing that this can lead to more logic than if I try to do all calculations when generating the localparam array, since this for sure will not give any multiplier in logic.
So with the above localparam definition, I perform the desired address calculation like this:
function [ADDR_BITS-1:0] addr_calc;
input [ADDR_BITS-1:0] base_addr;
input [NBITS-1:0] num;
addr_calc = base_addr + ADDR_OFFSET[num];
endfunction
I think perhaps I found a solution. Wouldn't I essentially accomplish the same by not defining a localparam array, but rather performing the address calculation inside a loop? Since systemverilog sees the loop variable as "constant" (when it comes to generating logic) that seems to accomplish the same? Like this (inside the function I wrote above):
for (int loop1 = 0; loop1 < MAXNUM ; loop1++) begin
if (num == loop1) begin
addr_offset = CSP_PAGE_SIZE*loop1;
end
addr_calc = base_addr + addr_offset;
end
You can set your localparam with the return value of a function.
localparam bit [7:0] [ADDR_BITS-1:0] ADDR_OFFSET = ADDR_CALC();
function bit [7:0] [ADDR_BITS-1:0] ADDR_CALC();
for(int ii=0;ii<$size(ADDR_CALC,1); ii++)
ADDR_CALC[ii] = ii * PAGE_SIZE;
endfunction

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

Assigning vector values from a variable generated inside for loop matlab

In Matlab I am trying to assign values of a variable generated within a for-loop to an array.
for i=1:4
S = 2*i;
P(i) = S;
end
S is generated within the for loop and all the values it will have are: 2, 4, 6 and 8.
Now I want to assign each of these values of S to an array P such that I want
P(1) = 2, P(2) = 4, P(3) = 6, P(4) = 8
But the for-loop I have included does not work and I have no idea why. First of all it creates a char rather than creating and array. Secondly, none of the values are added and at the end P is empty.
I am not sure why its not working? Does anybody know how to fix this?
You already have a variable P which is a char. Subscript assigning does not change the type of the variable. Delete it using clear P and you get what you want. Alternatively you can overwrite P with zeros as Photon suggested.
This may also be solved without a loop:
P=2.*[1:4]
or:
P=2:2:8

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

Resources