NOTE: This is not the final version of my Bitmap Smoother ASIC.
I will post the final version in the future.
--file addivider_beh.VHD.
--The input to this program is an ASCII file, and its name is in.bmp.
--It must exist in the same directory as this source code.
--The name of the output file is out.txt.
--The input and output format follows this format:
--The header consists of the first 4 rows:
--BM		reserved word
--00		reserved
--rows		
--cols
--The pixels grey levels follow the header. Each line contains one row
--of pixels, and each byte(two characters) represent the gray level of a pixel.
--For example:
--BM
--00
--20
--20
--FFAA009BCDEF0707096600011111000101010101
--1111000100111111000101001111001111000100
--11110001011011110
library std;
use std.textio.all;
package declarations is
 	constant dbus:integer:=8;--dbus stands for data bus
 	constant col_adres_bus:integer:=12;
 	constant col_ram_size:integer:=100	constant maxrow:bit_vector:="10";
--The biggest picture can have 99 cols. Therefore the max RAM col
--size needed is 101.
	subtype data is bit_vector(dbus downto 1);
	type RAM is array (0 to 2,0 to col_ram_size) of data;
 	constant dbus2:integer:=dbus+2;
 	constant dbus3:integer:=dbus+3;
	subtype data2 is bit_vector(dbus2 downto 1);
	subtype data3 is bit_vector(dbus3 downto 1);
	subtype col_adres is bit_vector(1 to col_adres_bus);
	subtype row_adres is bit_vector(1 to 2);
	type hex is ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
	--redefine if lower case letters are desired
	function add2(a,b:bit_vector) return bit_vector;
	function char2hex(inchar:character) return hex;
	function hex2char(inchar:hex) return character;
	function increment(val:bit_vector;upper_limit:bit_vector) return bit_vector;
	procedure int2bv(coming:in integer;leaving:inout bit_vector);
	function bv2int(coming:in bit_vector) return integer;
end declarations;
package body declarations is
--Note:In a procedure or function I can have signals as parameters. If no type is specified
--then variable is the default.
	function add2(a,b:bit_vector) return bit_vector is
	--This function accepts two 10-bit binary numbers and outputs their sum (11-bits).
			variable vsum:bit_vector(dbus3 downto 1);
			variable carry:bit:='0';
	begin
		for i in 1 to dbus2 loop
			vsum(i):=(a(i) xor b(i)) xor carry;
			carry:=(a(i) and b(i)) or (carry and (a(i) or b(i)));
		end loop;
			vsum(dbus3):=carry;
			return vsum;
	end add2;
	function char2hex(inchar:character) return hex is
			variable x:integer;
	begin
		case inchar is
			when '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' => x:=character'pos(inchar)-character'pos('0');
			when 'A'|'B'|'C'|'D'|'E'|'F' => x:=character'pos(inchar) - 55;
			when others => x := 0;--return 0h when invalid character
		end case;
		return hex'val(x);
	end;
	function hex2char(inchar:hex) return character is
			variable x:integer;
	begin
		case inchar is
			when '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' => x:=hex'pos(inchar)+48;
			when 'A'|'B'|'C'|'D'|'E'|'F' => x:=hex'pos(inchar) + 55;
			when others => x := 48;--return '0' when invalid character
		end case;
		return character'val(x);
	end;
	function increment(val:bit_vector;upper_limit:bit_vector) return bit_vector is
			alias input:bit_vector(val'length downto 1) is val;
			variable result:bit_vector(input'range):=input;
			variable carry:bit:='1';
	begin
			if (val=upper_limit)
			then result:=(others=>'0');
			else	for i in input'low to input'high loop
					result(i) := input(i) xor carry;
					carry := input(i) and carry;
					exit when carry = '0';
				end loop;
			end if;
			return result;
	end increment;
	procedure int2bv(coming:in integer;leaving:inout bit_vector) is
			variable bv : bit_vector(leaving'length downto 1) := (others => '0');
			variable pos : integer := 0;
			variable tmpval : integer := coming;
	begin
			for i in 1 to leaving'length loop
				pos := pos + 1;
				if (tmpval mod 2) = 1 then bv(i) := '1';
				end if;
				tmpval := tmpval / 2;
				exit when tmpval = 0;
			end loop;
			leaving:=bv;
	end;
	function bv2int(coming:in bit_vector) return integer is
	--conversion of array of logic values (bit vector) to an integer
			variable work:integer:=0;
	begin
			for i in coming'range loop
				work:=work*2;
				if coming(i)='1' then work:=work+1; end if;
			end loop;
			return work;
	end bv2int;
end declarations;
use work.declarations.all;
package chips is
	component cadd2 port(ac,bc:bit_vector;sum2:out bit_vector); end component;
end chips;
use work.declarations.all;
entity cadd2 is port(ac,bc:bit_vector;sum2:out bit_vector); end cadd2;
architecture structural of cadd2 is
begin
	a2:process(ac,bc)
	--This component accepts two 10-bit binary numbers and outputs their sum (11-bits).
			variable vsum:bit_vector(dbus3 downto 1);
			variable carry:bit:='0';
	begin
		for i in 1 to dbus2 loop
			vsum(i):=(ac(i) xor bc(i)) xor carry;
			carry:=(ac(i) and bc(i)) or (carry and (ac(i) or bc(i)));
		end loop;
		vsum(dbus3):=carry;
		sum2 <= vsum;
	end process;
end structural;
entity cmod is port(acm,bcm:integer;cmodo:out integer); end cmod;
use work.declarations.all;
entity main_body is
end;
library std;
use std.textio.all;
architecture behavioral of main_body is
	signal getpel:bit:='1';--must be 1. Do not change
	signal bitCLK:bit:='0';
	signal bitCLKcycle:bit_vector(1 to 4):="0000";
	signal zreadallowed:boolean:=true;
	signal zdone:boolean;
	signal No_read:data:=(others => '0');
	signal No1,No2,No3,No4,No5,div8,div16,div64:data2:=(others => '0');
	signal res,sum2,sum3,sum4,sum5,semires:data3;
	signal rdbytectr:integer:=-1;
	signal rdlinectr,wrbytectr,wrlinectr:integer:=0;--wrmodcols=wrbyte mod cols
--	signal p2c,f3rc:col_adres := (others => '0');
--	signal p4c:col_adres := "000000000001";
--	signal frontr,p234r,:row_adres:="00";
--	signal rearr:row_adres:="00";--insert data into RAM at (rearr,f3rc)
	component cadd2 port(ac,bc:bit_vector;sum2:out bit_vector); end component;
	for csum2,csum3,csum4,csum5 : cadd2 use entity work.cadd2(structural);
	file inf:text is "in.bmp";
	file outf:text is out "out.txt";
	file troublee:text is out "trouble.txt";
	procedure write_string(l:inout line;value:in string;justified:in side:=right;field:in width:=0) is
	begin write(l,value,justified,field);end;
begin
	csum2: cadd2 port map (No1,No2,sum2);
	csum3: cadd2 port map (sum2(dbus2 downto 1),No3,sum3);
	csum4: cadd2 port map (sum3(dbus2 downto 1),No4,sum4);
	csum5: cadd2 port map (sum4(dbus2 downto 1),No5,sum5);
--	cdiva: cadd2 port map (div8,div16,semires);
--	cavg5: cadd2 port map (semires(dbus2 downto 1),div64,res);
	readbmp:process(getpel,bitCLK)
			variable eol:boolean;
			variable za2,zb2:data2;
			variable zres:data3;
			variable zhibyte,zNo,zrows,zcols:natural;
			variable zin,zout:line;
			variable mem:RAM;
			variable byte:string(1 to 2);
			variable zpelbyte:hex;
			variable zmaxcol:col_adres;
			variable p2c,f3rc:col_adres := (others => '0');
			variable p4c:col_adres := "000000000001";
			variable frontr,p234r,rearr:row_adres:="00";
				--insert data into RAM at (rearr,f3rc)
	begin
	if getpel = '1' and bitCLK = '0' and rdbytectr<0
	then	--reading the header
		readline(inf,zin);writeline(outf,zin);--BM
		readline(inf,zin);writeline(outf,zin);--00
		readline(inf,zin);read(zin,zcols,eol);write(zin,zcols);writeline(outf,zin);
		int2bv(zcols-1,zmaxcol);
		readline(inf,zin);read(zin,zrows,eol);write(zin,zrows);writeline(outf,zin);
		rdbytectr<=0;
	--processing the pixels
	elsif	getpel = '1' and bitCLK = '1' and not zdone
	then	if wrbytectr > 1 and (wrbytectr mod zcols) = 0
		then p234r:=increment(p234r,maxrow);
			writeline(outf,zout);--flush before eof
			wrlinectr<=wrlinectr+1;
		end if;
		if wrlinectr > 0 and (wrbytectr mod zcols) = 0
		--skipping increasing first row, because of first row mirroring
		then frontr:=increment(frontr,maxrow);
		end if;
		p4c:=increment(p4c,zmaxcol);
		p2c:=increment(p2c,zmaxcol);
		if (wrbytectr mod zcols) = 0 --don't touch
		then	p4c := "000000000001";--no need to modify f3rc
			p2c := (others => '0');--mirroring 1st column
		elsif (wrbytectr mod zcols) = 1
		then	p2c := (others => '0');--rewinding 1st column
		elsif (wrbytectr mod zcols) = zcols - 1 -- right edge mirroring
		then	p4c := zmaxcol;--no need to modify other col pointers
		end if;
		if (rdbytectr mod zcols) = 0 and rdbytectr < zrows*zcols
		then	readline(inf,zin);
			rdlinectr<=rdlinectr+1;
		end if;
		if rdbytectr > 1 and (rdbytectr mod zcols) = 0 
		then	rearr:=increment(rearr,maxrow);
		end if;
		if rdbytectr>0
		then	f3rc:=increment(f3rc,zmaxcol);
		end if;
		--The following algorithm is used:
		--read			inc ctrs, read		inc ctrs,read
		--inc ctrs,read,avg5	inc ctrs,read,avg5......
		if rdbytectr < zrows*zcols
		then	read(zin,byte,eol);
			zhibyte:=hex'pos(char2hex(byte(1)));
			zNo:=hex'pos(char2hex(byte(2)));--low byte
			zNo:=16*zhibyte + zNo;--grey level in decimal
			int2bv(zNo,za2);
			No_read<=za2(dbus downto 1);
			mem(bv2int(rearr),bv2int(f3rc)):=za2(dbus downto 1);
		end if;
		rdbytectr<=rdbytectr+1;
		bitCLKcycle<="0001";
	elsif getpel = '0' and  bitCLK = '0' and rdbytectr > 1 and not zdone
	then case bitCLKcycle is
			when "0011"=>if wrbytectr>zrows*zcols then zdone<=true;
					 end if;
			when "1000"=>if rdbytectr=zrows*zcols then zreadallowed<=false;
					 end if; 
			when others=>null;
			end case;
	elsif getpel = '0' and  bitCLK = '1' and not zdone
	then
		if rdbytectr > zcols --don't touch
		then
	 case bitCLKcycle is	--add numbers
		when "0010"=>No1<="00" & mem(bv2int(frontr),bv2int(f3rc));
				No2<="00" & mem(bv2int(p234r),bv2int(p2c));
				--& = concatenation
				--extend 8 bit signals to 10 bits
		when "0011"=>No3<="00" & mem(bv2int(p234r),bv2int(f3rc));
		when "0100"=>No4<="00" & mem(bv2int(p234r),bv2int(p4c));
		when "0101"=>No5<="00" & mem(bv2int(rearr),bv2int(f3rc));
--za2:="00" & mem(bv2int(rearr),bv2int(f3rc));
--				 No5<=za2;
--				sum5<=add2(za2,sum4(dbus2 downto 1));
		when "0110"=>za2:="00" & sum5(dbus3 downto 4);--divide by 8
				zb2:="000" & sum5(dbus3 downto 5);--divide by 16
				div64<="00000" & sum5(dbus3 downto 7);--divide by 64
				div8<=za2;
				div16<=zb2;
				semires<=add2(za2,zb2);
		when "0111"=>zres:=add2(semires(dbus2 downto 1),div64);
				res<=zres;
				--FLUSHING JUST PROCESSED BYTE
				zNo:=bv2int(zres);
				zpelbyte:=hex'val(zNo/16);
				byte(1):=hex2char(zpelbyte);
				zpelbyte:=hex'val(zNo mod 16);
				byte(2):=hex2char(zpelbyte);
				write(zout,byte);
				wrbytectr <= wrbytectr + 1;
		when others=>null;
		end case;
		end if;
	 bitCLKcycle<=increment(bitCLKcycle,"1000");
	end if;--header or pixels
	end process;
end behavioral;