VHDL: Is it possible to concurrently shift array elements? - arrays

I would like to crearte own implementation of insertion sort for learning purposes.
As you may now, one of the steps reqiure shifting array elements to right by 1. The main difficulty here that the range of this operation has to be dynamic.
so if sort_reg is array from 0 to array_length, I need to acheive sort_reg(n)<=sort_reg(n-1), sort_reg(n-1)<=sort_reg(n-2) ... sort_reg(n-i+1)<=sort_reg(n-i); (n-m)>=i>=1, where m starting array index of the range, which would be shifted right by 1 from range ( m to n-1) to (m+1 to n).
The question is if it is possible to acheive this in one step, and then how?

Yes, it is possible in one step. You must store the element in registers and than assign the new value for all array elements at the same rising edge.
Let's make a simple example with just two signals a and b of type std_logic. Then this process would swap both elements at the rising edge of the clock:
process(clock)
begin
if rising_edge(clock) then
a <= b;
b <= a;
end if;
end process;
This works, because the signals get there new values after the process has finished. Thus, in the assignment of b the old value of a (before the rising clock edge) is assigned.
Let's continue with your example.
You didn't specify an specific array, so I take this one:
type array_type is array(0 to SIZE-1) of std_logic_vector(7 downto 0);
signal sort_reg : array_type;
Then the process can be written using a for loop.
EDIT: Within each iteration step, anif statement can be used to check if an element should be actually shifted. The signals n and m should be of type unsigned (prefered), or integer with range 0 to SIZE-1.
EDIT 2: Example changed to rotation as indicated in comments.
-- value to insert in case of rotation
value_to_insert <= sort_reg(to_integer(n)); -- to_integer required if type of 'n' is unsigned
process(clock)
begin
if rising_edge(clock) then
-- This loop is unrolled by the synthesis tool.
for i in SIZE-1 downto 1 loop
-- shift elements [n-1:m] to [n:m+1]
if (i <= n) and (i >= m+1) then
sort_reg(i) <= sort_reg(i-1);
end if;
-- insert new value
if i = m then
sort_reg(i) <= value_to_insert;
end if;
end loop;
-- insert into position zero
if m = 0 then
sort_reg(0) <= value_to_insert;
end if;
end if;
end process;

How about this;
sort_reg <= sort_reg(1 to sort_reg'high) & sort_reg(0);
I'm assuming sort_reg is a signal defined as;
signal sort_reg : some_array_type(0 to N);
In this case sort_reg'high is an attribute that is equal to N.
In vhdl & is used as concatenation operators. It joins two vector/arrays together to form a single vector/array.
Above example shifts only by 1 item. If you want to shift by M, you can use something like this;
sort_reg <= sort_reg(M to sort_reg'high) & sort_reg(0 to M-1);
Note that if you want to shift a signal (not assign it to a different signal) you should do it in a process as described by Martin.

Related

Printing array of integers generates weird output in Ada

I created a simple Ada program that allows a user to populate an array with a maximum of 100 non negative and non zero integers and then prints them out. When I call the function to print out the numbers it prints them out but at the same time it also prints out a bunch of strange and seemingly random numbers. What mistake have I made in my code that is causing the program to output such strange results? This is my first time writing in Ada. For example when I populate the empty array with the numbers [1,2,3,4,5] is prints out this:
1
2
3
4
5
32624
911328835
32624
911328836
32624
67043328
134217726
134217726
2013265921
134217726
134217726
134217726
67043328
909181968
32624
2114692683
89452
914381552
32624
1543503876
2
14
2
14
I am using the gnatmake compiler on ubuntu and when compiling the source code it doesn't give me any error/warning messages.
Here is my source code, I know that I probably don't need to use seperate functions but I implemented them anyways for learning purposes.
with Ada.Containers.Vectors;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
use Ada.Containers;
procedure thing is
type Vector is array (1..100) of Integer;
A: Vector;--array doesn't need to be completely filled up
K: Integer;
--array filling function below
function mkarr return Vector is --asks user to fill empty array with positive and non zero integers
begin
Ada.Text_IO.Put ("enter numbers to fill array, negative or 0 will stop process: ");
for I in 1..100 loop
Ada.Integer_Text_IO.Get(K);
if K>0 then
A(I) := K;
end if;
if K<=0 then
return A;
end if;
end loop;
return A;
end;
--array printing prodcedure below
procedure printarr(A: in out Vector) is
begin
for I in A'Range loop
if A(I)>0 then
Ada.Integer_Text_IO.Put(A(I));
New_Line(1);
end if;
end loop;
end printarr;
B: Vector := mkarr;
--main method below
begin
printarr(A);
end thing;
In mkarr, you use a 0 or negative value to mark the end of the input, but you don't store that value in the array. If whatever garbage is stored in the array after the end of the values you entered happens to be positive, there's no way to tell that it's not a valid value.
In printarr, if you encounter a 0 or negative value you don't print it -- but you continue printing the remaining positive values (which are garbage).
If you store a sentinel value in mkarr, and quit printing in printarr when you encounter the sentinel, the program should work.
Some other notes:
A and K are used only inside mkarr. They should be local to mkarr.
You never use Ada.Containers.Vectors. You can delete the corresponding with and use directives.
For more advanced usage, you can have mkarr return an array containing only the entered data, by making Vector an unconstrained array type and returning a slice. It's still easier to define a fixed-length array inside mkarr. Allowing arbitrarily many inputs is tricker -- but Ada.Containers is probably a good way to do that. (Disclaimer: I haven't looked at Ada.Containers.)
Expanding on Keith’s answer:
You want a variable-length result, so the more Ada-like way is to use an "unconstrained array":
type Vector is array (Positive range <>) of Integer;
This means that you can create instances of the array of any size you like, so long as the bounds are positive: 1 .. 100, 42 .. 43 etc. You can even create a zero-length array by specifying the last bound (called ’Last) to be less than the first (called ’First). In this special circumstance, you’re allowed to use a ’Last outside the range of the index type (in this case, 0, or even -42 if you want to confuse people!).
function mkarr return Vector is
We have to have an actual array to accumulate the values, so set an upper limit of 100.
Result : Vector (1 .. 100);
We need to know how many elements there are.
Last : Natural := Result'First - 1;
More or less as before,
K : Integer;
begin
Ada.Text_IO.Put
("enter numbers to fill array, negative or 0 will stop process: ");
for I in Result'Range loop
We can return an array with at most Result’Length elements.
Ada.Integer_Text_IO.Get (K);
if K > 0 then
We can add one more element.
Last := Last + 1;
Result (Last) := K;
else
There are fewer than 100 elements, so return just that slice.
return Result (Result'First .. Last);
end if;
end loop;
We’ve accumulated 100 results, so return all of them.
return Result;
end mkarr;
As noted here, your example mentions Ada.Containers.Vectors with no further reference to the package. If you pursue such a solution, discussed here, you might first instantiate the generic package Vectors to get a resizable container of integers:
package Integer_Container is new Vectors (Natural, Integer);
Your function to make an array can then declare a Vector named A and initialize its elements and length to specific values:
function Make_Array (Size : Count_Type) return Vector is
A : Vector := To_Vector (New_Item => -1, Length => Size);
…
You can use Iteration in Ada 2012 to simplify your data collection in Make_Array:
for E of A loop
Get (K);
if K > 0 then
E := K;
else
exit;
end if;
end loop;
Similarly, a procedure Print_Array (A : in Vector) might loop like this:
for E of A loop
Put (E, 4);
end loop;
A typical usage might look something like this:
Print_Array (Make_Array (42));
Additional details may be found here and here.

VHDL shift Array elements of an (N+1) x 13 Array

I seem to have problems with shifting vector array elements. When my FSM enters a state, a 0 should be added to the beginning of an input, which then is saved at the 0th array position. The rest of the array entries should be shifted one step further, so position 0 to position 1 etc.
What I tried to use in my statemachine is
when readAndShift =>
x(0) <= "0" & x_in;
for i in N to 1 loop
x(i) <= x(i-1);
end loop;
The type and variable declaration is:
type tap_line is array(0 to N) of std_logic_vector(12 downto 0);
.
.
.
signal x : tap_line := (others=>(others=>'0'));
As far as I understood, in VHDL the for loop "unfolds" itself and executes every step of the for loop simultaneously, so one rising clock edge should be sufficient, right? My simulation only shows change in the 0th array element.
Okay, so what I wanted to write is
when readAndShift =>
x(0) <= "0" & x_in;
for i in N downto 1 loop
x(i) <= x(i-1);
end loop;
I thought the direction would be determined automatically.
Thanks for the help, now I can continue with fixing the rest of the logical issues

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