HowTo & multidimensional matrix in Ada - matrix

I was wondering about how to create a multidimensional matrix using Ada language, I mean, stacking i number of matrix of j x k dimension:
One way I have found is using multidimensional arrays, quite easy.
Are there other ways to accomplish it? Maybe using Ada.Containers.Vectors or mixing it within the array declaration? Any formal library?
Thanks

Here are two examples that might be of use.
The first example shows the use of an array of multi-dimensional arrays. When using this method you need, at some point, to fix the size of the stack of matrices (here: during the declaration of S, the size is fixed to 4). Memory is preallocated to hold all four matrices.
The second example shows the use of an Ada vector container to which matrices can be added. Vectors are "dynamic arrays". Memory is allocated when matrices added.
The Ada standard library that ships with (recent versions of) the GNAT compiler contains formal containers packages (see also here).
example_1.adb
with Ada.Text_IO; use Ada.Text_IO;
procedure Example_1 is
type Rows is new Natural range 0 .. 2;
type Cols is new Natural range 0 .. 2;
type Matrix is array (Rows, Cols) of Integer;
-- A 2D matrix.
type Stack is array (Natural range <>) of Matrix;
-- Stack of 2D matrices.
S : constant Stack (1 .. 4) :=
(1 => (others => (others => 1)),
2 => (others => (others => 2)),
3 => (others => (others => 3)),
4 => (others => (others => 4)));
begin
for Mtx of S loop -- using "of", not "in", such to iterate over the elements.
for R in Rows loop
Put ("[");
for C in Cols loop
Put (Mtx (R, C)'Image);
end loop;
Put_Line (" ]");
end loop;
New_Line;
end loop;
end Example_1;
example_2.adb
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;
procedure Example_2 is
type Rows is new Natural range 0 .. 2;
type Cols is new Natural range 0 .. 2;
type Matrix is array (Rows, Cols) of Integer;
-- A 2D matrix.
package Stacks is new Ada.Containers.Vectors (Natural, Matrix);
use Stacks;
subtype Stack is Stacks.Vector;
-- Stack of 2D matrices.
Empty_Stack : constant Stack := Stacks.Empty_Vector;
-- An empty stack.
S : Stack;
-- Instead of using Append (..) shown below, you can also
-- initialize the stack using:
--
-- S : Stack := Empty_Stack
-- & (others => (others => 1))
-- & (others => (others => 2))
-- & (others => (others => 3))
-- & (others => (others => 4));
begin
S.Append ((others => (others => 1)));
S.Append ((others => (others => 2)));
S.Append ((others => (others => 3)));
S.Append ((others => (others => 4)));
-- ...
for Mtx of S loop -- using "of", not "in", such to iterate over the elements.
for R in Rows loop
Put ("[");
for C in Cols loop
Put (Mtx (R, C)'Image);
end loop;
Put_Line (" ]");
end loop;
New_Line;
end loop;
end Example_2;
output (same for both examples)
[ 1 1 1 ]
[ 1 1 1 ]
[ 1 1 1 ]
[ 2 2 2 ]
[ 2 2 2 ]
[ 2 2 2 ]
[ 3 3 3 ]
[ 3 3 3 ]
[ 3 3 3 ]
[ 4 4 4 ]
[ 4 4 4 ]
[ 4 4 4 ]

You could also try standard Ada packages Real Vectors and Matrices or Complex Vectors and Matrices which also provide some operations on matrices. It can be the easiest way to accomplish it.

Related

Loop operator "For" to fill an array in VHDL

I want to understand and improve an VHDL code I got.
In the VHDL implementation there is the following part:
m1(000) <= MetricA(000) + BrMet(3);
m1(001) <= MetricA(001) + BrMet(1);
m1(002) <= MetricA(002) + BrMet(0);
m1(003) <= MetricA(003) + BrMet(2);
m1(004) <= MetricA(004) + BrMet(0);
m1(005) <= MetricA(005) + BrMet(2);
m1(006) <= MetricA(006) + BrMet(3);
m1(007) <= MetricA(007) + BrMet(1);
m1(008) <= MetricA(008) + BrMet(2);
m1(009) <= MetricA(009) + BrMet(0);
m1(010) <= MetricA(010) + BrMet(1);
m1(011) <= MetricA(011) + BrMet(3);
m1(012) <= MetricA(012) + BrMet(1);
m1(013) <= MetricA(013) + BrMet(3);
m1(014) <= MetricA(014) + BrMet(2);
m1(015) <= MetricA(015) + BrMet(0);
where
type BRANCH_METRIC is array (3 downto 0) of STD_LOGIC_VECTOR (7 downto 0);
signal BrMet: RANCH_METRIC := (OTHERS =>(OTHERS => '0'));
type PATH_METRIC is array (15downto 0) of STD_LOGIC_VECTOR (7 downto 0);
signal MetricA: PATH_METRIC := (OTHERS =>(OTHERS => '0'));
My questions:
1. m1(001), .... m1(015) , MetricA(001), .... MetricA(015) mean a value in a position:
m1(001) means a value on the first cell, m1(015) is on the 15th cell.
Can BrMet(0) mean something else?
2. My task is to rewrite code above using for-loop.
I can write :
for i in 1 to 15 loop
m1(i) <= MetricA(i) + BrMet(?);
How can I add BrMet in this loop?
I was thinking to create a table as:
Tab = {3,1,0,2,0,2...}
{3,1,0,2,0,2...} expresses BrMet(3), BrMet(1), BrMet(0) and so on
and the I would write the loop as
for i in 1 to 15 loop
m1(i) <= MetricA(i) + Tab(i);
But unfortunately I didnt find any information how to create a table in VHDL. There is LUT table , bit It doesnt pass for it.
"m1(001) means a value on the first cell, m1(015) is on the 15th cell"
If by "first cell" you mean the cell with the smallest index then no, m1(1) is not the "first" cell, it is the "second" (and m1(15) is the "sixteenth") because you declared your array type with 0 as the "first" index, not 1. Note that, according these array definitions your loops are probably wrong: they should start at index 0, not 1.
"Can BrMet(0) mean something else?"
Else than what? BrMet(0) is the cell of array BrMet with the smallest index.
"How can I add BrMet in this loop?"
You apparently know how to declare array types and use them. This is no different. Just declare an array type and a constant of this type:
type BrMetIdx_t is array(0 to 15) of integer;
constant BrMetIdx: BrMetIdx_t := (3, 1, 0, 2, 0, 2, 3, 1, 2, 0, 1, 3, 1, 3, 2, 0);
...
for i in 0 to 15 loop
m1(i) <= MetricA(i) + BrMet(BrMetIdx(i));
end loop;
...
Note: it would probably be safer to restrict the type of elements of BrMetIdx_t arrays to integers in the 0 to 3 range:
type BrMetIdx_t is array(0 to 15) of integer range 0 to 3;
This way, if there is a typo with, e.g., value 4, in your constant declaration you will get a clear error message from the compiler.
Note: you don't have to declare your array types with a "downto" index range. This is a common practice for vectors of bits because indexing them from right to left is also common but for your m1, MetricA and BrMet arrays you could probably as well index them in a more "natural" way:
type BRANCH_METRIC is array (0 to 3) of STD_LOGIC_VECTOR (7 downto 0);
type PATH_METRIC is array (0 to 15) of STD_LOGIC_VECTOR (7 downto 0);
This would probably help the global understanding.
Note: I doubt that you will ever use multiple drive for the path and branch metrics of your (Viterbi?) decoder. It would thus be safer to use an unresolved type like std_ulogic_vector instead of std_logic_vector. This way, if by accident you create a multiple drive situation, you will get a clear error message from the compiler instead of spending hours trying to understand why you see all these X values during simulation.

How to assign an array of a custom type of length one in VHDL [duplicate]

I'm trying to create a flexible array of constants. I want to use a 2D array which may sometimes be for example a 2x1, 2x2, 3x2 array etc. For example:
type int_2d_array is array (integer range<>, integer range<>) of integer;
constant M : positive := 2;
constant nMax : positive := 1;
constant n : int_2d_array(M - 1 downto 0, nMax - 1 downto 0) := ( (1) , (2) ); -- wrong
error: type int_2d_array does not match with the integer literal
If I do this, it doesn't complain:
type int_2d_array is array (integer range<>, integer range<>) of integer;
constant M : positive := 2;
constant nMax : positive := 2;
constant n : int_2d_array(M - 1 downto 0, nMax - 1 downto 0) := ( ( 0,1 ) , ( 2,2 )); -- accepted
Is the first example even possible using a 2D array?
The LRM (section 9.3.3 Aggregates) states:
Aggregates containing a single element association
shall always be specified using named association in order to distinguish them from parenthesized expressions.
So, this is OK:
constant n : int_1d_array(0 downto 0) := ( 0 => 1 );
and this is not:
constant n : int_1d_array(0 downto 0) := ( 1 );
http://www.edaplayground.com/x/6a4
I managed to compile the first example in the following ugly way:
type int_2d_array is array (integer range<>, integer range<>) of integer;
constant M : positive := 2;
constant nMax : positive := 1;
constant n : int_2d_array(M - 1 downto 0, nMax - 1 downto 0) := ( (others => 1) , (others => 2) );
Strange behavior, indeed.

Function clogb2() generated by vivado can't synthesize with loop limit error

I'm trying to design an AXI_master peripheral with vivado. I used the axi peripheral generator in vivado menu and modified the vhdl code generated.
In vhdl code there is a function clogb2 declared with following code:
function clogb2 (bit_depth : integer) return integer is
variable depth : integer := bit_depth;
variable count : integer := 1;
begin
for clogb2 in 1 to bit_depth loop -- Works for up to 32 bit integers
if (bit_depth <= 2) then
count := 1;
else
if(depth <= 1) then
count := count;
else
depth := depth / 2;
count := count + 1;
end if;
end if;
end loop;
return(count);
end;
This works in simulation (GHDL) but fail in synthesis with error :
[Synth 8-403] loop limit (65538) exceeded
I tried to increase loop limit in vivado with following tcl command :
set_param synth.elaboration.rodinMoreOptions "rt::set_parameter max_loop_limit <X>"
As explained here, but vivado synthesize with an infinite time and never finish.
Do you know how to solve this problem ?
You could also try a different path. Although floating point is not supported in logic (although support is increasing), it is allowed for internal calculations and such. (By at least Xilinx and Altera/Intel).
Try this:
use ieee.math_real.all;
function ceillog2(input : positive) return natural is
begin
return integer(ceil(log2(real(input))));
end function;
Try constraining the range of the input, for example:
function clogb2 (bit_depth : integer range 1 to 32) return integer is
Also, if Vivado is generating code that it cannot compile, this is a bug that you should report on the Xilinx forums.
Finally I found a solution that work by rewriting the function with a big case :
function clogb2 (bit_depth : integer) return integer is
begin
case bit_depth is
when 0 to 2 => return( 1);
when (2** 1)+1 to 2** 2 => return( 2);
when (2** 2)+1 to 2** 3 => return( 3);
when (2** 3)+1 to 2** 4 => return( 4);
when (2** 4)+1 to 2** 5 => return( 5);
when (2** 5)+1 to 2** 6 => return( 6);
when (2** 6)+1 to 2** 7 => return( 7);
when (2** 7)+1 to 2** 8 => return( 8);
when (2** 8)+1 to 2** 9 => return( 9);
when (2** 9)+1 to 2**10 => return(10);
when (2**10)+1 to 2**11 => return(11);
when (2**11)+1 to 2**12 => return(12);
when (2**12)+1 to 2**13 => return(13);
when (2**13)+1 to 2**14 => return(14);
when (2**14)+1 to 2**15 => return(15);
when (2**15)+1 to 2**16 => return(16);
when (2**16)+1 to 2**17 => return(17);
when (2**17)+1 to 2**18 => return(18);
when (2**18)+1 to 2**19 => return(19);
when (2**19)+1 to 2**20 => return(20);
when (2**20)+1 to 2**21 => return(21);
when (2**21)+1 to 2**22 => return(22);
when (2**22)+1 to 2**23 => return(23);
when (2**23)+1 to 2**24 => return(24);
when (2**24)+1 to 2**25 => return(25);
when (2**25)+1 to 2**26 => return(26);
when (2**26)+1 to 2**27 => return(27);
when (2**27)+1 to 2**28 => return(28);
when (2**28)+1 to 2**29 => return(29);
when (2**29)+1 to 2**30 => return(30);
when (2**30)+1 to (2**31)-1 => return(31);
when others => return(0);
end case;
end;
With this weird code structure, that works in synthesis and simulation.
This recursive version synthesises:
function clogb2 (bit_depth : integer) return integer is
begin
if bit_depth <= 1 then
return 0;
else
return clogb2(bit_depth / 2) + 1;
end if;
end function clogb2;
You can use it to dimension other things, eg
entity counter is
generic (max_count : POSITIVE);
port (clock, reset : in std_logic;
Q : out std_logic_vector(clogb2(max_count) downto 0)
);
end;
or you can use it as combinational logic:
process (I)
begin
O <= clogb2(I);
end process;
BTW: you would be better using an integer subtype for your input:
function clogb2 (bit_depth : positive) return integer is
-- ^
-- |

Please help me with the syntax errors in the following vhdl code that i wrote

I used Xlinix ISE 14.1 to write the following code.
I found the syntax to be correct but the xilinx IDE shows errors at line 27 and 30.
I am trying to find the first partial derivatives of a matrix of numbers which is similar to finding the edges in an image.
The function by2i is used to convert the bytes (i.e. bits) to integer number.
In this VHDL code I am getting error messages:
"ERROR:HDLCompiler:806 B:/gxgyVHDL.vhd" Line 27: Syntax error near "return".
"ERROR:HDLCompiler:806 - "B:/gxgyVHDL.vhd" Line 30: Syntax error near ","".
I am unable to correct these errors as I know very little in VHDL. I learned basic programming in VHDL like implementing MUX, counters etc.
This is the first time I am writing a program for image processing And I'm not sure whether this program works like expected but it works well matlab and python.
Please help to correct these errors.
Here is vhdl code:
enter code here
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.numeric_std.ALL;
use IEEE.math_real.ALL;
entity getGxGy is
generic (width : natural := 66;
height : natural := 130); --width and height of the image window.
Port( pxl : in STD_LOGIC_VECTOR(7 downto 0);
clk : in bit;
fv : out real); --need to configure 'fv' signal properly to appropriate bit vector.
end getHOGfv;
architecture behave of getGxGy is
function by2i (b : STD_LOGIC_VECTOR(7 downto 0)) return natural is
variable num : natural;
begin
num := 0;
for i in b'Range loop
if b(i) = '1' then
num := num + 2**i;
end if;
end loop
return num
end by2i;
type bufarr is array (1 to height, 1 to width) of natural;
type gxgy is array (1 to height-2, 1 to width-2) of integer;
--signal tempfv : mat4;
process(clk, pxl)
variable buf: bufarr;
variable gx, gy: gxgy;
begin
--Buffer to store/create 64*128 pixels/widthindowidth
for h in 2 to height-1 loop
for w in 2 to width-1 loop
buf(h)(w) := by2i(pxl);
end loop;
end loop;
--1pixel padding
for w in 1 to width loop
buf(1)(w) := 0;
end loop;
for w in 1 to width loop
buf(height)(w) := 0;
end loop;
for h in 2 to height-1 loop
buf(h)(1) := 0;
end loop;
for h in 2 to height-1 loop
buf(h)(width) := 0;
end loop;
--compute gradients
for h in 2 to height-1 loop
for w in 2 to width-1 loop
gx(h)(w) := buf(h+1)(w)-buf(h-1)(w);
gy(h)(w) := buf(h)(w+1)-buf(h)(w-1);
mag(h)(w) := abs(gx(h)(w)+gy(h)(w));
ang(h)(w) := gy(h)(w)/gx(h)(w);
end loop;
end loop;
end process;
end behave;
Several problems:
Your entity names do not match. That is, entity getGxGy does not match end getHOGfv;
You are missing a trailing ; on the end loop in by2i
You are missing a trailing ; on the return in by2i
You are missing a begin statement in your architecture (between the type gxgy and the process(clk, pxl)
Your syntax for the use of multidimensional arrays is wrong. Rather than buf(1)(w), it should be buf(1, 2).
Neither mag nor ang are defined.
When you have a large number of errors, it can be difficult to track down the exact cause. Often the compilers get confused at reporting the errors. Start with the first one, fix it, and re-compile. Continue until things cleanup.
Also, a point of clarification. You don't need by2i. You can use numeric_std to do the converstion (thanks to scary_jeff for pointing this out). Use to_integer(unsigned(pxl)) to do the conversion.
And one further point. Do not use both std_logic_unsigned and numeric_std at the same time. numeric_std is the standard way to use signed and unsigned numbers. std_logic_unsigned was a vendor specific extension that is not standard.
Edit: You used the following syntax to define your arrays:
type bufarr is array (1 to height, 1 to width) of natural;
This is fine. And as I noted above you have to use the buf(h, w) syntax. But you could define it differently, such as:
type width_array is array(1 to width) of natural;
type bufarr is array(1 to height) of width_array;
Which you could then index using buf(h)(w).
I prefer the former.
In addition to the syntax items and missing declarations noted by PlayDough there are two superfluous context clauses for packages numeric_std (which should not be mixed with the Synopsys arithmetic pages std_logic_unsigned) and math_real (which isn't yet used).
After all the changes are edited in:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
-- use ieee.numeric_std.all;
-- use ieee.math_real.all;
entity getgxgy is
generic (width : natural := 66;
height : natural := 130); -- width and height of the image window.
port( pxl : in std_logic_vector(7 downto 0);
clk : in bit;
fv : out real); -- need to configure 'fv' signal properly to appropriate bit vector.
end getgxgy; -- WAS gethogfv;
architecture behave of getgxgy is
function by2i (b : std_logic_vector(7 downto 0)) return natural is
variable num : natural;
begin
num := 0;
for i in b'range loop
if b(i) = '1' then
num := num + 2 ** i;
end if;
end loop; -- MISSING ';'
return num; -- MISSING ';'
end function by2i;
type bufarr is array (1 to height, 1 to width) of natural;
type gxgy is array (1 to height - 2, 1 to width - 2) of integer;
--signal tempfv : mat4;
begin -- for architecture modiy WAS MISSING
process (clk, pxl)
variable buf: bufarr;
variable gx, gy: gxgy;
variable mag, ang: gxgy; -- MISSING DECLARATIONS
begin
--buffer to store/create 64*128 pixels/widthindowidth
for h in 2 to height - 1 loop
for w in 2 to width - 1 loop
buf(h, w) := by2i(pxl); -- WAS buf(h)(w)
end loop;
end loop;
--1pixel padding
for w in 1 to width loop
buf(1, w) := 0; -- WAS buf(1)(w)
end loop;
for w in 1 to width loop
buf(height, w) := 0; -- WAS buf(height)(w)
end loop;
for h in 2 to height - 1 loop
buf(h, 1) := 0; -- WAS buf(h)(1)
end loop;
for h in 2 to height - 1 loop
buf(h, width) := 0; -- WAS buf(h)(width)
end loop;
--compute gradients
for h in 2 to height - 1 loop
for w in 2 to width - 1 loop
gx(h, w) := buf(h + 1, w) - buf(h - 1, w); -- WAS gx(h)(w), buf(h+1)(w) and buf(h-1)(w)
gy(h, w) := buf(h, w + 1) - buf(h, w - 1); -- WAS gy(h)(w), buf(h)(w+1) and buf(h)(w-1)
mag(h, w) := abs(gx(h, w) + gy(h, w)); -- WAS mag(h)(w), x(h)(w) and gy(h)(w)
ang(h, w) := gy(h, w) / gx(h, w); --WAS ang(h)(w), gy(h)(w) and gx(h)(w)
end loop;
end loop;
end process;
end architecture behave;
your code analyzes and elaborates, noting there is no assignment to fv, type REAL is not synthesis eligible and there is no synthesis eligible use of clk.
If clk were std_logic (or std_ulogic) you could use the std_logic_1164 function rising_edge.
Adding a recognized sequential logic RTL construct for a clock edge gives:
process (clk) -- pxl NOT NEEDED , pxl)
variable buf: bufarr;
variable gx, gy: gxgy;
variable mag, ang: gxgy; -- MISSING DECLARATIONS
begin
if clk'event and clk = '1' then
--buffer to store/create 64*128 pixels/widthindowidth
for h in 2 to height - 1 loop
for w in 2 to width - 1 loop
buf(h, w) := conv_integer(pxl); -- WAS buf(h)(w)
end loop; -- CHANGED to use conv_integer
end loop;
--1pixel padding
for w in 1 to width loop
buf(1, w) := 0; -- WAS buf(1)(w)
end loop;
for w in 1 to width loop
buf(height, w) := 0; -- WAS buf(height)(w)
end loop;
for h in 2 to height - 1 loop
buf(h, 1) := 0; -- WAS buf(h)(1)
end loop;
for h in 2 to height - 1 loop
buf(h, width) := 0; -- WAS buf(h)(width)
end loop;
--compute gradients
for h in 2 to height - 1 loop
for w in 2 to width - 1 loop
gx(h, w) := buf(h + 1, w) - buf(h - 1, w); -- WAS gx(h)(w), buf(h+1)(w) and buf(h-1)(w)
gy(h, w) := buf(h, w + 1) - buf(h, w - 1); -- WAS gy(h)(w), buf(h)(w+1) and buf(h)(w-1)
mag(h, w) := abs(gx(h, w) + gy(h, w)); -- WAS mag(h)(w), x(h)(w) and gy(h)(w)
ang(h, w) := gy(h, w) / gx(h, w); --WAS ang(h)(w), gy(h)(w) and gx(h)(w)
end loop;
end loop;
end if;
end process;
also noting the switch to the package std_logic_unsigned function conv_integer from using function by2i.
So these changes along with deleting the function by2i analyzes.
Genning up a testbench to look for bounds errors:
library ieee;
use ieee.std_logic_1164.all;
entity getgxgy_tb is
end entity;
architecture foo of getgxgy_tb is
signal pxl: std_logic_vector(7 downto 0) := (others => '0');
signal clk: bit;
signal fv: real;
begin
DUT:
entity work.getgxgy
port map (
pxl => pxl,
clk => clk,
fv => fv
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if now > 120 ns then
wait;
end if;
end process;
end architecture;
And we elaborate and run the testbench and get a run time error!
The error is division by zero in the assignment to ang, so your algorithm needs a bit of work still.
Blocking that with an if statement and we find there's a bounds error in the assignment:
gx(h, w) := buf(h + 1, w) - buf(h - 1, w); -- WAS gx(h)(w), buf(h+1)(w) and buf(h-1)(w)
And that's caused by hitting w = 65 when
type gxgy is array (1 to height - 2, 1 to width - 2) of integer;
type gxgy's second dimension corresponding to w has a range to width - 2 while w reaches width - 1 which is out of bounds.
So a bit more algorithmic expression tuning still to do.
It isn't particularly clear what you intend to register. If it's just fv that could occur in a different process, with the current processes sensitivity list set to just pxl and gx, gy, mag and ang made into signals.
It's likely that all the abs, multiplies and divides may not fit in a target FPGA, requiring operations be spread over some number of clocks using common resources for arithmetic operations. VHDL describes hardware and every operator invocation or function call can imply it's own hardware.
In synthesis a loop statement has it's sequence of statements 'unrolled' and where no interdependencies are found produce separate hardware. For h in 2 to height - 1 and w in 2 to width - 1 ranges in your nested loops your generic values are implying 8001 subtracts for each of gx and gy, abs and addition for mag and divides for ang, all from changing the value of pxl. This tells us your hardware isn't going to fit in any FPGA without sharing resources over some number of clocks, a time and space tradeoff.
So not only does your algorithm need a bit work, you need to take implementation resources into account.
You don't program in VHDL you describe hardware.

Controlling an LCD in VHDL on spartan 6

I found this code which controls an LCD display of an FPGA but it can't seen to understand some of the code, in particular this part
type LCD_CMDS_T is array(integer range <>) of std_logic_vector(9 downto 0);
constant LCD_CMDS : LCD_CMDS_T := ( 0 => "00"&X"3C", --Function Set
1 => "00"&X"0C", --Display ON, Cursor OFF, Blink OFF
2 => "00"&X"01", --Clear Display
3 => "00"&X"02", --return home
4 => "10"&X"48", --H
5 => "10"&X"65", --e
6 => "10"&X"6C", --l
7 => "10"&X"6C", --l
8 => "10"&X"6F", --o
9 => "10"&X"20", --blank
10 => "10"&X"46", --F
11 => "10"&X"72", --r
12 => "10"&X"6F", --o
13 => "10"&X"6D", --m
14 => "10"&X"20", --blank
15 => "10"&X"44", --D
16 => "10"&X"69", --i
17 => "10"&X"67", --g
18 => "10"&X"69", --i
19 => "10"&X"6C", --l
20 => "10"&X"65", --e
21 => "10"&X"6E", --n
22 => "10"&X"74", --t
23 => "00"&X"18"); --Shift left
signal lcd_cmd_ptr : integer range 0 to LCD_CMDS'HIGH + 1 := 0;
I understand that an array has been made to hold values of character to be displayed on the display. but i don't understand this line.
signal lcd_cmd_ptr : integer range 0 to LCD_CMDS'HIGH + 1 := 0;
Can anyone help me to understand whats done here
This signal is being created to index into the string that was created. The constant LCD_CMDS is an array that needs to be indexed. The signal lcd_cmd_ptr is indexing into that constant to drive the display. It is an integer than can be from 0 to 23 in this case.
I bet somewhere there's a line that has:
LCD_CMDS(lcd_cmd_ptr)
signal lcd_cmd_ptr : integer range 0 to LCD_CMDS'HIGH + 1 := 0;
This code defines a signal which can range from 0 to 'whatever the highest index in the LCD_CMDS array is + 1'.
The 'tick' attributes in VHDL are very useful for writing generic code. To be completely generic, the line above ought to be:
signal lcd_cmd_ptr : integer range LCD_CMDS'low to LCD_CMDS'HIGH + 1;
then if someone removed the entry for item 0 in the array, the signal would have a more limited range. Note that explicitly initialising to '0' in the original case and to LCD_CMDS'LOW in the most generic case is not necessary. The VHDL spec guarantees that integers are always initialised to the lowest value they are allowed to have.
If the signal above only needed to go up to the highest value in the array, you could write more concisely:
signal lcd_cmd_ptr : integer range LCD_CMDS'range;
Again, no explicit initialisation required.

Resources