【问题标题】:FIFO implementation - VHDLFIFO 实现 - VHDL
【发布时间】:2017-07-04 09:29:56
【问题描述】:

在将 fifo 代码实例化到我的顶级模块时,我又遇到了一个困难。我想从我的串行端口(接收子系统)存储一些数据说“欢迎来到 FPGA 世界”,然后我想在按下 fpga 板上的按钮或 FIFO 已满时将其取回。我写了我的fifo代码和串行通信代码。想法是从键盘发送数据 -> 接收子系统 -> FIFO -> 发送子系统 -> 超级终端。我目前使用 8 位宽的 fifo 并说 28 深只是为了存储一些小数据。请在这方面帮助我如何实现它。我有来自接收器的字节保存在 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;      

现在刚刚添加了更正的代码,似乎可以正常工作。增加 fifo 的深度时会出现问题。当 depth>2 时,每三个字节丢失一次。 请帮忙,为什么我会丢失数据。

【问题讨论】:

  • 如果您对某些特定代码有具体问题,请提出,有人会很乐意回答。但这不是代码编写服务。
  • 嗨。我明白你的话。但是我每次都需要帮助来增加或附加接收到的字节,直到 fifo 变满。这部分让我感到困惑,我是否应该在每次保存字节时检查 fifo 深度,或者它会自行保存直到它满为止。
  • 这个问题完全看不懂。请阅读How do I ask a good question
  • 很抱歉,您编辑越来越多的代码并不能澄清您的问题。
  • 请再次检查已编辑的问题,我在这里缺少字节。请查看代码和链接。

标签: vhdl fpga fifo spartan


【解决方案1】:

fifo 的原则是先进先出。你不必管理它。

  1. 您将数据放在 fifo 的输入中
  2. 您将写使能位设置为“1”
  3. 你等待一个时钟周期
  4. 您将写使能位设置为“0”

然后数据被存储,你再做一次来存储另一个值。

当你想读取所有数据时(Fifo full / any case you want)

您将读取启用位设置为“1”,并且每个时钟周期,您都会收到一个数据。

【讨论】:

  • 如果rising_edge(ck) then if counts
  • 在此我尝试将收到的每个字节(num_received)写入fifo。我是否也应该检查 fifo full。
  • 小心,因为当counts &gt; count_max返回0后的时钟周期,它会在第一个if条件下重新进入,它会尝试写入FIFO并且计数将是递增。您应该使用启用信号来控制它。
  • 在处理先进先出时强烈推荐使用full_fifoempty_fifo(必须限制)。
  • 能否请您解释一下使用full和empty信号。我试过这样 if counts
【解决方案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;

刚刚发现错误并按照上面的方法进行了更正,效果很好。欢迎提出改进意见。

【讨论】:

  • 这不是答案。这只是一大段无法使用/不完整的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
  • 2012-04-30
  • 2012-11-30
相关资源
最近更新 更多