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

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

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.

Endless loop for Write a function first_n_evens(n) that returns an array of the first N many even numbers

I can't figure out how to correctly complete this question.
Write a function first_n_evens(n) that returns an array of the first N many even numbers, starting from 0.
Please help me understand what I am doing wrong.
Many Thanks
def first_n_evens(n)
array = []
number = 0
while array.count <= n
if number % 2 == 0
array.push(number)
number += 1
end
end
return array
end
test = first_n_evens(5)
puts test
This line:
number += 1
Is inside of your if block. If number is even, number gets incremented. If number is odd, then the if condition isn't met, and nothing happens.
Move that line outside of the if..end block, and you should be okay.

Unable to do vector division (every element) and append to a new array

I need to append the division between two arrays into a new array. But the same value being iteratively stored into the new array.
clear; close all;
%Plot G (small - signal gain) vs v (frequency)
%Assume frequency probe region to be thrice the line-width
f=input('Line Width Frequency(in Hz) :');
v=(-3*f):10e10:(3*f);
l=length(v);
g=zeros(1,l);
k=zeros(1,l);
h=ones(1,l);
% Substituing the constants we realize g(v) is a function
% line shaping function
for i=1:l
k(1:i)=((v(1:i)-2.82*10e-4)+((627.95*10e9)^2));
end
g=rdivide(h,k);
You are assigning multiple elements of k at once. Try this:
for i=1:l
k(i)=((v(i)-2.82*10e-4)+((627.95*10e9)^2));
end
or even more simply, this is a great example of a vectorized operation:
k = (v -2.82*10e-4)+((627.95*10e9)^2)); %% works the same as above
k(1:i) is a slice of the array k, containing the elements 1, 2, .. i. So in the last loop iteration, you assign the entire array k(1:l), wiping out the calculations from previous iterations.

VHDL: Is it possible to concurrently shift array elements?

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.

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.

Resources