URL
https://opencores.org/ocsvn/usb1_funct/usb1_funct/trunk
Subversion Repositories usb1_funct
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/trunk/rtl/verilog/usb1_fifo.v
0,0 → 1,176
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Generic FIFO //// |
//// //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// rudi@asics.ws //// |
//// //// |
//// //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2001 Rudolf Usselmann //// |
//// 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_fifo.v,v 1.1.1.1 2002-09-19 12:07:32 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:32 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
// |
// |
// |
|
/* |
Special feature: |
|
|
full_n - indicates if there is no more space for 'n' bytes in the FIFO. |
empty_n - indicates if there is less than 'n' bytes in the FIFO. |
|
'n' is a parameter. |
|
*/ |
|
module usb1_fifo(clk, rst, clr, din, we, dout, re, |
full, empty, full_n, empty_n); |
|
parameter dw=8; |
parameter aw=8; |
parameter n=32; |
|
parameter max_size = 1<<aw; |
|
input clk, rst, clr; |
input [dw-1:0] din; |
input we; |
output [dw-1:0] dout; |
input re; |
output full; |
output empty; |
output full_n; |
output empty_n; |
|
//////////////////////////////////////////////////////////////////// |
// |
// Local Wires |
// |
|
reg [aw-1:0] wp; |
wire [aw-1:0] wp_pl1; |
reg [aw-1:0] rp; |
wire [aw-1:0] ra; |
wire [aw-1:0] rp_pl1; |
reg gb; |
|
reg [aw:0] cnt; |
wire full_n, empty_n; |
|
//////////////////////////////////////////////////////////////////// |
// |
// Memory Block |
// |
|
generic_dpram #(aw,dw) u0( |
.rclk( clk ), |
.rrst( !rst ), |
.rce( 1'b1 ), |
.oe( 1'b1 ), |
.raddr( ra ), |
.do( dout ), |
.wclk( clk ), |
.wrst( !rst ), |
.wce( 1'b1 ), |
.we( we ), |
.waddr( wp ), |
.di( din ) |
); |
|
//////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
assign ra = rp; |
|
always @(posedge clk) |
if(!rst) wp <= #1 {aw{1'b0}}; |
else |
if(clr) wp <= #1 {aw{1'b0}}; |
else |
if(we & !full) wp <= #1 wp_pl1; |
|
assign wp_pl1 = wp + { {aw-1{1'b0}}, 1'b1}; |
|
always @(posedge clk) |
if(!rst) rp <= #1 {aw{1'b0}}; |
else |
if(clr) rp <= #1 {aw{1'b0}}; |
else |
if(re & !empty) rp <= #1 rp_pl1; |
|
assign rp_pl1 = rp + { {aw-1{1'b0}}, 1'b1}; |
|
// Status |
assign empty = ((wp == rp) & !gb); |
assign full = ((wp == rp) & gb); |
|
// Guard Bit ... |
always @(posedge clk) |
if(!rst) gb <= #1 1'b0; |
else |
if(clr) gb <= #1 1'b0; |
else |
if((wp_pl1 == rp) & we) gb <= #1 1'b1; |
else |
if(re) gb <= #1 1'b0; |
|
always @(posedge clk) |
if(!rst) cnt <= #1 {aw+1{1'b0}}; |
else |
if(clr) cnt <= #1 {aw+1{1'b0}}; |
else |
if( re & !we) cnt <= #1 cnt + { {aw{1'b1}}, 1'b1}; |
else |
if(!re & we) cnt <= #1 cnt + { {aw{1'b0}}, 1'b1}; |
|
assign empty_n = cnt < n; |
assign full_n = !(cnt < (max_size-n+1)); |
|
endmodule |
|
/trunk/rtl/verilog/usb1_ep_in.v
0,0 → 1,114
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Endpoint Interface //// |
//// //// |
//// 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_ep_in.v,v 1.1.1.1 2002-09-19 12:07:10 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:10 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
module usb1_ep_in(clk, rst, clr, ep_sel, |
usb_dout, usb_re, |
|
// External Endpoint interface |
ep_din, ep_we, ep_stat |
); |
|
parameter MY_EP_ID = 0; |
parameter aw = 6; |
parameter n = 32; |
|
input clk, rst, clr; |
input [3:0] ep_sel; |
output [7:0] usb_dout; |
input usb_re; |
|
input [7:0] ep_din; |
input ep_we; |
output [3:0] ep_stat; |
|
//////////////////////////////////////////////////////////////////// |
// |
// Local Wires |
// |
|
wire usb_we_t, usb_re_t; |
|
//////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
assign usb_re_t = usb_re & (ep_sel == MY_EP_ID); |
|
//////////////////////////////////////////////////////////////////// |
// |
// FIFOs |
// |
|
// dw,aw |
usb1_fifo #(8,aw,n) |
f1( |
.clk( clk ), |
.rst( rst ), |
.clr( clr ), |
.din( ep_din ), |
.we( ep_we ), |
.dout( usb_dout ), |
.re( usb_re_t ), |
.full( ep_stat[0] ), |
.empty( ep_stat[1] ), |
.full_n( ep_stat[2] ), |
.empty_n( ep_stat[3] ) |
); |
|
endmodule |
/trunk/rtl/verilog/usb1_ep_out.v
0,0 → 1,119
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Endpoint Interface //// |
//// //// |
//// 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_ep_out.v,v 1.1.1.1 2002-09-19 12:07:41 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:41 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
module usb1_ep_out( clk, rst, clr, ep_sel, |
usb_din, usb_we, |
|
// External Endpoint interface |
ep_dout, ep_re, ep_stat |
); |
|
parameter MY_EP_ID = 0; |
parameter aw = 6; |
parameter n = 32; |
|
input clk, rst, clr; |
input [3:0] ep_sel; |
input [7:0] usb_din; |
input usb_we; |
|
output [7:0] ep_dout; |
input ep_re; |
output [3:0] ep_stat; |
|
//////////////////////////////////////////////////////////////////// |
// |
// Local Wires |
// |
|
wire usb_we_t, usb_re_t; |
|
//////////////////////////////////////////////////////////////////// |
// |
// Aliases |
// |
|
//////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
assign usb_we_t = usb_we & (ep_sel == MY_EP_ID); |
|
//////////////////////////////////////////////////////////////////// |
// |
// FIFOs |
// |
|
// dw,aw |
usb1_fifo #(8,aw,n) |
f0( |
.clk( clk ), |
.rst( rst ), |
.clr( clr ), |
.din( usb_din ), |
.we( usb_we_t ), |
.dout( ep_dout ), |
.re( ep_re ), |
.full( ep_stat[0] ), |
.empty( ep_stat[1] ), |
.full_n( ep_stat[2] ), |
.empty_n( ep_stat[3] ) |
); |
|
endmodule |
/trunk/rtl/verilog/usb1_utmi_if.v
0,0 → 1,147
///////////////////////////////////////////////////////////////////// |
//// //// |
//// UTMI Interface //// |
//// //// |
//// //// |
//// 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_utmi_if.v,v 1.1.1.1 2002-09-19 12:07:14 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:14 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
module usb1_utmi_if( // UTMI Interface (EXTERNAL) |
phy_clk, rst, |
DataOut, TxValid, TxReady, |
RxValid, RxActive, RxError, DataIn, |
|
// Internal Interface |
rx_data, rx_valid, rx_active, rx_err, |
tx_data, tx_valid, tx_valid_last, tx_ready, |
tx_first |
|
); |
|
input phy_clk; |
input rst; |
|
output [7:0] DataOut; |
output TxValid; |
input TxReady; |
|
input [7:0] DataIn; |
input RxValid; |
input RxActive; |
input RxError; |
|
|
output [7:0] rx_data; |
output rx_valid, rx_active, rx_err; |
input [7:0] tx_data; |
input tx_valid; |
input tx_valid_last; |
output tx_ready; |
input tx_first; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Local Wires and Registers |
// |
reg [7:0] rx_data; |
reg rx_valid, rx_active, rx_err; |
reg [7:0] DataOut; |
reg tx_ready; |
reg TxValid; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
|
/////////////////////////////////////////////////////////////////// |
// |
// RX Interface Input registers |
// |
|
always @(posedge phy_clk or negedge rst) |
if(!rst) rx_valid <= #1 1'b0; |
else rx_valid <= #1 RxValid; |
|
always @(posedge phy_clk or negedge rst) |
if(!rst) rx_active <= #1 1'b0; |
else rx_active <= #1 RxActive; |
|
always @(posedge phy_clk or negedge rst) |
if(!rst) rx_err <= #1 1'b0; |
else rx_err <= #1 RxError; |
|
always @(posedge phy_clk) |
rx_data <= #1 DataIn; |
|
/////////////////////////////////////////////////////////////////// |
// |
// TX Interface Output/Input registers |
// |
|
always @(posedge phy_clk) |
if(TxReady | tx_first) DataOut <= #1 tx_data; |
|
always @(posedge phy_clk) |
tx_ready <= #1 TxReady; |
|
always @(posedge phy_clk or negedge rst) |
if(!rst) TxValid <= #1 1'b0; |
else |
TxValid <= #1 tx_valid | tx_valid_last | (TxValid & !TxReady); |
|
endmodule |
|
/trunk/rtl/verilog/usb1_crc5.v
0,0 → 1,89
///////////////////////////////////////////////////////////////////// |
//// //// |
//// USB CRC5 Modules //// |
//// //// |
//// //// |
//// 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_crc5.v,v 1.1.1.1 2002-09-19 12:07:05 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:05 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
/////////////////////////////////////////////////////////////////// |
// |
// CRC5 |
// |
/////////////////////////////////////////////////////////////////// |
|
module usb1_crc5(crc_in, din, crc_out); |
input [4:0] crc_in; |
input [10:0] din; |
output [4:0] crc_out; |
|
assign crc_out[0] = din[10] ^ din[9] ^ din[6] ^ din[5] ^ din[3] ^ |
din[0] ^ crc_in[0] ^ crc_in[3] ^ crc_in[4]; |
|
assign crc_out[1] = din[10] ^ din[7] ^ din[6] ^ din[4] ^ din[1] ^ |
crc_in[0] ^ crc_in[1] ^ crc_in[4]; |
|
assign crc_out[2] = din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[6] ^ |
din[3] ^ din[2] ^ din[0] ^ crc_in[0] ^ crc_in[1] ^ |
crc_in[2] ^ crc_in[3] ^ crc_in[4]; |
|
assign crc_out[3] = din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[4] ^ din[3] ^ |
din[1] ^ crc_in[1] ^ crc_in[2] ^ crc_in[3] ^ crc_in[4]; |
|
assign crc_out[4] = din[10] ^ din[9] ^ din[8] ^ din[5] ^ din[4] ^ din[2] ^ |
crc_in[2] ^ crc_in[3] ^ crc_in[4]; |
|
endmodule |
|
/trunk/rtl/verilog/usb1_pa.v
0,0 → 1,332
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Packet Assembler //// |
//// Assembles Token and Data USB packets //// |
//// //// |
//// 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_pa.v,v 1.1.1.1 2002-09-19 12:07:13 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:13 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
module usb1_pa( clk, rst, |
|
// UTMI TX I/F |
tx_data, tx_valid, tx_valid_last, tx_ready, |
tx_first, |
|
// Protocol Engine Interface |
send_token, token_pid_sel, |
send_data, data_pid_sel, |
|
// IDMA Interface |
tx_data_st, rd_next, |
|
ep_empty |
); |
|
input clk, rst; |
|
// UTMI TX Interface |
output [7:0] tx_data; |
output tx_valid; |
output tx_valid_last; |
input tx_ready; |
output tx_first; |
|
// Protocol Engine Interface |
input send_token; |
input [1:0] token_pid_sel; |
input send_data; |
input [1:0] data_pid_sel; |
|
// IDMA Interface |
input [7:0] tx_data_st; |
output rd_next; |
|
input ep_empty; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Local Wires and Registers |
// |
|
parameter [3:0] // synopsys enum state |
IDLE = 4'b0001, |
DATA = 4'b0010, |
CRC1 = 4'b0100, |
CRC2 = 4'b1000; |
|
reg [3:0] /* synopsys enum state */ state, next_state; |
// synopsys state_vector state |
|
reg last; |
reg rd_next; |
|
reg [7:0] token_pid, data_pid; // PIDs from selectors |
reg [7:0] tx_data_d; |
reg [7:0] tx_data_data; |
reg dsel; |
reg tx_valid_d; |
reg send_token_r; |
reg [7:0] tx_spec_data; |
reg crc_sel1, crc_sel2; |
reg tx_first_r; |
reg send_data_r; |
wire crc16_clr; |
reg [15:0] crc16; |
wire [15:0] crc16_next; |
wire [15:0] crc16_rev; |
reg crc16_add; |
reg send_data_r2; |
reg tx_valid_r; |
reg tx_valid_r1; |
|
wire zero_length; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
reg zero_length_r; |
assign zero_length = ep_empty; |
|
always @(posedge clk or negedge rst) |
if(!rst) zero_length_r <= #1 1'b0; |
else |
if(last) zero_length_r <= #1 1'b0; |
else |
if(crc16_clr) zero_length_r <= #1 zero_length; |
|
always @(posedge clk) |
tx_valid_r1 <= #1 tx_valid; |
|
always @(posedge clk) |
tx_valid_r <= #1 tx_valid_r1; |
|
always @(posedge clk or negedge rst) |
if(!rst) send_token_r <= #1 1'b0; |
else |
if(send_token) send_token_r <= #1 1'b1; |
else |
if(tx_ready) send_token_r <= #1 1'b0; |
|
// PID Select |
always @(token_pid_sel) |
case(token_pid_sel) // synopsys full_case parallel_case |
2'd0: token_pid = { ~`USBF_T_PID_ACK, `USBF_T_PID_ACK}; |
2'd1: token_pid = { ~`USBF_T_PID_NACK, `USBF_T_PID_NACK}; |
2'd2: token_pid = {~`USBF_T_PID_STALL, `USBF_T_PID_STALL}; |
2'd3: token_pid = { ~`USBF_T_PID_NYET, `USBF_T_PID_NYET}; |
endcase |
|
always @(data_pid_sel) |
case(data_pid_sel) // synopsys full_case parallel_case |
2'd0: data_pid = { ~`USBF_T_PID_DATA0, `USBF_T_PID_DATA0}; |
2'd1: data_pid = { ~`USBF_T_PID_DATA1, `USBF_T_PID_DATA1}; |
2'd2: data_pid = { ~`USBF_T_PID_DATA2, `USBF_T_PID_DATA2}; |
2'd3: data_pid = { ~`USBF_T_PID_MDATA, `USBF_T_PID_MDATA}; |
endcase |
|
// Data path Muxes |
|
always @(send_token or send_token_r or token_pid or tx_data_data) |
if(send_token | send_token_r) tx_data_d = token_pid; |
else tx_data_d = tx_data_data; |
|
always @(dsel or tx_data_st or tx_spec_data) |
if(dsel) tx_data_data = tx_spec_data; |
else tx_data_data = tx_data_st; |
|
always @(crc_sel1 or crc_sel2 or data_pid or crc16_rev) |
if(!crc_sel1 & !crc_sel2) tx_spec_data = data_pid; |
else |
if(crc_sel1) tx_spec_data = crc16_rev[15:8]; // CRC 1 |
else tx_spec_data = crc16_rev[7:0]; // CRC 2 |
|
assign tx_data = tx_data_d; |
|
// TX Valid assignment |
assign tx_valid_last = send_token | last; |
assign tx_valid = tx_valid_d; |
|
always @(posedge clk) |
tx_first_r <= #1 send_token | send_data; |
|
assign tx_first = (send_token | send_data) & ! tx_first_r; |
|
// CRC Logic |
always @(posedge clk) |
send_data_r <= #1 send_data; |
|
always @(posedge clk) |
send_data_r2 <= #1 send_data_r; |
|
assign crc16_clr = send_data & !send_data_r; |
|
always @(posedge clk) |
crc16_add <= #1 !zero_length_r & |
((send_data_r & !send_data_r2) | (rd_next & !crc_sel1)); |
|
always @(posedge clk) |
if(crc16_clr) crc16 <= #1 16'hffff; |
else |
if(crc16_add) crc16 <= #1 crc16_next; |
|
usb1_crc16 u1( |
.crc_in( crc16 ), |
.din( {tx_data_st[0], tx_data_st[1], |
tx_data_st[2], tx_data_st[3], |
tx_data_st[4], tx_data_st[5], |
tx_data_st[6], tx_data_st[7]} ), |
.crc_out( crc16_next ) ); |
|
assign crc16_rev[15] = ~crc16[8]; |
assign crc16_rev[14] = ~crc16[9]; |
assign crc16_rev[13] = ~crc16[10]; |
assign crc16_rev[12] = ~crc16[11]; |
assign crc16_rev[11] = ~crc16[12]; |
assign crc16_rev[10] = ~crc16[13]; |
assign crc16_rev[9] = ~crc16[14]; |
assign crc16_rev[8] = ~crc16[15]; |
assign crc16_rev[7] = ~crc16[0]; |
assign crc16_rev[6] = ~crc16[1]; |
assign crc16_rev[5] = ~crc16[2]; |
assign crc16_rev[4] = ~crc16[3]; |
assign crc16_rev[3] = ~crc16[4]; |
assign crc16_rev[2] = ~crc16[5]; |
assign crc16_rev[1] = ~crc16[6]; |
assign crc16_rev[0] = ~crc16[7]; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Transmit/Encode state machine |
// |
|
always @(posedge clk or negedge rst) |
if(!rst) state <= #1 IDLE; |
else state <= #1 next_state; |
|
always @(state or send_data or tx_ready or tx_valid_r or zero_length) |
begin |
next_state = state; // Default don't change current state |
tx_valid_d = 1'b0; |
dsel = 1'b0; |
rd_next = 1'b0; |
last = 1'b0; |
crc_sel1 = 1'b0; |
crc_sel2 = 1'b0; |
case(state) // synopsys full_case parallel_case |
IDLE: |
begin |
if(zero_length & send_data) |
begin |
tx_valid_d = 1'b1; |
dsel = 1'b1; |
next_state = CRC1; |
end |
else |
if(send_data) // Send DATA packet |
begin |
tx_valid_d = 1'b1; |
dsel = 1'b1; |
next_state = DATA; |
end |
end |
DATA: |
begin |
if(tx_ready & tx_valid_r) |
rd_next = 1'b1; |
|
tx_valid_d = 1'b1; |
if(!send_data & tx_ready & tx_valid_r) |
begin |
dsel = 1'b1; |
crc_sel1 = 1'b1; |
next_state = CRC1; |
end |
end |
CRC1: |
begin |
dsel = 1'b1; |
tx_valid_d = 1'b1; |
if(tx_ready) |
begin |
last = 1'b1; |
crc_sel2 = 1'b1; |
next_state = CRC2; |
end |
else |
begin |
tx_valid_d = 1'b1; |
crc_sel1 = 1'b1; |
end |
|
end |
CRC2: |
begin |
dsel = 1'b1; |
crc_sel2 = 1'b1; |
if(tx_ready) |
begin |
next_state = IDLE; |
end |
else |
begin |
last = 1'b1; |
end |
|
end |
endcase |
end |
|
endmodule |
|
/trunk/rtl/verilog/usb1_top.v
0,0 → 1,488
///////////////////////////////////////////////////////////////////// |
//// //// |
//// USB 1.1 function IP core //// |
//// //// |
//// //// |
//// 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_top.v,v 1.1.1.1 2002-09-19 12:07:36 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:36 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
module usb1_top(clk_i, rst_i, |
|
// USB Misc |
phy_tx_mode, usb_rst, loop, |
|
// Interrupts |
dropped_frame, misaligned_frame, |
crc16_err, |
|
// Vendor Features |
v_set_int, v_set_feature, wValue, |
wIndex, vendor_data, |
|
// USB PHY Interface |
tx_dp, tx_dn, tx_oe, |
rx_d, rx_dp, rx_dn, |
|
// Endpoint Interface |
ep1_din, ep1_we, ep1_stat, |
ep2_dout, ep2_re, ep2_stat, |
ep3_din, ep3_we, ep3_stat, |
ep4_dout, ep4_re, ep4_stat, |
ep5_din, ep5_we, ep5_stat, |
|
// Clearing FIFOs |
iso_idle, bulk_idle, |
clr_iso, clr_bulk |
); |
|
input clk_i; |
input rst_i; |
|
input phy_tx_mode; |
output usb_rst; |
input loop; |
output dropped_frame, misaligned_frame; |
output crc16_err; |
|
output v_set_int; |
output v_set_feature; |
output [15:0] wValue; |
output [15:0] wIndex; |
input [15:0] vendor_data; |
|
output tx_dp, tx_dn, tx_oe; |
input rx_d, rx_dp, rx_dn; |
|
// Endpoint Interfaces |
input [7:0] ep1_din; |
input ep1_we; |
output [3:0] ep1_stat; |
|
output [7:0] ep2_dout; |
input ep2_re; |
output [3:0] ep2_stat; |
|
input [7:0] ep3_din; |
input ep3_we; |
output [3:0] ep3_stat; |
|
output [7:0] ep4_dout; |
input ep4_re; |
output [3:0] ep4_stat; |
|
input [7:0] ep5_din; |
input ep5_we; |
output [3:0] ep5_stat; |
|
output iso_idle, bulk_idle; |
input clr_iso, clr_bulk; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Local Wires and Registers |
// |
|
// UTMI Interface |
wire [7:0] DataOut; |
wire TxValid; |
wire TxReady; |
wire [7:0] DataIn; |
wire RxValid; |
wire RxActive; |
wire RxError; |
wire [1:0] LineState; |
|
wire [7:0] rx_data; |
wire rx_valid, rx_active, rx_err; |
wire [7:0] tx_data; |
wire tx_valid; |
wire tx_ready; |
wire tx_first; |
wire tx_valid_last; |
|
// Internal Register File Interface |
wire [6:0] funct_adr; // This functions address (set by controller) |
wire [31:0] idin; // Data Input |
wire [3:0] ep_sel; // Endpoint Number Input |
wire crc16_err; // Set CRC16 error interrupt |
wire int_to_set; // Set time out interrupt |
wire int_seqerr_set; // Set PID sequence error interrupt |
wire out_to_small; // OUT packet was to small for DMA operation |
wire [31:0] frm_nat; // Frame Number and Time Register |
wire nse_err; // No Such Endpoint Error |
wire pid_cs_err; // PID CS error |
wire crc5_err; // CRC5 Error |
|
reg [7:0] tx_data_st; |
wire [7:0] rx_data_st; |
reg [13:0] cfg; |
|
wire [7:0] tx_data_st_ep0, tx_data_st_ep1, tx_data_st_ep3, tx_data_st_ep5; |
|
reg ep_empty; |
reg ep_full; |
wire [7:0] rx_size; |
wire rx_done; |
|
wire [7:0] ep0_din; |
wire [7:0] ep0_dout; |
wire ep0_re, ep0_we; |
wire [13:0] ep0_cfg; |
wire [3:0] ep0_stat; |
wire [7:0] ep0_size; |
|
wire ctrl_setup, ctrl_in, ctrl_out; |
wire send_stall; |
wire token_valid; |
reg rst_local; // internal reset |
|
wire [7:0] ep1_din_int; |
wire ep1_we_int; |
wire [3:0] ep2_stat_int; |
wire [7:0] ep3_din_int; |
wire ep3_we_int; |
wire [3:0] ep4_stat_int; |
wire [13:0] ep1_cfg; |
wire [13:0] ep2_cfg; |
wire [13:0] ep3_cfg; |
wire [13:0] ep4_cfg; |
wire [13:0] ep5_cfg; |
wire loop; |
wire dropped_frame; |
wire misaligned_frame; |
wire v_set_int; |
wire v_set_feature; |
wire [15:0] wValue; |
wire [15:0] wIndex; |
reg iso_idle, bulk_idle; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
// Endpoint type and Max transfer size |
assign ep0_cfg = `CTRL | ep0_size; |
assign ep1_cfg = `ISO | `IN | 14'd0256; |
assign ep2_cfg = `ISO | `OUT | 14'd0256; |
assign ep3_cfg = `BULK | `IN | 14'd064; |
assign ep4_cfg = `BULK | `OUT | 14'd064; |
assign ep5_cfg = `INT | `IN | 14'd064; |
|
always @(posedge clk_i) |
rst_local <= #1 rst_i & ~usb_rst; |
|
always @(posedge clk_i) |
iso_idle <= #1 (ep_sel != 4'h1) & (ep_sel != 4'h2); |
|
always @(posedge clk_i) |
bulk_idle <= #1 (ep_sel != 4'h3) & (ep_sel != 4'h4); |
|
/////////////////////////////////////////////////////////////////// |
// |
// Module Instantiations |
// |
|
usb_phy phy( |
.clk( clk_i ), |
.rst( rst_i ), // ONLY external reset |
.phy_tx_mode( phy_tx_mode ), |
.usb_rst( usb_rst ), |
|
// Transciever Interface |
.rxd( rx_d ), |
.rxdp( rx_dp ), |
.rxdn( rx_dn ), |
.txdp( tx_dp ), |
.txdn( tx_dn ), |
.txoe( tx_oe ), |
|
// UTMI Interface |
.DataIn_o( DataIn ), |
.RxValid_o( RxValid ), |
.RxActive_o( RxActive ), |
.RxError_o( RxError ), |
.DataOut_i( DataOut ), |
.TxValid_i( TxValid ), |
.TxReady_o( TxReady ), |
.LineState_o( LineState ) |
); |
|
// UTMI Interface |
usb1_utmi_if u0( |
.phy_clk( clk_i ), |
.rst( rst_local ), |
.DataOut( DataOut ), |
.TxValid( TxValid ), |
.TxReady( TxReady ), |
.RxValid( RxValid ), |
.RxActive( RxActive ), |
.RxError( RxError ), |
.DataIn( DataIn ), |
.rx_data( rx_data ), |
.rx_valid( rx_valid ), |
.rx_active( rx_active ), |
.rx_err( rx_err ), |
.tx_data( tx_data ), |
.tx_valid( tx_valid ), |
.tx_valid_last( tx_valid_last ), |
.tx_ready( tx_ready ), |
.tx_first( tx_first ) |
); |
|
// Protocol Layer |
usb1_pl u1( .clk( clk_i ), |
.rst( rst_local ), |
.rx_data( rx_data ), |
.rx_valid( rx_valid ), |
.rx_active( rx_active ), |
.rx_err( rx_err ), |
.tx_data( tx_data ), |
.tx_valid( tx_valid ), |
.tx_valid_last( tx_valid_last ), |
.tx_ready( tx_ready ), |
.tx_first( tx_first ), |
.tx_valid_out( TxValid ), |
.token_valid( token_valid ), |
.fa( funct_adr ), |
.ep_sel( ep_sel ), |
.int_crc16_set( crc16_err ), |
.int_to_set( int_to_set ), |
.int_seqerr_set( int_seqerr_set ), |
.frm_nat( frm_nat ), |
.pid_cs_err( pid_cs_err ), |
.nse_err( nse_err ), |
.crc5_err( crc5_err ), |
.rx_size( rx_size ), |
.rx_done( rx_done ), |
.ctrl_setup( ctrl_setup ), |
.ctrl_in( ctrl_in ), |
.ctrl_out( ctrl_out ), |
.dropped_frame( dropped_frame ), |
.misaligned_frame( misaligned_frame ), |
.csr( cfg ), |
.tx_data_st( tx_data_st ), |
.rx_data_st( rx_data_st ), |
.idma_re( idma_re ), |
.idma_we( idma_we ), |
.ep_empty( ep_empty ), |
.ep_full( ep_full ), |
.send_stall( send_stall ) |
); |
|
usb1_ctrl u4( .clk( clk_i ), |
.rst( rst_local ), |
|
.ctrl_setup( ctrl_setup ), |
.ctrl_in( ctrl_in ), |
.ctrl_out( ctrl_out ), |
|
.ep0_din( ep0_dout ), |
.ep0_dout( ep0_din ), |
.ep0_re( ep0_re ), |
.ep0_we( ep0_we ), |
.ep0_stat( ep0_stat ), |
.ep0_size( ep0_size ), |
|
.send_stall( send_stall ), |
.frame_no( frm_nat[26:16] ), |
.funct_adr( funct_adr ), |
.configured( ), |
.halt( ), |
|
.v_set_int( v_set_int ), |
.v_set_feature( v_set_feature ), |
.wValue( wValue ), |
.wIndex( wIndex ), |
.vendor_data( vendor_data ) |
|
); |
|
always @(ep_sel or ep0_cfg or ep1_cfg or ep2_cfg or ep3_cfg or |
ep4_cfg or ep5_cfg) |
case(ep_sel) // synopsys full_case parallel_case |
4'h0: cfg = ep0_cfg; |
4'h1: cfg = ep1_cfg; |
4'h2: cfg = ep2_cfg; |
4'h3: cfg = ep3_cfg; |
4'h4: cfg = ep4_cfg; |
4'h5: cfg = ep5_cfg; |
endcase |
|
// In endpoints only |
always @(posedge clk_i) |
case(ep_sel) // synopsys full_case parallel_case |
4'h0: tx_data_st <= #1 tx_data_st_ep0; |
4'h1: tx_data_st <= #1 tx_data_st_ep1; |
4'h3: tx_data_st <= #1 tx_data_st_ep3; |
4'h5: tx_data_st <= #1 tx_data_st_ep5; |
endcase |
|
// In endpoints only |
always @(posedge clk_i) |
case(ep_sel) // synopsys full_case parallel_case |
4'h0: ep_empty <= #1 ep0_stat[3]; |
4'h1: ep_empty <= #1 ep1_stat[3]; |
4'h3: ep_empty <= #1 ep3_stat[1]; |
4'h5: ep_empty <= #1 ep5_stat[1]; |
endcase |
|
// OUT endpoints only |
always @(ep_sel or ep0_stat or ep1_stat or ep2_stat or ep3_stat or |
ep4_stat or ep5_stat) |
case(ep_sel) // synopsys full_case parallel_case |
4'h0: ep_full = ep0_stat[2]; |
4'h2: ep_full = ep2_stat[2]; |
4'h4: ep_full = ep4_stat[0]; |
endcase |
|
usb1_ep #(0,6) |
u10( .clk( clk_i ), |
.rst( rst_local ), |
.clr( 1'b0 ), |
.ep_sel( ep_sel ), |
.usb_dout( tx_data_st_ep0 ), |
.usb_din( rx_data_st ), |
.usb_we( idma_we ), |
.usb_re( idma_re ), |
.ep_din( ep0_din ), |
.ep_dout( ep0_dout ), |
.ep_re( ep0_re ), |
.ep_we( ep0_we ), |
.ep_stat( ep0_stat ) |
); |
|
usb1_ep_in #(1,9,32) |
u11( .clk( clk_i ), |
.rst( rst_local ), |
.clr( clr_iso ), |
.ep_sel( ep_sel ), |
.usb_dout( tx_data_st_ep1 ), |
.usb_re( idma_re ), |
.ep_din( ep1_din_int ), |
.ep_we( ep1_we_int ), |
.ep_stat( ep1_stat ) |
); |
|
`define HAVE_LOOP |
// Loopback between endpoint 1&2 |
`ifdef HAVE_LOOP |
assign ep1_din_int = loop ? rx_data_st : ep1_din; |
assign ep1_we_int = loop ? (idma_we & (ep_sel == 4'h2)) : ep1_we; |
assign ep2_stat = loop ? ep1_stat : ep2_stat_int; |
`else |
assign ep1_din_int = ep1_din; |
assign ep1_we_int = ep1_we; |
assign ep2_stat = ep2_stat_int; |
`endif |
|
usb1_ep_out #(2,9,32) |
u12( .clk( clk_i ), |
.rst( rst_local ), |
.clr( clr_iso ), |
.ep_sel( ep_sel ), |
.usb_din( rx_data_st ), |
.usb_we( idma_we ), |
.ep_dout( ep2_dout ), |
.ep_re( ep2_re ), |
.ep_stat( ep2_stat_int ) |
); |
|
usb1_ep_in #(3,8,2) |
u13( .clk( clk_i ), |
.rst( rst_local ), |
.clr( clr_bulk ), |
.ep_sel( ep_sel ), |
.usb_dout( tx_data_st_ep3 ), |
.usb_re( idma_re ), |
.ep_din( ep3_din_int ), |
.ep_we( ep3_we_int ), |
.ep_stat( ep3_stat ) |
); |
|
// Loopback between endpoint 3&4 |
`ifdef HAVE_LOOP |
assign ep3_din_int = loop ? rx_data_st : ep3_din; |
assign ep3_we_int = loop ? (idma_we & (ep_sel == 4'h4)) : ep3_we; |
assign ep4_stat = loop ? ep3_stat : ep4_stat_int; |
`else |
assign ep3_din_int = ep3_din; |
assign ep3_we_int = ep3_we; |
assign ep4_stat = ep4_stat_int; |
`endif |
|
usb1_ep_out #(4,8,2) |
u14( .clk( clk_i ), |
.rst( rst_local ), |
.clr( clr_bulk ), |
.ep_sel( ep_sel ), |
.usb_din( rx_data_st ), |
.usb_we( idma_we ), |
.ep_dout( ep4_dout ), |
.ep_re( ep4_re ), |
.ep_stat( ep4_stat_int ) |
); |
|
usb1_ep_in #(5,6) |
u15( .clk( clk_i ), |
.rst( rst_local ), |
.clr( 1'b0 ), |
.ep_sel( ep_sel ), |
.usb_dout( tx_data_st_ep5 ), |
.usb_re( idma_re ), |
.ep_din( ep5_din ), |
.ep_we( ep5_we ), |
.ep_stat( ep5_stat ) |
); |
endmodule |
|
/trunk/rtl/verilog/usb1_pd.v
0,0 → 1,382
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Packet Disassembler //// |
//// Disassembles Token and Data USB packets //// |
//// //// |
//// 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_pd.v,v 1.1.1.1 2002-09-19 12:07:17 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:17 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
module usb1_pd( clk, rst, |
|
// UTMI RX I/F |
rx_data, rx_valid, rx_active, rx_err, |
|
// PID Information |
pid_OUT, pid_IN, pid_SOF, pid_SETUP, |
pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA, |
pid_ACK, pid_NACK, pid_STALL, pid_NYET, |
pid_PRE, pid_ERR, pid_SPLIT, pid_PING, |
pid_cks_err, |
|
// Token Information |
token_fadr, token_endp, token_valid, crc5_err, |
frame_no, |
|
// Receive Data Output |
rx_data_st, rx_data_valid, rx_data_done, crc16_err, |
|
// Misc. |
seq_err |
); |
|
input clk, rst; |
|
//UTMI RX Interface |
input [7:0] rx_data; |
input rx_valid, rx_active, rx_err; |
|
// Decoded PIDs (used when token_valid is asserted) |
output pid_OUT, pid_IN, pid_SOF, pid_SETUP; |
output pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; |
output pid_ACK, pid_NACK, pid_STALL, pid_NYET; |
output pid_PRE, pid_ERR, pid_SPLIT, pid_PING; |
output pid_cks_err; // Indicates a PID checksum error |
|
|
output [6:0] token_fadr; // Function address from token |
output [3:0] token_endp; // Endpoint number from token |
output token_valid; // Token is valid |
output crc5_err; // Token crc5 error |
output [10:0] frame_no; // Frame number for SOF tokens |
|
output [7:0] rx_data_st; // Data to memory store unit |
output rx_data_valid; // Data on rx_data_st is valid |
output rx_data_done; // Indicates end of a transfer |
output crc16_err; // Data packet CRC 16 error |
|
output seq_err; // State Machine Sequence Error |
|
/////////////////////////////////////////////////////////////////// |
// |
// Local Wires and Registers |
// |
|
parameter [3:0] // synopsys enum state |
IDLE = 4'b0001, |
ACTIVE = 4'b0010, |
TOKEN = 4'b0100, |
DATA = 4'b1000; |
|
reg [3:0] /* synopsys enum state */ state, next_state; |
// synopsys state_vector state |
|
reg [7:0] pid; // Packet PDI |
reg pid_le_sm; // PID Load enable from State Machine |
wire pid_ld_en; // Enable loading of PID (all conditions) |
wire pid_cks_err; // Indicates a pid checksum err |
|
// Decoded PID values |
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, pid_RES; |
wire pid_TOKEN; // All TOKEN packet that we recognize |
wire pid_DATA; // All DATA packets that we recognize |
|
reg [7:0] token0, token1; // Token Registers |
reg token_le_1, token_le_2; // Latch enables for token storage registers |
wire [4:0] token_crc5; |
|
reg [7:0] d0, d1, d2; // Data path delay line (used to filter out crcs) |
reg data_valid_d; // Data Valid output from State Machine |
reg data_done; // Data cycle complete output from State Machine |
reg data_valid0; // Data valid delay line |
reg rxv1; |
reg rxv2; |
|
reg seq_err; // State machine sequence error |
|
reg pid_ack; |
|
reg token_valid_r1; |
reg token_valid_str1, token_valid_str2; |
|
reg rx_active_r; |
|
wire [4:0] crc5_out; |
wire [4:0] crc5_out2; |
wire crc16_clr; |
reg [15:0] crc16_sum; |
wire [15:0] crc16_out; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
// PID Decoding Logic |
assign pid_ld_en = pid_le_sm & rx_active & rx_valid; |
|
always @(posedge clk or negedge rst) |
if(!rst) pid <= #1 8'hf0; |
else |
if(pid_ld_en) pid <= #1 rx_data; |
|
assign pid_cks_err = (pid[3:0] != ~pid[7:4]); |
|
assign pid_OUT = pid[3:0] == `USBF_T_PID_OUT; |
assign pid_IN = pid[3:0] == `USBF_T_PID_IN; |
assign pid_SOF = pid[3:0] == `USBF_T_PID_SOF; |
assign pid_SETUP = pid[3:0] == `USBF_T_PID_SETUP; |
assign pid_DATA0 = pid[3:0] == `USBF_T_PID_DATA0; |
assign pid_DATA1 = pid[3:0] == `USBF_T_PID_DATA1; |
assign pid_DATA2 = pid[3:0] == `USBF_T_PID_DATA2; |
assign pid_MDATA = pid[3:0] == `USBF_T_PID_MDATA; |
assign pid_ACK = pid[3:0] == `USBF_T_PID_ACK; |
assign pid_NACK = pid[3:0] == `USBF_T_PID_NACK; |
assign pid_STALL = pid[3:0] == `USBF_T_PID_STALL; |
assign pid_NYET = pid[3:0] == `USBF_T_PID_NYET; |
assign pid_PRE = pid[3:0] == `USBF_T_PID_PRE; |
assign pid_ERR = pid[3:0] == `USBF_T_PID_ERR; |
assign pid_SPLIT = pid[3:0] == `USBF_T_PID_SPLIT; |
assign pid_PING = pid[3:0] == `USBF_T_PID_PING; |
assign pid_RES = pid[3:0] == `USBF_T_PID_RES; |
|
assign pid_TOKEN = pid_OUT | pid_IN | pid_SOF | pid_SETUP | pid_PING; |
assign pid_DATA = pid_DATA0 | pid_DATA1 | pid_DATA2 | pid_MDATA; |
|
// Token Decoding LOGIC |
always @(posedge clk) |
if(token_le_1) token0 <= #1 rx_data; |
|
always @(posedge clk) |
if(token_le_2) token1 <= #1 rx_data; |
|
always @(posedge clk) |
token_valid_r1 <= #1 token_le_2; |
|
always @(posedge clk) |
token_valid_str1 <= #1 token_valid_r1 | pid_ack; |
|
always @(posedge clk) |
token_valid_str2 <= #1 token_valid_str1; |
|
assign token_valid = token_valid_str1; |
|
// CRC 5 should perform the check in one cycle (flow through logic) |
// 11 bits and crc5 input, 1 bit output |
assign crc5_err = token_valid & (crc5_out2 != token_crc5); |
|
usb1_crc5 u0( |
.crc_in( 5'h1f ), |
.din( { token_fadr[0], |
token_fadr[1], |
token_fadr[2], |
token_fadr[3], |
token_fadr[4], |
token_fadr[5], |
token_fadr[6], |
token_endp[0], |
token_endp[1], |
token_endp[2], |
token_endp[3] } ), |
.crc_out( crc5_out ) ); |
|
// Invert and reverse result bits |
assign crc5_out2 = ~{crc5_out[0], crc5_out[1], crc5_out[2], crc5_out[3], |
crc5_out[4]}; |
|
assign frame_no = { token1[2:0], token0}; |
assign token_fadr = token0[6:0]; |
assign token_endp = {token1[2:0], token0[7]}; |
assign token_crc5 = token1[7:3]; |
|
// Data receiving logic |
// build a delay line and stop when we are about to get crc |
always @(posedge clk or negedge rst) |
if(!rst) rxv1 <= #1 1'b0; |
else |
if(data_valid_d) rxv1 <= #1 1'b1; |
else |
if(data_done) rxv1 <= #1 1'b0; |
|
always @(posedge clk or negedge rst) |
if(!rst) rxv2 <= #1 1'b0; |
else |
if(rxv1 & data_valid_d) rxv2 <= #1 1'b1; |
else |
if(data_done) rxv2 <= #1 1'b0; |
|
always @(posedge clk) |
data_valid0 <= #1 rxv2 & data_valid_d; |
|
always @(posedge clk) |
begin |
if(data_valid_d) d0 <= #1 rx_data; |
if(data_valid_d) d1 <= #1 d0; |
if(data_valid_d) d2 <= #1 d1; |
end |
|
assign rx_data_st = d2; |
assign rx_data_valid = data_valid0; |
assign rx_data_done = data_done; |
|
// crc16 accumulates rx_data as long as data_valid_d is asserted. |
// when data_done is asserted, crc16 reports status, and resets itself |
// next cycle. |
always @(posedge clk) |
rx_active_r <= #1 rx_active; |
|
assign crc16_clr = rx_active & !rx_active_r; |
|
always @(posedge clk) |
if(crc16_clr) crc16_sum <= #1 16'hffff; |
else |
if(data_valid_d) crc16_sum <= #1 crc16_out; |
|
usb1_crc16 u1( |
.crc_in( crc16_sum ), |
.din( {rx_data[0], rx_data[1], rx_data[2], rx_data[3], |
rx_data[4], rx_data[5], rx_data[6], rx_data[7]} ), |
.crc_out( crc16_out ) ); |
|
// Verify against polynomial |
assign crc16_err = data_done & (crc16_sum != 16'h800d); |
|
/////////////////////////////////////////////////////////////////// |
// |
// Receive/Decode State machine |
// |
|
always @(posedge clk or negedge rst) |
if(!rst) state <= #1 IDLE; |
else state <= #1 next_state; |
|
always @(state or rx_valid or rx_active or rx_err or pid_ACK or pid_TOKEN |
or pid_DATA) |
begin |
next_state = state; // Default don't change current state |
pid_le_sm = 1'b0; |
token_le_1 = 1'b0; |
token_le_2 = 1'b0; |
data_valid_d = 1'b0; |
data_done = 1'b0; |
seq_err = 1'b0; |
pid_ack = 1'b0; |
case(state) // synopsys full_case parallel_case |
IDLE: |
begin |
pid_le_sm = 1'b1; |
if(rx_valid & rx_active) next_state = ACTIVE; |
end |
ACTIVE: |
begin |
// Received a ACK from Host |
if(pid_ACK & !rx_err) |
begin |
pid_ack = 1'b1; |
if(!rx_active) next_state = IDLE; |
end |
else |
// Receiving a TOKEN |
if(pid_TOKEN & rx_valid & rx_active & !rx_err) |
begin |
token_le_1 = 1'b1; |
next_state = TOKEN; |
end |
else |
// Receiving DATA |
if(pid_DATA & rx_valid & rx_active & !rx_err) |
begin |
data_valid_d = 1'b1; |
next_state = DATA; |
end |
else |
if( !rx_active | rx_err | |
(rx_valid & !(pid_TOKEN | pid_DATA)) ) // ERROR |
begin |
seq_err = !rx_err; |
if(!rx_active) next_state = IDLE; |
end |
end |
TOKEN: |
begin |
if(rx_valid & rx_active & !rx_err) |
begin |
token_le_2 = 1'b1; |
next_state = IDLE; |
end |
else |
if(!rx_active | rx_err) // ERROR |
begin |
seq_err = !rx_err; |
if(!rx_active) next_state = IDLE; |
end |
end |
DATA: |
begin |
if(rx_valid & rx_active & !rx_err) data_valid_d = 1'b1; |
if(!rx_active | rx_err) |
begin |
data_done = 1'b1; |
if(!rx_active) next_state = IDLE; |
end |
end |
|
endcase |
end |
|
endmodule |
|
/trunk/rtl/verilog/usb1_ctrl.v
0,0 → 1,685
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Internal Setup Engine //// |
//// //// |
//// //// |
//// 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_ctrl.v,v 1.1.1.1 2002-09-19 12:07:09 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:09 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
module usb1_ctrl( clk, rst, |
|
ctrl_setup, ctrl_in, ctrl_out, |
|
ep0_din, ep0_dout, ep0_re, ep0_we, ep0_stat, |
ep0_size, |
|
send_stall, frame_no, |
funct_adr, configured, halt, |
|
v_set_int, v_set_feature, wValue, wIndex, vendor_data |
); |
|
input clk, rst; |
|
input ctrl_setup; |
input ctrl_in; |
input ctrl_out; |
|
input [7:0] ep0_din; |
output [7:0] ep0_dout; |
output ep0_re, ep0_we; |
input [3:0] ep0_stat; |
output [7:0] ep0_size; |
|
output send_stall; |
input [10:0] frame_no; |
output [6:0] funct_adr; |
output configured, halt; |
|
output v_set_int; |
output v_set_feature; |
output [15:0] wValue; |
output [15:0] wIndex; |
input [15:0] vendor_data; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Local Wires and Registers |
// |
|
parameter IDLE = 20'b0000_0000_0000_0000_0001, |
GET_HDR = 20'b0000_0000_0000_0000_0010, |
GET_STATUS_S = 20'b0000_0000_0000_0000_0100, |
CLEAR_FEATURE_S = 20'b0000_0000_0000_0000_1000, |
SET_FEATURE_S = 20'b0000_0000_0000_0001_0000, |
SET_ADDRESS_S = 20'b0000_0000_0000_0010_0000, |
GET_DESCRIPTOR_S = 20'b0000_0000_0000_0100_0000, |
SET_DESCRIPTOR_S = 20'b0000_0000_0000_1000_0000, |
GET_CONFIG_S = 20'b0000_0000_0001_0000_0000, |
SET_CONFIG_S = 20'b0000_0000_0010_0000_0000, |
GET_INTERFACE_S = 20'b0000_0000_0100_0000_0000, |
SET_INTERFACE_S = 20'b0000_0000_1000_0000_0000, |
SYNCH_FRAME_S = 20'b0000_0001_0000_0000_0000, |
WAIT_IN_DATA = 20'b0000_0010_0000_0000_0000, |
STATUS_IN = 20'b0000_0100_0000_0000_0000, |
STATUS_OUT = 20'b0000_1000_0000_0000_0000, |
V_SET_INT_S = 20'b0001_0000_0000_0000_0000, |
V_GET_STATUS_S = 20'b0010_0000_0000_0000_0000; |
|
|
wire [7:0] bmReqType, bRequest; |
wire [15:0] wValue, wIndex, wLength; |
wire bm_req_dir; |
wire [1:0] bm_req_type; |
wire [4:0] bm_req_recp; |
|
reg get_status, clear_feature, set_feature, set_address; |
reg get_descriptor, set_descriptor, get_config, set_config; |
reg get_interface, set_interface, synch_frame; |
reg hdr_done_r, config_err; |
reg v_set_int, v_set_feature, v_get_status; |
|
wire fifo_re1, fifo_full, fifo_empty; |
reg fifo_we_d; |
reg [4:0] data_sel; |
reg ep0_we; |
reg [7:0] ep0_dout; |
reg [7:0] ep0_size; |
reg send_stall; |
reg [19:0] state, next_state; |
reg get_hdr; |
reg [7:0] le; |
wire hdr_done; |
reg adv; |
reg [7:0] hdr0, hdr1, hdr2, hdr3, hdr4, hdr5, hdr6, hdr7; |
reg [6:0] funct_adr; |
reg set_adr_pending; |
reg [6:0] funct_adr_tmp; |
|
reg in_size_0; |
reg in_size_1; |
reg in_size_2; |
wire high_sel; |
reg write_done, write_done_r; |
|
/////////////////////////////////////////////////////////////////// |
// |
// FIFO interface |
// |
|
assign ep0_re = fifo_re1; |
assign fifo_empty = ep0_stat[1]; |
assign fifo_full = ep0_stat[2]; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Current States |
// |
reg addressed; |
reg configured; |
reg halt; |
wire clr_halt; |
wire set_halt=0; // FIX_ME |
|
// For this implementation we do not implement HALT for the |
// device nor for any of the endpoints. This is is useless for |
// this device, but can be added here later ... |
// FYI, we report device/endpoint errors via interrupts, |
// instead of halting the entire or paret of the device, much |
// nicer for non-critical errors. |
|
assign clr_halt = ctrl_setup; |
|
always @(posedge clk) |
if(!rst) addressed <= #1 1'b0; |
else |
if(set_address) addressed <= #1 1'b1; |
|
always @(posedge clk) |
if(!rst) configured <= #1 1'b0; |
else |
if(set_config) configured <= #1 1'b1; |
|
always @(posedge clk) |
if(!rst) halt <= #1 1'b0; |
else |
if(clr_halt) halt <= #1 1'b0; |
else |
if(set_halt) halt <= #1 1'b1; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Descriptor ROM |
// |
reg [6:0] rom_adr; |
wire [7:0] rom_dout; |
reg rom_sel, rom_sel_r; |
wire rom_done; |
reg [6:0] rom_size; |
reg fifo_we_rom_r; |
reg fifo_we_rom_r2; |
wire fifo_we_rom; |
reg [7:0] rom_start_d; |
|
reg [6:0] rom_size_dd; |
wire [6:0] rom_size_d; |
|
parameter ROM_SIZE0 = 7'd018, |
ROM_SIZE1 = 7'd053, |
ROM_SIZE2A = 7'd004, |
ROM_SIZE2B = 7'd010, |
ROM_SIZE2C = 7'd010, |
ROM_SIZE2D = 7'd010; |
|
parameter ROM_START0 = 7'h00, |
ROM_START1 = 7'h12, |
ROM_START2A = 7'h47, |
ROM_START2B = 7'h50, |
ROM_START2C = 7'h60, |
ROM_START2D = 7'h70; |
|
usb1_rom1 rom1( .clk( clk ), |
.adr( rom_adr ), |
.dout( rom_dout ) |
); |
|
always @(wValue) |
case(wValue[11:8]) // synopsys full_case parallel_case |
4'h1: rom_start_d = ROM_START0; |
4'h2: rom_start_d = ROM_START1; |
4'h3: |
case(wValue[3:0]) // synopsys full_case parallel_case |
4'h00: rom_start_d = ROM_START2A; |
4'h01: rom_start_d = ROM_START2B; |
4'h02: rom_start_d = ROM_START2C; |
4'h03: rom_start_d = ROM_START2D; |
default: rom_start_d = ROM_START2A; |
endcase |
default: rom_start_d = 7'h00; |
endcase |
|
always @(wValue) |
case(wValue[11:8]) // synopsys full_case parallel_case |
4'h1: rom_size_dd = ROM_SIZE0; |
4'h2: rom_size_dd = ROM_SIZE1; |
4'h3: |
case(wValue[3:0]) // synopsys full_case parallel_case |
4'h00: rom_size_dd = ROM_SIZE2A; |
4'h01: rom_size_dd = ROM_SIZE2B; |
4'h02: rom_size_dd = ROM_SIZE2C; |
4'h03: rom_size_dd = ROM_SIZE2D; |
default: rom_size_dd = ROM_SIZE2A; |
endcase |
default: rom_size_dd = 7'h01; |
endcase |
|
assign rom_size_d = (rom_size_dd > wLength[6:0]) ? wLength[6:0] : rom_size_dd; |
|
always @(posedge clk) |
rom_sel_r <= #1 rom_sel; |
|
always @(posedge clk) |
if(!rst) rom_adr <= #1 7'h0; |
else |
if(rom_sel & !rom_sel_r) rom_adr <= #1 rom_start_d; |
else |
if(rom_sel & !fifo_full) rom_adr <= #1 rom_adr + 7'h1; |
|
always @(posedge clk) |
if(!rst) rom_size <= #1 7'h0; |
else |
if(rom_sel & !rom_sel_r) rom_size <= #1 rom_size_d; |
else |
if(rom_sel & !fifo_full) rom_size <= #1 rom_size - 7'h01; |
|
always @(posedge clk) |
fifo_we_rom_r <= #1 rom_sel; |
|
always @(posedge clk) |
fifo_we_rom_r2 <= #1 fifo_we_rom_r; |
|
assign fifo_we_rom = rom_sel & fifo_we_rom_r2; |
|
assign rom_done = (rom_size == 7'h0) & !(rom_sel & !rom_sel_r); |
|
/////////////////////////////////////////////////////////////////// |
// |
// Get Header |
// |
|
assign fifo_re1 = get_hdr & !fifo_empty; |
|
always @(posedge clk) |
adv <= #1 get_hdr & !fifo_empty & !adv; |
|
always @(posedge clk) |
if(!rst) le <= #1 8'h0; |
else |
if(!get_hdr) le <= #1 8'h0; |
else |
if(!(|le)) le <= #1 8'h1; |
else |
if(adv) le <= #1 {le[6:0], 1'b0}; |
|
always @(posedge clk) |
if(le[0]) hdr0 <= #1 ep0_din; |
|
always @(posedge clk) |
if(le[1]) hdr1 <= #1 ep0_din; |
|
always @(posedge clk) |
if(le[2]) hdr2 <= #1 ep0_din; |
|
always @(posedge clk) |
if(le[3]) hdr3 <= #1 ep0_din; |
|
always @(posedge clk) |
if(le[4]) hdr4 <= #1 ep0_din; |
|
always @(posedge clk) |
if(le[5]) hdr5 <= #1 ep0_din; |
|
always @(posedge clk) |
if(le[6]) hdr6 <= #1 ep0_din; |
|
always @(posedge clk) |
if(le[7]) hdr7 <= #1 ep0_din; |
|
assign hdr_done = le[7] & adv; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Send Data to Host |
// |
parameter ZERO_DATA = 5'b00001, |
ZERO_ONE_DATA = 5'b00010, |
CONFIG_DATA = 5'b00100, |
SYNC_FRAME_DATA = 5'b01000, |
VEND_DATA = 5'b10000; |
|
assign high_sel = write_done_r; |
|
always @(posedge clk) |
case(data_sel) // synopsys full_case parallel_case |
ZERO_DATA: ep0_dout <= #1 rom_sel ? rom_dout : 8'h0; |
ZERO_ONE_DATA: ep0_dout <= #1 high_sel ? 8'h1 : 8'h0; |
CONFIG_DATA: ep0_dout <= #1 {7'h0, configured}; // return configuration |
SYNC_FRAME_DATA: ep0_dout <= #1 high_sel ? {5'h0, frame_no[10:8]} : frame_no[7:0]; |
VEND_DATA: ep0_dout <= #1 high_sel ? vendor_data[15:8] : vendor_data[7:0]; |
endcase |
|
always @(posedge clk) |
ep0_we <= #1 fifo_we_d | fifo_we_rom; |
|
always @(posedge clk) |
if(in_size_0) ep0_size <= #1 8'h0; |
else |
if(in_size_1) ep0_size <= #1 8'h1; |
else |
if(in_size_2) ep0_size <= #1 8'h2; |
else |
if(rom_sel) ep0_size <= #1 {1'b0, rom_size_d}; |
|
|
always @(posedge clk) |
write_done_r <= #1 in_size_2 & !fifo_full & fifo_we_d & !write_done_r & !write_done; |
|
always @(posedge clk) |
write_done <= #1 in_size_2 & !fifo_full & fifo_we_d & write_done_r & !write_done; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Decode Header |
// |
|
// Valid bRequest Codes |
parameter GET_STATUS = 8'h00, |
CLEAR_FEATURE = 8'h01, |
SET_FEATURE = 8'h03, |
SET_ADDRESS = 8'h05, |
GET_DESCRIPTOR = 8'h06, |
SET_DESCRIPTOR = 8'h07, |
GET_CONFIG = 8'h08, |
SET_CONFIG = 8'h09, |
GET_INTERFACE = 8'h0a, |
SET_INTERFACE = 8'h0b, |
SYNCH_FRAME = 8'h0c; |
|
parameter V_SET_INT = 8'h0f; |
|
|
assign bmReqType = hdr0; |
assign bm_req_dir = bmReqType[7]; // 0-Host to device; 1-device to host |
assign bm_req_type = bmReqType[6:5]; // 0-standard; 1-class; 2-vendor; 3-RESERVED |
assign bm_req_recp = bmReqType[4:0]; // 0-device; 1-interface; 2-endpoint; 3-other |
// 4..31-reserved |
assign bRequest = hdr1; |
assign wValue = {hdr3, hdr2}; |
assign wIndex = {hdr5, hdr4}; |
assign wLength = {hdr7, hdr6}; |
|
always @(posedge clk) |
hdr_done_r <= #1 hdr_done; |
|
always @(posedge clk) |
get_status <= #1 hdr_done & (bRequest == GET_STATUS) & (bm_req_type==2'h0); |
|
always @(posedge clk) |
clear_feature <= #1 hdr_done & (bRequest == CLEAR_FEATURE) & (bm_req_type==2'h0); |
|
always @(posedge clk) |
set_feature <= #1 hdr_done & (bRequest == SET_FEATURE) & (bm_req_type==2'h0); |
|
always @(posedge clk) |
set_address <= #1 hdr_done & (bRequest == SET_ADDRESS) & (bm_req_type==2'h0); |
|
always @(posedge clk) |
get_descriptor <= #1 hdr_done & (bRequest == GET_DESCRIPTOR) & (bm_req_type==2'h0); |
|
always @(posedge clk) |
set_descriptor <= #1 hdr_done & (bRequest == SET_DESCRIPTOR) & (bm_req_type==2'h0); |
|
always @(posedge clk) |
get_config <= #1 hdr_done & (bRequest == GET_CONFIG) & (bm_req_type==2'h0); |
|
always @(posedge clk) |
set_config <= #1 hdr_done & (bRequest == SET_CONFIG) & (bm_req_type==2'h0); |
|
always @(posedge clk) |
get_interface <= #1 hdr_done & (bRequest == GET_INTERFACE) & (bm_req_type==2'h0); |
|
always @(posedge clk) |
set_interface <= #1 hdr_done & (bRequest == SET_INTERFACE) & (bm_req_type==2'h0); |
|
always @(posedge clk) |
synch_frame <= #1 hdr_done & (bRequest == SYNCH_FRAME) & (bm_req_type==2'h0); |
|
always @(posedge clk) |
v_set_int <= #1 hdr_done & (bRequest == V_SET_INT) & (bm_req_type==2'h2); |
|
always @(posedge clk) |
v_set_feature <= #1 hdr_done & (bRequest == SET_FEATURE) & (bm_req_type==2'h2); |
|
always @(posedge clk) |
v_get_status <= #1 hdr_done & (bRequest == GET_STATUS) & (bm_req_type==2'h2); |
|
// A config err must cause the device to send a STALL for an ACK |
always @(posedge clk) |
config_err <= #1 hdr_done_r & !(get_status | clear_feature | |
set_feature | set_address | get_descriptor | |
set_descriptor | get_config | set_config | |
get_interface | set_interface | synch_frame | |
v_set_int | v_set_feature | v_get_status); |
|
|
always @(posedge clk) |
send_stall <= #1 config_err; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Set address |
// |
|
always @(posedge clk) |
if(!rst) set_adr_pending <= #1 1'b0; |
else |
if(ctrl_in | ctrl_out | ctrl_setup) set_adr_pending <= #1 1'b0; |
else |
if(set_address) set_adr_pending <= #1 1'b1; |
|
always @(posedge clk) |
if(!rst) funct_adr_tmp <= #1 7'h0; |
else |
if(set_address) funct_adr_tmp <= #1 wValue[6:0]; |
|
always @(posedge clk) |
if(!rst) funct_adr <= #1 7'h0; |
else |
if(set_adr_pending & ctrl_in) funct_adr <= #1 funct_adr_tmp; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Main FSM |
// |
|
always @(posedge clk) |
if(!rst) state <= #1 IDLE; |
else state <= next_state; |
|
always @(state or ctrl_setup or ctrl_in or ctrl_out or hdr_done or |
fifo_full or rom_done or write_done_r or wValue or bm_req_recp or |
get_status or clear_feature or set_feature or set_address or |
get_descriptor or set_descriptor or get_config or set_config or |
get_interface or set_interface or synch_frame or v_set_int or |
v_set_feature or v_get_status |
) |
begin |
next_state = state; |
get_hdr = 1'b0; |
data_sel = ZERO_DATA; |
fifo_we_d = 1'b0; |
in_size_0 = 1'b0; |
in_size_1 = 1'b0; |
in_size_2 = 1'b0; |
rom_sel = 1'b0; |
|
case(state) // synopsys full_case parallel_case |
|
// Wait for Setup token |
IDLE: |
begin |
if(ctrl_setup) next_state = GET_HDR; |
if(get_status) next_state = GET_STATUS_S; |
if(clear_feature) next_state = CLEAR_FEATURE_S; |
if(set_feature) next_state = SET_FEATURE_S; |
if(set_address) next_state = SET_ADDRESS_S; |
if(get_descriptor) next_state = GET_DESCRIPTOR_S; |
if(set_descriptor) next_state = SET_DESCRIPTOR_S; |
if(get_config) next_state = GET_CONFIG_S; |
if(set_config) next_state = SET_CONFIG_S; |
if(get_interface) next_state = GET_INTERFACE_S; |
if(set_interface) next_state = SET_INTERFACE_S; |
if(synch_frame) next_state = SYNCH_FRAME_S; |
if(v_set_int) next_state = V_SET_INT_S; |
if(v_set_feature) next_state = V_SET_INT_S; |
if(v_get_status) next_state = V_GET_STATUS_S; |
end |
|
// Retrieve Setup Header |
GET_HDR: |
begin |
get_hdr = 1'b1; |
if(hdr_done) next_state = IDLE; |
end |
|
|
// Actions for supported commands |
GET_STATUS_S: |
begin |
// Returns to host |
// 16'h0001 for device |
// 16'h0000 for interface |
// 16'h0000 for endpoint |
if(bm_req_recp == 5'h00) data_sel = ZERO_ONE_DATA; |
else data_sel = ZERO_DATA; |
|
in_size_2 = 1'b1; |
if(!fifo_full) |
begin |
fifo_we_d = 1'b1; |
if(write_done_r) next_state = WAIT_IN_DATA; |
end |
|
end |
V_GET_STATUS_S: |
begin |
data_sel = VEND_DATA; |
in_size_2 = 1'b1; |
if(!fifo_full) |
begin |
fifo_we_d = 1'b1; |
if(write_done_r) next_state = WAIT_IN_DATA; |
end |
end |
|
CLEAR_FEATURE_S: |
begin |
// just ignore this for now |
next_state = STATUS_IN; |
end |
|
SET_FEATURE_S: |
begin |
// just ignore this for now |
next_state = STATUS_IN; |
end |
|
SET_ADDRESS_S: |
begin |
// done elsewhere .... |
next_state = STATUS_IN; |
end |
|
GET_DESCRIPTOR_S: |
begin |
if( wValue[15:8] == 8'h01 | |
wValue[15:8] == 8'h02 | |
wValue[15:8] == 8'h03 ) |
rom_sel = 1'b1; |
else |
next_state = IDLE; |
|
if(rom_done) |
next_state = IDLE; |
end |
|
SET_DESCRIPTOR_S: |
begin |
// This doesn't do anything since we do not support |
// seting the descriptor |
next_state = IDLE; |
end |
|
GET_CONFIG_S: |
begin |
// Send one byte back that indicates current status |
in_size_1 = 1'b1; |
data_sel = CONFIG_DATA; |
if(!fifo_full) |
begin |
fifo_we_d = 1'b1; |
next_state = WAIT_IN_DATA; |
end |
end |
|
SET_CONFIG_S: |
begin |
// done elsewhere .... |
next_state = STATUS_IN; |
end |
|
GET_INTERFACE_S: |
begin |
// Return interface '0' |
in_size_1 = 1'b1; |
if(!fifo_full) |
begin |
fifo_we_d = 1'b1; |
next_state = WAIT_IN_DATA; |
end |
end |
|
SET_INTERFACE_S: |
begin |
// just ignore this for now |
next_state = STATUS_IN; |
end |
|
SYNCH_FRAME_S: |
begin |
// Return Frame current frame number |
data_sel = SYNC_FRAME_DATA; |
in_size_2 = 1'b1; |
if(!fifo_full) |
begin |
fifo_we_d = 1'b1; |
if(write_done_r) next_state = WAIT_IN_DATA; |
end |
end |
|
V_SET_INT_S: |
begin |
// done elsewhere .... |
next_state = STATUS_IN; |
end |
|
WAIT_IN_DATA: |
begin |
if(ctrl_in) next_state = STATUS_OUT; |
end |
|
STATUS_IN: |
begin |
in_size_0 = 1'b1; |
if(ctrl_in) next_state = IDLE; |
end |
|
STATUS_OUT: |
begin |
if(ctrl_out) next_state = IDLE; |
end |
endcase |
end |
|
endmodule |
|
/trunk/rtl/verilog/usb1_ep.v
0,0 → 1,136
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Endpoint Interface //// |
//// //// |
//// 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_ep.v,v 1.1.1.1 2002-09-19 12:07:30 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:30 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
module usb1_ep( clk, rst, clr, ep_sel, |
usb_dout, usb_din, usb_we, usb_re, |
|
// External Endpoint interface |
ep_din, ep_dout, ep_re, ep_we, ep_stat |
); |
|
parameter MY_EP_ID = 0; |
parameter aw = 6; |
|
input clk, rst, clr; |
input [3:0] ep_sel; |
output [7:0] usb_dout; |
input [7:0] usb_din; |
input usb_we, usb_re; |
|
input [7:0] ep_din; |
output [7:0] ep_dout; |
input ep_re, ep_we; |
output [3:0] ep_stat; |
|
//////////////////////////////////////////////////////////////////// |
// |
// Local Wires |
// |
|
wire usb_we_t, usb_re_t; |
|
//////////////////////////////////////////////////////////////////// |
// |
// Aliases |
// |
|
//////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
assign usb_we_t = usb_we & (ep_sel == MY_EP_ID); |
assign usb_re_t = usb_re & (ep_sel == MY_EP_ID); |
|
//////////////////////////////////////////////////////////////////// |
// |
// FIFOs |
// |
|
// dw,aw |
usb1_fifo #(8,aw) |
f0( |
.clk( clk ), |
.rst( rst ), |
.clr( clr ), |
.din( usb_din ), |
.we( usb_we_t ), |
.dout( ep_dout ), |
.re( ep_re ), |
.full( ep_stat[0] ), |
.empty( ep_stat[1] ), |
.full_n( ), |
.empty_n( ) |
); |
|
usb1_fifo #(8,aw) |
f1( |
.clk( clk ), |
.rst( rst ), |
.clr( clr ), |
.din( ep_din ), |
.we( ep_we ), |
.dout( usb_dout ), |
.re( usb_re_t ), |
.full( ep_stat[2] ), |
.empty( ep_stat[3] ), |
.full_n( ), |
.empty_n( ) |
); |
|
endmodule |
/trunk/rtl/verilog/usb1_pe.v
0,0 → 1,836
///////////////////////////////////////////////////////////////////// |
//// //// |
//// 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: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
|
`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 |
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 packets |
assign data_pid_sel = this_dpid; |
|
// Verify PID for incoming data packets |
always @(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 endpoints |
always @(posedge clk or negedge rst) |
if(!rst) in_token <= #1 1'b0; |
else |
if(pid_IN) in_token <= #1 1'b1; |
else |
if(pid_OUT | pid_SETUP) in_token <= #1 1'b0; |
|
always @(posedge clk or negedge rst) |
if(!rst) out_token <= #1 1'b0; |
else |
if(pid_OUT | pid_SETUP) out_token <= #1 1'b1; |
else |
if(pid_IN) out_token <= #1 1'b0; |
|
always @(posedge clk or negedge rst) |
if(!rst) setup_token <= #1 1'b0; |
else |
if(pid_SETUP) setup_token <= #1 1'b1; |
else |
if(pid_OUT | pid_IN) setup_token <= #1 1'b0; |
|
// Indicates if we are performing an IN operation |
assign in_op = IN_ep | (CTRL_ep & in_token); |
|
// Indicates if we are performing an OUT operation |
assign out_op = OUT_ep | (CTRL_ep & out_token); |
|
|
/////////////////////////////////////////////////////////////////// |
// |
// Determine if packet is to small or to large |
// This is used to NACK and ignore packet for OUT endpoints |
// |
|
|
/////////////////////////////////////////////////////////////////// |
// |
// Register File Update Logic |
// |
|
always @(posedge clk) |
uc_dpd_set <= #1 uc_stat_set_d; |
|
// Abort signal |
always @(posedge clk) |
abort <= #1 match & fsel & (state != IDLE); |
|
/////////////////////////////////////////////////////////////////// |
// |
// 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 timer |
|
always @(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 8'h0; |
else rx_ack_to_cnt <= #1 rx_ack_to_cnt + 8'h1; |
|
always @(posedge clk) |
rx_ack_to <= #1 (rx_ack_to_cnt == rx_ack_to_val); |
|
assign rx_ack_to_val = `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 timer |
|
assign tx_data_to_clr = rx_active; |
|
always @(posedge clk) |
if(tx_data_to_clr) tx_data_to_cnt <= #1 8'h0; |
else tx_data_to_cnt <= #1 tx_data_to_cnt + 8'h1; |
|
always @(posedge clk) |
tx_data_to <= #1 (tx_data_to_cnt == tx_data_to_val); |
|
assign tx_data_to_val = `USBF_TX_DATA_TO_VAL_FS; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Interrupts |
// |
reg pid_OUT_r, pid_IN_r, pid_PING_r, pid_SETUP_r; |
|
always @(posedge clk) |
pid_OUT_r <= #1 pid_OUT; |
|
always @(posedge clk) |
pid_IN_r <= #1 pid_IN; |
|
always @(posedge clk) |
pid_PING_r <= #1 pid_PING; |
|
always @(posedge clk) |
pid_SETUP_r <= #1 pid_SETUP; |
|
always @(posedge clk) |
int_upid_set <= #1 match_r & !pid_SOF & ( |
( OUT_ep & !(pid_OUT_r | pid_PING_r)) | |
( IN_ep & !pid_IN_r) | |
(CTRL_ep & !(pid_IN_r | pid_OUT_r | pid_PING_r | pid_SETUP_r)) |
); |
|
|
assign int_to_set = ((state == IN2) & rx_ack_to) | ((state == OUT) & tx_data_to); |
|
assign int_crc16_set = rx_data_done & crc16_err; |
|
always @(posedge clk) |
int_seqerr_set <= #1 int_seqerr_set_d; |
|
reg send_stall_r; |
|
always @(posedge clk or negedge rst) |
if(!rst) send_stall_r <= #1 1'b0; |
else |
if(send_stall) send_stall_r <= #1 1'b1; |
else |
if(send_token) send_stall_r <= #1 1'b0; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Main Protocol State Machine |
// |
|
always @(posedge clk or negedge rst) |
if(!rst) state <= #1 IDLE; |
else |
if(match) state <= #1 IDLE; |
else state <= #1 next_state; |
|
always @(state or |
pid_seq_err or idma_done or ep_full or ep_empty or |
token_valid or pid_ACK or rx_data_done or |
tx_data_to or crc16_err or |
rx_ack_to or pid_PING or txfr_iso or txfr_int 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 send_stall_r |
) |
begin |
next_state = state; |
token_pid_sel_d = ACK; |
send_token_d = 1'b0; |
rx_dma_en = 1'b0; |
tx_dma_en = 1'b0; |
uc_stat_set_d = 1'b0; |
rx_ack_to_clr_d = 1'b1; |
int_seqerr_set_d = 1'b0; |
|
case(state) // synopsys full_case parallel_case |
IDLE: |
begin |
// synopsys translate_off |
`ifdef USBF_VERBOSE_DEBUG |
$display("PE: Entered state IDLE (%t)", $time); |
`endif |
`ifdef USBF_DEBUG |
if(rst & match_r & !pid_SOF) |
begin |
if(match_r === 1'bx) $display("ERROR: IDLE: match_r is unknown. (%t)", $time); |
if(pid_SOF === 1'bx) $display("ERROR: IDLE: pid_SOF is unknown. (%t)", $time); |
if(CTRL_ep === 1'bx) $display("ERROR: IDLE: CTRL_ep is unknown. (%t)", $time); |
if(pid_IN === 1'bx) $display("ERROR: IDLE: pid_IN is unknown. (%t)", $time); |
if(pid_OUT === 1'bx) $display("ERROR: IDLE: pid_OUT is unknown. (%t)", $time); |
if(pid_SETUP === 1'bx) $display("ERROR: IDLE: pid_SETUP is unknown. (%t)", $time); |
if(pid_PING === 1'bx) $display("ERROR: IDLE: pid_PING is unknown. (%t)", $time); |
if(IN_ep === 1'bx) $display("ERROR: IDLE: IN_ep is unknown. (%t)", $time); |
if(OUT_ep === 1'bx) $display("ERROR: IDLE: OUT_ep is unknown. (%t)", $time); |
end |
`endif |
// synopsys translate_on |
|
if(match_r & !pid_SOF) |
begin |
/* |
if(ep_stall) // Halt Forced send STALL |
begin |
token_pid_sel_d = STALL; |
send_token_d = 1'b1; |
next_state = TOKEN; |
end |
else |
*/ |
if(IN_ep | (CTRL_ep & pid_IN)) |
begin |
if(txfr_int & ep_empty) |
begin |
token_pid_sel_d = NACK; |
send_token_d = 1'b1; |
next_state = TOKEN; |
end |
else |
begin |
tx_dma_en = 1'b1; |
next_state = IN; |
end |
end |
else |
if(OUT_ep | (CTRL_ep & (pid_OUT | pid_SETUP))) |
begin |
rx_dma_en = 1'b1; |
next_state = OUT; |
end |
end |
end |
|
TOKEN: |
begin |
// synopsys translate_off |
`ifdef USBF_VERBOSE_DEBUG |
$display("PE: Entered state TOKEN (%t)", $time); |
`endif |
// synopsys translate_on |
next_state = IDLE; |
end |
|
IN: |
begin |
// synopsys translate_off |
`ifdef USBF_VERBOSE_DEBUG |
$display("PE: Entered state IN (%t)", $time); |
`endif |
`ifdef USBF_DEBUG |
if(idma_done === 1'bx) $display("ERROR: IN: idma_done is unknown. (%t)", $time); |
if(txfr_iso === 1'bx) $display("ERROR: IN: txfr_iso is unknown. (%t)", $time); |
`endif |
// synopsys translate_on |
rx_ack_to_clr_d = 1'b0; |
if(idma_done) |
begin |
if(txfr_iso) next_state = UPDATE; |
else next_state = IN2; |
end |
|
end |
IN2: |
begin |
// synopsys translate_off |
`ifdef USBF_VERBOSE_DEBUG |
$display("PE: Entered state IN2 (%t)", $time); |
`endif |
`ifdef USBF_DEBUG |
if(rx_ack_to === 1'bx) $display("ERROR: IN2: rx_ack_to is unknown. (%t)", $time); |
if(token_valid === 1'bx)$display("ERROR: IN2: token_valid is unknown. (%t)", $time); |
if(pid_ACK === 1'bx) $display("ERROR: IN2: pid_ACK is unknown. (%t)", $time); |
`endif |
// synopsys translate_on |
rx_ack_to_clr_d = 1'b0; |
// 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 |
end |
|
OUT: |
begin |
// synopsys translate_off |
`ifdef USBF_VERBOSE_DEBUG |
$display("PE: Entered state OUT (%t)", $time); |
`endif |
`ifdef USBF_DEBUG |
if(tx_data_to === 1'bx) $display("ERROR: OUT: tx_data_to is unknown. (%t)", $time); |
if(crc16_err === 1'bx) $display("ERROR: OUT: crc16_err is unknown. (%t)", $time); |
if(abort === 1'bx) $display("ERROR: OUT: abort is unknown. (%t)", $time); |
if(rx_data_done === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time); |
if(txfr_iso === 1'bx) $display("ERROR: OUT: txfr_iso is unknown. (%t)", $time); |
if(pid_seq_err === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time); |
`endif |
// synopsys translate_on |
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'b1; |
next_state = UPDATEW; |
end |
else next_state = OUT2A; |
end |
end |
|
OUT2B: |
begin // This is a delay State to NACK to small or to |
// large packets. this state could be skipped |
// synopsys translate_off |
`ifdef USBF_VERBOSE_DEBUG |
$display("PE: Entered state OUT2B (%t)", $time); |
`endif |
`ifdef USBF_DEBUG |
if(abort === 1'bx) $display("ERROR: OUT2A: abort is unknown. (%t)", $time); |
`endif |
// synopsys translate_on |
if(abort) next_state = IDLE; |
else next_state = OUT2B; |
end |
OUT2A: |
begin // Send ACK/NACK/NYET |
// synopsys translate_off |
`ifdef USBF_VERBOSE_DEBUG |
$display("PE: Entered state OUT2A (%t)", $time); |
`endif |
`ifdef USBF_DEBUG |
if(abort === 1'bx) $display("ERROR: OUT2A: abort is unknown. (%t)", $time); |
if(pid_seq_err === 1'bx)$display("ERROR: OUT2A: rx_data_done is unknown. (%t)", $time); |
`endif |
// synopsys translate_on |
if(abort) next_state = IDLE; |
else |
|
if(send_stall_r) |
begin |
token_pid_sel_d = STALL; |
send_token_d = 1'b1; |
next_state = IDLE; |
end |
else |
if(ep_full) |
begin |
token_pid_sel_d = NACK; |
send_token_d = 1'b1; |
next_state = IDLE; |
end |
else |
begin |
token_pid_sel_d = ACK; |
send_token_d = 1'b1; |
if(pid_seq_err) next_state = IDLE; |
else next_state = UPDATE; |
end |
end |
|
UPDATEW: |
begin |
// synopsys translate_off |
`ifdef USBF_VERBOSE_DEBUG |
$display("PE: Entered state UPDATEW (%t)", $time); |
`endif |
// synopsys translate_on |
next_state = UPDATE; |
end |
|
UPDATE: |
begin |
// synopsys translate_off |
`ifdef USBF_VERBOSE_DEBUG |
$display("PE: Entered state UPDATE (%t)", $time); |
`endif |
// synopsys translate_on |
uc_stat_set_d = 1'b1; |
next_state = IDLE; |
end |
endcase |
end |
|
endmodule |
|
/trunk/rtl/verilog/usb1_fifo2.v
0,0 → 1,105
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Fast FIFO 2 entries deep //// |
//// //// |
//// //// |
//// 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_fifo2.v,v 1.1.1.1 2002-09-19 12:07:31 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:31 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
|
`include "timescale.v" |
|
module usb1_fifo2(clk, rst, clr, din, we, dout, re); |
|
input clk, rst; |
input clr; |
input [7:0] din; |
input we; |
output [7:0] dout; |
input re; |
|
|
//////////////////////////////////////////////////////////////////// |
// |
// Local Wires |
// |
|
reg [7:0] mem[0:1]; |
reg wp; |
reg rp; |
|
//////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
always @(posedge clk or negedge rst) |
if(!rst) wp <= #1 1'h0; |
else |
if(clr) wp <= #1 1'h0; |
else |
if(we) wp <= #1 ~wp; |
|
always @(posedge clk or negedge rst) |
if(!rst) rp <= #1 1'h0; |
else |
if(clr) rp <= #1 1'h0; |
else |
if(re) rp <= #1 ~rp; |
|
// Fifo Output |
assign dout = mem[ rp ]; |
|
// Fifo Input |
always @(posedge clk) |
if(we) mem[ wp ] <= #1 din; |
|
endmodule |
|
/trunk/rtl/verilog/usb1_idma.v
0,0 → 1,372
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Internal DMA Engine //// |
//// //// |
//// //// |
//// 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_idma.v,v 1.1.1.1 2002-09-19 12:07:38 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:38 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
module usb1_idma( clk, rst, |
|
// Packet Disassembler/Assembler interface |
rx_data_valid, |
rx_data_done, |
send_data, |
rd_next, |
|
tx_valid, |
tx_data_st_i, |
tx_data_st_o, |
|
// Protocol Engine |
tx_dma_en, rx_dma_en, idma_done, |
ep_sel, |
|
// Register File Manager Interface |
size, |
rx_cnt, rx_done, |
dropped_frame, misaligned_frame, |
|
// Memory Arb interface |
mwe, mre, ep_empty, ep_empty_latched, ep_full |
); |
|
|
// Packet Disassembler/Assembler interface |
input clk, rst; |
input rx_data_valid; |
input rx_data_done; |
output send_data; |
input rd_next; |
|
input tx_valid; |
input [7:0] tx_data_st_i; |
output [7:0] tx_data_st_o; |
|
// Protocol Engine |
input tx_dma_en; |
input rx_dma_en; |
output idma_done; // DMA is done |
input [3:0] ep_sel; |
|
// Register File Manager Interface |
input [8:0] size; // MAX PL Size in bytes |
output [7:0] rx_cnt; |
output rx_done; |
output dropped_frame; |
output misaligned_frame; |
|
// Memory Arb interface |
output mwe; |
output mre; |
input ep_empty; |
output ep_empty_latched; |
input ep_full; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Local Wires and Registers |
// |
|
reg tx_dma_en_r; |
reg [8:0] sizd_c; // Internal size counter |
wire adr_incw; |
wire adr_incb; |
wire siz_dec; |
wire mwe; // Memory Write enable |
wire mre; // Memory Read enable |
reg mwe_r; |
reg sizd_is_zero; // Indicates when all bytes have been |
// transferred |
wire sizd_is_zero_d; |
reg idma_done; // DMA transfer is done |
wire send_data; // Enable UTMI Transmitter |
reg rx_data_done_r; |
reg rx_data_valid_r; |
wire ff_re, ff_full, ff_empty; |
reg ff_we, ff_we1; |
reg tx_dma_en_r1; |
reg tx_dma_en_r2; |
reg tx_dma_en_r3; |
reg send_data_r; |
wire ff_clr; |
reg [7:0] rx_cnt; |
reg [7:0] rx_cnt_r; |
reg ep_empty_r; |
reg ep_empty_latched; |
wire sp_ep_sel; |
wire ep_empty_int; |
reg [5:0] ec; |
wire ec_clr; |
reg dropped_frame; |
reg [5:0] rc_cnt; |
wire sp_ep2_sel; |
wire rc_clr; |
reg ep_full_latched; |
wire ep_full_int; |
reg misaligned_frame; |
|
/////////////////////////////////////////////////////////////////// |
// |
// For ISO interface transmit frames in 32 byte quantities |
// |
|
assign sp_ep_sel = (ep_sel==4'h1); // Special endpoint |
|
`ifdef USB1_ISO_CHUNKS |
assign ep_empty_int = sp_ep_sel ? ep_empty_latched : ep_empty; |
`else |
assign ep_empty_int = ep_empty; |
`endif |
|
always @(posedge clk) |
if(!rst) ec <= #1 6'h0; |
else |
if(!sp_ep_sel | ec_clr) ec <= #1 6'h0; |
else |
if(mre) ec <= #1 ec + 6'h1; |
|
assign ec_clr = (ec == 6'd032) | tx_dma_en; |
|
always @(posedge clk) |
if(!rst) ep_empty_latched <= #1 1'b0; |
else |
if(ec_clr) ep_empty_latched <= #1 ep_empty; |
|
/////////////////////////////////////////////////////////////////// |
// |
// For ISO interface OUT always store in 32 byte chunks |
// if fifo can't accept 32 bytes junk the entire 32 byte frame |
// |
|
assign sp_ep2_sel = (ep_sel==4'h2); // Special endpoint |
|
always @(posedge clk) |
if(!rst) rc_cnt <= #1 6'h0; |
else |
if(!sp_ep2_sel | rc_clr) rc_cnt <= #1 6'h0; |
else |
if(mwe_r) rc_cnt <= #1 rc_cnt + 6'h1; |
|
assign rc_clr = ((rc_cnt == 6'd031) & mwe_r) | rx_dma_en; |
|
always @(posedge clk) |
if(!rst) ep_full_latched <= #1 1'b0; |
else |
if(rc_clr) ep_full_latched <= #1 ep_full; |
|
`ifdef USB1_ISO_CHUNKS |
assign ep_full_int = sp_ep2_sel ? ep_full_latched : ep_full; |
`else |
assign ep_full_int = ep_full; |
`endif |
|
always @(posedge clk) |
dropped_frame <= #1 rc_clr & ep_full & sp_ep2_sel; |
|
always @(posedge clk) |
misaligned_frame <= #1 rx_data_done_r & sp_ep2_sel & (rc_cnt!=6'd00); |
|
// synopsys translate_off |
`ifdef USBF_VERBOSE_DEBUG |
always @(posedge dropped_frame) |
$display("WARNING: Droped one OUT frame (no space in FIFO) (%t)",$time); |
|
always @(posedge misaligned_frame) |
$display("WARNING: Received misaligned frame (%t)",$time); |
`endif |
// synopsys translate_on |
/////////////////////////////////////////////////////////////////// |
// |
// FIFO interface |
// |
|
always @(posedge clk) |
mwe_r <= #1 rx_data_valid; |
|
assign mwe = mwe_r & !ep_full_int; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
always @(posedge clk) |
rx_data_valid_r <= #1 rx_data_valid; |
|
always @(posedge clk) |
rx_data_done_r <= #1 rx_data_done; |
|
// Generate one cycle pulses for tx and rx dma enable |
always @(posedge clk) |
tx_dma_en_r <= #1 tx_dma_en; |
|
always @(posedge clk) |
tx_dma_en_r1 <= tx_dma_en_r; |
|
always @(posedge clk) |
tx_dma_en_r2 <= tx_dma_en_r1; |
|
always @(posedge clk) |
tx_dma_en_r3 <= tx_dma_en_r2; |
|
// DMA Done Indicator |
always @(posedge clk) |
idma_done <= #1 (rx_data_done_r | sizd_is_zero_d | ep_empty_int); |
|
/////////////////////////////////////////////////////////////////// |
// |
// RX Size Counter |
// |
|
always @(posedge clk or negedge rst) |
if(!rst) rx_cnt_r <= #1 8'h00; |
else |
if(rx_data_done_r) rx_cnt_r <= #1 8'h00; |
else |
if(rx_data_valid) rx_cnt_r <= #1 rx_cnt_r + 8'h01; |
|
always @(posedge clk or negedge rst) |
if(!rst) rx_cnt <= #1 8'h00; |
else |
if(rx_data_done_r) rx_cnt <= #1 rx_cnt_r; |
|
assign rx_done = rx_data_done_r; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Transmit Size Counter (counting backward from input size) |
// For MAX packet size |
// |
|
always @(posedge clk or negedge rst) |
if(!rst) sizd_c <= #1 9'h1ff; |
else |
if(tx_dma_en) sizd_c <= #1 size; |
else |
if(siz_dec) sizd_c <= #1 sizd_c - 9'h1; |
|
assign siz_dec = (tx_dma_en_r | tx_dma_en_r1 | rd_next) & !sizd_is_zero_d; |
|
assign sizd_is_zero_d = sizd_c == 9'h0; |
|
always @(posedge clk) |
sizd_is_zero <= #1 sizd_is_zero_d; |
|
/////////////////////////////////////////////////////////////////// |
// |
// TX Logic |
// |
|
reg tx_valid_r; |
wire tx_valid_e; |
|
always @(posedge clk) |
tx_valid_r <= #1 tx_valid; |
|
assign tx_valid_e = tx_valid_r & !tx_valid; |
|
// Since we are prefetching two entries in to our fast fifo, we |
// need to know when exactly ep_empty was asserted, as we might |
// only need 1 or 2 bytes. This is for ep_empty_r |
|
always @(posedge clk or negedge rst) |
if(!rst) ep_empty_r <= #1 1'b0; |
else |
if(!tx_valid) ep_empty_r <= #1 1'b0; |
else |
if(tx_dma_en_r2) ep_empty_r <= #1 ep_empty_int; |
|
always @(posedge clk or negedge rst) |
if(!rst) send_data_r <= #1 1'b0; |
else |
if((tx_dma_en_r & !ep_empty_int)) send_data_r <= #1 1'b1; |
else |
if(rd_next & (sizd_is_zero_d | (ep_empty_int & !sizd_is_zero_d)) ) |
send_data_r <= #1 1'b0; |
|
assign send_data = (send_data_r & !ep_empty_r & |
!(sizd_is_zero & size==9'h01)) | tx_dma_en_r1; |
|
assign mre = (tx_dma_en_r1 | tx_dma_en_r | rd_next) & |
!sizd_is_zero_d & !ep_empty_int & (send_data | tx_dma_en_r1 | tx_dma_en_r); |
|
always @(posedge clk) |
ff_we1 <= mre; |
|
always @(posedge clk) |
ff_we <= ff_we1; |
|
assign ff_re = rd_next; |
|
assign ff_clr = !tx_valid; |
|
/////////////////////////////////////////////////////////////////// |
// |
// IDMA fast prefetch fifo |
// |
|
// tx fifo |
usb1_fifo2 ff( |
.clk( clk ), |
.rst( rst ), |
.clr( ff_clr ), |
.din( tx_data_st_i ), |
.we( ff_we ), |
.dout( tx_data_st_o ), |
.re( ff_re ) |
); |
|
endmodule |
|
|
/trunk/rtl/verilog/usb1_pl.v
0,0 → 1,395
///////////////////////////////////////////////////////////////////// |
//// //// |
//// 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/usb1_fucnt///// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// 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_pl.v,v 1.1.1.1 2002-09-19 12:07:28 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:28 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
// |
// |
|
module usb1_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, |
|
token_valid, |
|
// Register File Interface |
fa, |
ep_sel, |
|
int_crc16_set, int_to_set, int_seqerr_set, |
|
// Misc |
frm_nat, |
pid_cs_err, nse_err, |
crc5_err, |
rx_size, rx_done, |
ctrl_setup, ctrl_in, ctrl_out, |
dropped_frame, misaligned_frame, |
|
// EP Interface |
csr, |
tx_data_st, rx_data_st, idma_re, idma_we, |
ep_empty, ep_full, send_stall |
|
); |
|
// 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; |
|
output token_valid; |
|
// Register File interface |
input [6:0] fa; // Function Address (as set by the controller) |
output [3:0] ep_sel; // Endpoint Number Input |
|
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 |
|
// Misc |
output pid_cs_err; // pid checksum error |
output crc5_err; // crc5 error |
output [31:0] frm_nat; |
output nse_err; // no such endpoint error |
output [7:0] rx_size; |
output rx_done; |
output ctrl_setup; |
output ctrl_in; |
output ctrl_out; |
output dropped_frame, misaligned_frame; |
|
// Endpoint Interfaces |
input [13:0] csr; |
input [7:0] tx_data_st; |
output [7:0] rx_data_st; |
output idma_re, idma_we; |
input ep_empty; |
input ep_full; |
|
input send_stall; |
|
/////////////////////////////////////////////////////////////////// |
// |
// 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; |
reg [7:0] rx_data_st; |
wire [7:0] rx_data_st_d; |
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 [7:0] tx_data_st_o; |
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 |
|
// Memory Arbiter Interface |
wire idma_we; |
wire idma_re; |
|
// Local signals |
wire pid_bad; |
|
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 [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; |
reg ctrl_setup; |
reg ctrl_in; |
reg ctrl_out; |
|
wire idma_we_d; |
wire ep_empty_latched; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
// PIDs we should never receive |
assign pid_bad = pid_ACK | pid_NACK | pid_STALL | pid_NYET | pid_PRE | |
pid_ERR | pid_SPLIT | pid_PING; |
|
assign match_o = !pid_bad & token_valid & !crc5_err; |
|
// Recieving Setup |
always @(posedge clk) |
ctrl_setup <= #1 token_valid & pid_SETUP & (ep_sel==4'h0); |
|
always @(posedge clk) |
ctrl_in <= #1 token_valid & pid_IN & (ep_sel==4'h0); |
|
always @(posedge clk) |
ctrl_out <= #1 token_valid & pid_OUT & (ep_sel==4'h0); |
|
// Frame Number (from SOF token) |
assign frame_no_we = token_valid & !crc5_err & pid_SOF; |
|
always @(posedge clk) |
frame_no_we_r <= #1 frame_no_we; |
|
always @(posedge clk or negedge rst) |
if(!rst) frame_no_r <= #1 11'h0; |
else |
if(frame_no_we_r) frame_no_r <= #1 frame_no; |
|
//SOF delay counter |
always @(posedge clk) |
clr_sof_time <= #1 frame_no_we; |
|
always @(posedge clk) |
if(clr_sof_time) sof_time <= #1 12'h0; |
else |
if(hms_clk) sof_time <= #1 sof_time + 12'h1; |
|
assign frm_nat = {4'h0, 1'b0, frame_no_r, 4'h0, sof_time}; |
|
// 0.5 Micro Seconds Clock Generator |
always @(posedge clk or negedge rst) |
if(!rst) hms_cnt <= #1 5'h0; |
else |
if(hms_clk | frame_no_we_r) hms_cnt <= #1 5'h0; |
else hms_cnt <= #1 hms_cnt + 5'h1; |
|
always @(posedge clk) |
hms_clk <= #1 (hms_cnt == `USBF_HMS_DEL); |
|
always @(posedge clk) |
rx_data_st <= rx_data_st_d; |
|
/////////////////////////////////////////////////////////////////// |
|
// This function is addressed |
assign fsel = (token_fadr == fa); |
|
// Only write when we are addressed !!! |
assign idma_we = idma_we_d & fsel; // moved full check to idma ... & !ep_full; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Module Instantiations |
// |
|
|
//Packet Decoder |
usb1_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_d ), |
.rx_data_valid( rx_data_valid ), |
.rx_data_done( rx_data_done ), |
.crc16_err( crc16_err ), |
.seq_err( rx_seq_err ) |
); |
|
// Packet Assembler |
usb1_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 ), |
.tx_data_st( tx_data_st_o ), |
.rd_next( rd_next ), |
.ep_empty( ep_empty_latched) |
); |
|
// Internal DMA / Memory Arbiter Interface |
usb1_idma |
u2( .clk( clk ), |
.rst( rst ), |
|
.tx_valid( tx_valid ), |
.rx_data_valid( rx_data_valid ), |
.rx_data_done( rx_data_done ), |
.send_data( send_data ), |
.rd_next( rd_next ), |
|
.tx_data_st_i( tx_data_st ), |
.tx_data_st_o( tx_data_st_o ), |
.ep_sel( ep_sel ), |
|
.dropped_frame(dropped_frame ), |
.misaligned_frame(misaligned_frame), |
|
.tx_dma_en( tx_dma_en ), |
.rx_dma_en( rx_dma_en ), |
.idma_done( idma_done ), |
.size( csr[8:0] ), |
.rx_cnt( rx_size ), |
.rx_done( rx_done ), |
.mwe( idma_we_d ), |
.mre( idma_re ), |
.ep_empty( ep_empty ), |
.ep_empty_latched(ep_empty_latched), |
.ep_full( ep_full ) |
); |
|
// Protocol Engine |
usb1_pe |
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_PING( pid_PING ), |
.token_valid( token_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 ), |
.rx_dma_en( rx_dma_en ), |
.tx_dma_en( tx_dma_en ), |
.abort( abort ), |
.idma_done( idma_done ), |
.fsel( fsel ), |
.ep_sel( ep_sel ), |
.ep_full( ep_full ), |
.ep_empty( ep_empty ), |
.match( match_o ), |
.nse_err( nse_err ), |
.int_upid_set( int_upid_set ), |
.int_crc16_set( int_crc16_set ), |
.int_to_set( int_to_set ), |
.int_seqerr_set( int_seqerr_set ), |
.csr( csr ), |
.send_stall( send_stall ) |
); |
|
|
endmodule |
|
/trunk/rtl/verilog/timescale.v
0,0 → 1,395
`timescale 1ns / 10ps |
/trunk/rtl/verilog/usb1_defines.v
0,0 → 1,124
///////////////////////////////////////////////////////////////////// |
//// //// |
//// USB 1.1 function defines file //// |
//// //// |
//// //// |
//// 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_defines.v,v 1.1.1.1 2002-09-19 12:07:40 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:40 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
// |
|
`include "timescale.v" |
|
//`define USBF_DEBUG |
//`define USBF_VERBOSE_DEBUG |
|
|
// Enable or disable using chunkc for isochronous endpoints |
`USB1_ISO_CHUNKS |
|
///////////////////////////////////////////////////////////////////// |
// |
// Items below this point should NOT be modified by the end user |
// UNLESS you know exactly what you are doing ! |
// Modify at you own risk !!! |
// |
///////////////////////////////////////////////////////////////////// |
|
`define IN 14'b00_001_000000000 |
`define OUT 14'b00_010_000000000 |
`define CTRL 14'b10_100_000000000 |
`define ISO 14'b01_000_000000000 |
`define BULK 14'b10_000_000000000 |
`define INT 14'b00_000_000000000 |
|
// PID Encodings |
`define USBF_T_PID_OUT 4'b0001 |
`define USBF_T_PID_IN 4'b1001 |
`define USBF_T_PID_SOF 4'b0101 |
`define USBF_T_PID_SETUP 4'b1101 |
`define USBF_T_PID_DATA0 4'b0011 |
`define USBF_T_PID_DATA1 4'b1011 |
`define USBF_T_PID_DATA2 4'b0111 |
`define USBF_T_PID_MDATA 4'b1111 |
`define USBF_T_PID_ACK 4'b0010 |
`define USBF_T_PID_NACK 4'b1010 |
`define USBF_T_PID_STALL 4'b1110 |
`define USBF_T_PID_NYET 4'b0110 |
`define USBF_T_PID_PRE 4'b1100 |
`define USBF_T_PID_ERR 4'b1100 |
`define USBF_T_PID_SPLIT 4'b1000 |
`define USBF_T_PID_PING 4'b0100 |
`define USBF_T_PID_RES 4'b0000 |
|
// The HMS_DEL is a constant for the "Half Micro Second" |
// Clock pulse generator. This constant specifies how many |
// Phy clocks there are between two hms_clock pulses. This |
// constant plus 2 represents the actual delay. |
// Example: For a 60 Mhz (16.667 nS period) Phy Clock, the |
// delay must be 30 phy clock: 500ns / 16.667nS = 30 clocks |
`define USBF_HMS_DEL 5'h16 |
|
// 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_VAL_FS |
// and RX_ACK_TO_VAL_HS are the numbers of UTMI clock cycles |
// minus 2 for Full and High Speed modes. |
//`define USBF_RX_ACK_TO_VAL_FS 8'd36 |
`define USBF_RX_ACK_TO_VAL_FS 8'd200 |
|
// 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_VAL_FS and TX_DATA_TO_VAL_HS are is the numbers of |
// UTMI clock cycles minus 2. |
//`define USBF_TX_DATA_TO_VAL_FS 8'd36 |
`define USBF_TX_DATA_TO_VAL_FS 8'd200 |
/trunk/rtl/verilog/usb1_rom1.v
0,0 → 1,243
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Descriptor ROM //// |
//// //// |
//// //// |
//// 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_rom1.v,v 1.1.1.1 2002-09-19 12:07:29 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:29 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
module usb1_rom1(clk, adr, dout); |
input clk; |
input [6:0] adr; |
output [7:0] dout; |
|
reg [7:0] dout; |
|
always @(posedge clk) |
case(adr) // synopsys full_case parallel_case |
|
// ==================================== |
// ===== DEVICE Descriptor ===== |
// ==================================== |
|
7'h00: dout <= #1 8'd18; // this descriptor length |
7'h01: dout <= #1 8'h01; // descriptor type |
7'h02: dout <= #1 8'h00; // USB version low byte |
7'h03: dout <= #1 8'h01; // USB version high byte |
7'h04: dout <= #1 8'hff; // device class |
7'h05: dout <= #1 8'h00; // device sub class |
7'h06: dout <= #1 8'hff; // device protocol |
7'h07: dout <= #1 8'd64; // max packet size |
7'h08: dout <= #1 8'h34; // vendor ID low byte |
7'h09: dout <= #1 8'h12; // vendor ID high byte |
7'h0a: dout <= #1 8'h78; // product ID low byte |
7'h0b: dout <= #1 8'h56; // product ID high byte |
7'h0c: dout <= #1 8'h10; // device rel. number low byte |
7'h0d: dout <= #1 8'h00; // device rel. number high byte |
7'h0e: dout <= #1 8'h00; // Manufacturer String Index |
7'h0f: dout <= #1 8'h00; // Product Descr. String Index |
7'h10: dout <= #1 8'h00; // S/N String Index |
7'h11: dout <= #1 8'h01; // Number of possible config. |
|
// ==================================== |
// ===== Configuration Descriptor ===== |
// ==================================== |
7'h12: dout <= #1 8'h09; // this descriptor length |
7'h13: dout <= #1 8'h02; // descriptor type |
7'h14: dout <= #1 8'd53; // total data length low byte |
7'h15: dout <= #1 8'd00; // total data length high byte |
7'h16: dout <= #1 8'h01; // number of interfaces |
7'h17: dout <= #1 8'h01; // number of configurations |
7'h18: dout <= #1 8'h00; // Conf. String Index |
7'h19: dout <= #1 8'h40; // Config. Characteristics |
7'h1a: dout <= #1 8'h00; // Max. Power Consumption |
|
// ==================================== |
// ===== Interface Descriptor ===== |
// ==================================== |
7'h1b: dout <= #1 8'h09; // this descriptor length |
7'h1c: dout <= #1 8'h04; // descriptor type |
7'h1d: dout <= #1 8'h00; // interface number |
7'h1e: dout <= #1 8'h00; // alternate setting |
7'h1f: dout <= #1 8'h05; // number of endpoints |
7'h20: dout <= #1 8'hff; // interface class |
7'h21: dout <= #1 8'h01; // interface sub class |
7'h22: dout <= #1 8'hff; // interface protocol |
7'h23: dout <= #1 8'h00; // interface string index |
|
// ==================================== |
// ===== Endpoint 1 Descriptor ===== |
// ==================================== |
7'h24: dout <= #1 8'h07; // this descriptor length |
7'h25: dout <= #1 8'h05; // descriptor type |
7'h26: dout <= #1 8'h81; // endpoint address |
7'h27: dout <= #1 8'h01; // endpoint attributes |
7'h28: dout <= #1 8'h00; // max packet size low byte |
7'h29: dout <= #1 8'h01; // max packet size high byte |
7'h2a: dout <= #1 8'h01; // polling interval |
|
// ==================================== |
// ===== Endpoint 2 Descriptor ===== |
// ==================================== |
7'h2b: dout <= #1 8'h07; // this descriptor length |
7'h2c: dout <= #1 8'h05; // descriptor type |
7'h2d: dout <= #1 8'h02; // endpoint address |
7'h2e: dout <= #1 8'h01; // endpoint attributes |
7'h2f: dout <= #1 8'h00; // max packet size low byte |
7'h30: dout <= #1 8'h01; // max packet size high byte |
7'h31: dout <= #1 8'h01; // polling interval |
|
// ==================================== |
// ===== Endpoint 3 Descriptor ===== |
// ==================================== |
7'h32: dout <= #1 8'h07; // this descriptor length |
7'h33: dout <= #1 8'h05; // descriptor type |
7'h34: dout <= #1 8'h83; // endpoint address |
7'h35: dout <= #1 8'h02; // endpoint attributes |
7'h36: dout <= #1 8'd64; // max packet size low byte |
7'h37: dout <= #1 8'd00; // max packet size high byte |
7'h38: dout <= #1 8'h01; // polling interval |
|
// ==================================== |
// ===== Endpoint 4 Descriptor ===== |
// ==================================== |
7'h39: dout <= #1 8'h07; // this descriptor length |
7'h3a: dout <= #1 8'h05; // descriptor type |
7'h3b: dout <= #1 8'h04; // endpoint address |
7'h3c: dout <= #1 8'h02; // endpoint attributes |
7'h3d: dout <= #1 8'd64; // max packet size low byte |
7'h3e: dout <= #1 8'd00; // max packet size high byte |
7'h3f: dout <= #1 8'h01; // polling interval |
|
// ==================================== |
// ===== Endpoint 5 Descriptor ===== |
// ==================================== |
7'h40: dout <= #1 8'h07; // this descriptor length |
7'h41: dout <= #1 8'h05; // descriptor type |
7'h42: dout <= #1 8'h85; // endpoint address |
7'h43: dout <= #1 8'h03; // endpoint attributes |
7'h44: dout <= #1 8'd64; // max packet size low byte |
7'h45: dout <= #1 8'd00; // max packet size high byte |
7'h46: dout <= #1 8'h01; // polling interval |
|
/* |
// ==================================== |
// ===== String Descriptor Lang ID===== |
// ==================================== |
|
7'h47: dout <= #1 8'd06; // this descriptor length |
7'h48: dout <= #1 8'd03; // descriptor type |
|
7'h49: dout <= #1 8'd09; // Language ID 0 low byte |
7'h4a: dout <= #1 8'd04; // Language ID 0 high byte |
|
7'h4b: dout <= #1 8'd09; // Language ID 1 low byte |
7'h4c: dout <= #1 8'd04; // Language ID 1 high byte |
|
7'h4d: dout <= #1 8'd09; // Language ID 2 low byte |
7'h4e: dout <= #1 8'd04; // Language ID 2 high byte |
|
// ==================================== |
// ===== String Descriptor 0 ===== |
// ==================================== |
|
7'h50: dout <= #1 8'd010; // this descriptor length |
7'h51: dout <= #1 8'd03; // descriptor type |
7'h52: dout <= #1 "0"; |
7'h53: dout <= #1 " "; |
7'h54: dout <= #1 "g"; |
7'h55: dout <= #1 "n"; |
7'h56: dout <= #1 "i"; |
7'h57: dout <= #1 "r"; |
7'h58: dout <= #1 "t"; |
7'h59: dout <= #1 "S"; |
|
// ==================================== |
// ===== String Descriptor 1 ===== |
// ==================================== |
|
7'h60: dout <= #1 8'd010; // this descriptor length |
7'h61: dout <= #1 8'd03; // descriptor type |
7'h62: dout <= #1 "1"; |
7'h63: dout <= #1 " "; |
7'h64: dout <= #1 "g"; |
7'h65: dout <= #1 "n"; |
7'h66: dout <= #1 "i"; |
7'h67: dout <= #1 "r"; |
7'h68: dout <= #1 "t"; |
7'h69: dout <= #1 "S"; |
|
// ==================================== |
// ===== String Descriptor 2 ===== |
// ==================================== |
|
7'h70: dout <= #1 8'd010; // this descriptor length |
7'h71: dout <= #1 8'd03; // descriptor type |
7'h72: dout <= #1 "2"; |
7'h73: dout <= #1 " "; |
7'h74: dout <= #1 "g"; |
7'h75: dout <= #1 "n"; |
7'h76: dout <= #1 "i"; |
7'h77: dout <= #1 "r"; |
7'h78: dout <= #1 "t"; |
7'h79: dout <= #1 "S"; |
|
*/ |
|
// ==================================== |
// ==================================== |
|
//default: dout <= #1 8'd00; |
endcase |
|
endmodule |
/trunk/rtl/verilog/usb1_crc16.v
0,0 → 1,98
///////////////////////////////////////////////////////////////////// |
//// //// |
//// USB CRC16 Modules //// |
//// //// |
//// //// |
//// 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_crc16.v,v 1.1.1.1 2002-09-19 12:07:39 rudi Exp $ |
// |
// $Date: 2002-09-19 12:07:39 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
// |
|
`include "usb1_defines.v" |
|
/////////////////////////////////////////////////////////////////// |
// |
// CRC16 |
// |
/////////////////////////////////////////////////////////////////// |
|
module usb1_crc16(crc_in, din, crc_out); |
input [15:0] crc_in; |
input [7:0] din; |
output [15:0] crc_out; |
|
assign crc_out[0] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ |
din[2] ^ din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9] ^ |
crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^ |
crc_in[14] ^ crc_in[15]; |
assign crc_out[1] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^ |
din[1] ^ crc_in[9] ^ crc_in[10] ^ crc_in[11] ^ |
crc_in[12] ^ crc_in[13] ^ crc_in[14] ^ crc_in[15]; |
assign crc_out[2] = din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9]; |
assign crc_out[3] = din[2] ^ din[1] ^ crc_in[9] ^ crc_in[10]; |
assign crc_out[4] = din[3] ^ din[2] ^ crc_in[10] ^ crc_in[11]; |
assign crc_out[5] = din[4] ^ din[3] ^ crc_in[11] ^ crc_in[12]; |
assign crc_out[6] = din[5] ^ din[4] ^ crc_in[12] ^ crc_in[13]; |
assign crc_out[7] = din[6] ^ din[5] ^ crc_in[13] ^ crc_in[14]; |
assign crc_out[8] = din[7] ^ din[6] ^ crc_in[0] ^ crc_in[14] ^ crc_in[15]; |
assign crc_out[9] = din[7] ^ crc_in[1] ^ crc_in[15]; |
assign crc_out[10] = crc_in[2]; |
assign crc_out[11] = crc_in[3]; |
assign crc_out[12] = crc_in[4]; |
assign crc_out[13] = crc_in[5]; |
assign crc_out[14] = crc_in[6]; |
assign crc_out[15] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^ |
din[1] ^ din[0] ^ crc_in[7] ^ crc_in[8] ^ crc_in[9] ^ |
crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^ |
crc_in[14] ^ crc_in[15]; |
|
endmodule |
|
/trunk/doc/README.txt
0,0 → 1,124
|
|
The USB 1.1 Function IP Core |
============================================ |
|
Status |
------ |
This core is done. It was tested on a XESS XCV800 board with |
a Philips USB transceiver. |
|
Test Bench |
---------- |
There is no test bench, period ! |
Please don't email me asking for one, unless you want to hire |
me to write one ! As I said above I have tested this core in |
real hardware and it works just fine. |
|
Documentation |
------------- |
Sorry, there is none. I just don't have the time to write it. |
However, since this core is derived from my USB 2.0 Function |
IP core, you might find something useful in there. Main |
difference is that all the high speed support features have |
been ripped out, and the interface was changed from a shared |
memory model to a FIFO based interface. Further there is no |
need for a micro-controller interface and/or register file. |
|
|
Here is the quick info: |
|
The core comes pre-configured with 6 endpoints: |
|
ep 0 - Control endpoint [64/64] |
ep 1 - isochronous IN [256/512] |
ep 2 - isochronous OUT [256/512] |
ep 3 - bulk IN [64/256] |
ep 4 - bulk OUT [64/256] |
ep 5 - interrupt IN [64/64] |
|
The numbers in brackets are [Max Payload Size/Max FIFO Size] |
|
The isochronous endpoints are handled special. Data is |
always transfered in 32 byte "chunks". If the FIFO can not |
accept a 32 "byte" chunk, that chunk is dropped and |
'dropped_frame" signal is asserted. If the host sends a |
packet that is not in multiple of 32 bytes the |
"misaligned_frame" signal is asserted. |
|
This of this "chunks" as being video frames for example. |
It's OK to drop one entire frame, or to display one frame |
multiple times. However you don't want to loose synchronization, |
where the frame begins or ends. You might want to add some |
encoding on to the data stream itself as well, as a fail |
save mechanism to not get out of sync. All of this might be |
disabled by making sure USB1_ISO_CHUNKS is NOT defined |
anywahere. |
|
Vendor Features allow you to define your own features and |
set and check various device parameters. For example you |
might wan tot count the number of drooped frames so that |
the host can read this out for statistics purposes. |
|
This core will perform the entire USB 1.1 enumeration |
process in hardware. All you need is to edit the usb1_rom1.v |
file and put appropriate values there. This allows you to build |
a USB 1.1 device without the need for a micro-controller/CPU. |
For example a mouse or joystick ... |
|
The top level should be considered an example how to build |
your own customized USB 1.1 device. |
|
The 'loop' signal allows you to place the isochronous and |
bulk endpoints in to a loop back mode. Use that is you just |
wan to see the core talk to your Linux box. Place it in to |
loop-back mode, compile it in to and FPGA and plug in to your |
PC running Linux. Type 'lsusb' and you should see a device |
which enumerated to "1234:5678" Strings don't work without a |
dedicated driver that takes control of the device (At least |
under RedHat linux 7.3). |
|
|
Misc |
---- |
The USB 1.1 Function Project Page is: |
http://www.opencores.org/cores/usb1_funct/ |
|
To find out more about me (Rudolf Usselmann), please visit: |
http://www.asics.ws |
|
|
Directory Structure |
------------------- |
[core_root] |
| |
+-doc Documentation |
| |
+-bench--+ Test Bench |
| +-verilog Verilog Sources |
| +-vhdl VHDL Sources |
| |
+-rtl----+ Core RTL Sources |
| +-verilog Verilog Sources |
| +-vhdl VHDL Sources |
| |
+-sim----+ |
| +-rtl_sim---+ Functional verification Directory |
| | +-bin Makefiles/Run Scripts |
| | +-run Working Directory |
| | |
| +-gate_sim--+ Functional & Timing Gate Level |
| | Verification Directory |
| +-bin Makefiles/Run Scripts |
| +-run Working Directory |
| |
+-lint--+ Lint Directory Tree |
| +-bin Makefiles/Run Scripts |
| +-run Working Directory |
| +-log Linter log & result files |
| |
+-syn---+ Synthesis Directory Tree |
| +-bin Synthesis Scripts |
| +-run Working Directory |
| +-log Synthesis log files |
| +-out Synthesis Output |