上一节实现了USB2.0 基于FPGA的同步写递增数据的操作,本节即实现简单的USB读取数据,所读取的数据使用黑金AX516开发板配套的EZ—USB。如果使用其他的上位机可能会导致电脑识别不了AX516的USB端口。首先明确一点我们在上一节所讲到的,我们的固件库烧进去的模式是工作在SLAVE FIFO的同步模式下,根据数据手册上面所提到的框图如下图所示:
根据上图可以看到我们设置为SLAVEFIFO模式后,所用到的端口以及端口的方向即如下图:
端口解释:
IFCLK:FX2输出的时钟,可作为通信的同步时钟。
FLAGA、FLAGB、FLAGC、FLAGD:FX2输出的FIFO状态信息,如满、空等。
SLCS:FIFO的片选信号,外部逻辑控制,当SLCS输出高时,不可进行数据传输。
SLOE:FIFO输出使能,外部逻辑控制,当SLOE无效时,数据线不输出有效数据。
SLRD:FIFO读信号,外部逻辑控制,同步读时,FIFO指针在SLRD有效时的每个IFCLK的上升沿递增,异步读时,FIFO读指针在SLRD的每个有效至无效的跳变沿时递增。
SLWR:FIFO写信号,外部逻辑控制,同步写时,在SLWR有效时的每个IFCLK的上升沿时数据被写入,FIFO指针递增,异步写时,在SLWR的每个有效至无效的跳变沿时数据被写入,FIFO写指针递增。
PKTEND:包结束信号,外部逻辑控制,在正常情况下,外部逻辑向FX2的FIFO中写数,当写入FIFO端点的字节数等于FX2固件设定的包大小时,数据将自动被打成一包进行传输,但有时外部逻辑可能需要传输一个字节数小于FX2固件设定的包大小的包,这时,它只需在写入一定数目的字节后,声明此信号,此时FX2硬件不管外部逻辑写入了多少字节,都自动将之打成一包进行传输。
FD[15:0]:数据线。
FIFOADR[1:0]:选择4个FIFO端点的地址线,外部逻辑控制。
由此可以写出我们的端口信号:
1 module usb_read( 2 3 input wire s_rst_n , 4 input wire usb_ifclk , 5 input wire usb_empty , 6 input wire usb_full , 7 output wire usb_slcs , 8 output wire usb_slwr , 9 output wire usb_slrd , 10 output wire usb_sloe , 11 output wire [1:0] usb_fifoaddr, 12 input wire [15:0] usb_fifodata 13 14 15 16 );
其中s_rst_n 是系统的复位信号。同步时钟使用USB芯片提供的的IFCLK-->usb_ifclk,在FLAG{2:0}中我们只使用了FLAGB读满标志和卸空标志,在同步度状态下使能相关端口,
1 assign usb_slrd = (usb_empty ==1'b1&& usb_slrd_reg==1'b0)? 1'b0 : 1'b1; 2 assign usb_slwr = 1'b1 ; 3 assign usb_sloe = 1'b0 ; 4 assign usb_slcs = 1'b0 ; 5 assign usb_fifoaddr = 2'b00 ;
SLOE是输出使能,拉低的时候有效。slcs片选信号低有效,FIFOADDR[1:0];4个FIFO配置与其中
00:代表2—out——FIFO端口,
01:代表4——out——FIFO端口,
10:代表6——in——FIFO端口 ,
11: :代表8——in-----FIFO端口
88根据数据手册所给出的同步读的时序图:
通过时序图可以发现FLAGS标志位为高的时候数据可以读出来,可以推出读满的的标志位是在拉低的是后表示读空,由此为出发点画出同步读的时序图:
实现上图时序:
reg usb_slrd_reg ; assign usb_slrd = (usb_empty ==1'b1&& usb_slrd_reg==1'b0)? 1'b0 : 1'b1; //usb_slrd_reg always @(posedge usb_ifclk or negedge s_rst_n)begin if(!s_rst_n) usb_slrd_reg <= 1'b1 ; else if(usb_empty == 1'b1) usb_slrd_reg <= 1'b0 ; else usb_slrd_reg <= 1'b1 ; end
除此意外我们希望加一个计数器计算接收到的数据是不是和我们发送的数据个数一致:
reg [15:0] usb_rd_cnt ; //usb_rd_cnt always @(posedge usb_ifclk or negedge s_rst_n)begin if(!s_rst_n) usb_rd_cnt <= 'd0 ; else if(usb_slrd == 1'b0 ) usb_rd_cnt <= usb_rd_cnt + 1'b1 ; end
接下就是如何使用CHIOPSCOP来抓取接收到的数据波形:加入ILA——IP核和icon IP核,并例化到我们的模块中:
/********************chiop scop ***************************/ wire [35:0] CONTROL ; wire [35:0] ila_trig ; assign ila_trig[15:00] = usb_fifodata ; assign ila_trig[16:16]= usb_full ; assign ila_trig[17:17]= usb_slrd_reg ; assign ila_trig[18:18]= usb_slrd ; assign ila_trig[19:19]= usb_empty ; assign ila_trig[35:20]= usb_rd_cnt ; //例化ILA_IP chipscope_ila chipscope_ila_inst( .CONTROL (CONTROL ), // INOUT BUS [35:0] .CLK (usb_ifclk), // IN .TRIG0 (ila_trig ) // IN BUS [18:0] ); //lihua chipscope_icon chipscope_icon_inst( .CONTROL0 (CONTROL ) // INOUT BUS [35:0] );
这样就实现了,对USB对的数据进行抓取从而验证驱动是否正确。当然需要用到上位机Cypress。总体代码如下,验证就不贴图片了,大家可自行验证,总体代码如下:
1 module usb_read( 2 3 input wire s_rst_n , 4 input wire usb_ifclk , 5 input wire usb_empty , 6 input wire usb_full , 7 output wire usb_slcs , 8 output wire usb_slwr , 9 output wire usb_slrd , 10 output wire usb_sloe , 11 output wire [1:0] usb_fifoaddr, 12 input wire [15:0] usb_fifodata 13 14 15 16 ); 17 18 /********************************************************************** 19 ****************define parameter and signals************************** 20 ***********************************************************************/ 21 reg usb_slrd_reg ; 22 reg [15:0] usb_rd_cnt ; 23 /********************************************************************** 24 *******************main code ***************************************** 25 ***********************************************************************/ 26 27 28 assign usb_slrd = (usb_empty ==1'b1&& usb_slrd_reg==1'b0)? 1'b0 : 1'b1; 29 assign usb_slwr = 1'b1 ; 30 assign usb_sloe = 1'b0 ; 31 assign usb_slcs = 1'b0 ; 32 assign usb_fifoaddr = 2'b00 ; 33 //usb_slrd_reg 34 always @(posedge usb_ifclk or negedge s_rst_n)begin 35 if(!s_rst_n) 36 usb_slrd_reg <= 1'b1 ; 37 else if(usb_empty == 1'b1) 38 usb_slrd_reg <= 1'b0 ; 39 else 40 usb_slrd_reg <= 1'b1 ; 41 end 42 //usb_rd_cnt 43 always @(posedge usb_ifclk or negedge s_rst_n)begin 44 if(!s_rst_n) 45 usb_rd_cnt <= 'd0 ; 46 else if(usb_slrd == 1'b0 ) 47 usb_rd_cnt <= usb_rd_cnt + 1'b1 ; 48 end 49 50 /********************chiop scop ***************************/ 51 52 wire [35:0] CONTROL ; 53 wire [35:0] ila_trig ; 54 55 assign ila_trig[15:00] = usb_fifodata ; 56 assign ila_trig[16:16]= usb_full ; 57 assign ila_trig[17:17]= usb_slrd_reg ; 58 assign ila_trig[18:18]= usb_slrd ; 59 assign ila_trig[19:19]= usb_empty ; 60 assign ila_trig[35:20]= usb_rd_cnt ; 61 62 //例化ILA_IP 63 64 chipscope_ila chipscope_ila_inst( 65 .CONTROL (CONTROL ), // INOUT BUS [35:0] 66 .CLK (usb_ifclk), // IN 67 .TRIG0 (ila_trig ) // IN BUS [18:0] 68 ); 69 //lihua 70 chipscope_icon chipscope_icon_inst( 71 .CONTROL0 (CONTROL ) // INOUT BUS [35:0] 72 ); 73 74 75 endmodule