?? 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 valid
input rx_data_done; // Indicates end of a transfer
input crc16_err; // Data packet CRC 16 error
// Packet Assembler Interface
output send_token;
output [1:0] token_pid_sel;
output [1:0] data_pid_sel;
// IDMA Interface
output rx_dma_en; // Allows the data to be stored
output tx_dma_en; // Allows for data to be retrieved
output abort; // Abort Transfer (time_out, crc_err or rx_error)
input idma_done; // DMA is done indicator
input ep_full; // Indicates the endpoints fifo is full
input ep_empty; // Indicates the endpoints fifo is empty
// Register File interface
input fsel; // This function is selected
input [3:0] ep_sel; // Endpoint Number Input
input match; // Endpoint Matched
output nse_err; // no such endpoint error
output int_upid_set; // Set unsupported PID interrupt
output int_crc16_set; // Set CRC16 error interrupt
output int_to_set; // Set time out interrupt
output int_seqerr_set; // Set PID sequence error interrupt
input [13:0] csr; // Internal CSR Output
input send_stall; // Force sending a STALL during setup
///////////////////////////////////////////////////////////////////
//
// Local Wires and Registers
//
// tx token decoding
parameter ACK = 0,
NACK = 1,
STALL = 2,
NYET = 3;
// State decoding
parameter [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 Decoding
wire IN_ep, OUT_ep, CTRL_ep; // Endpoint Types
wire txfr_iso, txfr_bulk, txfr_int; // Transfer Types
reg [1:0] uc_dpd;
// Buffer checks
reg [9:0] /* synopsys enum state */ state, next_state;
// synopsys state_vector state
// PID next and current decoders
reg [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 timer
reg 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 timer
wire 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 operation
reg [1:0] allow_pid;
reg nse_err;
reg abort;
wire [1:0] ep_type, txfr_type;
///////////////////////////////////////////////////////////////////
//
// Misc Logic
//
// Endpoint/CSR Decoding
assign 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 Indicator
always @(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 zero
always @(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;
endcase
always @(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
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -