Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] fifo implementation using a counter

Status
Not open for further replies.
1.Why is the full and the empty high initially?
2.Why are you getting dataout as 0 for first 2 reads?
 

The timing of the signals is all wrong due to using the wrong clock wr_clk to generate both the wr_en1 and the rd_en1. In fact it appears the only signals related to the rd_clk are the dataout, empty, almost_empty, and rd_data_count signals. As rd_en1 isn't related to the rd_clk, any ratio of wr_clk/rd_clk NOT exactly double are unlikely to work correctly. This also means that your flags will likely not work correctly for anything other than the 2:1 ratio nor will this work in hardware if the clocks come from a PLL (as it's unlikely you would realize that you have to phase shift the rd_clk by 90 degrees).

Try running a rd_clk that is 30% of the wr_clk: i.e. wr_clk_period = 1000ps and rd_clk_period=3333ps. You'll find your code won't work correctly.

You should show your latest code.

- - - Updated - - -

1.Why is the full and the empty high initially?

Xilinx FIFO IP generates a high on both full empty after reset or startup. Once that is over the current flag state shows up.
 
i think for the first 2 reads, dataout is 0 is bcz of delay since we are reading the 5 writes at a same time,, actually i dont have original simulation i just simulated it on my own,it still wasnt approved by my sir completly , its embarassing but i cnt do anything:-?.

k my new code @ads-ee.



Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_arith.ALL;
use IEEE.STD_LOGIC_misc.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;

entity fifo_5r is
	port(	reset: in std_logic;
			wr_clk: in std_logic;
			rd_clk: in std_logic;
			wr_en1: out std_logic;
			rd_en1: out std_logic;
			din: out std_logic_vector(31 downto 0);
			dataout: out std_logic_vector(127 downto 0);
			full: out std_logic;
			almost_full: out std_logic;
			empty: out std_logic;
			almost_empty: out std_logic;
			rd_data_count: out std_logic_vector(8 downto 0);
			wr_data_count: out std_logic_vector(10 downto 0);
			prog_full: out std_logic;
			prog_empty: out std_logic
			  );
end fifo_5r;

architecture Behavioral of fifo_5r is

signal dout: std_logic_vector(127 downto 0);
signal count : std_logic_vector(31 downto 0 );
signal wr_en : std_logic;
signal rd_en : std_logic;

type state_type is (rst1,write1,write2,write3,write4,write5,read1);
signal state : state_type;

component fifo_generator_v6_2
	port (
	rst: in std_logic;
	wr_clk: in std_logic;
	rd_clk: in std_logic;
	din: in std_logic_vector(31 downto 0);
	wr_en: in std_logic;
	rd_en: in std_logic;
	dout: out std_logic_vector(127 downto 0);
	full: out std_logic;
	almost_full: out std_logic;
	empty: out std_logic;
	almost_empty: out std_logic;
	rd_data_count: out std_logic_vector(8 downto 0);
	wr_data_count: out std_logic_vector(10 downto 0);
	prog_full: out std_logic;
	prog_empty: out std_logic);
end component;


begin
wr_en1<=wr_en;
rd_en1<=rd_en;
din<=count;


process(wr_clk,reset)
  begin
   if(wr_clk'event and wr_clk='1') then
      if(reset ='1') then
		count <= (others=>'0');
      elsif(wr_en= '1') then
		count<= count + 1;
		end if;
     end if;
	 end process;

process(wr_clk)
begin
if(wr_clk'event and wr_clk='1') then
   if (reset='1') then
	 wr_en<= '0';
	 rd_en<='0';
     state<= write1;
	  else
	     case (state) is 
    
   	            when rst1=>
						          state<=write1;
      				when write1=>
					              wr_en<='1';
                             rd_en<='0';                             
                            state<=write2;
					   when write2=>
					              wr_en<='1';
                             rd_en<='0';                             
                            state<=write3;
						when write3=>
					              wr_en<='1';
                             rd_en<='0';                             
                            state<=write4;
                   when write4=>
					              wr_en<='1';
                             rd_en<='0';                             
                            state<=write5;
                   when write5=>
					              wr_en<='1';
                             rd_en<='0';                             
                            state<=read1;
						when read1=>
					              wr_en<='0';
                             rd_en<='1';                             
                            state<=write1;			 
					 when others=> 
					            state <= rst1;
									
	     end case;
	  end if;
end if;	
end process;


U0 : fifo_generator_v6_2
		port map (
			rst => reset,
			wr_clk => wr_clk,
			rd_clk => rd_clk,
			din => count,
			wr_en => wr_en,
			rd_en => rd_en,
			dout => dataout,
			full => full,
			almost_full => almost_full,
			empty => empty,
			almost_empty => almost_empty,
			rd_data_count => rd_data_count,
			wr_data_count => wr_data_count,
			prog_full => prog_full,
			prog_empty => prog_empty
			);
 end Behavioral;

Capture3.PNG
 

You have repeated your mistakes.
1.Don't generate wr_en and rd_en in the same process block. rd_en should be generated on rd_clk and not on wr_clk. Have a different process block for that.
2.What about the reset in the sensitivity block of the process generating wr_en?
Please recode and resimulate it..
 

i think for the first 2 reads, dataout is 0 is bcz of delay since we are reading the 5 writes at a same time,, actually i dont have original simulation i just simulated it on my own,it still wasnt approved by my sir completly , its embarassing but i cnt do anything:-?.

You don't seem to understand multiple clock domains, so why are you using an asynchronous FIFO?

Each port of the FIFO uses a different clock, all signals interfacing with that port should use the same clock that is used on that port. One port is the read port (dout, re, empty, rd_count, rd_clk, etc), the other port is the write port (din, we, full, wr_count, wr_clk, etc).

Now write something that has those clock domains separate from each other (i.e. in different processes).
 

i wrote using 2 clock processes.



Code:
process(wr_clk)
begin
if(wr_clk'event and wr_clk='1') then
   if (reset='1') then
	 wr_en<= '0';
	 rd_en<='0';
     else
	     state<= write1;
		  case (state) is 

       	            when rst1=>
			    state<=write1;
               	    
                    when write1=>
			    wr_en<='1';
                            rd_en<='0';                             
                            state<=write2;

		    when write2=>
			    wr_en<='1';
                            rd_en<='0';                             
                            state<=write3;

		    when write3=>
			    wr_en<='1';
                            rd_en<='0';                             
                            state<=write4;

                    when write4=>
			    wr_en<='1';
                            rd_en<='0';                             
                            state<=write5;

                    when write5=>
			    wr_en<='1';
                            rd_en<='0';                             
                            state<=read1;
									 
		    when others=> 
			    state <= rst1;
									
	     end case;
	  end if;
     end if;	
end process;


process(rd_clk)
begin
if(rd_clk'event and rd_clk='1') then
   if (reset='1') then
	 wr_en<= '0';
	 rd_en<='0';
      else
	      state2<= read1;
	  case (state2) is 

     	            when rst1=>
			          state2<=read1;
      		    when read1=>
		                  wr_en<='0';
                                  rd_en<='1';                             
                                  state2<=write1;
		    when others=> 
				  state2 <= rst1;
								
	     end case;
	end if;
    end if;	
end process;
 

! sir it is said that to not to "generate wr_en and rd_en in the same process block. rd_en should be generated on rd_clk and not on wr_clk. Have a different process block for that." ???? so i did like that .
 

A signal can be generated ONLY in 1 block. wr_en using wr_clk and rd_en using rd_clk and in different process blocks.
You have not added reset to the sensitivity list either.
 

! sir it is said that to not to "generate wr_en and rd_en in the same process block. rd_en should be generated on rd_clk and not on wr_clk. Have a different process block for that." ???? so i did like that .

Code:
process(wr_clk)
begin
if(wr_clk'event and wr_clk='1') then
   if (reset='1') then
	 [COLOR="#00FF00"]wr_en<= '0';[/COLOR]
	 [COLOR="#FF0000"]rd_en<='0';[/COLOR]
     else
	     state<= write1;
		  case (state) is

No you did not separate the rd_en from the process block that is clocked by wr_clk.

You are also not resetting state and state2 signal in both processes. You also assign state2 with a state value for the write process state2<=write1;

You should double check you code BEFORE you post it. Makes me think you don't care enough about this (which makes me wonder why I should care about helping you fix it).

- - - Updated - - -

A signal can be generated ONLY in 1 block. wr_en using wr_clk and rd_en using rd_clk and in different process blocks.
You have not added reset to the sensitivity list either.

No reset doesn't need to be added to the sensitivity list, it is a synchronous reset by it's description, the reset is inside the clock'event if.
 
Last edited:




Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_arith.ALL;
use IEEE.STD_LOGIC_misc.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;

entity fifo_5r is
	port(	reset: in std_logic;
			wr_clk: in std_logic;
			rd_clk: in std_logic;
			wr_en1: out std_logic;
			rd_en1: out std_logic;
			din: out std_logic_vector(31 downto 0);
			dataout: out std_logic_vector(127 downto 0);
			full: out std_logic;
			almost_full: out std_logic;
			empty: out std_logic;
			almost_empty: out std_logic;
			rd_data_count: out std_logic_vector(8 downto 0);
			wr_data_count: out std_logic_vector(10 downto 0);
			prog_full: out std_logic;
			prog_empty: out std_logic
			  );
end fifo_5r;

architecture Behavioral of fifo_5r is

signal dout: std_logic_vector(127 downto 0);
signal count : std_logic_vector(31 downto 0 );
signal wr_en : std_logic;
signal rd_en : std_logic;

type state_type is (rst1,write1,write2,write3,write4,write5,read1);
signal state,state2 : state_type;

component fifo_generator_v6_2
	port (
	rst: in std_logic;
	wr_clk: in std_logic;
	rd_clk: in std_logic;
	din: in std_logic_vector(31 downto 0);
	wr_en: in std_logic;
	rd_en: in std_logic;
	dout: out std_logic_vector(127 downto 0);
	full: out std_logic;
	almost_full: out std_logic;
	empty: out std_logic;
	almost_empty: out std_logic;
	rd_data_count: out std_logic_vector(8 downto 0);
	wr_data_count: out std_logic_vector(10 downto 0);
	prog_full: out std_logic;
	prog_empty: out std_logic);
end component;


begin
wr_en1<=wr_en;
rd_en1<=rd_en;
din<=count;


process(wr_clk)
  begin
   if(wr_clk'event and wr_clk='1') then
      if(reset ='1') then
		count <= (others=>'0');
                elsif(wr_en= '1') then
		count<= count + 1;
	end if;
     end if;
	 end process;

process(wr_clk)
begin
if(wr_clk'event and wr_clk='1') then
   if (reset='1') then
	 wr_en<= '0';
	 else
	     state<= write1;
		  case (state) is 
    
   	            when rst1=>
					state<=write1;
      		    when write1=>
		            wr_en<='1';
                            state<=write2;
		   when write2=>
		            wr_en<='1';
                            state<=write3;
		    when write3=>
		            wr_en<='1';
                            state<=write4;
                    when write4=>
		           wr_en<='1';
                            state<=read1;
                   
		    when others=> 
		           state <= rst1;
	      end case;
	    end if;
  end if;	
end process;


process(rd_clk)
begin
if(rd_clk'event and rd_clk='1') then
   if (reset='1') then
	  rd_en<='0';
      else
	      state2<= read1;
			case (state2) is 
     	            when rst1=>
		                 state2<=read1;
      		    when read1=>
	                          rd_en<='1';                             
                                  state2<=write1;
		    when others=> 
			           state2 <= rst1;
									
	     end case;
	  end if;
  end if;	
end process;			 
									 

U0 : fifo_generator_v6_2
		port map (
			rst => reset,
			wr_clk => wr_clk,
			rd_clk => rd_clk,
			din => count,
			wr_en => wr_en,
			rd_en => rd_en,
			dout => dataout,
			full => full,
			almost_full => almost_full,
			empty => empty,
			almost_empty => almost_empty,
			rd_data_count => rd_data_count,
			wr_data_count => wr_data_count,
			prog_full => prog_full,
			prog_empty => prog_empty
			);
 end Behavioral;
Capture3.PNG
 

This is some progress. Some more flaws:
1.You are not setting the values of state & state2 under reset.
2.The case statement should be present directly after the else statement. Remove the state <= write1 and state2 <= read1 statements which come after the else statements.
 
k i removed those case statements ,


Code:
process(wr_clk)
begin
if(wr_clk'event and wr_clk='1') then
   if (reset='1') then
	 wr_en<= '0';
	 state<=write1;
	     else
	   	  case (state) is 
     	                    when rst1=>
				        state<=write1;
      		            when write1=>
		                       wr_en<='1';
                                       state<=write2;
		            when write2=>
		                      wr_en<='1';
                                       state<=write3;
		            when write3=>
		                      wr_en<='1';
                                      state<=write4;
                            when write4=>
		                      wr_en<='1';
                                      state<=read1;			 
                            when others=> 
			              state <= rst1;
		 end case;
	    end if;
  end if;	
end process;


process(rd_clk)
begin
if(rd_clk'event and rd_clk='1') then
   if (reset='1') then
	  rd_en<='0';
	  state2<=read1;
      else
	     	case (state2) is 
     	               when rst1=>
			          state2<=read1;
         		when read1=>
	                          rd_en<='1';                             
                                  state2<=write1;
			when others=> 
		                  state2 <= rst1;
		end case;
	  end if;
  end if;	
end process;
 

Under reset assign the states to rst1 state as there are no writes or reads happening under reset.
 

process(wr_clk)
begin
if(wr_clk'event and wr_clk='1') then
if (reset='1') then
wr_en<= '0';
state<=write1;
else
case (state) is
when rst1=>
wr_en<='0';
state<=write1;
when write1=>
wr_en<='1';
state<=write2;
when write2=>
wr_en<='1';
state<=write3;
when write3=>
wr_en<='1';
state<=write4;
when write4=>
wr_en<='1';
state<=write5;
when write5=>
wr_en<='1';
state<=read1;
when others=>
state <= rst1;
end case;
end if;
end if;
end process;


process(rd_clk)
begin
if(rd_clk'event and rd_clk='1') then
if (reset='1') then
rd_en<='0';
state2<=read1;
else
case (state2) is
when rst1=>
rd_en<='0';
state2<=read1;
when read1=>
rd_en<='1';
state2<=write1;
when others=>
state2 <= rst1;
end case;
end if;
end if;
end process;

- - - Updated - - -




Code:
process(wr_clk)
begin
if(wr_clk'event and wr_clk='1') then
   if (reset='1') then
	 wr_en<= '0';
          state<=write1;
	    else
	   	  case (state) is 
     	            when rst1=>
		      	             wr_en<='0';
				     state<=write1;
      		 when write1=>
		                      wr_en<='1';
                                      state<=write2;
                  when write2=>
		                      wr_en<='1';
                                      state<=write3;
                  when write3=>
		                      wr_en<='1';
                                      state<=write4;
                  when write4=>
		                      wr_en<='1';
                                      state<=write5;
                  when write5=>
		                      wr_en<='1';
                                      state<=read1;									 
                  when others=> 
				      state <= rst1;
		end case;
	    end if;
  end if;	
end process;


process(rd_clk)
begin
if(rd_clk'event and rd_clk='1') then
   if (reset='1') then
	  rd_en<='0';
          state<=read1;
	   else
	     	case (state2) is 
     	            when rst1=>
				rd_en<='0';
				state2<=read1;
      		    when read1=>
	                        rd_en<='1';                             
                                state2<=write1;
		    when others=> 
				state2 <= rst1;
		end case;
	  end if;
  end if;	
end process;

- - - Updated - - -

@sharath: counting is starting from 2 onwards ??
 

I've been debating whether or not I should post to this thread again. I get the feeling you are not trying to work any of this out yourself. You keep posting code with only the specific changes mentioned by each poster to this thread. I've made some suggestions, some of which were ignored or perhaps not understood. Is it your intent to have forum members fix this code work for you?

Now that you're going to ignore the rest of my post ;-)
Your original problem statement was:
sandy3129 said:
hai every one , my question is , normally in a fifo we write into the fifo and then read it from the fifo in the next cycle, so datacount will be '1', but what if i want to write 5 data serially and then read it from fifo , i want dataout to be read as 5 bunches at a time . here is my code
1. You were told to use a width changing FIFO (32 -> 5*32) in posts #2 & #4 (which was wrong, I'll get back to that).
2. You posted code without a width changing FIFO in post #15, but with asynchronous read and write clocks.
3. Finally in post #23 you show us code with a width changing FIFO but the widths are now 32 -> 128, which is 32 -> 4*32. I thought the original requirement was reading 5 words not 4 words? This is also the reason why #2 & #4 were the wrong advice. You can't build a width changing FIFO that has non-binary width changes i.e. 1-to-2, 1-to-4, 1-to-8 will work, but you can't make a 1-to-3, 1-to-5, 1-to-6 etc. You can emulate a 1-to-5 as long as you can correctly map the address/data on the write side to the correct locations on the read side, but then you can't use a FIFO if you do this.
4. You've continually mixed signals between the read and write side of the FSMs. Currently you have the following code:
Code:
    when write5=>
        wr_en<='1';
        state<=read1;
what state is read1 in the state FSM? read1 is a state in the state2 FSM. That is going to end up producing incorrect results. You are also using write1 from the write FSM in the read FSM. This is also incorrect.

You were also told to assign the rst1 state to both FSMs at reset='1'. Besides not doing that, you've also used the same state name for both FSMs, probably not the best idea to do stuff like this. Now you are relying on the simulator/synthesis to recognize they aren't the same. Do you know how to write a proper FSM? I suspect you need to study this some more.

You changed your clocks to be identical for the simulation in post #32, why? I thought you used an asynchronous FIFO expressly for the purpose of writing faster than the reading of the FIFO. As you want to write 5 words and read out the entire 5*32 bits of data all at once. As your current code stands you aren't reading 5 words at a time.
Code:
FIFO writing:
w1, w2, w3, w4, w5, w6, w7, w8, w9, w10

FIFO reading from your 32-to-128 FIFO
w1,w2,w3,w4 = first word read
w5,w6,w7,w8 = second word read
w9,w10....   = third word read

according to what you are trying to do you want to read:
w1,w2,w3,w4,w5  = first word read (5 write words)
w6,w7,w8,w9,w10 = second word read (5 more write words)
Your current implementation doesn't do this, look at your simulation results, which are garbled because of the previously mentioned errors.

You have what I see are three options:
1. Use the holding registers like FvM mentioned in post #4, along with a 160-bit wide FIFO.
2. Use 5 32-bit wide FIFOs and write to the FIFOs sequentially. e.g. First word goes into FIFO0, 2nd word into FIFO1, ..., 6th word into FIFO0 again.
3. Use a dual port memory and map the write side and the read side. This will likely require storing some of the input data to reformat the bit positions.

Of these options 1 is the easiest to implement, and 2 could be done quite efficiently in distributed RAM if the required FIFO depth is small <32 entries, 3 I wouldn't recommend as you are struggling with writing a simple FSM design.

I'm almost attempted to just write you an example design of a 1x-to-3x width changing FIFO design and let you infer from my example how to implement it as a 1x-to-5x FIFO design. I'll think about this...I'm not sure if this would be a good or bad idea.

Given the state of this thread (39 posts and still not resolved), I think you either don't have the necessary background knowledge to accomplish this design, or you just don't have the aptitude in engineering to be successful. If it's the former you can learn the necessary background by studying. If it's the later, you probably should rethink why you are tying to study a field that is basically foreign to your thought processes.

Regards
 
Last edited:
  • Like
Reactions: FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top