USB

USB介绍

  USB,通用串行总线,支持热插拔,为了解决即插即用的需求,USB2.0比较常用。由于USB是主从模式的结构,设备与设备、主机与主机相互之间不能互联,为了解决这个问题,出现了USB OTG(on the go),同一个设备在不同场合下可以在主从机之间切换。

  特点

  usb2.0以上支持480Mb/s高速模式

性能 应用 特性

低速(1.5Mbps)

交互式设备

10-100kbps

键盘鼠标

手写笔

外设

虚拟设备

成本低

热插拔

同时使用多个外设

全速(12Mbps)

电话、音频

压缩的视频

500kbps - 10Mbps

话音

宽带

音频

麦克风

成本低

热插拔

同时使用多个外设

保证带宽和延迟

高速(480Mbps)

视频,大容量存储

25-400Mbps

视频

大容量存储

图像

宽带

成本低

热插拔

同时使用多个外设

保证带宽与延迟

高带宽

供电方式

  自供电:设备从外部电源获取电压

  总线供电:设备从VBUS(5V)取电

    总线供电区分低功耗和高功耗USB设备,低功耗设备最大功耗不超过100mA,高功耗设备枚举时候最大不超100mA,枚举完成配置结束后功耗不超500mA

    设备在枚举过程中,通过设备的配置描述符向主机报告供电设置(自供电/总线供电)以及功耗要求

  

USB传输

  一个传输有多个事务组成,一个事务有2/3个包

  传输分为4种:批量传输、同步传输、中断传输、控制传输

  

  USB发送数据低位优先

  包的内容

  

   Packet分四大类: 命令 (Token) 、Packet 帧首 (Start of Frame) 、Packet 数据 (Data) 、Packet 握手 (Handshake) Packet不同类型包,以上的组成部件有所不同

PID

  

PID只用0-3位,高4位是低4位的取反,用于校验PID

  

PID类型 名称 PID[3:0] 对应packet种类
Token 令牌包 OUT 0001 通知设备将要输出数据
IN 1001 通知设备将要输入数据
SOF 0101 通知设备这是一个帧起始数据包
SET UP 1101 通知设备将要开始一个控制传输
data 数据包 DATA0 0011  
DATA1 1011  
DATA2 0111  
MDATA 1111  
Handshake 握手包 ACK 0010 确认
NAK 1010 非确认
STALL 1110 挂起
NYET 0110 为准备好
Special 特殊包 PRE 1100 前导(这是一个令牌包)
ERR 1100 错误(握手包)
SPLIT 1000 分列事务(令牌包)
PING 0100 PING测试(这是一个令牌包)

 

  

令牌包(Token Packet)

  用来启动一次USB传输

  SETUP 和 OUT的区别在于SETUP令牌包后只使用DATA0数据包,而且只能发送到设备的控制端点,且设备必须要接收,OUT令牌包没有这些限制

 

 一次USB传输事务,以令牌包开始,然后数据包最后可能会有握手包结束。事务可能会有如下4种传输模式,控制传输、同步传输、中断传输和批量传输。如下,是一包的数据构成,payload是实际传输的数据。 

//===================================================================================================================

USB内部8051的core,通过向8051下载固件来管理USB芯片的工作机制,右边有用户接口供用户操作

  USB芯片:封装好USB协议,使得FPGA无须构造USB协议,在实际应用中可以将USB芯片当做FIFO,FPGA向USB写入数据,USB将数据发送PC

  FLAGC:FIFOADR指定的FIFO的EMPTY标志

  FLAGB:FIFOADR指定的FIFO的FULL标志

  FLAGA:FIFOADR指定的FIFO的可操作标志

       FIFOADR:地址分别对应00,01,10,11。具体使用哪个FIFO,作为输入还是输出,需要固件编写。

       SLRD: FIFO读信号。同步读时,FIFO指针在SLRD有效时的每个IFCLK的上升沿递增;异步读时,FIFO读指针在SLRD的每个有效到无效的跳变沿时递增;

       SLWR:FIFO写信号。同步写时,在SLWR有效时的每个IFCLK的上升沿时数据被写入,FIFO指针递增;异步写时,在SLWR的每个有效到无效的跳变沿时数据被写入,FIFO写指针递增。

     SLCS:gates all other slave FIFO enable/strobes, FIFO片选标志,当输出高时,不可进行数据传输。   

          SLOE: Input-only output enable with programmable polarity for the slave FIFO.   FPGA输出的,控制对FIFO读数据使能的信号。IC 输出使能,低电平有效。即在FPGA读的时候需要使其置低,写的时候拉高。也就是FIFO 输出使能

     PKTEND:包结束标志信号

     FD[15]-FD[0]   FIFO数据双向总线

USB FIFO同步写数据

  IFCLK :同步时钟

  SWLR:写使能,低有效,和FLAGS信号是时序逻辑产生,组合逻辑输出,保证SLWR和FULL拉低同时变化

  DATA:FIFO数据总线

  FLAGS:泛指FLAGA B C三个标志信号,低电平有效

  需要保证数据正确传输进入FIFO内部,不能写满

同步读

USB 异步读写

 根据异步读时的时序图:可以看出SLRD信号的低电平有效时间最少为50ns,FIFO输出数据到FLAG输出有70ns的延迟,因此读数据到写请求输出前的判断必须要大于70ns,否则可能造成误判。而我们使用的FPGA时钟周期是20ns,在每一个状态中可能需要停留几个时钟周期。

FPGA通过控制信号以及读取到的EP FLAG来判断是进行读还是写;

FPGA从EP2(FLAGADDR = 2'b00)读出数据后发送到EP6(FLAGADDR = 2'b10)

USB 异步读写回环

module usb(
	//sys
	input				clk			,
	input				rst_n		,
	//input
	input				usb_flag_a	,//EP2空标志
	input				usb_flag_b	,//EP4空标志
	input				usb_flag_c	,//EP6满标志
	//output
	output	reg [1:0]	usb_addr	,
	output	reg			usb_slcs	,
	output	reg 		usb_sloe	,
	output	reg			usb_slwr	,
	output	reg 		usb_slrd	,
	inout		[15:0]	usb_fd
);
//=========================================
//================define===================
//=========================================
parameter 	IDEL	=	5'd0;
parameter	RD_REQ	= 	5'd1;
parameter	RD_DATA	=	5'd2;
parameter	RD_OVER	= 	5'd4;
parameter	WR_REQ	= 	5'd8;
parameter	WR_OVER	= 	5'd16;



    reg	[15:0]		data_reg;//inout 输出接口数据存储
reg 			access_req;//表示EP2 有数据,EP6没有满,且不忙碌
reg 			busy;//busy 表示一次传输
reg 			usb_fd_en;
reg	[4:0]		usb_state;
reg [4:0]		i;//延时操作计数


//=========================================
//================main code================
//=========================================
assign usb_fd = usb_fd_en ? data_reg : 16'bz;

always@(posedge clk or negedge rst_n)begin
	if(!rst_n)
		access_req <= 1'b0;
	else if(usb_flag_a & usb_flag_c && (busy == 1'b0))
		access_req <= 1'b1;
	else
		access_req <= 1'b0;
end

always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		usb_state 	<= IDEL;
		usb_addr 	<= 2'b00;
		usb_slcs	<= 1'b0;
		usb_sloe 	<= 1'b1;
		usb_slwr	<= 1'b1;
		usb_slrd	<= 1'b1;
		usb_fd_en 	<= 1'b0;
	end
	else begin
		case(usb_state)
			IDEL:begin
				usb_addr <= 2'b00;
				usb_fd_en <= 1'b0;
				i=5'd0;
				if(access_req)begin
					usb_state <= RD_REQ;
					busy <= 1'b1;
				end
				else begin
					usb_state <= IDEL;
					busy <= 1'b0;
				end
			end
			RD_REQ:begin
				if(i == 'd2)begin
					usb_slrd <= 1'b1;
					usb_sloe <= 1'b0;
					i <= i+ 1'b1;
				end
				else if(i == 'd8)begin
					usb_slrd <= 1'b0;
					usb_sloe <= 1'b0;
					usb_state <= RD_DATA;
					i <= 'd0;
				end
				else
					i <= i+1;
			end
			RD_DATA:begin
				if(i == 'd8)begin
					usb_slrd <= 1'b1;
					usb_sloe <= 1'b0;
					data_reg <= usb_fd;
					usb_state <= RD_OVER;
				end
				else
					i <= i+1;
			end
			RD_OVER:begin
				if(i == 'd4)begin
					usb_slrd <= 1'b1;
					usb_sloe <= 1'b1;
					usb_addr <= 2'b10;
					usb_state <= WR_REQ;
					i <= 'd0;
				end
				else
					i <= i+1;
			end
			WR_REQ:begin
				if(i == 'd8)begin
					usb_slwr <= 1'b1;
					usb_state <= WR_OVER;
					i <= 'd0;
				end 
				else begin
					usb_slwr <= 1'b0;
					usb_fd_en <= 1'b1;
					i <= i+1;
				end
			end
			WR_OVER:begin
				if(i == 'd4)begin
					usb_fd_en <= 1'b0;
					busy <= 1'b0;
					i <= 'd0;
					usb_state <= IDEL;
				end
				else
					i <= i+1;
			end
			default:usb_state <= IDEL;
		endcase
	end	
end
endmodule

USB传输图像 首先要把图像转换成bin文件,直接选择图像传输会发送多余数据(bmp文件前边包含了文件头信息,也就是前边会发送非图像信息)

      图像数据转换成TXT传输会对TXT中的数据进行ASCII转码  

 

posted @ 2023-04-19 15:40  VincentZJ  阅读(240)  评论(0编辑  收藏  举报