Hi I have been writing a code in VHDL for some image processing. However, due to some reasons I have not yet determined the sythesis does not stop. I suspect that efficiency of the code is not as much as I need it to be, which slows down the process of sythesis. I am new to hardware world and still learning. I am using Basys3 board and Vivado2017.2 environment. My computer is not old and works fine in terms of speed/power. How can I reduce sythesis time and reach a result??
Code is complex I am aware but it will get more complex because extra features will be added. What I do is moving a frame on the picture and depending on the operation chosen changing pixels inside the frame.
Here is the code I wrote
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
use IEEE.std_logic_unsigned.all;
use std.textio.all;
entity vga_core is
generic (
PICTURE_WIDTH_HEIGHT : integer := 250;
COLOR_BIT : integer := 4);
port (
default_clk : in std_logic := '0';
rst : in std_logic:= '0';
data_r : out std_logic_vector(COLOR_BIT-1 downto 0);
data_g : out std_logic_vector(COLOR_BIT-1 downto 0);
data_b : out std_logic_vector(COLOR_BIT-1 downto 0);
hs_out : out std_logic;
vs_out : out std_logic;
operation : in std_logic_vector(1 downto 0);
mode: in std_logic;
go_left : in std_logic;
go_right: in std_logic;
go_down: in std_logic;
go_up: in std_logic;
enable : in std_logic;
cursor_mode : in std_logic_vector(1 downto 0)
);
end vga_core;
architecture VGA of vga_core is
---------------------------------------------------------
---------CONSTANTS FOR VGA-------------------------------
---------------------------------------------------------
constant RES_H : integer := 640;
constant RES_V : integer := 480;
constant H_FRONT_PORCH : integer := 16;
constant H_SYNC_TIME : integer := 96;
constant H_BACK_PORCH : integer := 48;
constant V_FRONT_PORCH : integer := 11;
constant V_SYNC_TIME : integer := 2;
constant V_BACK_PORCH : integer := 31;
constant TOTAL_H : integer := RES_H + H_FRONT_PORCH + H_SYNC_TIME + H_BACK_PORCH; -- 800
constant TOTAL_V : integer := RES_V + V_FRONT_PORCH + V_SYNC_TIME + V_BACK_PORCH; -- 524
---------------------------------------------------------
constant LENGTH_1 : integer := PICTURE_WIDTH_HEIGHT;
constant LENGTH_2 : integer := 10;
constant LENGTH_3 : integer := 25;
constant LENGTH_4 : integer := 50;
signal length : integer range 0 to PICTURE_WIDTH_HEIGHT := LENGTH_1;
---------------------------------------------------------
----------------Signals used for VGA operations ---------
---------------------------------------------------------
signal COUNTER_H : integer range 0 to TOTAL_H := 0; -- 0 to 800
signal COUNTER_V : integer range 0 to TOTAL_V := 0; -- 0 to 524
signal NEW_LINE : std_logic := '0';
signal h_visible : std_logic := '0';
signal v_visible : std_logic := '0';
signal visible : std_logic := '0';
---------------------------------------------------------
------------------Clock things---------------------------
---------------------------------------------------------
signal clk : std_logic := '0';
signal temporal: std_logic := '0';
signal counter : integer range 0 to 1 := 0;
---------------------------------------------------------
--------Upper-left positions of the frame----------------
---------------------------------------------------------
signal cursor_pos_x : integer range 0 to PICTURE_WIDTH_HEIGHT := 0;
signal cursor_pos_y : integer range 0 to PICTURE_WIDTH_HEIGHT := 0;
---------------------------------------------------------
----------Positions of the pixels on the screen----------
---------------------------------------------------------
signal pos_x : integer range 0 to 2047 := 0;
signal pos_y : integer range 0 to 2047 := 0;
---------------------------------------------------------
signal vgaData : std_logic_vector(3*COLOR_BIT-1 downto 0) := "000000000000";
type RamType is array(0 to PICTURE_WIDTH_HEIGHT - 1, 0 to PICTURE_WIDTH_HEIGHT - 1) of bit_vector(11 downto 0);
--My ram is 2-dimensional by the way
impure function InitRamFromFile (RamFileName : in string) return RamType is
FILE RamFile : text is in RamFileName;
variable RamFileLine : line;
variable RAM : RamType;
begin
for y in 0 to 249 loop
for x in 0 to 249 loop
readline (RamFile, RamFileLine);
read (RamFileLine, RAM(x,y));
end loop;
end loop;
return RAM;
end function;
signal RAM : RamType := InitRamFromFile("\\ASUS\Users\AsusPc\Desktop\project_son\pictureData.data");
begin
-- according to cursor mode, length is adjusted
with cursor_mode select length <=
LENGTH_1 when "00",
LENGTH_2 when "01",
LENGTH_3 when "10",
LENGTH_4 when "11";
--I obtain a clock signal with 25Mhz frequency
CLOCK_DIVIDER: process (default_clk) begin
if rising_edge(default_clk) then
if (counter = 1) then
temporal <= NOT(temporal);
counter <= 0;
else
counter <= counter + 1;
end if;
end if;
end process;
clk <= temporal;
---------------------------------------------------------
--------------VGA THINGS---------------------------------
---------------------------------------------------------
CNT_H : process (clk) is
begin
if clk'event and clk = '1' then
if (COUNTER_H = TOTAL_H-1) then
COUNTER_H <= 0;
NEW_LINE <= '1';
else
COUNTER_H <= COUNTER_H + 1;
NEW_LINE <= '0';
end if;
end if;
end process CNT_H;
CNT_V : process (clk) is
begin
if clk'event and clk = '1' then
if (NEW_LINE = '1') then
if (COUNTER_V = TOTAL_V-1) then
COUNTER_V <= 0;
else
COUNTER_V <= COUNTER_V + 1;
end if;
end if;
end if;
end process CNT_V;
SYNC_H : process (clk) is
begin
if clk'event and clk = '1' then
if (COUNTER_H < H_SYNC_TIME) then
hs_out <= '0';
else
hs_out <= '1';
end if;
end if;
end process SYNC_H;
SYNC_V : process (clk) is
begin
if clk'event and clk = '1' then
if (COUNTER_V < V_SYNC_TIME) then
vs_out <= '0';
else
vs_out <= '1';
end if;
end if;
end process SYNC_V;
AREA_H : process (clk, rst) is
begin
if clk'event and clk = '1' then
if (COUNTER_H > H_SYNC_TIME + H_BACK_PORCH - 1) and (COUNTER_H < TOTAL_H - H_FRONT_PORCH) then
h_visible <= '1';
if ((COUNTER_H - (H_SYNC_TIME + H_BACK_PORCH)) <641) then
pos_x <= COUNTER_H - (H_SYNC_TIME + H_BACK_PORCH);
end if;
else
h_visible <= '0';
end if;
end if;
end process AREA_H;
AREA_V : process (clk) is
begin
if clk'event and clk = '1' then
if (COUNTER_V > V_SYNC_TIME + V_BACK_PORCH - 1) and (COUNTER_V < TOTAL_V - V_FRONT_PORCH) then
v_visible <= '1';
if ((COUNTER_V - (V_SYNC_TIME + V_BACK_PORCH)) < 481) then
pos_y <= COUNTER_V - (V_SYNC_TIME + V_BACK_PORCH);
end if;
else
v_visible <= '0';
end if;
end if;
end process AREA_V;
visible <= h_visible and v_visible;
--------------------------------------------------------------
--------------------------------------------------------------
--------------------------------------------------------------
--Used to move the frame to left
GOING_LEFT: process (go_left, clk) is
begin
if rising_edge(clk) then
if go_left = '1' then
if (cursor_pos_x - length - 1 > 0) then
cursor_pos_x <= cursor_pos_x - length - 1;
else
cursor_pos_x <= 0;
end if;
end if;
end if;
end process GOING_LEFT;
--Used to move the frame to right
GOING_RIGHT: process (go_right, clk) is
begin
if rising_edge(clk) then
if go_right = '1' then
if (cursor_pos_x + length - 1 < PICTURE_WIDTH_HEIGHT) then
cursor_pos_x <= cursor_pos_x + length - 1;
else
cursor_pos_x <= PICTURE_WIDTH_HEIGHT - 1;
end if;
end if;
end if;
end process GOING_RIGHT;
--Used to move the frame up
GOING_UP: process (go_up, clk) is
begin
if rising_edge(clk) then
if go_up = '1' then
if (cursor_pos_y - length -1 > 0) then
cursor_pos_y <= cursor_pos_y - length - 1;
else
cursor_pos_y <= 0;
end if;
end if;
end if;
end process GOING_UP;
--Used to move the frame down
GOING_DOWN: process (go_down,clk) is
begin
if rising_edge(clk) then
if go_down = '1' then
if (cursor_pos_y + length - 1 < PICTURE_WIDTH_HEIGHT) then
cursor_pos_y <= cursor_pos_y + length - 1;
else
cursor_pos_y <= PICTURE_WIDTH_HEIGHT - length ;
end if;
end if;
end if;
end process GOING_DOWN;
--------------------------------------------------------------
--------------Most important part----------------------------
--------------------------------------------------------------
SHOW : process (clk, rst) is
begin
if rising_edge(clk) then --clk
if rst = '1' then --rst
RAM <= InitRamFromFile("\\ASUS\Users\AsusPc\Desktop\project_son\pictureData.data");
cursor_pos_x <= 0;
cursor_pos_y <= 0;
elsif (visible = '1') and ( pos_x < PICTURE_WIDTH_HEIGHT) and (pos_y <PICTURE_WIDTH_HEIGHT) and (pos_x > -1) and (pos_y > -1) then
if((pos_y = cursor_pos_y) and ((pos_x > cursor_pos_x -1) or (pos_x < cursor_pos_x + length ))) or ((pos_y = cursor_pos_y + length -1) and ((pos_x > cursor_pos_x -1) or (pos_x < cursor_pos_x + length))) then --drawing the frame part 1
vgaData <= "000000000000"; --black
data_r <= vgaData(3*COLOR_BIT-1 downto 2*COLOR_BIT);
data_g <= vgaData(2*COLOR_BIT-1 downto COLOR_BIT);
data_b <= vgaData(COLOR_BIT-1 downto 0);
elsif ((pos_x = cursor_pos_x) and ((pos_y > cursor_pos_y - 1) or (pos_y < cursor_pos_y + length))) or ((pos_x = cursor_pos_x + length -1) and ((pos_y > cursor_pos_y - 1) or (pos_y < cursor_pos_y + length))) then --drawing the frame part 2
vgaData <= "000000000000"; --black
data_r <= vgaData(3*COLOR_BIT-1 downto 2*COLOR_BIT);
data_g <= vgaData(2*COLOR_BIT-1 downto COLOR_BIT);
data_b <= vgaData(COLOR_BIT-1 downto 0);
else
vgaData <= to_stdlogicvector(RAM(pos_x,pos_y));
data_r <= vgaData(3*COLOR_BIT-1 downto 2*COLOR_BIT);
data_g <= vgaData(2*COLOR_BIT-1 downto COLOR_BIT);
data_b <= vgaData(COLOR_BIT-1 downto 0);
end if;
if ((pos_x > PICTURE_WIDTH_HEIGHT - 1) and (pos_y > -1)) or ((pos_y > PICTURE_WIDTH_HEIGHT - 1) and ((pos_x > -1) or (pos_x < PICTURE_WIDTH_HEIGHT))) then
vgaData <= "000000001111"; -- blue
data_r <= vgaData(3*COLOR_BIT-1 downto 2*COLOR_BIT);
data_g <= vgaData(2*COLOR_BIT-1 downto COLOR_BIT);
data_b <= vgaData(COLOR_BIT-1 downto 0);
end if;
end if;
end if;
end process SHOW;
--Whenever cursor_mode changes, cursor positions are reset
ADJUSTING_cpx_and_cpy: process(cursor_mode) is
begin
cursor_pos_x <= 0;
cursor_pos_y <= 0;
end process;
BRIGHTNESS: process(enable,clk) is
begin
if rising_edge(clk) then
if enable = '1' then
if operation = "00" then
if ( pos_x > cursor_pos_x - 1) and (pos_x < cursor_pos_x + length) and ( pos_y > cursor_pos_y - 1) and (pos_y < cursor_pos_y + length) then -- condition
if mode = '0' then
if to_stdlogicvector(RAM(pos_x, pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) < 14 then
RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) + 2);
end if;
if to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) < 14 then
RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) + 2);
end if;
if to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) < 14 then
RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) + 2);
end if;
elsif mode = '1' then
if to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) > 1 then
RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) - 2);
end if;
if to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) > 1 then
RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) - 2);
end if;
if to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) > 1 then
RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) - 2);
end if;
end if; --mode
end if; --condition
end if; --operation
end if; --enable
end if; --clock
end process BRIGHTNESS;
CONTRAST: process(enable, clk) is
begin
if rising_edge(clk) then
if enable = '1' then
if operation = "01" then
if (pos_x > cursor_pos_x - 1) and (pos_x < cursor_pos_x + length) and ( pos_y > cursor_pos_y - 1) and (pos_y < cursor_pos_y + length) then -- condition
if mode = '0' then
if to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) < 8 and to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) > 1 then
RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) - 2);
elsif to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) > 7 and to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) < 14 then
RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) +2) ;
end if;
if to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) < 8 and to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) > 1 then
RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) - 2);
elsif to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) > 7 and to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) < 14 then
RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) +2) ;
end if;
if to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) < 8 and to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) > 1 then
RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) - 2);
elsif to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) > 7 and to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) < 14 then
RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) +2) ;
end if;
elsif mode = '1' then
if to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) < 8 and to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) > 2 then
RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) - 3);
elsif to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) > 7 and to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) < 13 then
RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(3*COLOR_BIT-1 downto 2*COLOR_BIT)) +3) ;
end if;
if to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) < 8 and to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) > 2 then
RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) - 3);
elsif to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) > 7 and to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) < 13 then
RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(2*COLOR_BIT-1 downto COLOR_BIT)) +3) ;
end if;
if to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) < 8 and to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) > 2 then
RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) - 3);
elsif to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) > 7 and to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) < 13 then
RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0) <= to_bitvector(to_stdlogicvector(RAM(pos_x,pos_y)(COLOR_BIT-1 downto 0)) + 3) ;
end if;
end if; --mode
end if; --condition
end if; --OPERATION
end if; --ENABLE
end if; --CLK
end process CONTRAST;
end VGA;
This code unfortunately did not get me anywhere.
bit_vector
s might synthesize as latches rather than RAM, which might be your issue. Have you tried it with a smaller size to see if the correct element type is selected? I'd suggest instead using a standard predefined RAM module and calculating addresses (probably by concatenating bits, so you get a 256*256 array, rather than using a multiplier to get 250*250 - this may be a little inefficient in RAM space but is likely to save a lot more in the way of addressing logic, and you have the RAM to spare). \$\endgroup\$