⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb1_ctrl.v

📁 usb1.1 ip核
💻 V
📖 第 1 页 / 共 2 页
字号:
	   CONFIG_DATA:		ep0_dout <= #1 {7'h0, configured};	// return configuration表明是否被配置?	   SYNC_FRAME_DATA:	ep0_dout <= #1 high_sel ? {5'h0, frame_no[10:8]} : frame_no[7:0];//返回帧号	   VEND_DATA:		ep0_dout <= #1 high_sel ? vendor_data[15:8] : vendor_data[7:0];//返回用户定义数据	endcasealways @(posedge clk)//ep0_we用来使能控制端点的发送缓冲fifo的,写允许	ep0_we <= #1 fifo_we_d | fifo_we_rom;//第二个是什么条件?是不是指用rom中的数据写fifo,注意或的关系always @(posedge clk)//对ep0_size赋值	if(in_size_0)	ep0_size <= #1 8'h0;//无可选数据stage	else	if(in_size_1)	ep0_size <= #1 8'h1;//一字节	else	if(in_size_2)	ep0_size <= #1 8'h2;//二字节	else	if(rom_sel)	ep0_size <= #1 {1'b0, rom_size_d};//自定的长度,即超出2字节的长度,rom_size_d 7位always @(posedge clk)//这个条件分明看不懂!!我来解释:是二字节返回信息,且发送fifo未满,且写使能开着,且write_done为低	write_done_r <= #1 in_size_2 & !fifo_full & fifo_we_d &				!write_done_r & !write_done;always @(posedge clk)//这个也不明白。一个中间变量而已,为了write_done_r而设。	write_done <= #1 in_size_2 & !fifo_full & fifo_we_d &				write_done_r & !write_done;/////////////////////////////////////////////////////////////////////// Decode Header,解码来自主机的setup stage的data0数据包//// Valid bRequest Codesparameter	GET_STATUS	=	8'h00,		CLEAR_FEATURE	=	8'h01,		SET_FEATURE	=	8'h03,		SET_ADDRESS	=	8'h05,		GET_DESCRIPTOR	=	8'h06,		SET_DESCRIPTOR	=	8'h07,		GET_CONFIG	=	8'h08,		SET_CONFIG	=	8'h09,		GET_INTERFACE	=	8'h0a,		SET_INTERFACE	=	8'h0b,		SYNCH_FRAME	=	8'h0c;parameter	V_SET_INT	=	8'h0f;//这是什么?用户自定义的		assign bmReqType = hdr0;assign bm_req_dir = bmReqType[7];	// 0-Host to device; 1-device to host assign bm_req_type = bmReqType[6:5];	// 0-standard; 1-class; 2-vendor(用户定义的请求); 3-RESERVEDassign bm_req_recp = bmReqType[4:0];	// 0-device; 1-interface; 2-endpoint; 3-other					// 4..31-reservedassign bRequest =  hdr1;//看到这里全明白了assign wValue   = {hdr3, hdr2};//这个和下面的一个还要输出的,但是wLength就不要输出了,本地使用assign wIndex   = {hdr5, hdr4};assign wLength  = {hdr7, hdr6};always @(posedge clk)	hdr_done_r <= #1 hdr_done;//这里为什么要搞一级缓冲// Standard commands that MUST support,这里开始干解码的核心工作always @(posedge clk)	get_status <= #1	hdr_done & (bRequest == GET_STATUS) &								(bm_req_type==2'h0);//这个条件表明是标准请求命令always @(posedge clk)	clear_feature <= #1	hdr_done & (bRequest == CLEAR_FEATURE) &								(bm_req_type==2'h0);always @(posedge clk)	set_feature <= #1	hdr_done & (bRequest == SET_FEATURE) &								(bm_req_type==2'h0);always @(posedge clk)	set_address <= #1	hdr_done & (bRequest == SET_ADDRESS) &								(bm_req_type==2'h0);always @(posedge clk)	get_descriptor <= #1	hdr_done & (bRequest == GET_DESCRIPTOR) &								(bm_req_type==2'h0);always @(posedge clk)	set_descriptor <= #1	hdr_done & (bRequest == SET_DESCRIPTOR) &								(bm_req_type==2'h0);always @(posedge clk)	get_config <= #1	hdr_done & (bRequest == GET_CONFIG) &								(bm_req_type==2'h0);always @(posedge clk)	set_config <= #1	hdr_done & (bRequest == SET_CONFIG) &								(bm_req_type==2'h0);always @(posedge clk)	get_interface <= #1	hdr_done & (bRequest == GET_INTERFACE) &								(bm_req_type==2'h0);always @(posedge clk)	set_interface <= #1	hdr_done & (bRequest == SET_INTERFACE) &								(bm_req_type==2'h0);always @(posedge clk)	synch_frame <= #1	hdr_done & (bRequest == SYNCH_FRAME) &								(bm_req_type==2'h0);always @(posedge clk)	v_set_int <= #1		hdr_done & (bRequest == V_SET_INT) &								(bm_req_type==2'h2);//从这里看出,v_set_int请求是用户自己定义的always @(posedge clk)	v_set_feature <= #1	hdr_done & (bRequest == SET_FEATURE) &								(bm_req_type==2'h2);//v_set_feature前面的v可能是vendor的意思,用户自定义always @(posedge clk)	v_get_status <= #1	hdr_done & (bRequest == GET_STATUS) &								(bm_req_type==2'h2);//用户自定义// A config err must cause the device to send a STALL for an ACKalways @(posedge clk)	config_err <= #1 hdr_done_r & !(get_status | clear_feature |//406行定义的hdr_done_r			set_feature | set_address | get_descriptor |			set_descriptor | get_config | set_config |			get_interface | set_interface | synch_frame |			v_set_int | v_set_feature | v_get_status);always @(posedge clk)	send_stall <= #1 config_err;//send_stall可是要输出的,这里对输出send_stall的含义和时机要进一步深入理解                                ///////////////////////////////////////////////////////////////////////// Set address,分配设备地址,注意他没有在状态机里完成这一步//always @(posedge clk)	if(!rst)				set_adr_pending <= #1 1'b0;	else	if(ctrl_in | ctrl_out | ctrl_setup)	set_adr_pending <= #1 1'b0;//这里为什么清零?因为重新开始了控制传输	else                                                    //而这次控制传输可能是在set address,address只可能在setup中       	if(set_address)				set_adr_pending <= #1 1'b1;always @(posedge clk)	if(!rst)			funct_adr_tmp <= #1 7'h0;	else	if(set_address)			funct_adr_tmp <= #1 wValue[6:0];//从指定地点获得分配的设备地址,低字节的低7位always @(posedge clk)//给funct_adr赋值	if(!rst)			funct_adr <= #1 7'h0;	else	if(set_adr_pending & ctrl_in)	funct_adr <= #1 funct_adr_tmp;//能不能体会ctrl_in,我必须去pl观察了.                                                                  //其实ctrl_in一定会出现的.现在看看,好象只能用ctrl_in了/////////////////////////////////////////////////////////////////////// Main FSM 主有限状态机,要多看看//always @(posedge clk)	if(!rst)	state <= #1 IDLE;	else		state <= next_state;always @(state or ctrl_setup or ctrl_in or ctrl_out or hdr_done or	fifo_full or rom_done or write_done_r or wValue or bm_req_recp or	get_status or clear_feature or set_feature or set_address or	get_descriptor or set_descriptor or get_config or set_config or	get_interface or set_interface or synch_frame or v_set_int or	v_set_feature or v_get_status	)   begin	next_state = state;	get_hdr  = 1'b0;	data_sel = ZERO_DATA;//默认状态	fifo_we_d = 1'b0;	in_size_0 = 1'b0;	in_size_1 = 1'b0;	in_size_2 = 1'b0;	rom_sel = 1'b0;	case(state)	// synopsys full_case parallel_case		// Wait for Setup token	   IDLE:		   begin			if(ctrl_setup)		next_state = GET_HDR;			if(get_status)		next_state = GET_STATUS_S;			if(clear_feature)	next_state = CLEAR_FEATURE_S;			if(set_feature)		next_state = SET_FEATURE_S;			if(set_address)		next_state = SET_ADDRESS_S;			if(get_descriptor)	next_state = GET_DESCRIPTOR_S;			if(set_descriptor)	next_state = SET_DESCRIPTOR_S;			if(get_config)		next_state = GET_CONFIG_S;			if(set_config)		next_state = SET_CONFIG_S;			if(get_interface)	next_state = GET_INTERFACE_S;			if(set_interface)	next_state = SET_INTERFACE_S;			if(synch_frame)		next_state = SYNCH_FRAME_S;			if(v_set_int)		next_state = V_SET_INT_S;			if(v_set_feature)	next_state = V_SET_INT_S;			if(v_get_status)	next_state = V_GET_STATUS_S;		   end		// Retrieve Setup Header保存来自主机的8字节命令	   GET_HDR:		   begin			get_hdr = 1'b1;//其效果在300行看得到			if(hdr_done)	next_state = IDLE;		   end		// Actions for supported commands	   GET_STATUS_S://这里是不是有点问题啊?与马伟的书有出入。		   begin			// Returns to host			// 16'h0001 for device,其实我认为返回的是0000h			// 16'h0000 for interface这两个都有严重的问题,你看564行,这就埋下了祸根,仿真时再说吧!!!			// 16'h0000 for endpoint			if(bm_req_recp == 5'h00)	data_sel = ZERO_ONE_DATA;//表明要返回设备的状态。不支持远程唤醒,总线供电			else				data_sel = ZERO_DATA;//要返回接口或端点的状态,怎觉得与协议有出入                                                     //是要从rom1中获得数据,但是rom_adr没有给啊?或者说是错误的			in_size_2 = 1'b1;//两个字节的返回信息   //因为get_status_s时,rom_adr被默认给了00地址			if(!fifo_full)			   begin				fifo_we_d = 1'b1;//ep0_we <= #1 fifo_we_d | fifo_we_rom,要返回的信息已被写到发送fifo中了				if(write_done_r)	next_state = WAIT_IN_DATA;//按ctrl_in,ctrl_out的顺序跳到idle			   end		   end	   V_GET_STATUS_S://用户定义的get_status_s		   begin			data_sel = VEND_DATA;//这个data_sel真让人头疼!!			in_size_2 = 1'b1;//注意write_done_r <= #1 in_size_2 & !fifo_full & fifo_we_d &!write_done_r & !write_done			if(!fifo_full)   //注意high_sel = write_done_r			   begin				fifo_we_d = 1'b1;//ep0_we <= #1 fifo_we_d | fifo_we_rom已将要返回信息写到发送fifo中,时序流畅				if(write_done_r)	next_state = WAIT_IN_DATA;			   end		   end	   CLEAR_FEATURE_S://不支持		   begin			// just ignore this for now			next_state = STATUS_IN;//之后无条件跳到idle了,而且没做其他数据流的事		   end	   SET_FEATURE_S://不支持		   begin			// just ignore this for now			next_state = STATUS_IN;//之后无条件跳到idle了,而且没做其他数据流的事		   end	   SET_ADDRESS_S:		   begin			// done elsewhere ....在上面处理过了,这里什么也不干			next_state = STATUS_IN;//之后无条件跳到idle了,而且没做其他数据流的事		   end	   GET_DESCRIPTOR_S:		   begin			if(	wValue[15:8] == 8'h01 |    //高字节为描述符编号,1:设备描述符				wValue[15:8] == 8'h02 |    //2:配置描述符				wValue[15:8] == 8'h03	)  //3:字符串描述符				rom_sel = 1'b1;//为什么?因为默认data_sel为ZERO_DATA,与rom_data有关			else               //ep0_dout <= #1 rom_sel ? rom_data : 8'h0,打开了来自rom的数据路径,而且rom_adr已设好				next_state = IDLE;			if(rom_done)//rom_done,当一次要传的数据传完且没有检测到下一次的in事务!(rom_sel&!rom_sel_r)				next_state = IDLE;		   end	   SET_DESCRIPTOR_S:		   begin			// This doesn't do anything since we do not support			// setting the descriptor,不支持,都存在rom里了,只读的			next_state = IDLE;		   end	   GET_CONFIG_S:		   begin			// Send one byte back that indicates current status			in_size_1 = 1'b1;//返回给主机一字节信息			data_sel = CONFIG_DATA;//慢慢知道怎么回事了,表明是否被配置过			if(!fifo_full)			   begin				fifo_we_d = 1'b1;//ep0_we <= #1 fifo_we_d | fifo_we_rom,已写到发送fifo中				next_state = WAIT_IN_DATA;			   end		   end	   SET_CONFIG_S:		   begin			// done elsewhere ....确实在前面已经做过处理了,组装时就体现了			next_state = STATUS_IN;//之后无条件跳到idle了,而且没做其他数据流的事		   end	   GET_INTERFACE_S:		   begin			// Return interface '0',确实是返回了0值			in_size_1 = 1'b1;//返回给主机一个字节的信息,默认状data_sel=ZERO_DATA,与rom有关			if(!fifo_full)			   begin				fifo_we_d = 1'b1;//ep0_we <= #1 fifo_we_d | fifo_we_rom,数据已写入到发送fifo中了				next_state = WAIT_IN_DATA;//下面对数据流确实什么也没做,只是按照ctrl_in,ctrl_out的顺序跳到idle			   end		   end	   SET_INTERFACE_S://不支持		   begin			// just ignore this for now			next_state = STATUS_IN;//之后无条件跳到idle了,而且没做其他数据流的事		   end	   SYNCH_FRAME_S:		   begin			// Return Frame current frame number			data_sel = SYNC_FRAME_DATA;			in_size_2 = 1'b1;//返回给主机二字节信息			if(!fifo_full)			   begin				fifo_we_d = 1'b1;//注意ep0_we <= #1 fifo_we_d | fifo_we_rom,别担心,high_sel会适时变高的				if(write_done_r)	next_state = WAIT_IN_DATA;//下面对数据流确实什么也没做,只是按照ctrl_in,ctrl_out的顺序跳到idle			   end		   end	   V_SET_INT_S:		   begin			// done elsewhere ....还没找到			next_state = STATUS_IN;//之后无条件跳到idle了,而且没做其他数据流的事		   end	   WAIT_IN_DATA://数据的实际输出在哪里触发?		   begin			if(ctrl_in)	next_state = STATUS_OUT;		   end	   STATUS_IN:		   begin			in_size_0 = 1'b1;//注意if(in_size_0)	ep0_size <= #1 8'h0,ep0_size是要输出到core内部使用的			if(ctrl_in)	next_state = IDLE;		   end	   STATUS_OUT:		   begin			if(ctrl_out)	next_state = IDLE;		   end	endcase   endendmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -