Continuous Queue in VHDL?

Joined
Nov 13, 2009
Messages
8
Reaction score
0
Hey guys:

I'm trying to work on a code in VHDL that basically has a queue. I want the queue to retrieve data continuously. So basically once the queue is full, it will start to write over the old data (in the last spots). I would like to have pointers to tell me where the first and the last entry, and if there is a wrapback, to be able to keep those pointers synced and correct.

I guess I am having a hard time trying to figure out how to keep track of the pointers.

Can another give me some pointers or advice?

Thanks
 
Joined
Mar 10, 2008
Messages
348
Reaction score
0
Take a look at this post: Must be what your looking for.

velocityreviews.com/forums/t703373-representing-the-buffer-with-logic-gates-flipflops.html
(copy the address to the browser) or look below your post in this group
 
Joined
Nov 13, 2009
Messages
8
Reaction score
0
I looked at it and I am getting some ideas. I have written code. I am trying to make a generic code, so that I have generic variables at the top and can change the width and size of my QUEUE.

for instance:

Code:
ENTITY FIFO IS
	GENERIC(	SIZE:	INTEGER:= 16;
				WIDE:	INTEGER:= 4
		   );
	PORT( 
	           CLK,RESET,WRITE_EN,READ_EN:	IN STD_LOGIC;
                   DATA_IN: 	IN  STD_LOGIC_VECTOR(WIDE-1 DOWNTO 0);
		   DATA_OUT:  OUT   STD_LOGIC_VECTOR(WIDE-1 DOWNTO 0);
     		   QUEUE_EMPTY,QUEUE_FULL:   OUT  STD_LOGIC
	    );
END FIFO;

ARCHITECTURE BEHAVIOR OF FIFO IS

COMPONENT QUEUE_ARRAY 
	PORT(	WRITE_EN,CLK:	IN	STD_LOGIC;
			DATA_IN:	IN	STD_LOGIC_VECTOR(WIDE-1 DOWNTO 0);
			DATA_OUT:	IN	STD_LOGIC_VECTOR(WIDE-1 DOWNTO 0);
			ADDR:		IN	STD_LOGIC_VECTOR(CONV_STD_LOGIC(SIZE,4))
		);
END COMPONENT;


I don't think I am doing it correctly.

LIke I want ADDR signal in the component QUEUE_ARRAY be std_logic_vector in the code, but want to initialize it with an integer, so I can easily change it.

Any suggestions?

Thanks
 
Joined
Mar 10, 2008
Messages
348
Reaction score
0
This will be a more correct start of your code.
You must use the conversion function inside QUEUE_ARRAY.

Code:
ENTITY FIFO IS
	GENERIC(	SIZE:	INTEGER:= 16;
				WIDE:	INTEGER:= 4
		   );
	PORT( 
	           CLK,RESET,WRITE_EN,READ_EN:	IN STD_LOGIC;
                   DATA_IN: 	IN  STD_LOGIC_VECTOR(WIDE-1 DOWNTO 0);
		   DATA_OUT:  OUT   STD_LOGIC_VECTOR(WIDE-1 DOWNTO 0);
     		   QUEUE_EMPTY,QUEUE_FULL:   OUT  STD_LOGIC
	    );
END FIFO;

ARCHITECTURE BEHAVIOR OF FIFO IS

COMPONENT QUEUE_ARRAY 
	PORT(	WRITE_EN,CLK:	IN	STD_LOGIC;
			DATA_IN:	IN	STD_LOGIC_VECTOR(WIDE-1 DOWNTO 0);
			DATA_OUT:	[B][COLOR="Red"]OUT[/COLOR][/B]	STD_LOGIC_VECTOR(WIDE-1 DOWNTO 0);
			ADDR:		IN	STD_LOGIC_VECTOR(2**SIZE-1 DOWNTO 0);
END COMPONENT;
 
Joined
Nov 13, 2009
Messages
8
Reaction score
0
what exactly does the 2**WIDE-1. Obviously it should turn out to be 3. What does ** do?

Thanks
 
Joined
Mar 10, 2008
Messages
348
Reaction score
0
2**1 = 2
2**2 = 4
2**3 = 8 and so on ** means power of
2**4 = 16
so 2**SIZE-1 actually 15

UPS - sorry should be (SIZE-1 DOWNTO 0) in the code
 
Last edited:
Joined
Nov 13, 2009
Messages
8
Reaction score
0
I need some help trying to figure out what is wrong with my code. I'm trying to make a continuous queue that will put data in until it is full, and then once it is full, it will overwrite the old data. I need a pointer at the start and the end of the queue. Can someone help me?

Code:
LIbrary IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

ENTITY FIFO_TEST IS
--	GENERIC(	SIZE:	INTEGER:= 16;
--				WIDE:	INTEGER:= 4
--		   );
	PORT( 
			CLK,RESET,WRITE_EN,READ_EN:		IN	STD_LOGIC;
		    DATA_IN: 						IN	STD_LOGIC_VECTOR(3 DOWNTO 0);
		    DATA_OUT: 						OUT	STD_LOGIC_VECTOR(3 DOWNTO 0);
     		ARRAY_COUNT:					OUT	STD_LOGIC_VECTOR(2 DOWNTO 0);
     		QUEUE_EMPTY,QUEUE_FULL:			OUT	STD_LOGIC;
			WRAP:							BUFFER	STD_LOGIC
	    );
END FIFO_TEST;

ARCHITECTURE BEHAVIOR OF FIFO_TEST IS

COMPONENT QUEUE_ARRAY 
	PORT(	WRITE_EN,CLK:	IN	STD_LOGIC;
			DATA_IN:	IN	STD_LOGIC_VECTOR(3 DOWNTO 0);
			DATA_OUT:	OUT	STD_LOGIC_VECTOR(3 DOWNTO 0);
			ADDR:		IN	STD_LOGIC_VECTOR(2 DOWNTO 0)
		);
END COMPONENT;

SIGNAL START_POINTER:	STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL END_POINTER:		STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL COUNTER:			STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL WRITE_ENABLE_S:	STD_LOGIC;
SIGNAL ADDR_S:			STD_LOGIC_VECTOR(2 DOWNTO 0);
--SIGNAL WRAP:			STD_LOGIC;
SIGNAL QUEUE_FULL_S:	STD_LOGIC;
SIGNAL QUEUE_EMPTY_S:	STD_LOGIC;

BEGIN

    FifoRam : QUEUE_ARRAY
		PORT MAP(
					WRITE_EN    =>  WRITE_ENABLE_S,
					CLK         =>  CLK,
                    DATA_IN     =>  DATA_IN,
                    DATA_OUT    =>  DATA_OUT,
					ADDR        =>  START_POINTER
				);
	
	PROCESS(CLK,RESET)
	BEGIN
		IF (RESET = '1') THEN
			START_POINTER <= (OTHERS=>'0');
			END_POINTER <= (OTHERS=>'0');
			COUNTER  <= (OTHERS=>'0');
		ELSIF(RISING_EDGE(CLK)) THEN
			IF(WRITE_EN = '1' AND WRAP = '0' AND READ_EN = '0') THEN				
				IF(COUNTER = "11111111") THEN
					START_POINTER <= (OTHERS => '0');
					END_POINTER <= END_POINTER + 1;
					WRAP <= '1';
				ELSE
					START_POINTER <= START_POINTER + 1;
					COUNTER <= COUNTER + 1;
				END IF;
			END IF;
			
			IF(WRITE_EN = '1' AND WRAP ='1' AND READ_EN ='0') THEN
				IF(END_POINTER = "11111111") THEN
					END_POINTER <= (OTHERS => '0');	
				ELSIF(START_POINTER = "11111111") THEN
					START_POINTER <= (OTHERS =>'0');
				ELSE
					START_POINTER <= START_POINTER + 1;
					END_POINTER <= END_POINTER + 1;
				END IF;				
			END IF;

			IF(READ_EN = '1' AND WRITE_EN ='0') THEN	
				IF(START_POINTER = END_POINTER) THEN
					QUEUE_EMPTY_S <= '1';
				ELSE
					START_POINTER <= START_POINTER - 1;
					COUNTER <= COUNTER - 1;
				END IF;
				
				IF(COUNTER = 0) THEN
					QUEUE_EMPTY_S <= '1';
				ELSE
					QUEUE_EMPTY_S <= '0';
				END IF;
			END IF;				
		END IF;
	END PROCESS;
-----------------------------------------------------------
--  Combinatorial Logic
-----------------------------------------------------------
	ARRAY_COUNT <= COUNTER;
	
	WRAP <= '1' WHEN (COUNTER = "11111111") ELSE '0';

	QUEUE_FULL <= '1' WHEN  (COUNTER = "11111111") ELSE '0';
	QUEUE_EMPTY <= QUEUE_EMPTY_S;

	WRITE_ENABLE_S <= '1' WHEN (WRITE_EN = '1') ELSE '0';
	
	

------------------------------------------------------------
END BEHAVIOR;


Code:
Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;


ENTITY QUEUE_ARRAY IS
	GENERIC(	LEN:	INTEGER:= 16;
				WIDE:	INTEGER:= 4
		   );
			
	PORT(	WRITE_EN,CLK:	IN	STD_LOGIC;
			DATA_IN:		IN	STD_LOGIC_VECTOR(3 DOWNTO 0);
			DATA_OUT:		OUT	STD_LOGIC_VECTOR(3 DOWNTO 0);
			ADDR:			IN	STD_LOGIC_VECTOR(2 DOWNTO 0)
		);
END QUEUE_ARRAY;

ARCHITECTURE BEHAVIOR OF QUEUE_ARRAY IS
	TYPE QUEUE_SIZE IS ARRAY(7 DOWNTO 0) OF STD_LOGIC_VECTOR(3 DOWNTO 0);
	SIGNAL QUEUE_ARRAY: QUEUE_SIZE;

BEGIN
	
PROCESS(CLK,QUEUE_ARRAY,ADDR)
BEGIN
	IF(RISING_EDGE(CLK)) THEN
		IF(WRITE_EN = '1') THEN
			QUEUE_ARRAY(CONV_INTEGER(ADDR)) <= DATA_IN;
		END IF;
	END IF;

DATA_OUT <= QUEUE_ARRAY(CONV_INTEGER(ADDR));

END PROCESS;

END BEHAVIOR;
 
Last edited:
Joined
Mar 10, 2008
Messages
348
Reaction score
0
First must you realise - its not possible to drive the signal "WRAP" from both a process and from concurrent code.
Besides do you not need this I believe, as a VECTOR<= VECTOR+1 will wrap around automaticly.

Your code also miss a way to select among the START_POINTER and the END_POINTER. It seems that the START_POINTER connected permanently to the QUEUE_ARRAY.

My version would look like this (but OK - the RAM must be a DUAL-PORT type)

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity FIFO_TEST2 is
      generic (
            B : natural :=8; -- number of bit
            W: natural :=4 -- number of address bit
            );
      port ( clk, reset : in std_logic;
             rd, wr : in std_logic;
             w_data : in std_logic_vector ( B-1 downto 0);
             empty, full : inout std_logic;
             r_data : out std_logic_vector (B-1 downto 0));
end FIFO_TEST2;

architecture Behavioral of FIFO_TEST2 is
   type array_type is array (0 to 2**W-1) of std_logic_vector( B-1 downto 0);
   signal ringbuffer: array_type;
   signal w_index, r_index: std_logic_vector( W-1 downto 0);  --integer range 0 to 2**W-1;
   signal count:            std_logic_vector( W downto 0);
begin

   empty <= '1' when count=0    else '0';
   full  <= '1' when count=2**W else '0';
   r_data <= ringbuffer( conv_integer(r_index));
   
   process( clk)
      variable wr_edge, rd_edge: std_logic_vector( 1 downto 0) := "00";
   begin
      if rising_edge( clk) then
         if reset = '1' then
            w_index <= (others=>'0');
            r_index <= (others=>'0');
            count   <= (others=>'0');
            wr_edge := wr&wr;
            rd_edge := rd&rd;
         else
            if wr_edge="01" then 
               ringbuffer( conv_integer(w_index)) <= w_data;
               w_index <= w_index+1;
               if full='0' then
                  count   <= count+1;
               else
                  r_index <= r_index + 1; -- Remove oldest data
               end if;
            end if;
            if rd_edge="01" and empty='0' then
               r_index <= r_index+1;
               count <= count-1;
            end if;
            wr_edge := wr_edge(0) & wr;
            rd_edge := rd_edge(0) & rd;
         end if;
      end if;
   end process;
end Behavioral;
 
Joined
Nov 13, 2009
Messages
8
Reaction score
0
I updated the code probably after you looked at it initially.

But the way I was trying to write my code was, that I would have a QUEUE of a a certain size (ie 16 entries). Then I would write continuously. If I write all the way up to the 16th entry and WRITE_EN is still '1', it would go back to the first entry and start filling over the old data.

I have the START_POINTER to point to the newest entry, and END_POINTER to the last old entry. I have the WRAP signal to fulfill the condition of if START = END. So in the beginning when it starts, I just want to increment the START_POINTER until it gets to the last entry, and if it fills up that 16th entry, for START_POINTER to go back to the first entry, and then END_POINTER increments to the second entry (because that is the oldest data entry).

I hope I am explaining it correctly?

I'll look over your code tonight and see how it works. Thanks for the help
 
Joined
Nov 13, 2009
Messages
8
Reaction score
0
I'm looking at the code, what is the wr_edge and rd_edge for? especially in the reset part, with wr_edge:=wr&wr ; rd_edge:=rd&rd
 
Joined
Mar 10, 2008
Messages
348
Reaction score
0
In order to detect edges at WR and RD do I use 2-bit shiftregisters.

-----_____------
1 1 1 0 0 0 1 1 1

Wr_edge <= Wr & Wr; --means that both bits Wr_edge(1) and Wr_edge(0) will get the same value 11 or 00
Wr_edge <= Wr_edge(0) & Wr; -- Will shift Wr_edge(0) to Wr_edge(1) and put the new Wr value at Wr_edge(0).

A positive edge will then result in Wr_edge = "01"
 
Joined
Nov 13, 2009
Messages
8
Reaction score
0
what is the point of having a variable rather than just using signals declared in the architecture for RD and WR?

I have not used variables before. Does the wr_edge and rd_edge also initialize to "00" at the beginning of the process, and changes whenever it appears within the process?
 
Joined
Mar 10, 2008
Messages
348
Reaction score
0
what is the point of having a variable rather than just using signals declared in the architecture for RD and WR?
Your right - they could/should be signals instead. In some cases could variables give more readable code, but this not the case.
Just an old habbit of mine :)

Does the wr_edge and rd_edge also initialize to "00" at the beginning of the process, and changes whenever it appears within the process?

There will be no difference - but if you place the WR_edge := WR_edge(0)&Wr in front will the synthesize give you a poor result :(
They will initialize to "00" or reset to WR&WR
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top