如需要绘制PCB,设计电路可以和我联系。sunhenu@163.com.
分类: LINUX
2012-05-22 14:48:54
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个状态就很简单了,不用多说了。