📄 usbf_pe.v
字号:
assign txfr_iso = csr[25:24]==2'b01;assign txfr_bulk = csr[25:24]==2'b10;assign ep_disabled = csr[23:22]==2'b01;assign ep_stall = csr[23:22]==2'b10;assign lrg_ok = csr[17];assign sml_ok = csr[16];assign dma_en = csr[15] & !CTRL_ep;assign tr_fr = csr[12:11];assign max_pl_sz = csr[10:0];assign uc_dpd = csr[29:28];assign uc_bsel = csr[31:30];// Buffer decoding and allocation checksassign buf0_adr = buf0[SSRAM_HADR + 2:0];assign buf1_adr = buf1[SSRAM_HADR + 2:0];assign buf0_sz = buf0[30:17];assign buf1_sz = buf1[30:17];// Buffers Not Availablealways @(posedge clk) buf0_na <= buf0[31] | ( &buf0_adr );always @(posedge clk) buf1_na <= buf1[31] | ( &buf1_adr );// Buffer Not Allocatedalways @(posedge clk) buf0_not_aloc <= &buf0_adr;always @(posedge clk) buf1_not_aloc <= &buf1_adr;always @(posedge clk) match_r <= match;// No Such Endpoint Indicatoralways @(posedge clk) nse_err <= token_valid & (pid_OUT | pid_IN | pid_SETUP) & !match;always @(posedge clk) send_token <= send_token_d;always @(posedge clk) token_pid_sel <= token_pid_sel_d;/////////////////////////////////////////////////////////////////////// Data Pid Sequencer//assign tr_fr_d = mode_hs ? tr_fr : 2'h0;always @(posedge clk) // tr/mf:ep/type:tr/type:last dpd casex({tr_fr_d,csr[27:26],csr[25:24],uc_dpd}) // synopsys full_case parallel_case 8'b0?_01_01_??: next_dpid <= 2'b00; // ISO txfr. IN, 1 tr/mf 8'b10_01_01_?0: next_dpid <= 2'b01; // ISO txfr. IN, 2 tr/mf 8'b10_01_01_?1: next_dpid <= 2'b00; // ISO txfr. IN, 2 tr/mf 8'b11_01_01_00: next_dpid <= 2'b01; // ISO txfr. IN, 3 tr/mf 8'b11_01_01_01: next_dpid <= 2'b10; // ISO txfr. IN, 3 tr/mf 8'b11_01_01_10: next_dpid <= 2'b00; // ISO txfr. IN, 3 tr/mf 8'b0?_10_01_??: next_dpid <= 2'b00; // ISO txfr. OUT, 1 tr/mf 8'b10_10_01_??: // ISO txfr. OUT, 2 tr/mf begin // Resynchronize in case of PID error case({pid_MDATA, pid_DATA1}) // synopsys full_case parallel_case 2'b10: next_dpid <= 2'b01; 2'b01: next_dpid <= 2'b00; endcase end 8'b11_10_01_00: // ISO txfr. OUT, 3 tr/mf begin // Resynchronize in case of PID error case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case 2'b10: next_dpid <= 2'b01; 2'b01: next_dpid <= 2'b00; endcase end 8'b11_10_01_01: // ISO txfr. OUT, 3 tr/mf begin // Resynchronize in case of PID error case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case 2'b10: next_dpid <= 2'b10; 2'b01: next_dpid <= 2'b00; endcase end 8'b11_10_01_10: // ISO txfr. OUT, 3 tr/mf begin // Resynchronize in case of PID error case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case 2'b10: next_dpid <= 2'b01; 2'b01: next_dpid <= 2'b00; endcase end 8'b??_01_00_?0, // IN/OUT endpoint only 8'b??_10_00_?0: next_dpid <= 2'b01; // INT transfers 8'b??_01_00_?1, // IN/OUT endpoint only 8'b??_10_00_?1: next_dpid <= 2'b00; // INT transfers 8'b??_01_10_?0, // IN/OUT endpoint only 8'b??_10_10_?0: next_dpid <= 2'b01; // BULK transfers 8'b??_01_10_?1, // IN/OUT endpoint only 8'b??_10_10_?1: next_dpid <= 2'b00; // BULK transfers 8'b??_00_??_??: // CTRL Endpoint casex({setup_token, in_op, out_op, uc_dpd}) // synopsys full_case parallel_case 5'b1_??_??: next_dpid <= 2'b11; // SETUP operation 5'b0_10_0?: next_dpid <= 2'b11; // IN operation 5'b0_10_1?: next_dpid <= 2'b01; // IN operation 5'b0_01_?0: next_dpid <= 2'b11; // OUT operation 5'b0_01_?1: next_dpid <= 2'b10; // OUT operation endcase endcase// Current PID decoder// Allow any PID for ISO. transfers when mode full speed or tr_fr is zeroalways @(pid_DATA0 or pid_DATA1 or pid_DATA2 or pid_MDATA) case({pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA} ) // synopsys full_case parallel_case 4'b1000: allow_pid = 2'b00; 4'b0100: allow_pid = 2'b01; 4'b0010: allow_pid = 2'b10; 4'b0001: allow_pid = 2'b11; endcasealways @(posedge clk) // tf/mf:ep/type:tr/type:last dpd casex({tr_fr_d,csr[27:26],csr[25:24],uc_dpd}) // synopsys full_case parallel_case 8'b0?_01_01_??: this_dpid <= 2'b00; // ISO txfr. IN, 1 tr/mf 8'b10_01_01_?0: this_dpid <= 2'b01; // ISO txfr. IN, 2 tr/mf 8'b10_01_01_?1: this_dpid <= 2'b00; // ISO txfr. IN, 2 tr/mf 8'b11_01_01_00: this_dpid <= 2'b10; // ISO txfr. IN, 3 tr/mf 8'b11_01_01_01: this_dpid <= 2'b01; // ISO txfr. IN, 3 tr/mf 8'b11_01_01_10: this_dpid <= 2'b00; // ISO txfr. IN, 3 tr/mf 8'b00_10_01_??: this_dpid <= allow_pid; // ISO txfr. OUT, 0 tr/mf 8'b01_10_01_??: this_dpid <= 2'b00; // ISO txfr. OUT, 1 tr/mf 8'b10_10_01_?0: this_dpid <= 2'b11; // ISO txfr. OUT, 2 tr/mf 8'b10_10_01_?1: this_dpid <= 2'b01; // ISO txfr. OUT, 2 tr/mf 8'b11_10_01_00: this_dpid <= 2'b11; // ISO txfr. OUT, 3 tr/mf 8'b11_10_01_01: this_dpid <= 2'b11; // ISO txfr. OUT, 3 tr/mf 8'b11_10_01_10: this_dpid <= 2'b10; // ISO txfr. OUT, 3 tr/mf 8'b??_01_00_?0, // IN/OUT endpoint only 8'b??_10_00_?0: this_dpid <= 2'b00; // INT transfers 8'b??_01_00_?1, // IN/OUT endpoint only 8'b??_10_00_?1: this_dpid <= 2'b01; // INT transfers 8'b??_01_10_?0, // IN/OUT endpoint only 8'b??_10_10_?0: this_dpid <= 2'b00; // BULK transfers 8'b??_01_10_?1, // IN/OUT endpoint only 8'b??_10_10_?1: this_dpid <= 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 <= 2'b00; // SETUP operation 5'b0_10_0?: this_dpid <= 2'b00; // IN operation 5'b0_10_1?: this_dpid <= 2'b01; // IN operation 5'b0_01_?0: this_dpid <= 2'b00; // OUT operation 5'b0_01_?1: this_dpid <= 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 <= !( (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 endpoints`ifdef USBF_ASYNC_RESETalways @(posedge clk or negedge rst)`elsealways @(posedge clk)`endif if(!rst) in_token <= 1'b0; else if(pid_IN) in_token <= 1'b1; else if(pid_OUT || pid_SETUP) in_token <= 1'b0;`ifdef USBF_ASYNC_RESETalways @(posedge clk or negedge rst)`elsealways @(posedge clk)`endif if(!rst) out_token <= 1'b0; else if(pid_OUT || pid_SETUP) out_token <= 1'b1; else if(pid_IN) out_token <= 1'b0;`ifdef USBF_ASYNC_RESETalways @(posedge clk or negedge rst)`elsealways @(posedge clk)`endif if(!rst) setup_token <= 1'b0; else if(pid_SETUP) setup_token <= 1'b1; else if(pid_OUT || pid_IN) setup_token <= 1'b0;// 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 ? 1'b0 : CTRL_ep ? in_token : ((uc_bsel[0] | buf0_na) & !buf1_na);// Select Address for IDMAalways @(posedge clk) 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 < {3'h0, 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 <= new_size < {3'h0, max_pl_sz};// Buffer Empty (only for IN endpoints)// Indicates that there are zero bytes left in the bufferalways @(posedge clk) buffer_empty <= (new_size == 14'h0);// Joint buffer full/empty flag This is the "USED" flagalways @(posedge clk) 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 <= (buf0_sz < {3'h0, max_pl_sz});always @(posedge clk) buf1_st_max <= (buf1_sz < {3'h0, max_pl_sz});always @(posedge clk) no_bufs0 <= buf0_na | no_buf0_dma | (buf_sel ? buf0_st_max : (buffer_full & !dma_en));always @(posedge clk) no_bufs1 <= buf1_na | (buf_sel ? buffer_full : buf1_st_max);assign no_bufs = no_bufs0 & no_bufs1;// New Size (to be written to register file)always @(posedge clk) new_sizeb <= (out_op && dma_en) ? max_pl_sz : (in_op ? size_next : sizu_c);always @(posedge clk) new_size <= buf_size - new_sizeb;// New Buffer Address (to be written to register file)always @(posedge clk) adr_r <= adr;always @(posedge clk) size_next_r <= size_next;assign new_adr = adr_r[SSRAM_HADR + 2:0] + ((out_op && dma_en) ? {{SSRAM_HADR + 2-10{1'b0}}, max_pl_sz[10:0]} : (in_op ? {{SSRAM_HADR + 2-13{1'b0}}, size_next_r[13:0] } : { {SSRAM_HADR + 2-10{1'b0}}, sizu_c[10:0]}));// Buffer Overflowalways @(posedge clk) buffer_overflow <= ( {3'h0, sizu_c} > buf_size) & rx_data_valid;// OUT packet smaller than MAX_PL_SZ in DMA operationalways @(posedge clk) out_to_small_r <= uc_stat_set_d & out_op & dma_en & (sizu_c != max_pl_sz);always @(posedge clk) out_to_small <= 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 <= !sml_ok & (sizu_c < max_pl_sz);always @(posedge clk) to_large <= !lrg_ok & (sizu_c > max_pl_sz);/////////////////////////////////////////////////////////////////////// Register File Update Logic//assign next_bsel = dma_en ? 2'h0 : buffer_done ? uc_bsel + 2'h1 : uc_bsel; // FIX_MEalways @(posedge clk) idin[31:17] <= out_to_small_r ? {4'h0,sizu_c} : {buffer_done,new_size};always @(posedge clk) idin[SSRAM_HADR + 2:4] <= 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] <= new_adr[3:0]; else if(out_to_small_r) idin[3:0] <= buf0_adr[3:0]; else idin[3:0] <= {next_dpid, next_bsel};always @(posedge clk) buf0_set <= !buf_sel & buf_set_d;always @(posedge clk) buf1_set <= buf_sel & buf_set_d;always @(posedge clk) uc_bsel_set <= uc_stat_set_d;always @(posedge clk) uc_dpd_set <= uc_stat_set_d;always @(posedge clk) buf0_rl <= buf0_rl_d;// Abort signalalways @(posedge clk)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -