设计背景:
USB(Universal Serial Bus2.0,通用串行总线)是一种应用在计算机领域的新型接口技术。USB接口具有传输速度更快,支持热插拔以及连接多个设备的特点。目前已经在各类外部设备中广泛的被采用。USB接口有三种:USB1.1,USB2.0和USB3.0。理论上USB1.1的传输速度可以达到12Mbps,而USB2.0则可以达到速度480Mbps,并且可以向下兼容USB1.1。
设计原理:
本次的设计主要设计我们用用的开发板是我们至芯出的第一代开发板,其中的USB芯片C是ypress的FX2LP系列中的CY7C68013A代,详细的介绍不多说,见Cypress的官网:在这里我就简化的给大家做一个简单介绍。
FX2的设计架构如下图,内嵌480MBit/s的收发器,锁相环PLL,串行接口引擎SIE——集成了整个USB 2.0协议的物理层。为适应USB 2.0的480MBit/s的速率,FIFO端点可配置成2,3,4个缓冲区。 配置用的是“软配置”——USB固件可由USB总线下载,片上不需集成ROM。拥有四个FIFO接口,可工作在内部或外部时钟下。端点和FIFO接口的应用使外部逻辑和USB总线可高速连接。
基于FX2LP的USB开发,包括三部分:固件程序、驱动、上位机软件。
固件程序我们在kiil中写出来,然后配置到我们的芯片中,固件的开发对我们FPGA工程师来说是不用写的,是别的工程师配置好芯片我们拿来用的,其主要的配置过程如下图:先上电复位,然后初始化我们的寄存器变量,然后调用配置函数,打开中断后,判断是否接受到了我们的配置包,如果接收到了就调用TD_POLL()函数,这个是函数是不停的执行扫描我们的端点等。然后判断我们的芯片是否挂起,如果挂起就叫醒芯片,如果没有就一直调用TD_POLL函数,这样完成我们所需要的配置。
我们的项目是要把我们的FX2配置成从FIFO的模式, 配置为单片机工作时钟24M,端点2输出,字节1024,端点6输入,字节1024,信号全设置为低电平有效等。我们的模块驱动时钟我们配置成内部输出时钟,也就是让FX2给我们的设计当做时钟源,输出一个最大的配置时钟48M的时钟。
在这边说一下,我们的FX2的数据存储区叫端点,有512,1024字节两个存储大小之分。
从FIFO的说明:
当有一个与FX2芯片相连的外部逻辑只需要利用FX2做为一个USB 2.0接口而实现与主机的高速通讯,而它本身又能够提供满足Slave FIFO要求的传输时序,可以做为Slave FIFO主控制器时,即可考虑用此传输方式。
Slave FIFO传输的示意图如下:
在这种方式下,FX2内嵌的8051固件的功能只是配置Slave FIFO相关的寄存器以及控制FX2何时工作在Slave FIFO模式下。一旦8051固件将相关的寄存器配置完毕,且使自身工作在Slave FIFO模式下后,外部逻辑(如FPGA)即可按照Slave FIFO的传输时序,高速与主机进行通讯,而在通讯过程中不需要8051固件的参与。
FX2系列的有3种封装方式,我们我的开发板用的是56引脚的封装方式的电路图,其电路图如下所示:
端口介绍:
IFCLK:FX2输出的时钟,可做为通讯的同步时钟;
SLCS:FIFO的片选信号,外部逻辑控制,当SLCS输出高时,不可进行数据传输;
SLOE:FIFO输出使能,外部逻辑控制,当SLOE无效时,数据线不输出有效数据;
SLRD:FIFO读信号,外部逻辑控制,同步读时,FIFO指针在SLRD有效时的每个IFCLK的上升沿递增。
SLWR:FIFO写信号,外部逻辑控制,同步写时,在SLWR有效时的每个IFCLK的上升沿时数据被写入,FIFO指针递增
FD[15:0]:数据线;
FIFOADR[1:0]:选择四个FIFO端点的地址线,外部逻辑控制。
FLAGA,B,C端点的空满标志位
我们的开发驱动大家可以在网上找,然后根据自己系统装上合适的驱动,或者在我们的至芯论坛上搜EZ-USB,就可以看到我们老师发的帖子来讲解驱动的安装。
我们的上位机软件用的是官方的开发工具,只有如下的安装包
然后安装第一个和第二个就好了。
设计代码:
读模块:
0moduleusb_rd(pi_clk,pi_rst_n,pi_usb_flagb,pi_usb_flagc, pio_usb_data,
1 po_usb_oe_n,po_usb_rd_n,po_usb_address,po_usb_wr_n,led);
2
3 inputpi_clk;
4 inputpi_rst_n;
5 inputpi_usb_flagb; //端点2标志信号
6 inputpi_usb_flagc;//端点6标志信号
7 inout[15:0]pio_usb_data;//输入输出端口
8
9 outputregpo_usb_oe_n;//读标志信号
10 outputregpo_usb_rd_n;//写使能
11 outputregpo_usb_wr_n;//读使能
12 outputreg[1:0]po_usb_address;//端点地址选择
13 outputregled; //接收标志正确指示灯
14
15 reg[15:0]temp_data;
16 reg[9:0]count;
17 reg[2:0]state;
18
19 assignpio_usb_data =(state ==10)?1:16'hzzzz; //读数 据,可以一直释放数据总线的控制权
20
21 always@(posedgepi_clk ornegedgepi_rst_n)
22 if(!pi_rst_n)
23 begin
24 state <=0;
25 po_usb_oe_n <=1;
26 po_usb_rd_n <=1;
27 count <=0;
28 po_usb_wr_n <=1;
29 temp_data <=0;
30 end
31 else
32 case(state)
33 0 : state <=1;
34
35 1 : begin
36 po_usb_address <=2'b00;//地址指向端点2
37 state <=2;
38 end
39
40 2 : if(!pi_usb_flagb) //判断端点2已经满
41 begin
42 po_usb_rd_n <=0;
43 state <=3;
44 po_usb_oe_n <=0;
45 end
46 else
47 state <=2;
48
49 3 : begin
50 if(count <512-1) //接收1024字节的数 据
51 begin
52 count <=count +1'b1;
53 end
54 else
55 begin
56 count <=0;
57 state <=4;
58 end
59 if(count ==2)
60 begin
61 temp_data <=pio_usb_data;
62 end
63 end
64
65 4 : begin
66 po_usb_rd_n <=1;
67 po_usb_oe_n <=1;
68 state <=0;
69 end
70
71 default: state <=0;
72 endcase
73
74 always@(*)
75 if(!pi_rst_n)
76 led <=1;
77 elseif(temp_data ==16'h33ff)//判断我们接收数据是否正确
78 led <=0;
79
80endmodule
写模块:
0moduleusb_wr(pi_clk,pi_rst_n,pi_usb_flagb,pi_usb_flagc, pio_usb_data,
1 po_usb_oe_n,po_usb_wr_n,po_usb_address,po_usb_rd_n);
2
3 inputpi_clk;
4 inputpi_rst_n;
5 inputpi_usb_flagb; //端点2标志信号
6 inputpi_usb_flagc; //端点6标志信号
7 inout[15:0]pio_usb_data; //输入输出端口
8
9 outputregpo_usb_oe_n; //读标志信号
10 outputregpo_usb_wr_n; //写使能
11 outputregpo_usb_rd_n; //读使能
12 outputreg[1:0]po_usb_address; //端点地址选择
13
14 reg[15:0]temp_data;
15 reg[2:0]state;
16
17 //在状态的3,拿回数据总线控制全,给写入数据
18 assignpio_usb_data =(state ==3)?temp_data :16'hzzzz;
19
20 always@(posedgepi_clk ornegedgepi_rst_n)
21 if(!pi_rst_n)
22 begin
23 state <=0;
24 po_usb_oe_n <=1;
25 po_usb_wr_n <=1;
26 temp_data <=0;
27 po_usb_rd_n <=1;
28 end
29 else
30 case(state)
31 0 : state <=1;
32
33 1 : begin
34 po_usb_address <=2'b10;//地址指向端点6
35 state <=2;
36 end
37
38 2 : if(!pi_usb_flagc) //判断端点6已经空
39 begin
40 po_usb_wr_n <=0;
41 state <=3;
42 end
43 else
44 state <=2;
45
46 3 : if(temp_data <256-1) //发送1024 字节的数据
47 temp_data <=temp_data +1'b1;
48 else
49 begin
50 temp_data <=0;
51 state <=4;
52 end
53
54 4 : begin
55 po_usb_wr_n <=1;
56 state <=0;
57 end
58
59 default: state <=0;
60 endcase
61
62endmodule
上位机测试:
我们安装好驱动和下载的上位机软件,然后在下面的界面中,点击”LGEEPROM”按钮,下载我们写好的的.IIC固件。
然后在下面的页面中会出现先选择other endpt xfers选项
会出现我们的4个端点,然后我们选择写入的端点或者读的端点执行读写操作
写的端点是6端点,我们选择这个端点,我们的写入端点是1024个字节,我设置的是512字节,也就是写入2次就可以写满了,
如下图,和我们代码中写入数据值是一样的。
读操作也就是要读我们的端点2,我们先要给端点一个数,然后才能读我们的端点,我们写入我们图中显示的数,因为我们设计的是读出的数如果第三个数位33ff 就让我们的灯亮,值得一说的是,我们上位机显示的时候是把低位显示到了前面,高位显示到了后面,我们一个包是1024字节,后面的数自动补零,读出数据后可以看到我们的led灯亮,验证出我们的设计正确。
-
FPGA
+关注
关注
1625文章
21663浏览量
601670
发布评论请先 登录
相关推荐
评论