📄 usb1_pd.v
字号:
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 + -