-->

FIFO implementation - VHDL

2019-09-27 10:32发布

问题:

I come across one more difficulty while instantiate the fifo code to my top module. I want to store some set of data say "WELCOME TO THE WORLD OF FPGA" from my serial port ( receiving subsystem) then i want to retrieve it back say when button on fpga board is pressed or FIFO is full. I have my fifo code and serial communication code written. Idea is data sent from keyboard ->receiving subsystem -> FIFO -> transmitting subsystem -> hyperterminal. I am at present using fifo of 8 bit wide and say 28 deep just to store some small data. Please help me in this regard how can I implement it.I have byte coming from receiver saved in register_save. fifo code

inst_bit8_recieve_unit : entity work.byte_recieve_8N1  
port map ( ck => ck,
         reset => reset, 
         new_byte_in_buffer => new_byte_in_buffer,
         byte_read_from_buffer => byte_read_from_buffer,
         recieve_buffer => register_save,
         JA_2 => JA(2));

---------------------FIFO instantiate-------------------------------
inst_of_fifo_Recieve_unit : entity work.fifo
generic map (B => data_bits, W => fifo_width)
port map ( ck => ck,
            reset => reset, 
            rd => rd_rx, 
            wr => wr_rx,
            write_data => num_recieved,
            read_data => num_recieved_fifo,
            empty => empty_rx,
            full => full_rx );

inst_bit8_transmit_unit : entity work.byte_transmit_8N1  
port map ( ck => ck,
           reset => reset, 
           send_byte_ready => send_byte_ready,
           send_byte_done => send_byte_done , 
           send_buffer => num_send, 
           JAOUT_0 => JAOUT );
proc_send5byte: process(ck, reset, state_byte5, send_byte_done, num_send, state_button_0, num_recieved_fifo, rd_rx) 

begin

if reset = '1' THEN
            state_byte5 <= idle;
            send_byte_ready <='0';
            num_send <= "00000000" ;

  else
  if rising_edge(ck) then

    case state_byte5 is 

         when idle =>          ---- in this, if btn(0) is high i.e pressed then only state_byte5 will go to next state
                if state_button_0 = transit_pressed then
                     state_byte5 <= byte;
                     end if; 
            -----===============================================================      
            when byte =>
                    if (not empty_rx = '1') then

                           if send_byte_ready ='0' and send_byte_done = '0'  then    ----here if condition is satified the send_byte_ready will be set
                                    send_byte_ready <='1';  --------- shows next byte is ready 
                                    num_send <= num_recieved_fifo;
                                     rd_rx <='1';

                         end if;
                            end if; 

                       if send_byte_ready = '1' and send_byte_done = '1'  then  --- during load state send_byte will be resets 
                         send_byte_ready <='0';  
                         rd_rx <= '0';                               
                              state_byte5  <= idle;         ----------- go back to idle
                       end if;
                --end if;  
            ---===============================================================

         when others =>
                        state_byte5 <= idle;     ------------- for other cases state state _byte5 will be in idle
                        send_byte_ready <= '0';
                            rd_rx <= '0';   
       end case;

   end if;
end if; 
end process;
proc_recieving_byte : process (ck, reset, register_save, new_byte_in_buffer, full_rx, num_recieved, wr_rx)
begin

if reset = '1' then
  byte_read_from_buffer <= '0';
  else

      if rising_edge(ck) then
                     if full_rx = '0' then     
                         if new_byte_in_buffer = '1' and byte_read_from_buffer = '0' then
                              byte_read_from_buffer <= '1'; 
                       wr_rx <= '1';                      
                             num_recieved(7 downto 0 ) <= register_save( 7 downto 0);   

                    end if;   
                        end if; 
                            if new_byte_in_buffer = '0' then
                               byte_read_from_buffer <= '0';
                                wr_rx <= '0';
                       end if;                      
                   --end if;
     end if;
end if;
end process;      

Just added the corrected code now which seems to be working. Problem araises when increase the depth of fifo. When depth>2 then every third byte is missing. Please help, why I am loosing data.

回答1:

The principe of a fifo is First In First Out. You have not to manage it.

  1. You place your data on input of fifo
  2. You set write enable bit to '1'
  3. You wait for one clock cycle
  4. You set write enable bit to '0'

then the data is store, you do it again to store another value.

When you want to read all data (Fifo full / any case you want)

You set Read enable bit to '1' and every clock cycle, you will receive a data.



回答2:

--- process for recieving bytes and sent to fifo input with write enable signal------------ 

proc_recieving_byte : process (ck, reset, register_save, new_byte_in_buffer, full_rx, num_recieved, wr_rx)
begin

if reset = '1' then
  byte_read_from_buffer <= '0';
  else

   if rising_edge(ck) then
           if full_rx = '0' then     
               if new_byte_in_buffer = '1' and byte_read_from_buffer = '0' then
                  byte_read_from_buffer <= '1'; 
                 wr_rx <= '1';                      
                     num_recieved(7 downto 0 ) <= register_save( 7 downto 0);   
               else
                      wr_rx <= '0';
             end if;      
            end if; 
            if new_byte_in_buffer = '0' then
               byte_read_from_buffer <= '0';
                wr_rx <= '0';
           end if;                      
   end if;
end if;
end process;      
------------------------------------------------------------------------------------------------------------------- 


---- this process checks first button state and then  transmission occurs from fifo untill empty------

proc_send5byte: process(ck, reset, state_byte5, send_byte_done, num_send, state_button_0, num_recieved_fifo, rd_rx) 

begin

if reset = '1' THEN
            state_byte5 <= idle;
            send_byte_ready <='0';
            num_send <= "00000000" ;

  else
  if rising_edge(ck) then
    case state_byte5 is 
         when idle =>          ---- in this, if btn(0) is high i.e pressed then only state_byte5 will go to next state
                if state_button_0 = transit_pressed then
                     state_byte5 <= byte;
                     end if; 
            -----===============================================================      
            when byte =>
               if (not empty_rx = '1') then
                        if send_byte_ready ='0' and send_byte_done = '0'  then    ----here if condition is satified the send_byte_ready will be set
                             send_byte_ready <='1';  --------- shows next byte is ready 
                            num_send <= num_recieved_fifo;
                             rd_rx <='1';
                   else 
                         rd_rx <='0';
                   end if;
                    end if; 

                if send_byte_ready = '1' and send_byte_done = '1'  then  --- during load state send_byte will be resets 
                  send_byte_ready <='0';  
                  rd_rx <= '0';                              
                       state_byte5  <= idle;         ----------- go back to idle
                   end if;
            ---===============================================================

       when others =>
                  state_byte5 <= idle;    
                  send_byte_ready <= '0';
                    rd_rx <= '0';   
    end case;

  end if;
end if; 

end process;

Just found the error and corrected as above which works very well. Comments to improve are welcome.