📄 usbf_pe.v
字号:
abort <= buffer_overflow | (match & (state != IDLE) ) | (match_r & to_large);/////////////////////////////////////////////////////////////////////// TIME OUT TIMERS//// After sending Data in response to an IN token from host, the// host must reply with an ack. The host has 622nS in Full Speed// mode and 400nS in High Speed mode to reply.// "rx_ack_to" indicates when this time has expired.// rx_ack_to_clr, clears the timeralways @(posedge clk) rx_ack_to_clr <= tx_valid | rx_ack_to_clr_d;always @(posedge clk) if(rx_ack_to_clr) rx_ack_to_cnt <= 8'h0; else rx_ack_to_cnt <= rx_ack_to_cnt + 8'h1;always @(posedge clk) rx_ack_to <= (rx_ack_to_cnt == rx_ack_to_val);assign rx_ack_to_val = mode_hs ? `USBF_RX_ACK_TO_VAL_HS : `USBF_RX_ACK_TO_VAL_FS;// After sending a OUT token the host must send a data packet.// The host has 622nS in Full Speed mode and 400nS in High Speed// mode to send the data packet.// "tx_data_to" indicates when this time has expired.// "tx_data_to_clr" clears the timerassign tx_data_to_clr = rx_active;always @(posedge clk) if(tx_data_to_clr) tx_data_to_cnt <= 8'h0; else tx_data_to_cnt <= tx_data_to_cnt + 8'h1;always @(posedge clk) tx_data_to <= (tx_data_to_cnt == tx_data_to_val);assign tx_data_to_val = mode_hs ? `USBF_TX_DATA_TO_VAL_HS : `USBF_TX_DATA_TO_VAL_FS;/////////////////////////////////////////////////////////////////////// Interrupts//reg pid_OUT_r, pid_IN_r, pid_PING_r, pid_SETUP_r;assign int_buf1_set = !buf_sel & buffer_done & int_set_en & !buf1_not_aloc;assign int_buf0_set = buf_sel & buffer_done & int_set_en & !buf0_not_aloc;always @(posedge clk) pid_OUT_r <= pid_OUT;always @(posedge clk) pid_IN_r <= pid_IN;always @(posedge clk) pid_PING_r <= pid_PING;always @(posedge clk) pid_SETUP_r <= pid_SETUP;always @(posedge clk) int_upid_set <= match_r & !pid_SOF & ( ( OUT_ep & !(pid_OUT_r | pid_PING_r)) | ( IN_ep & !pid_IN_r) | (CTRL_ep & !(pid_IN_r | pid_OUT_r | pid_PING_r | pid_SETUP_r)) );assign int_to_set = ((state == IN2) & rx_ack_to) | ((state == OUT) & tx_data_to);assign int_crc16_set = rx_data_done & crc16_err;always @(posedge clk) int_seqerr_set <= int_seqerr_set_d;/////////////////////////////////////////////////////////////////////// Main Protocol State Machine//`ifdef USBF_ASYNC_RESETalways @(posedge clk or negedge rst)`elsealways @(posedge clk)`endif if(!rst) state <= IDLE; else if(match) state <= IDLE; else state <= next_state;always @(state or ep_stall or buf0_na or buf1_na or pid_seq_err or idma_done or token_valid or pid_ACK or rx_data_done or tx_data_to or crc16_err or ep_disabled or no_bufs or mode_hs or dma_en or rx_ack_to or pid_PING or txfr_iso or to_small or to_large or CTRL_ep or pid_IN or pid_OUT or IN_ep or OUT_ep or pid_SETUP or pid_SOF or match_r or abort or buffer_done or no_buf0_dma or max_pl_sz) begin next_state = state; token_pid_sel_d = ACK; send_token_d = 1'b0; rx_dma_en = 1'b0; tx_dma_en = 1'b0; buf_set_d = 1'b0; uc_stat_set_d = 1'b0; buf0_rl_d = 1'b0; int_set_en = 1'b0; rx_ack_to_clr_d = 1'b1; int_seqerr_set_d = 1'b0; send_zero_length = 1'b0; case(state) // synopsys full_case parallel_case IDLE: begin// synopsys translate_off`ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state IDLE (%t)", $time);`endif`ifdef USBF_DEBUG if(rst && match_r && !ep_disabled && !pid_SOF) begin if(match_r === 1'bx) $display("ERROR: IDLE: match_r is unknown. (%t)", $time); if(ep_disabled === 1'bx)$display("ERROR: IDLE: ep_disabled is unknown. (%t)", $time); if(pid_SOF === 1'bx) $display("ERROR: IDLE: pid_SOF is unknown. (%t)", $time); if(ep_stall === 1'bx) $display("ERROR: IDLE: ep_stall is unknown. (%t)", $time); if(buf0_na === 1'bx) $display("ERROR: IDLE: buf0_na is unknown. (%t)", $time); if(buf1_na === 1'bx) $display("ERROR: IDLE: buf1_na is unknown. (%t)", $time); if(no_buf0_dma === 1'bx)$display("ERROR: IDLE: no_buf0_dma is unknown. (%t)", $time); if(CTRL_ep === 1'bx) $display("ERROR: IDLE: CTRL_ep is unknown. (%t)", $time); if(pid_IN === 1'bx) $display("ERROR: IDLE: pid_IN is unknown. (%t)", $time); if(pid_OUT === 1'bx) $display("ERROR: IDLE: pid_OUT is unknown. (%t)", $time); if(pid_SETUP === 1'bx) $display("ERROR: IDLE: pid_SETUP is unknown. (%t)", $time); if(pid_PING === 1'bx) $display("ERROR: IDLE: pid_PING is unknown. (%t)", $time); if(mode_hs === 1'bx) $display("ERROR: IDLE: mode_hs is unknown. (%t)", $time); if(IN_ep === 1'bx) $display("ERROR: IDLE: IN_ep is unknown. (%t)", $time); if(OUT_ep === 1'bx) $display("ERROR: IDLE: OUT_ep is unknown. (%t)", $time); end`endif// synopsys translate_on if(match_r && !ep_disabled && !pid_SOF) begin if(ep_stall) // Halt Forced send STALL begin token_pid_sel_d = STALL; send_token_d = 1'b1; next_state = TOKEN; end else if( (buf0_na && buf1_na) || no_buf0_dma || (CTRL_ep && pid_IN && buf1_na) || (CTRL_ep && pid_OUT && buf0_na) ) begin // No buffers send NAK token_pid_sel_d = NACK; send_token_d = 1'b1; next_state = TOKEN; end else if(pid_PING && mode_hs) begin token_pid_sel_d = ACK; send_token_d = 1'b1; next_state = TOKEN; end else if(IN_ep || (CTRL_ep && pid_IN)) begin if(max_pl_sz == 11'h0) send_zero_length = 1'b1; tx_dma_en = 1'b1; next_state = IN; end else if(OUT_ep || (CTRL_ep && (pid_OUT || pid_SETUP))) begin rx_dma_en = 1'b1; next_state = OUT; end end end TOKEN: begin// synopsys translate_off`ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state TOKEN (%t)", $time);`endif// synopsys translate_on next_state = IDLE; end IN: begin// synopsys translate_off`ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state IN (%t)", $time);`endif`ifdef USBF_DEBUG if(idma_done === 1'bx) $display("ERROR: IN: idma_done is unknown. (%t)", $time); if(txfr_iso === 1'bx) $display("ERROR: IN: txfr_iso is unknown. (%t)", $time);`endif// synopsys translate_on rx_ack_to_clr_d = 1'b0; if(idma_done) begin if(txfr_iso) next_state = UPDATE; else next_state = IN2; end end IN2: begin// synopsys translate_off`ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state IN2 (%t)", $time);`endif`ifdef USBF_DEBUG if(rx_ack_to === 1'bx) $display("ERROR: IN2: rx_ack_to is unknown. (%t)", $time); if(token_valid === 1'bx)$display("ERROR: IN2: token_valid is unknown. (%t)", $time); if(pid_ACK === 1'bx) $display("ERROR: IN2: pid_ACK is unknown. (%t)", $time);`endif// synopsys translate_on rx_ack_to_clr_d = 1'b0; // Wait for ACK from HOST or Timeout if(rx_ack_to) next_state = IDLE; else if(token_valid && pid_ACK) begin next_state = UPDATE; end end OUT: begin// synopsys translate_off`ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state OUT (%t)", $time);`endif`ifdef USBF_DEBUG if(tx_data_to === 1'bx) $display("ERROR: OUT: tx_data_to is unknown. (%t)", $time); if(crc16_err === 1'bx) $display("ERROR: OUT: crc16_err is unknown. (%t)", $time); if(abort === 1'bx) $display("ERROR: OUT: abort is unknown. (%t)", $time); if(rx_data_done === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time); if(txfr_iso === 1'bx) $display("ERROR: OUT: txfr_iso is unknown. (%t)", $time); if(pid_seq_err === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time);`endif// synopsys translate_on if(tx_data_to || crc16_err || abort ) next_state = IDLE; else if(rx_data_done) begin // Send Ack if(txfr_iso) begin if(pid_seq_err) int_seqerr_set_d = 1'b1; next_state = UPDATEW; end else next_state = OUT2A; end end OUT2A: begin // This is a delay State to NACK to small or to // large packets. this state could be skipped// synopsys translate_off`ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state OUT2A (%t)", $time);`endif`ifdef USBF_DEBUG if(abort === 1'bx) $display("ERROR: OUT2A: abort is unknown. (%t)", $time);`endif// synopsys translate_on if(abort) next_state = IDLE; else next_state = OUT2B; end OUT2B: begin // Send ACK/NACK/NYET// synopsys translate_off`ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state OUT2B (%t)", $time);`endif`ifdef USBF_DEBUG if(abort === 1'bx) $display("ERROR: OUT2B: abort is unknown. (%t)", $time); if(to_small === 1'bx) $display("ERROR: OUT2B: to_small is unknown. (%t)", $time); if(to_large === 1'bx) $display("ERROR: OUT2B: to_large is unknown. (%t)", $time); if(pid_seq_err === 1'bx)$display("ERROR: OUT2B: rx_data_done is unknown. (%t)", $time); if(mode_hs === 1'bx) $display("ERROR: OUT2B: mode_hs is unknown. (%t)", $time); if(no_bufs === 1'bx) $display("ERROR: OUT2B: no_bufs is unknown. (%t)", $time);`endif// synopsys translate_on if(abort) next_state = IDLE; else if(to_small || to_large) begin token_pid_sel_d = NACK; next_state = IDLE; end else if(pid_seq_err) begin token_pid_sel_d = ACK; send_token_d = 1'b1; next_state = IDLE; end else begin if(mode_hs && no_bufs) token_pid_sel_d = NYET; else token_pid_sel_d = ACK; send_token_d = 1'b1; next_state = UPDATE; end end UPDATEW: begin// synopsys translate_off`ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state UPDATEW (%t)", $time);`endif// synopsys translate_on next_state = UPDATE; end UPDATE: begin// synopsys translate_off`ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state UPDATE (%t)", $time);`endif`ifdef USBF_DEBUG if(buffer_done === 1'bx) $display("ERROR: UPDATE: buffer_done is unknown. (%t)", $time); if(dma_en === 1'bx) $display("ERROR: UPDATE: dma_en is unknown. (%t)", $time);`endif// synopsys translate_on // Interrupts int_set_en = 1'b1; // Buffer (used, size, adr) set or reload if(buffer_done && dma_en) begin buf0_rl_d = 1'b1; end else begin buf_set_d = 1'b1; end next_state = UPDATE2; end UPDATE2: // Update Register File & state begin// synopsys translate_off`ifdef USBF_VERBOSE_DEBUG $display("PE: Entered state UPDATE2 (%t)", $time);`endif// synopsys translate_on // pid sequence & buffer usage uc_stat_set_d = 1'b1; next_state = IDLE; end endcase endendmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -