OpenFPGA/openfpga_flow/benchmarks/iwls2005/usb_funct/rtl/usbf_pl.v

484 lines
14 KiB
Verilog

/////////////////////////////////////////////////////////////////////
//// ////
//// Protocol Layer ////
//// This block is typically referred to as the SEI in USB ////
//// Specification. It encapsulates the Packet Assembler, ////
//// disassembler, protocol engine and internal DMA ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/usb/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000-2003 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: usbf_pl.v,v 1.5 2003/10/17 02:36:57 rudi Exp $
//
// $Date: 2003/10/17 02:36:57 $
// $Revision: 1.5 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: usbf_pl.v,v $
// Revision 1.5 2003/10/17 02:36:57 rudi
// - Disabling bit stuffing and NRZI encoding during speed negotiation
// - Now the core can send zero size packets
// - Fixed register addresses for some of the higher endpoints
// (conversion between decimal/hex was wrong)
// - The core now does properly evaluate the function address to
// determine if the packet was intended for it.
// - Various other minor bugs and typos
//
// Revision 1.4 2001/11/04 12:22:45 rudi
//
// - Fixed previous fix (brocke something else ...)
// - Majore Synthesis cleanup
//
// Revision 1.3 2001/09/24 01:15:28 rudi
//
// Changed reset to be active high async.
//
// Revision 1.2 2001/08/10 08:48:33 rudi
//
// - Changed IO names to be more clear.
// - Uniquifyed define names to be core specific.
//
// Revision 1.1 2001/08/03 05:30:09 rudi
//
//
// 1) Reorganized directory structure
//
// Revision 1.2 2001/03/31 13:00:52 rudi
//
// - Added Core configuration
// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode
// - Modified WISHBONE interface and sync logic
// - Moved SSRAM outside the core (added interface)
// - Many small bug fixes ...
//
// Revision 1.0 2001/03/07 09:17:12 rudi
//
//
// Changed all revisions to revision 1.0. This is because OpenCores CVS
// interface could not handle the original '0.1' revision ....
//
// Revision 0.1.0.1 2001/02/28 08:11:11 rudi
// Initial Release
//
//
`include "usbf_defines.v"
module usbf_pl( clk, rst,
// UTMI Interface
rx_data, rx_valid, rx_active, rx_err,
tx_data, tx_valid, tx_valid_last, tx_ready,
tx_first, tx_valid_out,
mode_hs, usb_reset, usb_suspend, usb_attached,
// memory interface
madr, mdout, mdin, mwe, mreq, mack,
// Register File Interface
fa, idin,
ep_sel, match,
dma_in_buf_sz1, dma_out_buf_avail,
buf0_rl, buf0_set, buf1_set,
uc_bsel_set, uc_dpd_set,
int_buf1_set, int_buf0_set, int_upid_set,
int_crc16_set, int_to_set, int_seqerr_set,
out_to_small, csr, buf0, buf1,
// Misc
frm_nat,
pid_cs_err, nse_err,
crc5_err
);
parameter SSRAM_HADR = 14;
// UTMI Interface
input clk, rst;
input [7:0] rx_data;
input rx_valid, rx_active, rx_err;
output [7:0] tx_data;
output tx_valid;
output tx_valid_last;
input tx_ready;
output tx_first;
input tx_valid_out;
input mode_hs; // High Speed Mode
input usb_reset; // USB Reset
input usb_suspend; // USB Suspend
input usb_attached; // Attached to USB
// Memory Arbiter Interface
output [SSRAM_HADR:0] madr; // word address
output [31:0] mdout;
input [31:0] mdin;
output mwe;
output mreq;
input mack;
// Register File interface
input [6:0] fa; // Function Address (as set by the controller)
output [31:0] idin; // Data Input
output [3:0] ep_sel; // Endpoint Number Input
input match; // Endpoint Matched
input dma_in_buf_sz1;
input dma_out_buf_avail;
output nse_err; // no such endpoint error
output buf0_rl; // Reload Buf 0 with original values
output buf0_set; // Write to buf 0
output buf1_set; // Write to buf 1
output uc_bsel_set; // Write to the uc_bsel field
output uc_dpd_set; // Write to the uc_dpd field
output int_buf1_set; // Set buf1 full/empty interrupt
output int_buf0_set; // Set buf0 full/empty interrupt
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
output out_to_small; // OUT packet was to small for DMA operation
input [31:0] csr; // Internal CSR Output
input [31:0] buf0; // Internal Buf 0 Output
input [31:0] buf1; // Internal Buf 1 Output
// Misc
output pid_cs_err; // pid checksum error
output crc5_err; // crc5 error
output [31:0] frm_nat;
///////////////////////////////////////////////////////////////////
//
// Local Wires and Registers
//
// Packet Disassembler Interface
wire clk, rst;
wire [7:0] rx_data;
wire pid_OUT, pid_IN, pid_SOF, pid_SETUP;
wire pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA;
wire pid_ACK, pid_NACK, pid_STALL, pid_NYET;
wire pid_PRE, pid_ERR, pid_SPLIT, pid_PING;
wire [6:0] token_fadr;
wire token_valid;
wire crc5_err;
wire [10:0] frame_no;
wire [7:0] rx_data_st;
wire rx_data_valid;
wire rx_data_done;
wire crc16_err;
wire rx_seq_err;
// Packet Assembler Interface
wire send_token;
wire [1:0] token_pid_sel;
wire send_data;
wire [1:0] data_pid_sel;
wire [7:0] tx_data_st;
wire rd_next;
// IDMA Interface
wire rx_dma_en; // Allows the data to be stored
wire tx_dma_en; // Allows for data to be retrieved
wire abort; // Abort Transfer (time_out, crc_err or rx_error)
wire idma_done; // DMA is done
wire [SSRAM_HADR + 2:0] adr; // Byte Address
wire [13:0] size; // Size in bytes
wire [10:0] sizu_c; // Up and Down counting size registers, used
// to update
wire [13:0] buf_size; // Actual buffer size
wire dma_en; // external dma enabled
// Memory Arbiter Interface
wire [SSRAM_HADR:0] madr; // word address
wire [31:0] mdout;
wire [31:0] mdin;
wire mwe;
wire mreq;
wire mack;
// Local signals
wire pid_bad, pid_bad1, pid_bad2;
reg hms_clk; // 0.5 Micro Second Clock
reg [4:0] hms_cnt;
reg [10:0] frame_no_r; // Current Frame Number register
wire frame_no_we;
reg frame_no_same; // Indicates current and prev. frame numbers
// are equal
reg [3:0] mfm_cnt; // Micro Frame Counter
reg [11:0] sof_time; // Time since last sof
reg clr_sof_time;
wire fsel; // This Function is selected
wire match_o;
reg frame_no_we_r;
///////////////////////////////////////////////////////////////////
//
// Misc Logic
//
// PIDs we should never receive
assign pid_bad1 = pid_ACK | pid_NACK | pid_STALL | pid_NYET | pid_PRE |
pid_ERR | pid_SPLIT;
// PIDs we should never get in full speed mode (high speed mode only)
assign pid_bad2 = !mode_hs & pid_PING;
// All bad pids
assign pid_bad = pid_bad1 | pid_bad2;
assign match_o = !pid_bad & fsel & match & token_valid & !crc5_err;
// Frame Number (from SOF token)
assign frame_no_we = token_valid & !crc5_err & pid_SOF;
always @(posedge clk)
frame_no_we_r <= frame_no_we;
`ifdef USBF_ASYNC_RESET
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) frame_no_r <= 11'h0;
else
if(frame_no_we_r) frame_no_r <= frame_no;
// Micro Frame Counter
always @(posedge clk)
frame_no_same <= frame_no_we & (frame_no_r == frame_no);
`ifdef USBF_ASYNC_RESET
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) mfm_cnt <= 4'h0;
else
if(frame_no_we_r && !frame_no_same)
mfm_cnt <= 4'h0;
else
if(frame_no_same) mfm_cnt <= mfm_cnt + 4'h1;
//SOF delay counter
always @(posedge clk)
clr_sof_time <= frame_no_we;
always @(posedge clk)
if(clr_sof_time) sof_time <= 12'h0;
else
if(hms_clk) sof_time <= sof_time + 12'h1;
assign frm_nat = {mfm_cnt, 1'b0, frame_no_r, 4'h0, sof_time};
// 0.5 Micro Seconds Clock Generator
`ifdef USBF_ASYNC_RESET
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) hms_cnt <= 5'h0;
else
if(hms_clk || frame_no_we_r) hms_cnt <= 5'h0;
else hms_cnt <= hms_cnt + 5'h1;
always @(posedge clk)
hms_clk <= (hms_cnt == `USBF_HMS_DEL);
///////////////////////////////////////////////////////////////////
// This function is addressed
assign fsel = (token_fadr == fa);
///////////////////////////////////////////////////////////////////
//
// Module Instantiations
//
//Packet Decoder
usbf_pd u0( .clk( clk ),
.rst( rst ),
.rx_data( rx_data ),
.rx_valid( rx_valid ),
.rx_active( rx_active ),
.rx_err( rx_err ),
.pid_OUT( pid_OUT ),
.pid_IN( pid_IN ),
.pid_SOF( pid_SOF ),
.pid_SETUP( pid_SETUP ),
.pid_DATA0( pid_DATA0 ),
.pid_DATA1( pid_DATA1 ),
.pid_DATA2( pid_DATA2 ),
.pid_MDATA( pid_MDATA ),
.pid_ACK( pid_ACK ),
.pid_NACK( pid_NACK ),
.pid_STALL( pid_STALL ),
.pid_NYET( pid_NYET ),
.pid_PRE( pid_PRE ),
.pid_ERR( pid_ERR ),
.pid_SPLIT( pid_SPLIT ),
.pid_PING( pid_PING ),
.pid_cks_err( pid_cs_err ),
.token_fadr( token_fadr ),
.token_endp( ep_sel ),
.token_valid( token_valid ),
.crc5_err( crc5_err ),
.frame_no( frame_no ),
.rx_data_st( rx_data_st ),
.rx_data_valid( rx_data_valid ),
.rx_data_done( rx_data_done ),
.crc16_err( crc16_err ),
.seq_err( rx_seq_err )
);
// Packet Assembler
usbf_pa u1( .clk( clk ),
.rst( rst ),
.tx_data( tx_data ),
.tx_valid( tx_valid ),
.tx_valid_last( tx_valid_last ),
.tx_ready( tx_ready ),
.tx_first( tx_first ),
.send_token( send_token ),
.token_pid_sel( token_pid_sel ),
.send_data( send_data ),
.data_pid_sel( data_pid_sel ),
.send_zero_length( send_zero_length ),
.tx_data_st( tx_data_st ),
.rd_next( rd_next )
);
// Internal DMA / Memory Arbiter Interface
usbf_idma #(SSRAM_HADR)
u2( .clk( clk ),
.rst( rst ),
.rx_data_st( rx_data_st ),
.rx_data_valid( rx_data_valid ),
.rx_data_done( rx_data_done ),
.send_data( send_data ),
.tx_data_st( tx_data_st ),
.rd_next( rd_next ),
.rx_dma_en( rx_dma_en ),
.tx_dma_en( tx_dma_en ),
.abort( abort ),
.idma_done( idma_done ),
.adr( adr ),
.size( size ),
.buf_size( buf_size ),
.dma_en( dma_en ),
.send_zero_length( send_zero_length ),
.madr( madr ),
.sizu_c( sizu_c ),
.mdout( mdout ),
.mdin( mdin ),
.mwe( mwe ),
.mreq( mreq ),
.mack( mack )
);
// Protocol Engine
usbf_pe #(SSRAM_HADR)
u3( .clk( clk ),
.rst( rst ),
.tx_valid( tx_valid_out ),
.rx_active( rx_active ),
.pid_OUT( pid_OUT ),
.pid_IN( pid_IN ),
.pid_SOF( pid_SOF ),
.pid_SETUP( pid_SETUP ),
.pid_DATA0( pid_DATA0 ),
.pid_DATA1( pid_DATA1 ),
.pid_DATA2( pid_DATA2 ),
.pid_MDATA( pid_MDATA ),
.pid_ACK( pid_ACK ),
.pid_NACK( pid_NACK ),
.pid_STALL( pid_STALL ),
.pid_NYET( pid_NYET ),
.pid_PRE( pid_PRE ),
.pid_ERR( pid_ERR ),
.pid_SPLIT( pid_SPLIT ),
.pid_PING( pid_PING ),
.mode_hs( mode_hs ),
.token_valid( token_valid ),
.crc5_err( crc5_err ),
.rx_data_valid( rx_data_valid ),
.rx_data_done( rx_data_done ),
.crc16_err( crc16_err ),
.send_token( send_token ),
.token_pid_sel( token_pid_sel ),
.data_pid_sel( data_pid_sel ),
.send_zero_length( send_zero_length ),
.rx_dma_en( rx_dma_en ),
.tx_dma_en( tx_dma_en ),
.abort( abort ),
.idma_done( idma_done ),
.adr( adr ),
.size( size ),
.buf_size( buf_size ),
.sizu_c( sizu_c ),
.dma_en( dma_en ),
.fsel( fsel ),
.idin( idin ),
.ep_sel( ep_sel ),
.match( match_o ),
.dma_in_buf_sz1( dma_in_buf_sz1 ),
.dma_out_buf_avail( dma_out_buf_avail ),
.nse_err( nse_err ),
.buf0_rl( buf0_rl ),
.buf0_set( buf0_set ),
.buf1_set( buf1_set ),
.uc_bsel_set( uc_bsel_set ),
.uc_dpd_set( uc_dpd_set ),
.int_buf1_set( int_buf1_set ),
.int_buf0_set( int_buf0_set ),
.int_upid_set( int_upid_set ),
.int_crc16_set( int_crc16_set ),
.int_to_set( int_to_set ),
.int_seqerr_set( int_seqerr_set ),
.out_to_small( out_to_small ),
.csr( csr ),
.buf0( buf0 ),
.buf1( buf1 )
);
endmodule