📄 usb1_pe.v
字号:
///////////////////////////////////////////////////////////////////////// //////// Protocol Engine //////// Performs automatic protocol functions //////// //////// Author: Rudolf Usselmann //////// rudi@asics.ws //////// //////// //////// Downloaded from: http://www.opencores.org/cores/usb1_funct///////// ///////////////////////////////////////////////////////////////////////////// //////// Copyright (C) 2000-2002 Rudolf Usselmann //////// www.asics.ws //////// rudi@asics.ws //////// //////// This source file may be used and distributed without //////// restriction provided that this copyright statement is not //////// removed from the file and that any derivative work contains //////// the original copyright notice and the associated disclaimer.//////// //////// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //////// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //////// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //////// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //////// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //////// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //////// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //////// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //////// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //////// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //////// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //////// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //////// POSSIBILITY OF SUCH DAMAGE. //////// /////////////////////////////////////////////////////////////////////////// CVS Log//// $Id: usb1_pe.v,v 1.1.1.1 2002/09/19 12:07:24 rudi Exp $//// $Date: 2002/09/19 12:07:24 $// $Revision: 1.1.1.1 $// $Author: rudi $// $Locker: $// $State: Exp $//// Change History:// $Log: usb1_pe.v,v $// Revision 1.1.1.1 2002/09/19 12:07:24 rudi// Initial Checkin//////////////`include "usb1_defines.v"module usb1_pe( clk, rst, // UTMI Interfaces tx_valid, rx_active, // PID Information pid_OUT, pid_IN, pid_SOF, pid_SETUP, pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA, pid_ACK, pid_PING, // Token Information token_valid, // Receive Data Output rx_data_done, crc16_err, // Packet Assembler Interface send_token, token_pid_sel, data_pid_sel, // IDMA Interface rx_dma_en, tx_dma_en, abort, idma_done, // Register File Interface fsel, ep_sel, match, nse_err, ep_full, ep_empty, int_upid_set, int_crc16_set, int_to_set, int_seqerr_set, csr, send_stall );input clk, rst;input tx_valid, rx_active;// Packet Disassembler Interface // Decoded PIDs (used when token_valid is asserted)input pid_OUT, pid_IN, pid_SOF, pid_SETUP;input pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA;input pid_ACK, pid_PING;input token_valid; // Token is validinput rx_data_done; // Indicates end of a transferinput crc16_err; // Data packet CRC 16 error// Packet Assembler Interfaceoutput send_token;output [1:0] token_pid_sel;output [1:0] data_pid_sel;// IDMA Interfaceoutput rx_dma_en; // Allows the data to be storedoutput tx_dma_en; // Allows for data to be retrievedoutput abort; // Abort Transfer (time_out, crc_err or rx_error)input idma_done; // DMA is done indicatorinput ep_full; // Indicates the endpoints fifo is fullinput ep_empty; // Indicates the endpoints fifo is empty// Register File interfaceinput fsel; // This function is selectedinput [3:0] ep_sel; // Endpoint Number Inputinput match; // Endpoint Matchedoutput nse_err; // no such endpoint erroroutput int_upid_set; // Set unsupported PID interruptoutput int_crc16_set; // Set CRC16 error interruptoutput int_to_set; // Set time out interruptoutput int_seqerr_set; // Set PID sequence error interruptinput [13:0] csr; // Internal CSR Outputinput send_stall; // Force sending a STALL during setup/////////////////////////////////////////////////////////////////////// Local Wires and Registers//// tx token decodingparameter ACK = 0, NACK = 1, STALL = 2, NYET = 3;// State decodingparameter [9:0] // synopsys enum state IDLE = 10'b000000_0001, TOKEN = 10'b000000_0010, IN = 10'b000000_0100, IN2 = 10'b000000_1000, OUT = 10'b000001_0000, OUT2A = 10'b000010_0000, OUT2B = 10'b000100_0000, UPDATEW = 10'b001000_0000, UPDATE = 10'b010000_0000, UPDATE2 = 10'b100000_0000;reg [1:0] token_pid_sel;reg [1:0] token_pid_sel_d;reg send_token;reg send_token_d;reg rx_dma_en, tx_dma_en;reg int_seqerr_set_d;reg int_seqerr_set;reg int_upid_set;reg match_r;// Endpoint Decodingwire IN_ep, OUT_ep, CTRL_ep; // Endpoint Typeswire txfr_iso, txfr_bulk, txfr_int; // Transfer Typesreg [1:0] uc_dpd;// Buffer checksreg [9:0] /* synopsys enum state */ state, next_state;// synopsys state_vector state// PID next and current decodersreg [1:0] next_dpid;reg [1:0] this_dpid;reg pid_seq_err;wire [1:0] tr_fr_d;wire [13:0] size_next;wire buf_smaller;// After sending Data in response to an IN token from host, the// host must reply with an ack. The host has XXXnS to reply.// "rx_ack_to" indicates when this time has expired.// rx_ack_to_clr, clears the timerreg rx_ack_to_clr;reg rx_ack_to_clr_d;reg rx_ack_to;reg [7:0] rx_ack_to_cnt;// After sending a OUT token the host must send a data packet.// The host has XX nS to send the packet. "tx_data_to" indicates// when this time has expired.// tx_data_to_clr, clears the timerwire tx_data_to_clr;reg tx_data_to;reg [7:0] tx_data_to_cnt;wire [7:0] rx_ack_to_val, tx_data_to_val;wire [1:0] next_bsel;reg uc_stat_set_d;reg uc_dpd_set;reg in_token;reg out_token;reg setup_token;wire in_op, out_op; // Indicate a IN or OUT operationreg [1:0] allow_pid;reg nse_err;reg abort;wire [1:0] ep_type, txfr_type;/////////////////////////////////////////////////////////////////////// Misc Logic//// Endpoint/CSR Decodingassign IN_ep = csr[9];assign OUT_ep = csr[10];assign CTRL_ep = csr[11];assign txfr_iso = csr[12];assign txfr_bulk = csr[13];assign txfr_int = !csr[12] & !csr[13];assign ep_type = csr[10:9];assign txfr_type = csr[13:12];always @(posedge clk) match_r <= #1 match & fsel;// No Such Endpoint Indicatoralways @(posedge clk) nse_err <= #1 token_valid & (pid_OUT | pid_IN | pid_SETUP) & !match;always @(posedge clk) send_token <= #1 send_token_d;always @(posedge clk) token_pid_sel <= #1 token_pid_sel_d;/////////////////////////////////////////////////////////////////////// Data Pid Storage//reg [1:0] ep0_dpid, ep1_dpid, ep2_dpid, ep3_dpid;reg [1:0] ep4_dpid, ep5_dpid, ep6_dpid, ep7_dpid;always @(posedge clk or negedge rst) if(!rst) ep0_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h0)) ep0_dpid <= next_dpid;always @(posedge clk or negedge rst) if(!rst) ep1_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h1)) ep1_dpid <= next_dpid;always @(posedge clk or negedge rst) if(!rst) ep2_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h2)) ep2_dpid <= next_dpid;always @(posedge clk or negedge rst) if(!rst) ep3_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h3)) ep3_dpid <= next_dpid;always @(posedge clk or negedge rst) if(!rst) ep4_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h4)) ep4_dpid <= next_dpid;always @(posedge clk or negedge rst) if(!rst) ep5_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h5)) ep5_dpid <= next_dpid;always @(posedge clk or negedge rst) if(!rst) ep6_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h6)) ep6_dpid <= next_dpid;always @(posedge clk or negedge rst) if(!rst) ep7_dpid <= 2'b00; else if(uc_dpd_set & (ep_sel == 4'h7)) ep7_dpid <= next_dpid;always @(posedge clk) case(ep_sel) 4'h0: uc_dpd <= ep0_dpid; 4'h1: uc_dpd <= ep1_dpid; 4'h2: uc_dpd <= ep2_dpid; 4'h3: uc_dpd <= ep3_dpid; 4'h4: uc_dpd <= ep4_dpid; 4'h5: uc_dpd <= ep5_dpid; 4'h6: uc_dpd <= ep6_dpid; 4'h7: uc_dpd <= ep7_dpid; endcase/////////////////////////////////////////////////////////////////////// Data Pid Sequencer//assign tr_fr_d = 2'h0;always @(posedge clk) // tr/mf:ep/type:tr/type:last dpd casex({tr_fr_d,ep_type,txfr_type,uc_dpd}) // synopsys full_case parallel_case 8'b0?_01_01_??: next_dpid <= #1 2'b00; // ISO txfr. IN, 1 tr/mf 8'b10_01_01_?0: next_dpid <= #1 2'b01; // ISO txfr. IN, 2 tr/mf 8'b10_01_01_?1: next_dpid <= #1 2'b00; // ISO txfr. IN, 2 tr/mf 8'b11_01_01_00: next_dpid <= #1 2'b01; // ISO txfr. IN, 3 tr/mf 8'b11_01_01_01: next_dpid <= #1 2'b10; // ISO txfr. IN, 3 tr/mf 8'b11_01_01_10: next_dpid <= #1 2'b00; // ISO txfr. IN, 3 tr/mf 8'b0?_10_01_??: next_dpid <= #1 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 <= #1 2'b01; 2'b01: next_dpid <= #1 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 <= #1 2'b01; 2'b01: next_dpid <= #1 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 <= #1 2'b10; 2'b01: next_dpid <= #1 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 <= #1 2'b01; 2'b01: next_dpid <= #1 2'b00; endcase end 8'b??_01_00_?0, // IN/OUT endpoint only 8'b??_10_00_?0: next_dpid <= #1 2'b01; // INT transfers 8'b??_01_00_?1, // IN/OUT endpoint only 8'b??_10_00_?1: next_dpid <= #1 2'b00; // INT transfers 8'b??_01_10_?0, // IN/OUT endpoint only 8'b??_10_10_?0: next_dpid <= #1 2'b01; // BULK transfers 8'b??_01_10_?1, // IN/OUT endpoint only 8'b??_10_10_?1: next_dpid <= #1 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 <= #1 2'b11; // SETUP operation 5'b0_10_0?: next_dpid <= #1 2'b11; // IN operation 5'b0_10_1?: next_dpid <= #1 2'b01; // IN operation 5'b0_01_?0: next_dpid <= #1 2'b11; // OUT operation 5'b0_01_?1: next_dpid <= #1 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,ep_type,txfr_type,uc_dpd}) // synopsys full_case parallel_case 8'b0?_01_01_??: this_dpid <= #1 2'b00; // ISO txfr. IN, 1 tr/mf 8'b10_01_01_?0: this_dpid <= #1 2'b01; // ISO txfr. IN, 2 tr/mf 8'b10_01_01_?1: this_dpid <= #1 2'b00; // ISO txfr. IN, 2 tr/mf 8'b11_01_01_00: this_dpid <= #1 2'b10; // ISO txfr. IN, 3 tr/mf 8'b11_01_01_01: this_dpid <= #1 2'b01; // ISO txfr. IN, 3 tr/mf 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -