首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

FPGA读写2PORTRAM过程分析

FPGA读写2PORTRAM过程分析

if(!oPA0)
         begin
                                     data_wr<='h0;//写数据初始化
                                     ioRDY1_SLWRn<='b1;
                                     ioRDY0_SLRDn<='b1;
                                     oPA2_SLOEn<='b1;
                                     oPA4_FIFO0<='b1;
                                     oPA5_FIFO1<='b1;
                                     oe<='b0;
                                     FFlagA<='b0;
                                     sram_d<='h0;
                                     data_wr<='h0;         
                                     sram_a_i<='h1fff;
                                     sram_a_o<='h1fff;
                                     sram_rden<='b0;
                                     sram_wren<='b0;
                                     wr_flag<='b0;
                                     datacnt<='h1fff;
                                     STATE<=IDLE;
         End
OPA0 可以设置为中断输入,信号为电平或者下降沿,从程序看来是低电平触发。


ioRDY1_SLWRn<='b1;           pin4 output          写SLAVEFIFO 信号
ioRDY0_SLRDn<='b1;           pin5 output          读信号
oPA2_SLOEn<='b1;             pin45                输出使能信号
oPA4_FIFO0<='b1;
oPA5_FIFO1<='b1;


IDLE:
                                     begin
                                     //添加RESET状态
                                       data_wr<='h0;//写数据初始化
                                        ioRDY1_SLWRn<='b1;
                                        ioRDY0_SLRDn<='b1;         //USBFIFO 读
                                        oPA2_SLOEn<='b1;
                                        oPA4_FIFO0<='b1;
                                        oPA5_FIFO1<='b1;
//这里选择的是EP8,参考上面的图片,其实无所谓,待会还重新设置。

                                               oe<='b0;
                                               FFlagA<='b0;
                                               sram_d<='h0;
                                               data_wr<='h0;         
                                               sram_a_i<='h1fff;
                                               sram_a_o<='h1fff;
                                               sram_rden<='b0;
                                               sram_wren<='b0;
                                               wr_flag<='b0;
                                               datacnt<='h1fff;
                                               STATE<=READ_EVENT;
                                     End
进入下一个状态
READ_EVENT:                  //read from USB EP2
                                 begin
                                     wr_flag<='b1;
                                     oPA4_FIFO0<='b0;            
                                     oPA5_FIFO1<='b0;
                                     STATE<=POINT_TO_OUT_FIFO;
                                  End

POINT_TO_OUT_FIFO:        begin
                             if(ioCTL2_FLAGC)  //not empty 也就是有数据可以读取
                                    begin
                                          oPA2_SLOEn<='b0;
                                          ioRDY0_SLRDn<='b1;      
                                          STATE<=DATA_READY;
                                     end
                               else
                                    begin
                                       oPA2_SLOEn<='b1;
                                       ioRDY0_SLRDn<='b1;
                                       STATE<=POINT_TO_OUT_FIFO;
                                    end
                         end
然后进入数据准备好的状态
DATA_READY:  //write SRAM 这里指的是读取USBFIFO,然后把读到的数据写到SRAM里面
                             begin
                                  if(ioCTL2_FLAGC)  //not empty
                                          begin
                                              PA2_SLOEn<='b0;//最好也把这句加上吧
                                              ioRDY0_SLRDn<='b0;
                                              sram_a_i<=sram_a_i+1;                                    
                                              sram_d<=ioUSB_D;         
//这里是写数据到SRAM,所以SRAM地址使用了SRAM_A_I,在写之前加一,SRAM_WREN信号为1,使能写功能。        
                                              sram_wren<='b1;
                                              sram_rden<='b0;
                                              STATE<=READ;
                                          end
                                    else
                                          begin
                                              ioRDY0_SLRDn<='b1;
                                              oPA2_SLOEn<='b1;
                                              STATE<=POINT_TO_OUT_FIFO;
                                           end
                              end

READ:
           begin
              ioRDY0_SLRDn<='b1;//读结束要拉高
              sram_rden<='b0;
              sram_wren<='b0;
              //SRAM读写都没有使能
              if(sram_a_i!=ADDR_FULL)
                     STATE<=DATA_READY;
//如果SRAM的地址到了结尾处,说明写SRAM结束了,将状态转化为读取USBFIFO结束状态。这时候,可以读取SRAM了。注意这里又是读,又是写的。看清楚对象,就明白了。这上面的状态,就是大写的那个已经CASE的变量,是从FPGA对USBFIFO来说的。
                  else
                     STATE<=READ_END;
            End

READ_END:
               begin
                     ioRDY0_SLRDn<='b1;
                     oPA2_SLOEn<='b1;
                     oPA4_FIFO0<='b0;
                     oPA5_FIFO1<='b0;
                     sram_a_i<='h1fff; //2portRAM输入地址,也就是写地址为1FFF,就是结尾处。
                     STATE<=WRITE_EVENT;
                End


再说一遍,大写的状态,CASE的变量,是从FPGA对USBFIFO来说的,所以接下来是读取SRAM的内容,把这个内容写到USBFIFO上去,状态为WRITE_EVENT。同样的原理不多说了。
WRITE_EVENT:  //read sram to USB ep6
                  begin
                      oPA4_FIFO0<='b0;
                      oPA5_FIFO1<='b1;
                      oe<='b1;
                      wr_flag<='b0;
                      STATE<=POINT_TO_IN_FIFO;
                  end
POINT_TO_IN_FIFO:
                   begin
                       sram_a_o<=sram_a_o+1;  //SRAM_A_O=0000了
                       datacnt<=datacnt+1;   //这个时候DATACNT=0000了
                       sram_rden<='b1;
                       sram_wren<='b0;
                       //STATE<=WRITE_READY;
                       STATE<=WRITE_ADD;
                   End
WRITE_ADD:  
                   Begin
                         ram_rden<='b1;
                         sram_wren<='b0;   
                         sram_a_o<=sram_a_o+1;       //这个时候SRAM_A_O=0001了
                         datacnt<=datacnt+1;                //这个时候DATACNT=0001了
                         STATE<=WRITE_READY;
                   End
这个状态,就是多加了一次地址的值,有什么用,以后继续研究,现在放过。


WRITE_READY:
                   begin
                   if(ioCTL1_FLAGB) //not full
                          begin
                            if (datacnt==sram_a_o)
                                 begin
                                 data_wr<=sram_d_o;
                                 end
                             else
                                   begin
                                   fifodata[datacnt-sram_a_o]<=sram_d_o;
                                   fifodata[datacnt-sram_a_o-1]<=fifodata[datacnt-sram_a_o];
                                   data_wr<=fifodata[datacnt-sram_a_o-1];
                                   datacnt<=datacnt-1;
                                  end
                            ioRDY1_SLWRn<='b0;
                            ioRDY0_SLRDn<='b1;
                            STATE<=WRITE;
                            end
                   else
                            begin
                            //data_wr1<=sram_d_o;
                            ioRDY1_SLWRn<='b1;  ///??
                            ioRDY0_SLRDn<='b1;  ///?
                            //STATE<=WRITE_READY;  ///?
                            if (FFlagA==0)
                                     begin
                                         datacnt<=datacnt+1;
                                               fifodata[datacnt-sram_a_o]<=sram_d_o;
                                               FFlagA<=FFlagA+1;
                                     end
                                     else fifodata[datacnt-sram_a_o]<=sram_d_o;
                            STATE<=WRITE_READY;
                            end
                   end



关于那个FLAGA,FLAGB,FLAGC,代表PL,EMPTY,FULL标志。



从寄存器配置中可以看出FLAGB 代表EP6的FULL标志,FLAGC代表EP2的EMPTY标志,而且都是低电平有效,就是说如果FLAGB输出低电平,代表EP6FIFO是FULL的。默认的话EP2是OUT,EP6是IN.


从WRITE READY 到WRITE这状态跳转很繁琐,我具体说一下,
首先,我们的程序是经过读USBFIFO,然后写SRAM,现在执行到这里。
FLAGB=1,EP6FIFO不满,执行
if (datacnt==sram_a_o)
         begin
          data_wr<=sram_d_o;
         end
ioRDY1_SLWRn<='b0;
ioRDY0_SLRDn<='b1;
STATE<=WRITE;
状态跳转到WRITE,执行下面语句,
ioRDY1_SLWRn<='b1;
ioRDY0_SLRDn<='b1;
if(sram_a_o!=ADDR_FULL+1)  //SRAM_A_0===?1000
         begin
                   sram_a_o<=sram_a_o+1;
                   datacnt<=datacnt+1;
                   sram_wren<='b0;                                //将数据写到FIFO中
                   sram_rden<='b1;
                   STATE<=WRITE_READY;
         End
然后再跳转到WRITE_READY,直到我们将EP6FIFO填满,现在的数据是什么不重要,只是为了填满FIFO,使得FLAGB为低电平。大约写256次,因为数据是16位,FIFO大小是512字节。现在执行下面函数
if (FFlagA==0)
         begin
                   datacnt<=datacnt+1;
                   fifodata[datacnt-sram_a_o]<=sram_d_o;
                   FFlagA<=FFlagA+1;
         end
                  else
                            fifodata[datacnt-sram_a_o]<=sram_d_o;
                            STATE<=WRITE_READY;
注意这里把DATACUT加一,但是没有将SRAM_A_O加一,也就是它们不再相等了。执行结束,重新跳转到WRITE_READY,执行下面的语句,else后面的语句,黄色覆盖的部分。
if (datacnt==sram_a_o)
         begin
                   data_wr<=sram_d_o;
         end
         else
           begin
                  fifodata[datacnt-sram_a_o]<=sram_d_o;
                  fifodata[datacnt-sram_a_o-1]<=fifodata[datacnt-sram_a_o];
                  data_wr<=fifodata[datacnt-sram_a_o-1];
                  atacnt<=datacnt-1;
           end
ioRDY1_SLWRn<='b0;
ioRDY0_SLRDn<='b1;
STATE<=WRITE;
End
然后再跳转到WRITE状态,然后DATACNT和SRAM_A_O又相等了,然后重复上面提到的过程。直到SRAM_A_O=0X1000,然后写FIFO的流程才结束。
真是麻烦的,我都看得眼花了,估计还有分析不对的地方,以后再慢慢修改吧。
WRITE:
                   begin
                            ioRDY1_SLWRn<='b1;
                            ioRDY0_SLRDn<='b1;
                            if(sram_a_o!=ADDR_FULL+1)  //SRAM_A_0===?1FFF
                                     begin
                                     sram_a_o<=sram_a_o+1;
                                     datacnt<=datacnt+1;
                                     sram_wren<='b0;
                                     sram_rden<='b1;
                                     STATE<=WRITE_READY;
                                     end
                            else
                                     begin                          
                                     sram_wren<='b0;
                                     sram_rden<='b0;
                                     STATE<=WRITE_END;
                                     end
                   end


WRITE_END:
                   begin

                   wr_flag='b0;
                   ioRDY1_SLWRn<='b1;
                   ioRDY0_SLRDn<='b1;               
                   sram_a_o<='h1fff;
                   datacnt<='h1fff;
                   sram_wren<='b0;
                   sram_rden<='b0;
                   oPA4_FIFO0<='b1;
                   oPA5_FIFO1<='b1;
                   STATE<=IDLE;
                   end
         default:
                   STATE<=IDLE;
         Endcase

这2个状态就很简单了,不用多说了。
文章来自 sunhenu.blog.chinaunix.net
记录学习中的点点滴滴,让每一天过的更加有意义!
返回列表