📄 usbf_pe.v
字号:
8'b11_01_01_10: this_dpid <= #1 2'b00; // ISO txfr. IN, 3 tr/mf 8'b00_10_01_??: this_dpid <= #1 allow_pid; // ISO txfr. OUT, 0 tr/mf 8'b01_10_01_??: this_dpid <= #1 2'b00; // ISO txfr. OUT, 1 tr/mf 8'b10_10_01_?0: this_dpid <= #1 2'b11; // ISO txfr. OUT, 2 tr/mf 8'b10_10_01_?1: this_dpid <= #1 2'b01; // ISO txfr. OUT, 2 tr/mf 8'b11_10_01_00: this_dpid <= #1 2'b11; // ISO txfr. OUT, 3 tr/mf 8'b11_10_01_01: this_dpid <= #1 2'b11; // ISO txfr. OUT, 3 tr/mf 8'b11_10_01_10: this_dpid <= #1 2'b10; // ISO txfr. OUT, 3 tr/mf 8'b??_01_00_?0, // IN/OUT endpoint only 8'b??_10_00_?0: this_dpid <= #1 2'b00; // INT transfers 8'b??_01_00_?1, // IN/OUT endpoint only 8'b??_10_00_?1: this_dpid <= #1 2'b01; // INT transfers 8'b??_01_10_?0, // IN/OUT endpoint only 8'b??_10_10_?0: this_dpid <= #1 2'b00; // BULK transfers 8'b??_01_10_?1, // IN/OUT endpoint only 8'b??_10_10_?1: this_dpid <= #1 2'b01; // BULK transfers 8'b??_00_??_??: // CTRL Endpoint casex({setup_token,in_op, out_op, uc_dpd}) // synopsys full_case parallel_case 5'b1_??_??: this_dpid <= #1 2'b00; // SETUP operation 5'b0_10_0?: this_dpid <= #1 2'b00; // IN operation 5'b0_10_1?: this_dpid <= #1 2'b01; // IN operation 5'b0_01_?0: this_dpid <= #1 2'b00; // OUT operation 5'b0_01_?1: this_dpid <= #1 2'b01; // OUT operation endcase endcase// Assign PID for outgoing packetsassign data_pid_sel = this_dpid;// Verify PID for incoming data packetsalways @(posedge clk) pid_seq_err <= #1 !( (this_dpid==2'b00 & pid_DATA0) | (this_dpid==2'b01 & pid_DATA1) | (this_dpid==2'b10 & pid_DATA2) | (this_dpid==2'b11 & pid_MDATA) );/////////////////////////////////////////////////////////////////////// IDMA Setup & src/dst buffer select//// For Control endpoints things are different:// buffer0 is used for OUT (incoming) data packets// buffer1 is used for IN (outgoing) data packets// Keep track of last token for control endpointsalways @(posedge clk) if(!rst) in_token <= #1 0; else if(pid_IN) in_token <= #1 1; else if(pid_OUT | pid_SETUP) in_token <= #1 0;always @(posedge clk) if(!rst) out_token <= #1 0; else if(pid_OUT | pid_SETUP) out_token <= #1 1; else if(pid_IN) out_token <= #1 0;always @(posedge clk) if(!rst) setup_token <= #1 0; else if(pid_SETUP) setup_token <= #1 1; else if(pid_OUT | pid_IN) setup_token <= #1 0;// Indicates if we are performing an IN operationassign in_op = IN_ep | (CTRL_ep & in_token);// Indicates if we are performing an OUT operationassign out_op = OUT_ep | (CTRL_ep & out_token);// Select buffer: buf_sel==0 buffer0; buf_sel==1 buffer1assign buf_sel = dma_en ? 0 : CTRL_ep ? in_token : ((uc_bsel[0] | buf0_na) & !buf1_na);// Select Address for IDMAalways @(posedge clk) adr <= #1 buf_sel ? buf1_adr : buf0_adr;//assign adr = buf_sel ? buf1_adr : buf0_adr;// Size from Bufferassign buf_size = buf_sel ? buf1_sz : buf0_sz;// Determine which is smaller: buffer or max_pl_szassign buf_smaller = buf_size < max_pl_sz;// Determine actual size for this transfer (for IDMA) IN endpoint only// (OUT endpoint uses sizeu_c from IDMA)assign size_next = buf_smaller ? buf_size : max_pl_sz;assign size = size_next; // "size" is an output for IDMA// Buffer Full (only for OUT endpoints)// Indicates that there is not enough space in the buffer for one// more max_pl_sz packetalways @(posedge clk) buffer_full <= #1 new_size < max_pl_sz;//assign buffer_full = new_size < max_pl_sz;// Buffer Empty (only for IN endpoints)// Indicates that there are zero bytes left in the bufferalways @(posedge clk) buffer_empty <= #1 (new_size == 0);//assign buffer_empty = (new_size == 0);// Joint buffer full/empty flag This is the "USED" flagalways @(posedge clk) buffer_done <= #1 in_op ? buffer_empty : buffer_full;//assign buffer_done = in_op ? buffer_empty : buffer_full;//No More buffer space at all (For high speed out - issue NYET)assign no_buf0_dma = dma_en & ((IN_ep & !dma_in_buf_sz1) | (OUT_ep & !dma_out_buf_avail));always @(posedge clk) buf0_st_max <= #1 (buf0_sz < max_pl_sz);always @(posedge clk) buf1_st_max <= #1 (buf1_sz < max_pl_sz);always @(posedge clk) no_bufs0 <= #1 buf0_na | no_buf0_dma | (buf_sel ? buf0_st_max : (buffer_full & !dma_en));always @(posedge clk) no_bufs1 <= #1 buf1_na | (buf_sel ? buffer_full : buf1_st_max);//assign no_bufs0 = buf0_na | no_buf0_dma |// (buf_sel ? (buf0_sz < max_pl_sz) : (buffer_full & !dma_en));//assign no_bufs1 = buf1_na | (buf_sel ? buffer_full : (buf1_sz < max_pl_sz));//assign no_bufs = no_bufs0 & no_bufs1;assign no_bufs = no_bufs0 & no_bufs1;// New Size (to be written to register file)always @(posedge clk) new_sizeb <= #1 (out_op & dma_en) ? max_pl_sz : (in_op ? size_next : sizu_c);always @(posedge clk) new_size <= #1 buf_size - new_sizeb; //new_size <= #1 buf_size - ((out_op & dma_en) ? max_pl_sz : (in_op ? size_next : sizu_c));//assign new_size = buf_size - ((out_op & dma_en) ? max_pl_sz : (in_op ? size_next : sizu_c));// New Buffer Address (to be written to register file)always @(posedge clk) adr_r <= #1 adr;always @(posedge clk) size_next_r <= #1 size_next;//assign new_adr = adr_r + (in_op ? size_next_r : {3'h0, sizu_c});assign new_adr = adr_r + ((out_op & dma_en) ? max_pl_sz : (in_op ? size_next_r : {3'h0, sizu_c}));// Buffer Overflowalways @(posedge clk) buffer_overflow <= #1 (sizu_c > buf_size) & rx_data_valid;// OUT packet smaller than MAX_PL_SZ in DMA operationalways @(posedge clk) out_to_small_r <= #1 uc_stat_set_d & out_op & dma_en & (sizu_c != max_pl_sz);always @(posedge clk) out_to_small <= #1 out_to_small_r;/////////////////////////////////////////////////////////////////////// Determine if packet is to small or to large// This is used to NACK and ignore packet for OUT endpoints//always @(posedge clk) to_small <= #1 !sml_ok & (sizu_c < max_pl_sz);always @(posedge clk) to_large <= #1 !lrg_ok & (sizu_c > max_pl_sz);/////////////////////////////////////////////////////////////////////// Register File Update Logic//assign next_bsel = dma_en ? 0 : buffer_done ? uc_bsel + 1 : uc_bsel;always @(posedge clk) idin[31:17] <= #1 out_to_small_r ? {4'h0,sizu_c} : {buffer_done,new_size};always @(posedge clk) idin[SSRAM_HADR + 2:4] <= #1 out_to_small_r ? buf0_adr[SSRAM_HADR + 2:4] : new_adr[SSRAM_HADR + 2:4];always @(posedge clk) if(buf_set_d) idin[3:0] <= #1 new_adr[3:0]; else if(out_to_small_r) idin[3:0] <= #1 buf0_adr[3:0]; else idin[3:0] <= #1 {next_dpid, next_bsel};always @(posedge clk) buf0_set <= #1 !buf_sel & buf_set_d;always @(posedge clk) buf1_set <= #1 buf_sel & buf_set_d;always @(posedge clk) uc_bsel_set <= #1 uc_stat_set_d;always @(posedge clk) uc_dpd_set <= #1 uc_stat_set_d;always @(posedge clk) buf0_rl <= #1 buf0_rl_d;// Abort signalalways @(posedge clk) abort <= #1 buffer_overflow | (match & (state != IDLE) ) | to_large;//assign abort = buffer_overflow | (match & (state != IDLE) ) | 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 <= #1 tx_valid | rx_ack_to_clr_d;always @(posedge clk) if(rx_ack_to_clr) rx_ack_to_cnt <= #1 0; else rx_ack_to_cnt <= #1 rx_ack_to_cnt + 1;always @(posedge clk) rx_ack_to <= #1 (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 <= #1 0; else tx_data_to_cnt <= #1 tx_data_to_cnt + 1;always @(posedge clk) tx_data_to <= #1 (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//assign int_buf1_set = !buf_sel & buffer_done & int_set_en;assign int_buf0_set = buf_sel & buffer_done & int_set_en;always @(posedge clk) int_upid_set <= #1 match_r & !pid_SOF & ( // FIX_ME (OUT_ep & !pid_OUT & !pid_PING) | (IN_ep & !pid_IN) | (CTRL_ep & !pid_IN & !pid_OUT & !pid_PING) );assign int_to_set = rx_ack_to | tx_data_to;assign int_crc16_set = rx_data_done & crc16_err;always @(posedge clk) int_seqerr_set <= #1 int_seqerr_set_d;/////////////////////////////////////////////////////////////////////// Main Protocol State Machine//always @(posedge clk) if(!rst) state <= #1 IDLE; else if(match) state <= #1 IDLE; else state <= #1 next_state;always @(state or ep_stall or in_op or out_op 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 buf_sel 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) begin next_state = state; token_pid_sel_d = ACK; send_token_d = 0; rx_dma_en = 0; tx_dma_en = 0; buf_set_d = 0; uc_stat_set_d = 0; buf0_rl_d = 0; int_set_en = 0; rx_ack_to_clr_d = 1; int_seqerr_set_d = 0; case(state) // synopsys full_case parallel_case IDLE: begin 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; 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; next_state = TOKEN; end else if(pid_PING & mode_hs) begin token_pid_sel_d = ACK; send_token_d = 1; next_state = TOKEN; end else if(IN_ep | (CTRL_ep & pid_IN)) begin tx_dma_en = 1; next_state = IN; end else if(OUT_ep | (CTRL_ep & (pid_OUT | pid_SETUP))) begin rx_dma_en = 1; next_state = OUT; end end end TOKEN: begin next_state = IDLE; end IN: begin if(idma_done) begin if(txfr_iso) next_state = UPDATE; else next_state = IN2; end end IN2: begin rx_ack_to_clr_d = 0; // 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 //else //if(token_valid) next_state = IDLE; // FIX_ME end OUT: begin 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; 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 if(abort) next_state = IDLE; else next_state = OUT2B; end OUT2B: begin // Send ACK/NACK/NYET 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; 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; next_state = UPDATE; end end UPDATEW: begin next_state = UPDATE; end UPDATE: begin // Interrupts int_set_en = 1; // Buffer (used, size, adr) set or reload if(buffer_done & dma_en) begin buf0_rl_d = 1; end else begin buf_set_d = 1; end next_state = UPDATE2; end UPDATE2: // Update Register File & state begin // pid sequence & buffer usage uc_stat_set_d = 1; next_state = IDLE; end endcase endendmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -