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 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; 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 |