Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

First in Last out buffer consuming too much resources

Hi all,

I'm trying to implement a first in last out buffer, that has the soul purpose of

flipping image data horizontally. The image comes in as a stream of pixels in

the order

(1,1) , (2,1) , (3,1) ... (765,1) , (1,2) , (2,2) , (3,2) ... (765,2) etc

(where the width of the image is 765)

Each pixel is put through a threshold and represented by a color label, an x coordinate and a y coordinate.

I've implemented a block that instances 3 arrays of length 765

one for the color label (8 bits per label)

one for the x coordinate (10 bits per coordinate)

one for the y coordinate (10 bits per coordinate)

When the arrays are filled (a full line has come in) the direction of the arrays are reversed an the data comes out in effect flipping the row of data and delaying the output of the image by a single row.

The block works and I have verified this by modifying the block to flip the RGB values rather than the color label, x and y coordinate and the output image is a horizontally flipped image. However, before this block is used the total logic elements used is around 9% and after it is around 90% (not to mention the compile time is unbearable).

I have a feeling this is due to the following info I get during the compilation process

Info (276014): Found 3 instances of uninferred RAM logic

Info (276007): RAM logic "ImgModelling:inst32|FlipBuffer:inst5|CL_Stack~19" is uninferred due to asynchronous read logic

Info (276007): RAM logic "ImgModelling:inst32|FlipBuffer:inst5|X_Stack~21" is uninferred due to asynchronous read logic

Info (276007): RAM logic "ImgModelling:inst32|FlipBuffer:inst5|Y_Stack~21" is uninferred due to asynchronous read logic

I'm not to sure where I have asynchronous reading occuring (bear in mind I'm very new to VHDL and FPGA's) but the amount of resources being used by this block seems to high and I would like to fix it if possible

Can anyone confirm this is why the block is using that many logic elements or help me find out why. Also if anyone has a better idea of how to approach the flipping it would be greatly appreciated.

I have provided my code for the block below.

Thanks,

Mat.

CL is the color label

FVAL is true when the image frame is valid

DVAL is true for a valid pixel

so when DVAL = '1' and FVAL = '1' the data is a valid pixel and

DVAL = '0' and FVAL = '0' represents the end of a frame.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity FlipBuffer is
	generic(
		LABEL_WIDTH	:	integer	:=	8;
		COORD_WIDTH	:	integer	:=	10;
		BUFFER_SIZE	:	integer	:=	765	-- Screen width
	);
	port(
		-- Clock Signal
		CLK			:	in	std_logic;
		
		-- Input Signals
		CL_IN			:	in	unsigned(LABEL_WIDTH-1 downto 0);
		X_IN			 :	in unsigned(COORD_WIDTH-1 downto 0);
		Y_IN			 :	in	unsigned(COORD_WIDTH-1 downto 0);
		DVAL_IN :	in std_logic := '0';
		FVAL_IN : in std_logic := '0';
		
		-- Output Signals
		CL_OUT		  :	out unsigned(LABEL_WIDTH-1 downto 0) := to_unsigned(0,LABEL_WIDTH);
		X_OUT			  :	out unsigned(COORD_WIDTH-1 downto 0) := to_unsigned(0,COORD_WIDTH);
		Y_OUT			  :	out unsigned(COORD_WIDTH-1 downto 0) := to_unsigned(0,COORD_WIDTH);
		DVAL_OUT  :	out std_logic := '0';
		FVAL_OUT  : out std_logic := '0'
	);
end FlipBuffer;
architecture rt1 of FlipBuffer is
	-- output registers
	signal cl_reg  : unsigned(LABEL_WIDTH-1 downto 0);
	signal x_reg   : unsigned(COORD_WIDTH-1 downto 0);
	signal y_reg   : unsigned(COORD_WIDTH-1 downto 0);
	signal dval_reg    : std_logic := '0';
	signal fval_reg    : std_logic := '0';
	
	-- Buffer
	type FILO_CL_Stack is array(0 to BUFFER_SIZE-1) of unsigned(LABEL_WIDTH-1 downto 0);
	type FILO_COORD_Stack is array(0 to BUFFER_SIZE-1) of unsigned(COORD_WIDTH-1 downto 0);
	signal CL_Stack : FILO_CL_Stack;
	signal X_Stack  : FILO_COORD_Stack;
	signal Y_Stack  : FILO_COORD_Stack;
	
begin
	process (CLK)
	  variable read    : integer;
	  variable write   : integer;
	  variable reverse : std_logic;
	  variable read_count  : integer;
	  variable write_count : integer;
	begin
	  if (rising_edge(CLK)) then
		  if (DVAL_IN = '0' and FVAL_IN = '0') then
		    -- reset, this will ignore the final line of the frame to ensure
		    -- initial conditions are set when the frame starts. However, the
		    -- final line is black and therefore makes no difference.
		    reverse := '0';
		    read := BUFFER_SIZE-1;
		    write := 0;
		    read_count := 0;
		    write_count := 0;
		    cl_reg <= to_unsigned(0,LABEL_WIDTH);
		    x_reg <= to_unsigned(0,COORD_WIDTH);
		    y_reg <= to_unsigned(0,COORD_WIDTH);
		    dval_reg <= '0';
		    fval_reg <= '0';
		  elsif (DVAL_IN = '1' and FVAL_IN = '1' and read_count > 0) then
		    -- Reading and Writing state
		    -- Read first so data is not overwritten
		    cl_reg <= CL_Stack(read);
		    x_reg <= X_Stack(read);
		    y_reg <= Y_Stack(read);
		    dval_reg <= '1';
		    fval_reg <= '1';
		    
		    -- Write data
		    CL_Stack(write) <= CL_IN;
		    X_Stack(write) <= X_IN;
		    Y_Stack(write) <= Y_IN;
		    
		    -- Update counts and addresses
		    if (write_count + 1 = BUFFER_SIZE) then
		      -- Row writen, reverse buffer and start reading
		      reverse := not reverse;
		      write := write;
		      read := write;
		      write_count := 0;
		      read_count := BUFFER_SIZE;
		    else
		      -- Still writing row
		      reverse := reverse;
		      write_count := write_count + 1;
		      read_count := read_count + 1;
		      if (reverse = '0') then
		        write := write + 1;
		        read := read + 1;
		      else
		        write := write - 1;
		        read := read - 1;
		      end if;
		    end if;
		  elsif (DVAL_IN = '1' and FVAL_IN = '1' and read_count <= 0) then
		    -- Writing, NOT Reading state
		    -- NOT Reading
		    cl_reg <= to_unsigned(0,LABEL_WIDTH);
		    x_reg <= to_unsigned(0,COORD_WIDTH);
		    y_reg <= to_unsigned(0,COORD_WIDTH);
		    dval_reg <= '0';
		    fval_reg <= '1';
		    
		    -- Write data
		    CL_Stack(write) <= CL_IN;
		    X_Stack(write) <= X_IN;
		    Y_Stack(write) <= Y_IN;
		    
		    -- Update counts and addresses
		    if (write_count + 1 = BUFFER_SIZE) then
		      -- Row writen, reverse buffer and start reading
		      reverse := not reverse;
		      write := write;
		      read := write;
		      write_count := 0;
		      read_count := BUFFER_SIZE;
		    else
		      -- Still writing row
		      reverse := reverse;
		      write_count := write_count + 1;
		      if (reverse = '0') then
		        write := write + 1;
		      else
		        write := write - 1;
		      end if;
		      read_count := 0;
		      read := 0;
		    end if;
		  elsif (DVAL_IN = '0' and FVAL_IN = '0' and read_count > 0) then
		    -- Reading, NOT Writing state
		    -- NOT Writing
		    reverse := reverse;
		    write := write;
		    write_count := write_count;
		    
		    -- Read data
		    cl_reg <= CL_Stack(read);
		    x_reg <= X_Stack(read);
		    y_reg <= Y_Stack(read);
		    dval_reg <= '1';
		    fval_reg <= '1';
		    
		    -- Update counts and addresses
		    read_count := read_count + 1;
		    if (reverse = '0') then
		      read := read + 1;
		    else
		      read := read - 1;
		    end if;
		  else
		    -- DO NOTHING, maintain state
		    reverse := reverse;
		    read_count := read_count;
		    write_count := write_count;
		    read := read;
		    write := write;
		    cl_reg <= to_unsigned(0,LABEL_WIDTH);
		    x_reg <= to_unsigned(0,COORD_WIDTH);
		    y_reg <= to_unsigned(0,COORD_WIDTH);
		    dval_reg <= '0';
		    fval_reg <= '1';
		  end if;
		end if;
	end process;
CL_OUT <= cl_reg;
X_OUT <= x_reg;
Y_OUT <= y_reg;
DVAL_OUT <= dval_reg;
FVAL_OUT <= fval_reg;
end rt1;