Bit order for 2D array - multidimensional-array

I've got a 2x2 array of 4-bit std_logic_vector in my VHDL and when I simulate it my tool only gives me a 16 bit std_logic_vector, which bits are which?
More generally: how does VHDL store multidimensional arrays?

From the discussion on this answer it seems that there is no fixed way to store these bits and it's up to the tools you use to provide a correct interface. Mine are apparently a bit wonky.
I did a quick experiment and FOR MY TOOLS it appears the for an array A you get the A(i,j) in the order you specify them. So if you do:
type array_type is array (integer range 0 to 1,integer range 0 to 2) of std_logic_vector(3 downto 0);
you get: A(0,0), A(0,1), A(0,...), A(1,0), A(1,1), A(1,...).
But if you declare your array as:
type array_type is array (integer range 1 downto 0,integer range 2 downto 0) of std_logic_vector(3 downto 0);
(Note we're now using downto) you'll get A(1,2), A(1,1), A(1,0), A(0,2), A(1,1), A(0,0).
I'm making this deduction based on running the following code:
library ieee;
use ieee.std_logic_1164.all;
entity arrays is
port (
x : in std_logic_vector(3 downto 0);
y : out std_logic_vector(3 downto 0)
);
end entity arrays;
architecture rtl of arrays is
type array_type is array (integer range 0 to 1,integer range 0 to 2) of std_logic_vector(3 downto 0);
signal my_array : array_type;
begin
my_array(0,0) <= "0001";
my_array(0,1) <= "0010";
my_array(0,2) <= "0011";
my_array(1,0) <= "0100";
my_array(1,1) <= "0101";
my_array(1,2) <= "0110";
y <= x;
end architecture rtl;
and getting my_array to be 123456 where each character is a hex number.
Then I switched round the deceleration and got 654321.

Related

Fibonacci series in Ada using recursion

In this code, I am trying to write a program that prints out the Fibonacci series based on the users' input (Index, Size). An then, the program should print out all the Fibonacci numbers between Index..Size. I have trouble, writing a recursion that calculates and prints out the Fibonacci numbers. Any suggestions?
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Text_IO, Ada.Unchecked_Deallocation;
procedure Fibonacci is
type Arr is array (Positive range <>) of Integer;
type Array_Access is access Arr;
Size, Index : Positive;
Variable : Array_Access;
procedure Free is new Ada.Unchecked_Deallocation (Arr, Array_Access);
procedure Recursion (Item : Arr) is --Recursion
begin
Put_Line
(Item (Item'First)'Image); --Prints out the numbers
Recursion
(Item
(Item'First + Item'First + 1 ..
Item'Last)); --Calculating the Fibonacci numbers
end Recursion;
begin
Put ("Welcome to the Fibonacci number series!");
Put
("Enter an initial value and how many Fibonacci numbers you want to print: ");
Get (Index);
Get (Size);
Variable := new Arr (Index .. Size);
Recursion (Variable);
end Fibonacci;
Example: Enter Index (the initial value of the Fibonacci series): 1
Enter Size (how many Fibonacci numbers to print): 5
The first 5 Fibonacci numbers are: 1 1 2 3 5
From Wikipedia,
In mathematics, the Fibonacci numbers, commonly denoted Fn, form a sequence, called the Fibonacci sequence, such that each number is the sum of the two preceding ones, starting from 0 and 1. That is,
F0 = 0
F1 = 1
and
Fn = Fn - 1 + Fn - 2
which translates pretty directly into
function Fibonacci (N : Natural) return Natural is
(case N is
when 0 => 0,
when 1 => 1,
when others => Fibonacci (N - 1) + Fibonacci (N - 2));
or, old style,
function Fibonacci (N : Natural) return Natural is
begin
if N = 0 then
return 0;
elsif N = 1 then
return 1;
else
return Fibonacci (N - 1) + Fibonacci (N - 2);
end if;
end Fibonacci;
You do have to do your printing outside the function, and admittedly there’s an inefficiency in repeatedly calculating the lower results, but you weren’t asking for efficiency.
Here is how you can do it (this code is based on https://rosettacode.org/wiki/Fibonacci_sequence#Recursive)
with Ada.Text_IO;
with Ada.Integer_Text_IO;
procedure Fibonacci is
First, Amount: Positive;
function Fib(P: Positive) return Positive is --Recursion
begin
if P <= 2 then
return 1;
else
return Fib(P-1) + Fib(P-2);
end if;
end Fib;
begin
Ada.Text_IO.Put_Line("Welcome to the Fibonacci number series!");
Ada.Text_IO.Put_Line("Enter an initial value and how many Kombinacci numbers you want to print: ");
Ada.Integer_Text_IO.Get(First);
Ada.Integer_Text_IO.Get(Amount);
for I in First .. First + Amount loop
Ada.Text_IO.Put("Fibonacci(" & Positive'Image(I) & " ) = ");
Ada.Text_IO.Put_Line(Positive'Image(Fib(I)));
end loop;
end Fibonacci;

How to perform arithmetic contract operations on function taking in 2D array type as parameter in Ada

I have a function that should return the count of Islands found.
I name this function Count_Islands that takes in a parameter of
Map_Array of type Map, of which Map is an array of Islands.
Islands is an enumerator type with set of Land, Water.
I have the function specification in the .ads and the body in the
.adb
The problem I face now is how to proof that my function
Count_Islands'Result will be less than (X * Y)
I have tried: with post => Count_Islands'Result < X * Y
-- Whenever I ran prove all I got: medium: postcondition might
fail cannot prove Count_Islands'Result < X * Y
Function in .ads:
function Count_Islands(Map_Array : Map)
return Integer with Pre => Map_Array'Length /= 0,
Post => Count_Islands'Result < X * Y;
Function in .adb:
function Count_Islands(Map_Array : Map) return Integer
is
Visited_Array : Visited := (others => (others=> False));
Count : Integer := 0;
begin
if (Map_Array'Length = 0)then
return 0;
end if;
for i in X_Range loop
for j in Y_Range loop
if (Map_Array(i, j) = Land and then not Visited_Array(i,j)) then
Visited_Array := Visit_Islands(Map_Array, i, j,Visited_Array);
Count := Count + 1;
end if;
end loop;
end loop;
return Count;
end Count_Islands;
In a matrix of 4 * 5 for instance,i.e my X = 4 And Y = 5:
I expect the output result of an Islands(Lands) found to be 1 which is less than 4 * 5. But GNATprove cannot prove my initial code to analyze that,using Post => Count_Islands'Result < X * Y;
Is there any better way to prove this arithmetic? Thanks for your help.
As the example is not complete, I took the liberty to change it a little bit. You can prove the post condition by adding loop invariants. The program below proves in GNAT CE 2019:
main.adb
procedure Main with SPARK_Mode is
-- Limit the range of the array indices in order to prevent
-- problems with overflow, i.e.:
--
-- Pos'Last * Pos'Last <= Natural'Last
--
-- Hence, as Natural'Last = 2**31 - 1,
--
-- Pos'Last <= Sqrt (2**31 - 1) =approx. 46340
--
-- If Pos'Last >= 46341, then overflow problems might occur.
subtype Pos is Positive range 1 .. 46340;
type Map_Item is (Water, Land);
type Map is
array (Pos range <>, Pos range <>) of Map_Item;
type Visited is
array (Pos range <>, Pos range <>) of Boolean;
function Count_Islands (Map_Array : Map) return Natural with
Post => Count_Islands'Result <= Map_Array'Length (1) * Map_Array'Length (2);
-------------------
-- Count_Islands --
-------------------
function Count_Islands (Map_Array : Map) return Natural is
Visited_Array : Visited (Map_Array'Range (1), Map_Array'Range (2)) :=
(others => (others => False));
Count : Natural := 0;
begin
for I in Map_Array'Range (1) loop
pragma Loop_Invariant
(Count <= (I - Map_Array'First (1)) * Map_Array'Length (2));
for J in Map_Array'Range (2) loop
pragma Loop_Invariant
(Count - Count'Loop_Entry <= J - Map_Array'First (2));
if Map_Array(I, J) = Land and then not Visited_Array(I, J) then
Visited_Array (I, J) := True; -- Simplified
Count := Count + 1;
end if;
end loop;
end loop;
return Count;
end Count_Islands;
begin
null;
end Main;

VHDL concatenate array of vectors to vector

I have been trying to implement a method by which i can concatenate an array of vectors to a vector. Essentially i need something like:
data_received((rx_length_int + 5) * 8)downto 0) <= rx_ident & rx_length & rx_data & rx_checksum;
data_received(BUILD2_RX_PKT_LEN downto ((rx_length_int + 5) * 8)) <= (others => '0');
where BUILD2_RX_PKT_LEN is a constant size, rx_data has a variable number of bytes, but is defined as:
type t_rx_data is array (0 to MAX_PLD) of STD_LOGIC_VECTOR((ADDRESS_WIDTH - 1) downto 0)
I have implemented a few methods, such as a for loop to iterate through rx_data up to rx_length_int, but this has issues with concatenation to data_received as it grows in size... I'm sure there is a very simple solution to this, but I have been unable to come up with one. Any help would be appreciated.
Instead of an unconstrained aggregate, (others => 0), which relies on the result type to constrain the range, you can build an aggregate with a specified range, such as (7 downto 2 => '0').
So why not
data_received <= (BUILD2_RX_PKT_LEN downto ((rx_length_int + 5) * 8) => '0')
& rx_ident & rx_length & rx_data & rx_checksum;
However it's unreadably clumsy. A better approach would be a padding function:
function pad_packet (data : std_logic_vector) return std_logic_vector is
variable temp : std_logic_vector (BUILD2_RX_PKT_LEN downto 1) := (others => '0');
-- NB "downto 0" would be an off-by-1 error if LEN is actual length
-- Initialised vhole vector to zero
begin
temp (data'length downto 1) := data;
return temp;
end pad_packet;
...
data_received <= pad_packet ( rx_ident & rx_length & rx_data & rx_checksum );
Much clearer...

Create one 16-bit vector from two 8-bit vectors

I want to create one 16-bit-vector from two 8-bit-vectors but have errors like below. How to solve it?
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
ENTITY Binary2Gray IS
-- Declarations
port(data : in STD_LOGIC_VECTOR (3 downto 0);
data_out : inout STD_LOGIC_VECTOR (3 downto 0);
data1 : inout std_logic_vector (1 downto 0);
data2 : inout std_logic_vector (1 downto 0);
CLK_I : in std_logic;
y1 : out std_logic_vector (7 downto 0);
y2 : out std_logic_vector (7 downto 0);
op : out std_logic_vector (15 downto 0)
);
END Binary2Gray ;
-----------------------------
ARCHITECTURE rtl OF Binary2Gray IS
signal op : std_logic_vector (15 downto 0);
begin
process(CLK_I)
BEGIN
data_out(3) <=data(3);
data_out(2) <=data(3) xor data (2);
data_out(1) <=data(2) xor data (1);
data_out(0) <=data(1) xor data (0);
label_1: for data_out in 0 to 3 loop
if(data_out = 0 ) then
data1(0) <=data(1) xor data (0);
elsif (data_out = 1 ) then
data1(1) <=data(2) xor data (1);
elsif (data_out = 2 ) then
data2(0) <=data(3) xor data (2);
else
data2(1) <=data(3);
end if;
end loop label_1;
end process;
with data1 select y1 <=
"00110011" when "00",
"00111101" when "01",
"11010011" when "10",
"11011101" when others;
with data2 select y2 <=
"00110011" when "00",
"00111101" when "01",
"11010011" when "10",
"11011101" when others;
op <= y1 & y2 ;
END rtl;
Errors:
# Error: ELAB1_0008: QAM.vhd : (56, 8): Cannot read output : "y1".
# Error: ELAB1_0008: QAM.vhd : (56, 8): Cannot read output : "y2".
In VHDL-2002 (and earlier) it is not allowed to read an output port like y1
and y2, hence the error.
Possible fixes are any of:
declared y1 and y2 as buffer ports
create intermediate signals y1_sig and y2_sig with the values and
assign these to y1, y2, and op
use VHDL-2008 if possible in the tool chain.
Note that op should not be declared as signal when an output port. Note
also that the process does probably not work as expected, since it is not a
clocked process due to missing if rising_edge(CLK_I) then statement, nor a combinatorial
process due to missing data in sensitivity list.

Arithmetic operations on integers in vhdl

I'm trying to do a few mathematical operations on integers in a piece of vhdl code but when i try to compile the tool says "0 definitions of operator "+" match here". Here is what i'm trying to do:
for i in 0 to arr_size - 1 loop
for j in 0 to arr_size - 1 loop
for k in 0 to arr_size - 1 loop
for l in 0 to arr_size - 1 loop
for m in 0 to arr_size - 1 loop
mega_array(i)(j)(k)(l)(m) <= i*(arr_size**4) + j*(arr_size**3) + k*(arr_size**2) + l*(arr_size**1) + m*(arr_size**0);
end loop;
end loop;
end loop;
end loop;
end loop;
The problem was encountered in the line where mega_array is set. Note that this whole block is in a process.
Additionally:
arr_size : integer := 4;
sig_size : integer := 32
type \1-line\ is array (arr_size - 1 downto 0) of unsigned (sig_size - 1 downto 0);
type square is array (arr_size - 1 downto 0) of \1-line\;
type cube is array (arr_size - 1 downto 0) of square;
type hypercube is array (arr_size - 1 downto 0) of cube;
type \5-cube\ is array (arr_size - 1 downto 0) of hypercube;
signal mega_array : \5-cube\;
When reading your older post, the mega_array is an array of 4 levels with at the lowest level an unsigned. In your code in this question I see 5 levels. So at the fifth level you have bit. You can not assign an integer to a std_logic.
Could it be this code is what you want?
for i in 0 to arr_size - 1 loop -- 5-cube
for j in 0 to arr_size - 1 loop -- hypercube
for k in 0 to arr_size - 1 loop -- cube
for l in 0 to arr_size - 1 loop -- square
for m in 0 to arr_size - 1 loop -- 1-line
mega_array(i)(j)(k)(l) <= to_unsigned(i*(arr_size**4) + j*(arr_size**3) + k*(arr_size**2) + l*(arr_size**1), 32);
end loop
end loop;
end loop;
end loop;
end loop;
The to_unsigned functions converts the integer to an unsigned, what is the type of 1-line. The second parameter is the size of the vector to convert the integer into. It must be the same as the size of 1-line.

Resources