Assigning 1 bit values to a multidimensional array in Verilog? - arrays

I am writing a Verilog code in which a 1 bit input has to be serially assigned (bit-wise) to a 2D memory. As far as I understand if we make a memory then it can be assigned byte wise (or contiguously) only at run time. Is there any way I can easily fill up a multidimensional array bit wise in Verilog like in C. Here is a snippet of my code:
input in,clk;
reg [7:0] array [0:511];
reg [8:0] i=9'd 0;
reg [2:0] j=3'd 0;
always # (posedge clk)
begin
if (i<=9'd 511)
begin
if(j<=3'd 7)
begin
array[i][j]<=in;
j<=j+1;
end
else
j<=0;
i<=i+1;
end
else
i<=0;
end //end always
But this is not giving me the desired results in the post-route simulation. Any suggestions are welcome.

It is impossible for i & j to be above 511 & 7 respectively. Therefore, if (i<=9'd 511) and if(j<=3'd 7) will always evaluate to be true and the else condition is unreachable.
Furthermore your i<=i+1; does not have a condition statement so it will always incroment, updating the array in a diagonal: [0][0] -> [1][1] -> ... -> [7][7] -> [8][0] -> [9][1] -> .... I assume this is undesired.
To fill the byte before changing i, you should use something like this:
array[i][j] <= in;
if (j == 3'd7) begin
j <= 3'd0;
if (i == 9'd511) begin
i <= 0;
end
else begin
i <= i + 1;
end
end
else begin
j <= j + 1;
end
Since the addressable range is a power of two, you can simplify the logic
array[i][j] <= in;
j <= j + 1; // Reminder <= is eval now, update later
if (j == 3'd7) begin // 'j' here has the pre-eval value
i <= i + 1;
end
FYI: you should always run in simulation before post-route. It is way easier to debug RTL and a waveform.

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.

Array's length in Matlab

How I could determine the number of elements from an array in Matlab, without using functions such as length(), size(), etc. ?
Thanks you !
The logic is to iterate over the cells until an empty cell is encountered. I have taken two variables for iteration namely, i and j. i is for rows and j is for columns.
Initially set the value of i and j as i=1 and j=1. Now in a while loop iterate by incrementing j and keeping i = 1 as constant.
** First try to copy that cell in a variable x. If that cell is an empty cell an error will pop up. Aim is to take advantage of this error using try/catch statements.
Scince the statement x = vec(i,j); is written in the try block so on encountering an empty cell instead of try the catch block will be executed where flag = 0 makes the flag 0, this will cause the while loop to end.
So, we have the number of columns stored in j and the while loop terminates on encountering an empty cell.
flag = 1;
i = 1;
j = 1;
while(flag==1) % loop will continue till flag is 1 (or say flag is HIGH)
try
x = vec(i,j); % Try to copy this cell of array vec in x
j = j+1; % if successful to copy then increment value of j else catch block is executed
catch
flag = 0; % Set flag = 0 (or low) to end the while loop
end
end
j = j - 1; % The value of j comes out to be one greater than number of columns hence decrementing by 1
%
% WE HAVE THE NUMBER OF COLUMNS !!
%
% WE WILL PERFORM SAME THING TO GET THE NUMBER OF ROWS BY INCREMENTING i AND
% KEEPING j AS CONSTANT
flag=1;
while(flag==1)
try
x = vec(i,j);
i = i+1;
catch
flag = 0;
end
end
i = i - 1;
% i is the number of rows in the matrix or array
% j is the number of columns in the matrix
dim = [i,j] % vector named dim(or say matrix named dim) contains the required output
dim contains the size of vec

Comparing input signal with array values

As I wrote in my previous post Synthesizable array of XY values
I wanted to create an array in Verilog to store x, y values of a given function.
Now I want to compare an input with x values of this array. If the value is within a specific region I want to save the index of this region and perform an addition with y with the same index. The result goes to the output. The code compiles just fine but its not synthesizes any circuit. The idea later is to use this array to perform linear interpolation and determinate the value of y for a given value of x that its not inside the array. The code is the following. I save the save value for x and y for each index.
module memc (inp,outp,clk,reset);
input[2:0] inp;
input clk, reset;
output[2:0] outp;
reg[2:0] outp;
wire [2:0] test;
reg [5:0] mem[2:0];
always #(posedge clk)
if (reset == 1'b1) begin
mem[0] <= {3'b000, 3'b000};//y0,x0
mem[1] <= {3'b001, 3'b001};//y1,x1
mem[2] <= {3'b010, 3'b010};//y2,x2
end
assign test ={inp<mem[0][2:0],inp<mem[1][2:0],inp<mem[2][2:0]}; //create a test vector by comparing inp with xo,x1,x2
always #(test)
case (test)
3'b1xx: outp=mem[0][2:0]+mem[0][5:3];//if 0<inp<x1
3'b0xx: outp=mem[1][2:0]+mem[1][5:3];//if x1<inp<x2
3'b00x: outp=mem[2][2:0]+mem[2][5:3];//if x2<inp<x3
default: outp=3'b00;
endcase
endmodule
Firstly, all three of your if conditions are the same (inp > mem[0][2:0]). I'm assuming you want
always #(*)
begin
if (inp > mem[0][2:0] ) //index 0
begin
index = 0;
end
else if (inp > mem[1][2:0] ) // index 1
begin
index = 1;
end
else if(inp > mem[2][2:0] ) // index 2
begin
index = 2;
end
end
Secondly, if you are using a large array (hard to be exact on the size), the latency from inp -> outp will get quite long, and you may get timing violations, depending on your clock speed. In that case, you'd be better off building a very simple FSM, and checking one or two entries per clock cycle instead. Just something to keep in mind moving forward.

Carry over incrementing bytes in an array

I'm testing to see how easily (or quickly rather) our encryption can be cracked. The encryption key is an array of byte (could be any variable length). So, starting from an array populated with all 0's, I need to increment one byte at a time starting with the first. When any byte reaches its max and goes back to 0, the next byte in the array needs to increment (carry over).
It would be simple if the array were a short fixed length - but I'm clueless how to do so in a variable array length.
Variable declared inside the thread:
FKey: array of Byte;
After each thread iteration, it calls this procedure to increment the key by one byte:
procedure TCrackThread.NextKey;
begin
//Increment first byte
//If max, reset to 0 and increment next byte
//Recursively check the same for each following byte in array
end;
How can I increment (starting from the first) the bytes and carry over to the next in this variable length array?
This snippet will increase the first element and will continue to do so with the array elements as long as they are 255. If so, they are reset to zero. The routine will stop as soon as the condition is not fulfilled or the index reached maximum.
var
k: Integer;
...
if (Length(fKey) > 0) then begin
k := 0;
Inc(fKey[k]);
while (fKey[k] = 255) do begin
fKey[k] := 0;
Inc(k);
if (k >= Length(fKey)) then
break;
Inc(fKey[k]);
end;
end;
This would convert an array 254,0,0 into 0,1,0
If you want a carry to ripple through before the first increment,
this code will do that:
procedure Next;
var
k: Integer;
carry: Boolean;
begin
if (Length(fKey) > 0) then begin
k := 0;
repeat
carry := (fKey[k] = 255);
if carry then begin
fKey[k] := 0;
Inc(k);
if (k >= Length(fKey)) then
break;
end
else
Inc(fKey[k]);
until not carry;
end;
end;
This will convert 255,255,0 into 0,0,1.

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