首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | 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;         EndOPA0 可以设置为中断输入,信号为电平或者下降沿,从程序看来是低电平触发。 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                              endREAD:           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;                  endPOINT_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;                   EndWRITE_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;         endioRDY1_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;           endioRDY1_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
记录学习中的点点滴滴,让每一天过的更加有意义!
返回列表