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

📄 usb1_pd.v

📁 usb1.1 ip核
💻 V
📖 第 1 页 / 共 2 页
字号:
assign	pid_SETUP = pid[3:0] == `USBF_T_PID_SETUP;assign	pid_DATA0 = pid[3:0] == `USBF_T_PID_DATA0;assign	pid_DATA1 = pid[3:0] == `USBF_T_PID_DATA1;assign	pid_DATA2 = pid[3:0] == `USBF_T_PID_DATA2;assign	pid_MDATA = pid[3:0] == `USBF_T_PID_MDATA;assign	pid_ACK   = pid[3:0] == `USBF_T_PID_ACK;assign	pid_NACK  = pid[3:0] == `USBF_T_PID_NACK;assign	pid_STALL = pid[3:0] == `USBF_T_PID_STALL;assign	pid_NYET  = pid[3:0] == `USBF_T_PID_NYET;assign	pid_PRE   = pid[3:0] == `USBF_T_PID_PRE;assign	pid_ERR   = pid[3:0] == `USBF_T_PID_ERR;assign	pid_SPLIT = pid[3:0] == `USBF_T_PID_SPLIT;assign	pid_PING  = pid[3:0] == `USBF_T_PID_PING;assign	pid_RES   = pid[3:0] == `USBF_T_PID_RES;  //保留态,低四全零assign	pid_TOKEN = pid_OUT | pid_IN | pid_SOF | pid_SETUP | pid_PING;assign	pid_DATA = pid_DATA0 | pid_DATA1 | pid_DATA2 | pid_MDATA;// Token Decoding LOGICalways @(posedge clk)	if(token_le_1)	token0 <= #1 rx_data;always @(posedge clk)	if(token_le_2)	token1 <= #1 rx_data;always @(posedge clk)//难点	token_valid_r1 <= #1 token_le_2;//这是在干什么?always @(posedge clk)//难点	token_valid_str1 <= #1 token_valid_r1 | pid_ack;//在干什么?pid-ack在哪赋值?always @(posedge clk)//一级缓冲	token_valid_str2 <= #1 token_valid_str1; //干什么?assign token_valid = token_valid_str1;//记住这个持续赋值// CRC 5 should perform the check in one cycle (flow through logic)// 11 bits and crc5 input, 1 bit outputassign crc5_err = token_valid & (crc5_out2 != token_crc5);//必须是令牌包且crc5错                                                         //如果是握手包怎么办?usb1_crc5 u0(	.crc_in(	5'h1f			),//送进去的校验码怎么可能是常数??全一?	.din(	{	token_fadr[0],			token_fadr[1],			token_fadr[2],			token_fadr[3],			token_fadr[4],			token_fadr[5],			token_fadr[6],			token_endp[0],			token_endp[1],			token_endp[2],			token_endp[3]   }	),	.crc_out(	crc5_out		) );// Invert and reverse result bitsassign	crc5_out2 = ~{crc5_out[0], crc5_out[1], crc5_out[2], crc5_out[3],			crc5_out[4]};assign frame_no = { token1[2:0], token0};assign token_fadr = token0[6:0];assign token_endp = {token1[2:0], token0[7]};assign token_crc5 = token1[7:3];// Data receiving logic// build a delay line and stop when we are about to get crcalways @(posedge clk or negedge rst)//给rxv1赋值	if(!rst)		rxv1 <= #1 1'b0; //复位rxv1变低	else	if(data_valid_d)	rxv1 <= #1 1'b1;//152定义,但是不知在哪里赋值,状态机中	else	if(data_done)		rxv1 <= #1 1'b0;//153always @(posedge clk or negedge rst)//给rxv2赋值	if(!rst)		rxv2 <= #1 1'b0;	else	if(rxv1 & data_valid_d)	rxv2 <= #1 1'b1;	else	if(data_done)		rxv2 <= #1 1'b0;always @(posedge clk)//体会rxv1,rxv2,data_valid0的关系	data_valid0 <= #1 rxv2 & data_valid_d;//154always @(posedge clk)   begin	if(data_valid_d)	d0 <= #1 rx_data;  //好象三级缓冲!!分明是流水线。何必写三个if呢?	if(data_valid_d)	d1 <= #1 d0;	if(data_valid_d)	d2 <= #1 d1;   endassign rx_data_st = d2;//内部处理完后把有效结果给外部引脚assign rx_data_valid = data_valid0;//同上assign rx_data_done = data_done;//同上// crc16 accumulates rx_data as long as data_valid_d is asserted.// when data_done is asserted, crc16 reports status, and resets itself// next cycle.always @(posedge clk)	rx_active_r <= #1 rx_active;assign crc16_clr = rx_active & !rx_active_r;//crc16清零信号设计巧妙                                            //刚检测到同步头时清零always @(posedge clk)	if(crc16_clr)		crc16_sum <= #1 16'hffff;//170行定义	else	if(data_valid_d)	crc16_sum <= #1 crc16_out;//171行定义,正如298行的解释usb1_crc16 u1(	.crc_in(	crc16_sum		),//放它进去干什么?不是说了吗?好象与前一次的结果有关系	.din(	{rx_data[0], rx_data[1], rx_data[2], rx_data[3],		rx_data[4], rx_data[5], rx_data[6], rx_data[7]}	),	.crc_out(	crc16_out		) );// Verify against polynomial assign crc16_err = data_done & (crc16_sum != 16'h800d);//后面的条件不懂!好象是个固定值?很奇怪,我到现在还是不明白!!                                                       //有可能是它把最后的16位crc16也当数据算了,所以才可能是固定值/////////////////////////////////////////////////////////////////////// Receive/Decode State machine接收解码状态机来了!!//always @(posedge clk or negedge rst)	if(!rst)	state <= #1 IDLE;	else		state <= #1 next_state;always @(state or rx_valid or rx_active or rx_err or pid_ACK or pid_TOKEN   //岂不是pid_NACK,pid_STALL无法触发该进程	or pid_DATA)                                                            //当然!!你想想主机能发送的握手信号!!   begin	next_state = state;	// Default don't change current state	pid_le_sm = 1'b0;//禁止读取pid	token_le_1 = 1'b0;	token_le_2 = 1'b0;	data_valid_d = 1'b0;	data_done = 1'b0;	seq_err = 1'b0;	pid_ack = 1'b0;	case(state)		// synopsys full_case parallel_case	   IDLE:		   begin			pid_le_sm = 1'b1;//assign pid_ld_en = pid_le_sm & rx_active & rx_valid			if(rx_valid & rx_active)	next_state = ACTIVE;//其实如果能跳转到ACTIVE,那pid_ld_en也为1了。		   end	   ACTIVE://pid已从rx_data读到了包标识符		   begin			// Received a ACK from Host这里是按几种可能的情况讨论的			if(pid_ACK & !rx_err)//确认收到的是ACK且接收无错			   begin				pid_ack = 1'b1;//注意这个置位的时机				if(!rx_active)	next_state = IDLE;//如果仅收到来自主机的握手ACK			   end                                //信号,就会返回空闲状态			else			// Receiving a TOKEN第二种情况,收到令牌包			if(pid_TOKEN & rx_valid & rx_active & !rx_err)			   begin				token_le_1 = 1'b1;//准备接收包标识符后的第一个字节,token0 <= #1 rx_data				next_state = TOKEN;			   end			else			// Receiving DATA第三种情况,收到数据包			if(pid_DATA & rx_valid & rx_active & !rx_err)			   begin				data_valid_d = 1'b1;//数据包有效载荷的第一字节进入d0了				next_state = DATA;			   end			else			if(	!rx_active | rx_err |                   //打死也想不到要将rx_active考虑进去!!有必要吗??				(rx_valid & !(pid_TOKEN | pid_DATA)) )	// ERROR既非令牌包又非			   begin                                    //数据包且数据处于有效状态				seq_err = !rx_err;//为什么取非??懂了      //或检测不到同步头了,或接收				if(!rx_active)	next_state = IDLE;//跳回空闲 //有错,则执行if语句			   end		   end	   TOKEN:		   begin			if(rx_valid & rx_active & !rx_err)			   begin				token_le_2 = 1'b1;//令牌包标识符后的第二个字节读入 token1 <= #1 rx_data				next_state = IDLE;//令牌包取完了,所以空闲了			   end			else			if(!rx_active | rx_err)	// ERROR,令牌包不完全或接收数据是错的			   begin				seq_err = !rx_err;//如果错误是由rx_err引起的,则与seq_err无关,seq_err变低				if(!rx_active)	next_state = IDLE;			   end		   end	   DATA:		   begin			if(rx_valid & rx_active & !rx_err)	data_valid_d = 1'b1;//新的数据进入d0,上了delay line,前一个进了d1...			if(!rx_active | rx_err)//如果有接收错,或检测不到同步头,立刻停止接收			   begin				data_done = 1'b1;				if(!rx_active)	next_state = IDLE;			   end		   end			endcase   endendmodule

⌨️ 快捷键说明

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