VHDL Syntax error in user defined package RNG for genetic algorithm in line number 5 - syntax-error

Library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Type arr is array (1 to mut_bits) of integer;
type chrom_matrix is array (1 to pop_size) of std_logic_vector(1 to n_comp);
type fitness_arr is array (1 to pop_size) of integer range 0 to 1000;
--type fitness_arr1 is array(1 to pop_size) of real;
type adj_matrix is array (1 to n_comp,1 to n_comp) of bit;
function evalfnc (signal chromosome: in std_logic_vector(1 to 8); signal cut_info:adj_matrix) return integer;
procedure randg (variable x,y,t:in integer range 0 to 1000; variable z: out integer);
procedure convert_bit(variable a:in integer;variable y:out std_logic_vector(8 downto 1));
end rng;
package body rng is
procedure randg (variable x,y,t:in integer range 0 to 1000; variable z: out integer) is
variable val, a:integer range 0 to 1000:= 0;
begin
if x>y then
a:= x-y;
else
a:= y-x;
end if;
if t > 3*a then
val:= (t-a)/2;
elsif t > a then
val:= t-a;
else
val:= (x+y+t)/2;
end if;
z:= val;
end randg;
function evalfnc (signal chromosome: in std_logic_vector(1 to 8); signal cut_info:adj_matrix) return integer is
variable fitness: integer range 0 to 500:= 0;
variable cut_val: integer range 0 to 15:= 0;
variable max_fit:integer range 0 to 360:=100;
begin
for i in 1 to n_comp loop
for j in 1 to n_comp loop
if cut_info(i,j)= ‘1’ then
cut_val:= cut_val +1;
end if;
end loop;
end loop;
fitness := max_fit - cut_val;
return fitness;
end evalfnc;
procedure convert_bit(variable a:in integer ; variable y:out std_logic_vector(8 downto 1)) is
variable no:std_logic_vector(8 downto 1):=”00000000”;
variable num: integer range 0 to 256;
begin
num:= a;
if num <= 255 and num>= 128 then
no(8):=’1’;
num:=num - 128;
end if;
if num < 128 and num >= 64 then
no(7):=’1’;
num:=num - 64;
end if;
if num < 64 and num >= 32 then
no(6):=’1’;
num:=num −32;
end if;
if num < 32 and num >= 16 then
no(5):=’1’;
num:=num - 16;
end if;
if num < 16 and num >= 8 then
no(4):=’1’;
num:=num - 8;
end if;
if num < 8 and num >= 4 then
no(3):=’1’;
num:=num - 4;
end if;
if num < 4 and num >= 2 then
no(2):=’1’;
num:=num - 2;
end if;
if num < 2 then
no(1):=’1’;
end if;
y:= no;
end convert_bit;
end rng;

Line 5 should read package rng is.

Related

Rounding series of numbers to get as much "round" numbers as possible and sum up to 100

I have series of numbers that add up to nearly 100 (they are percentages), for example:
A
B
C
49.99
9.99
40.01
And I would like to adjust these to get something like:
A
B
C
50.00
10.00
40.00
Constraints :
The numbers count may vary,
The initial sum can be a little over/under 100 (I use a threshold of 0.1 : if the sum is below 99.9 or over 100.1 then I don't adjust),
sometimes there can be no "nice/round" numbers. In that case I want to distribute the missing/exceeding 1/100s in favor of the lowest numbers like so:
A
B
C
D
E
F
G
33.33
16.66
8.33
8.33
9.99
12.50
10.83
33.33
16.66
8.34
8.34
10.00
12.50
10.83
The function I currently use is working great for distributing the missing/exceeding 1.100s in a loop but does not address the 49.99 → 50.00 problem.
The principle it uses is :
multiply all the % by 100 (to get integers)
assign a "weight" to each integer based on the number of trailing zeroes (so that I adjust preferably the non-round numbers):
30 when (int mod 1000)=0
20 when (int mod 100)=0
10 when (int mod 10)=0
5 when (int mod 5) = 0
else 0.
calculate the missing/exceeding 1/100s for the lowest weight
sort the ints to get the lowest ints first (the sort takes the weight into account)
add/substract 1 to each int until I get a sum of 100.
The resulting function will be written in Postgres' Pl/PgSql but I'm mostly interested in knowing if such algorithms exist and how they are named (of course, a link to a working function would be very much appreciated).
I ended up splitting the problem in 2 :
adjust the original shares to get "nicer" numbers (49.99 → 50.00) and
add a few 1/100s here and there to obtain a 100% total.
The result is satisfying, I even integrated a few special values for common fractions (200/3, 100/3, 100/6, 100/12...) so that 3x33.33 don't end up with 33.35, 33.35 and 33.30, less "nice/round" but more fair. Note there is only one loop for the final adjustments. Performance is acceptable : 3.5 sec for 100000 rows.
The following SO question and the included Wikipedia article helped me understand the possible biases and their pros/cons.
Here is the code for those interested :
CREATE OR REPLACE FUNCTION public.normalizeshares_weight(share INT) RETURNS INT AS
$BODY$
SELECT CASE
WHEN share % 10000 = 0 THEN 40
WHEN share % 1000 = 0 THEN 30
WHEN share % 100 = 0 THEN 20
WHEN share % 50 = 0 OR (share = ANY('{6666,3333,1666,833,416}')) THEN 15
WHEN (share % 10 = 0) THEN 10
WHEN share % 5 = 0 THEN 5
ELSE 0 END;
$BODY$ LANGUAGE SQL IMMUTABLE;
CREATE OR REPLACE FUNCTION public.normalizeshares(shares NUMERIC[]) RETURNS NUMERIC(5,2)[] AS
$BODY$
DECLARE
intshares INT[];
adjshares INT[];
weight INT[];
result NUMERIC[];
nb0 INT = 0;
nb5 INT = 0;
nb10 INT = 0;
nb15 INT = 0;
nb20 INT = 0;
nb30 INT = 0;
nb40 INT = 0;
initot INT = 0;
tot INT = 0;
nb INT = 0;
w INT = 0;
diff INT;
each INT;
bestweight INT;
BEGIN
FOR i IN 1..ARRAY_LENGTH(shares,1) LOOP
intshares[i] := FLOOR(COALESCE(shares[i],0)*100);
weight[i] := normalizeshares_weight(intshares[i]);
bestweight := weight[i];
adjshares[i] := intshares[i];
IF normalizeshares_weight(intshares[i]+1) > bestweight THEN adjshares[i] := intshares[i]+1; bestweight := normalizeshares_weight(intshares[i]+1); END IF;
IF normalizeshares_weight(intshares[i]+2) > bestweight THEN adjshares[i] := intshares[i]+2; bestweight := normalizeshares_weight(intshares[i]+2); END IF;
IF normalizeshares_weight(intshares[i]+3) > bestweight THEN adjshares[i] := intshares[i]+2; bestweight := normalizeshares_weight(intshares[i]+3); END IF;
IF normalizeshares_weight(intshares[i]-1) > bestweight THEN adjshares[i] := intshares[i]-1; bestweight := normalizeshares_weight(intshares[i]-1); END IF;
IF normalizeshares_weight(intshares[i]-2) > bestweight THEN adjshares[i] := intshares[i]-2; bestweight := normalizeshares_weight(intshares[i]-2); END IF;
IF normalizeshares_weight(intshares[i]-3) > bestweight THEN adjshares[i] := intshares[i]-2; bestweight := normalizeshares_weight(intshares[i]-3); END IF;
tot := tot + adjshares[i];
initot := initot + intshares[i];
weight[i] := bestweight; -- normalizeshares_weight(adjshares[i]); already calculated
IF weight[i]=0 THEN nb0 := nb0 + 1;
ELSIF weight[i]=5 THEN nb5 := nb5 + 1;
ELSIF weight[i]=10 THEN nb10 := nb10 + 1;
ELSIF weight[i]=15 THEN nb15 := nb15 + 1;
ELSIF weight[i]=20 THEN nb20 := nb20 + 1;
ELSIF weight[i]=30 THEN nb30 := nb30 + 1;
ELSIF weight[i]=40 THEN nb40 := nb40 + 1;
END IF;
result[i] := (intshares[i]::NUMERIC / 100)::NUMERIC(5,2);
END LOOP;
IF tot=10000 THEN
-- RAISE NOTICE 'adjtot=100.00 : %',adjshares::numeric[];
FOR i IN 1..ARRAY_LENGTH(shares,1) LOOP
result[i] := (adjshares[i]::NUMERIC / 100)::NUMERIC(5,2);
END LOOP;
ELSIF (initot=10000) OR (ABS(10000-tot)>90) THEN
-- RAISE NOTICE 'No adj needed, initot=%, tot=%',initot,tot;
ELSE
IF nb0 > 0 THEN nb := nb0; w := 0;
ELSIF nb5 > 0 THEN nb := nb5; w := 5;
ELSIF nb10 > 0 THEN nb := nb10; w := 10;
ELSIF nb15 > 0 THEN nb := nb15; w := 15;
ELSIF nb20 > 0 THEN nb := nb20; w := 20;
ELSIF nb30 > 0 THEN nb := nb30; w := 30;
ELSIF nb40 > 0 THEN nb := nb40; w := 40;
END IF;
diff := 10000 - tot;
each := diff/nb+diff/abs(diff);
-- RAISE NOTICE 'nb=%, w=%, diff=%, tot=%, adj=%',nb,w,diff,tot,adjshares::numeric[];
FOR i IN 1..ARRAY_LENGTH(shares,1) LOOP
IF weight[i]=w THEN
IF diff=0 THEN
ELSIF nb=1 THEN
adjshares[i] := adjshares[i] + diff;
ELSIF nb>1 THEN
adjshares[i] := adjshares[i] + each;
diff := diff - each;
END IF;
nb := nb -1;
END IF;
result[i] := (adjshares[i]::NUMERIC / 100)::NUMERIC(5,2);
END LOOP;
END IF;
RETURN result;
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
And a few results :
% select normalizeshares('{49.99,9.99,40.01}');
normalizeshares
---------------------
{50.00,10.00,40.00}
% select normalizeshares('{33.33,16.66,8.33,8.33,9.99,12.5,10.83}');
normalizeshares
-------------------------------------------
{33.33,16.66,8.33,8.33,10.00,12.50,10.85}

found '0' definitions of operator "**", cannot determine exact overloaded matching definition for "**" in VHDL

I am trying to simulate the below code. However, it shows the error " found '0' definitions of operator "", cannot determine exact overloaded matching definition for "" ". I have had attached the required packages to my code. please guide me with this error. Thank you in advance.
library IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.numeric_std.all;
USE IEEE.std_logic_arith.all;
USE IEEE.math_real.all;
library IEEE_proposed;
use IEEE_proposed.fixed_pkg.all;
entity test_zp is
end;
Architecture ARCHofZP of test_zp is
TYPE matrix IS ARRAY ( NATURAL RANGE <>, NATURAL RANGE <> ) OF INTEGER RANGE 0 TO 500;
SIGNAL kernel : matrix ( 1 TO 3 , 1 TO 3 ) := ((1,0,0),(0,1,0),(1,0,1));
SIGNAL image1 : matrix ( 1 To 6 , 1 TO 6 ) := ((25,100,75,49,130,15),(50,80,0,70,100,34),(20,5,10,20,30,0),(45,60,50,12,24,32),(34,37,53,55,21,90),(45,65,55,78,20,16));
FUNCTION batchnorm (outimg : matrix ( 1 To 8 , 1 TO 8 ) ) RETURN matrix IS
VARIABLE sum1 : INTEGER RANGE 0 TO 500;
VARIABLE SD1,SD,mean,ave,sum : UFIXED (10 downto -2):= "00000000";
VARIABLE batchnorm_mat : matrix (outimg'RANGE(1), outimg'RANGE(2));
CONSTANT alpha,beta : UFIXED (1 downto -2):= "0010";
BEGIN
R1 : FOR i IN outimg'RANGE(1) LOOP
C1 : FOR j IN outimg'RANGE(2) LOOP
sum1 := sum1 + outimg(i,j);
END LOOP;
END LOOP;
mean := sum1 / outimg'LENGTH;
ave := to_ufixed(23,10,-2);
R2 : FOR i IN outimg'RANGE(1) LOOP
C2 : FOR j IN outimg'RANGE(2) LOOP
SD1 := ((to_ufixed(outimg(i,j),10,-2)-ave)/to_ufixed(outimg'LENGTH,10,-2)) + SD1;
END LOOP;
END LOOP;
SD := SD1 ** (2);
R3 : FOR i IN batchnorm_mat'RANGE(1) LOOP
C3 : FOR j IN batchnorm_mat'RANGE(2) LOOP
batchnorm_mat(i,j) := ((to_ufixed(outimg(i,j),10,-2) - ave)/(SD)) * alpha + beta ;
END LOOP;
END LOOP;
RETURN batchnorm_mat; -- return batch normalized outimg matrix named batchnorm_mat
END FUNCTION batchnorm;
begin
outimg <= zero_padding( kernel , image1 );
end Architecture ARCHofZP;

Jacobi method to a system with a tolerance

Evening all, I have had a similar issue previously with this type of code however I have not been able to figure this one out. I am trying to run my Jacobi code with an initial approximation of the 0 vector, and with tolerance Matrix norm (X^n - x^(n-1)) < 1e^-2
restart;
jacobi:=proc(A::Matrix,b::Vector,x0::Vector,m::integer)
local n,i,j,S,x::Vector,x1::Vector;
x1:=Vector(x0); x := Vector(m);
ee:= LinearAlgebra[VectorNorm](x-x1);
for n from 1 to 50 while ee < 1e-2 do
for i from 1 to m do
S:=0.0;
for j from 1 to m do
if j<>i then S:=S+A[i,j]*x1[j]; end if;
end do;
x[i]:=(-S+b[i])/A[i,i];
end do;
for j from 1 to m do
x1[j]:=x[j];
end do;
print(n,x);
end do;
return x
end proc;
A:=Matrix([[12.4,0.3,-2.2,0.2,3.6],[1.2,7.1,-1.7,-1.6,0.9],[1.3,3.1,10.8,2.2,0.7],[-1.4,0.8,1.1,-7.7,-1.8],[2.8,6.4,0.0,-1.2,-16.6]]);
b:=Vector([-3.5,19.58,-24.56,8.16,-9.28]);
x0:=Vector([0,0,0,0,0]);
jacobi(A,b,x0,5);
#Error, (in jacobi) Vector index out of range
Error, (in LinearAlgebra:-Norm) expects its 1st argument, A, to be of type {Matrix, Vector}, but received x-x1
I found a solution!
restart;
jacobi:=proc(A::Matrix,b::Vector,x0::Vector,m::integer,N::integer,tol::float)
local n,i,j,S,ee,x::Vector,x1::Vector;
x1:=Vector(x0); x := Vector(m); n:=1;
do
for i from 1 to m do
S:=0.0;
for j from 1 to i-1 do
S:=S+A[i,j]*x1[j]
end do;
for j from i+1 to m do
S:=S+A[i,j]*x1[j]
end do;
x[i]:=(-S+b[i])/A[i,i];
end do;
ee:= LinearAlgebra[VectorNorm](x-x1);
if(ee<tol) then
printf("The solution after %d iterations is:",n);
print(x);
break;
end if;
for j from 1 to m do
x1[j]:=x[j];
end do;
n:=n+1;
if (n>N) then error("No convergence after",N,"iterations") end if;
end do;
return x;
end proc;
jacobi := proc(A::Matrix, b::Vector, x0::Vector, m::integer,
N::integer, tol::float)
...
end;
A:=Matrix([[12.4,0.3,-2.2,0.2,3.6],[1.2,7.1,-1.7,-1.6,0.9],[1.3,3.1,10.8,2.2,0.7],[-1.4,0.8,1.1,-7.7,-1.8],[2.8,6.4,0.0,-1.2,-16.6]]);
b:=Vector([-3.5,19.58,-24.56,8.16,-9.28]);
x0:=Vector([0,0,0,0,0]);
jacobi(A,b,x0,5,100,0.01);
The solution after 8 iterations is:

How can I check if a value in DB Columns is a BSN (Dutch SSN)

I am looking for a way in which you are able to tell if values in your Column are valid BSN values. A BSN (Dutch SSN) has to conform to a sort of '11-test'. Mind you its not the same as a banking account. Checkout https://nl.wikipedia.org/wiki/Burgerservicenummer for details.
What I would like to return is a zero or a one indicating if I have a valid (=1) or an invalid BSN (=0). Currently it is stored as a number.
I tried to make a SQL statement for this. I started with the following actions:
First I only want rows where I have an actual value and skipp the (null) values:
SELECT D_BSN FROM EMPLOYEE WHERE D_BSN IS NOT NULL;
After that I want my BSN to be a VARCHAR2.
SELECT TO_CHAR(D_BSN) FROM EMPLOYEE WHERE D_BSN IS NOT NULL;
Now I want my BSN always to be of the same length:
SELECT DECODE(LENGTH(TO_CHAR(D_BSN)),8, '0' || D_BSN, D_BSN)
FROM EMPLOYEE
WHERE D_BSN IS NOT NULL;
Now if my length is not 9 I have an invalid field so 'exit' with 0.
SELECT
DECODE(
LENGTH(DECODE(LENGTH(TO_CHAR(D_BSN)),8, '0' || D_BSN, D_BSN)), 9,
DECODE(LENGTH(TO_CHAR(D_BSN)),8, '0' || D_BSN, D_BSN), 0)
FROM MW_DOCUMENTS
WHERE D_BSN IS NOT NULL;
At this point I find my SQL statement to become unreadable. Also because I have a long way to go. I have to pick each digit, multiply it by its position, sum up the result, divide it by eleven and see if the mod is equal to the last number of the BSN. This is easy in a programming language so why not put this in a function. So I could use it like this:
SELECT * FROM EMPLOYEE WHERE IS_BSN(D_BSN) = 0
to get all the invalid BSN's. See my answer for what I came up with.
UPDATE: (added the code for the function)
Here is my Function that returns a zero or a 1 indicating valid or invalid BSN:
create or replace FUNCTION is_bsn(num_in NUMBER) RETURN NUMBER IS
-- Yes is BSN = True == 1
-- NO not BSN = False == 0
checkValue NUMBER := -1;
factor NUMBER := 9;
result NUMBER := 0;
outcome NUMBER := 0;
bsn VARCHAR2(9);
BEGIN
bsn := to_char(num_in);
-- Check if length is 8 if so add zero in front
IF LENGTH(bsn) = 8 THEN
bsn := '0' || bsn;
END IF;
-- Now length should be 9
IF LENGTH(bsn) <> 9 THEN
RETURN 0;
END IF;
checkValue := TO_NUMBER(SUBSTR(bsn, 9, 1));
FOR Lcntr IN 1..8
LOOP
result := result + TO_NUMBER(SUBSTR(bsn, Lcntr, 1)) * factor;
factor := factor - 1;
END LOOP;
outcome := result mod 11;
if outcome = checkValue then
return 1;
ELSE
return 0;
END IF;
EXCEPTION
WHEN OTHERS THEN
RETURN 'FALSE';
END is_bsn;
UPDATE:
As Wildplasser answer was for Postgress and the original question was for Oracle I converted his answer for Oracle:
create or replace FUNCTION is_bsn2(inBsn in NUMBER) RETURN NUMBER IS
-- Yes is BSN = True = 0
-- NO not BSN = False => 1
val NUMBER;
mul NUMBER;
bsn NUMBER := inBsn;
BEGIN
val := 11 - (bsn mod 10); -- the check digit
mul := 1;
WHILE (bsn > 0) loop
bsn := FLOOR (bsn / 10);
mul := mul + 1;
val := val + (bsn mod 10) * mul;
END LOOP;
IF (mul < 9) THEN
RETURN 13;
END IF; -- too short
RETURN val mod 11;
END;
Be aware that I renamed it to is_bsn2 and that the outcome is > 0 means NOT a valid bsn. I couldn't see much performance gain one over the other but I haven't tested it extensively.
It can all be done in a single loop, without conversion to character.
This version accepts an integer argument. (a nine digit decimal number should fit into a 32bit signed integer)
it returns 0 on success, and > 0 otherwise (which makes more sense to me)
There is no need to handle exceptions,since there is no possible exception.
this is for postgres, but the differences should be minimal.
CREATE function bsn_invalid(bsn INTEGER) RETURNS INTEGER
AS
$func$
DECLARE
val INTEGER;
mul INTEGER;
BEGIN
val := 11- (bsn % 10); -- the check digit
mul := 1;
while (bsn > 0) loop
bsn := (bsn / 10);
mul := mul + 1;
val := val + (bsn%10)*mul;
end loop;
if (mul < 9) then return 13; END IF; -- too short
return val % 11;
END
$func$ LANGUAGE plpgsql
;
-- test it::
SELECT bsn_invalid( 123456782);
SELECT bsn_invalid( 111222333 );
SELECT bsn_invalid( 23456784); -- assume a leading zero
SELECT bsn_invalid( 1234567); -- too short

difference of two number from set of numbers input from file in VHDL

i am trying to find difference of two numbers from set of number available in file. "read.txt" contain numbers as
5
15
25
36
98
654
256
20
354
and i want output as 10 10 11 62 556 398 236 334
but i am getting in my output file "realout.txt" as 0
0
10
11
556
236
236
236
236
236
236
i don't know why every time at starting position 0 is printed and at the end number is repeated 5 times more..please help me to solve this problem my code is here.
library IEEE;
library std;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.all;
use IEEE.MATH_REAL.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_TEXTIO.ALL;
use std.textio.all; --include package textio.vhd
entity testvhdl is
end testvhdl;
architecture Behavioral of testvhdl is
constant MAX : integer := 256*256-1;
SIGNAL rstb : std_logic := '0';
SIGNAL clk : std_logic := '0';
SIGNAL a : std_logic_vector(7 downto 0) := (others=>'0');
--Outputs
SIGNAL sum : std_logic_vector(7 downto 0);
--period of clock,bit for indicating end of file.
signal endoffile : bit := '0';
signal d1,d2,intt,n: integer:=0;
signal aa,ab,ac: integer:=0;
signal linenumber : integer:=1;
--signal dbus: std_logic_vector(7 downto 0) := x"00";
--------------------------------------------------------------------------------------------
function CONV_STDLV8bit_2INT(ARG: std_logic_vector (7 downto 0))
return integer is
variable int: integer:=0;
variable tmp: std_logic_vector(7 downto 0);
begin
int :=0;
tmp := ARG;
for i in 0 to 7 loop
if (tmp(i) ='1') then
int := int+(2**i);
else
int := int+0;
end if;
end loop;
return int;
end CONV_STDLV8bit_2INT;
--------------------------------------------------------------------------------------------
function CONV_INT2STDLV(ARG: INTEGER; SIZE: INTEGER)
return STD_LOGIC_VECTOR is
variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0):=x"00";
variable temp: integer:= 0;
begin
temp := ARG;
for i in 0 to SIZE-1 loop
if ((temp mod 2) = 1) then
result(i) := '1';
else
result(i) := '0';
end if;
if temp > 0 then
temp := temp / 2;
elsif (temp > integer'low) then
temp := (temp - 1) / 2; -- simulate ASR
else
temp := temp / 2; -- simulate ASR
end if;
end loop;
return result;
end CONV_INT2STDLV;
--------------------------------------------------------------------------------------------
constant PERIOD : time := 20 ns;
constant DUTY_CYCLE : real := 0.5;
constant OFFSET : time := 30 ns;
begin
-- Instantiate the Unit Under Test (UUT)
--uut: imadder PORT MAP(
-- rstb => rstb,
-- clk => clk,
-- a => a,
-- b => b,
-- sum => sum
-- );
CLOCK: PROCESS -- clock process for clk
BEGIN
WAIT for OFFSET;
CLOCK_LOOP : LOOP
clk <= '0';
WAIT FOR (PERIOD - (PERIOD * DUTY_CYCLE));
clk <= '1';
WAIT FOR (PERIOD * DUTY_CYCLE);
END LOOP CLOCK_LOOP;
END PROCESS;
tb: PROCESS
BEGIN
rstb <='0';
wait for 60ns;
rstb <='1';
wait for 1312us; -- will wait forever
END PROCESS;
reading : process
file infile : text is in "real.txt"; --declare input file 1987
file outfile : text is out "realout.txt"; --declare output file 1987
--file infile2 : text is in "img2.txt"; --declare input file 1987
variable inline,inline2 : line; --line number declaration
variable dataread1 : integer;
variable dataread2 : integer;
variable buff_out : line; --line number declaration
-- variable aa,ab,ac: integer:=0;
begin
wait until clk = '0' and clk'event;
if(n < 10) then
if (not (endfile(infile))) then --checking the "END OF FILE" is not reached.
readline(infile, inline);
readline(infile, inline2);
read(inline, dataread1);
read(inline2, dataread2);
d1 <= dataread1;
d2 <= dataread2;
-- if n mod 5 = 0 then
aa <= abs(d1 - d2);
-- a <= CONV_INT2STDLV(aa,8);
--
-- n <= n+1;
-- elsif (d1 > aa) then
-- ab <= d1 - aa;
-- ac <= ac+ab;
-- aa <= d1;
--
-- else
-- ab <= aa - d1;
-- ac <= ac+ab;
-- aa <= d1;
--
-- end if;
-- d1 <= ac;
--readline(infile2, inline2);
--read(inline2, dataread1);
--d2 <=integer(dataread1);
--b <= CONV_INT2STDLV(d2,8);
else
a<=x"00";
--b<=x"00";
end if;
else
endoffile <='1'; --set signal to tell end of file read file is reached.
end if;
-- end process reading;
--write process #negative edge
--writing : process
-- begin
-- wait until clk = '0' and clk'event;
if(endoffile='0') then --if the file end is not reached.
--intt <= CONV_STDLV8bit_2INT(aa);
if(linenumber > 0) then
n <= n+1;
--if(linenumber>11) then
write(buff_out, aa);
writeline(outfile, buff_out);-- write line to output_image text file.
--end if;
end if;
linenumber <= linenumber + 1;
else
null;
end if;
end process reading;
end Behavioral;
--WRITE (buf, string'("hello"));
--WRITELINE(fileptr,buf);
--WRITE (buf, bit_vector'(" 010111 "));
--WRITELINE(fileptr,buf);
--http://myfpgablog.blogspot.in/2011/12/memory-initialization-methods.html
-- constant MEM_DEPTH : integer := 2**ADDR_WIDTH;
-- type mem_type is array (0 to MEM_DEPTH-1) of signed(DATA_WIDTH-1 downto 0);
-- impure function init_mem(mif_file_name : in string) return mem_type is
-- file mif_file : text open read_mode is mif_file_name;
-- variable mif_line : line;
-- variable temp_bv : bit_vector(DATA_WIDTH-1 downto 0);
-- variable temp_mem : mem_type;
-- begin
-- for i in mem_type'range loop
-- readline(mif_file, mif_line);
-- read(mif_line, temp_bv);
-- temp_mem(i) := signed(to_stdlogicvector(temp_bv));
-- end loop;
-- return temp_mem;
-- end function;
-- constant mem : mem_type := init_mem("mem_init_vhd.mif");
...i don't know why every time at starting position 0 is printed and at the end number is repeated 5 times more..please help me to solve this problem my code is here.
Besides the wild context clauses and all the extraneous noise there are two things observably wrong here. First you proposed input data set for real.txt has an odd number of lines (elements - integers). Second you are misapplying the BIT signal endofile:
reading :
process
file infile : text is in "real.txt";
file outfile : text is out "realout.txt";
variable inline,inline2 : line;
variable dataread1 : integer;
variable dataread2 : integer;
variable buff_out : line;
begin
wait until clk = '0' and clk'event;
if(n < 10) then
if (not (endfile(infile))) then
readline(infile, inline);
readline(infile, inline2);
read(inline, dataread1);
read(inline2, dataread2);
d1 <= dataread1;
d2 <= dataread2;
aa <= abs(d1 - d2);
else
a<=x"00";
end if;
else
endoffile <='1';
end if;
if(endoffile='0') then
if(linenumber > 0) then
n <= n+1;
write(buff_out, aa);
writeline(outfile, buff_out);
end if;
linenumber <= linenumber + 1;
else
null;
end if;
end process reading;
This is what your design with less than 20 integers on separate lines looks like:
As you can see from the waveform that results in the last value being repeated (the falling edge of the following clocks).
I added the 720 so it wouldn't get an integer read fail assertion.
The first two zeros are from not holding off output when rstb is true and a pipeline delay loading d0, d1 on a falling clock edge and then assigning aa on the next clock edge. There isn't a pipeline signal to qualify aa as valid for output.
endofile will never get written to a '1' where that assignment is unless your data set is big enough. n is counting input pairs of integers (pairs of lines):
So endofile should be fixed (on two counts, it's not set when an end of file condition is actually encountered, and the second readline is assumed to have been successful).
There's a third thing wrong, with enough data from real.txt you're missing the last absolute difference value in realout.txt, which says that pipeline signal specifying aa is valid should have a hold over as well as a hold off.
It might be easier to fix this by troubleshooting waveforms.
For the portion of your code not commented out the context clause should look like this:
library IEEE;
use ieee.std_logic_1164.all;
use std.textio.all;