URL
https://opencores.org/ocsvn/usb_phy/usb_phy/trunk
Subversion Repositories usb_phy
Compare Revisions
- This comparison shows the changes necessary to convert path
/usb_phy/tags/start/rtl
- from Rev 3 to Rev 12
- ↔ Reverse comparison
Rev 3 → Rev 12
/verilog/usb_rx_phy.v
0,0 → 1,411
///////////////////////////////////////////////////////////////////// |
//// //// |
//// USB 1.1 PHY //// |
//// RX & DPLL //// |
//// //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// rudi@asics.ws //// |
//// //// |
//// //// |
//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// 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: usb_rx_phy.v,v 1.1.1.1 2002-09-16 14:27:01 rudi Exp $ |
// |
// $Date: 2002-09-16 14:27:01 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
// |
|
`include "timescale.v" |
|
module usb_rx_phy( clk, rst, fs_ce, |
|
// Transciever Interface |
rxd, rxdp, rxdn, |
|
// UTMI Interface |
RxValid_o, RxActive_o, RxError_o, DataIn_o, |
RxEn_i, LineState); |
|
input clk; |
input rst; |
output fs_ce; |
input rxd, rxdp, rxdn; |
output [7:0] DataIn_o; |
output RxValid_o; |
output RxActive_o; |
output RxError_o; |
input RxEn_i; |
output [1:0] LineState; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Local Wires and Registers |
// |
|
reg rxd_t1, rxd_s1, rxd_s; |
reg rxdp_t1, rxdp_s1, rxdp_s; |
reg rxdn_t1, rxdn_s1, rxdn_s; |
reg synced_d; |
wire k, j, se0; |
reg rx_en; |
reg rx_active; |
reg [2:0] bit_cnt; |
reg rx_valid1, rx_valid; |
reg shift_en; |
reg sd_r; |
reg sd_nrzi; |
reg [7:0] hold_reg; |
wire drop_bit; // Indicates a stuffed bit |
reg [2:0] one_cnt; |
|
reg [1:0] dpll_state, dpll_next_state; |
reg fs_ce_d, fs_ce; |
wire change; |
reg rxdp_s1r, rxdn_s1r; |
wire lock_en; |
reg fs_ce_r1, fs_ce_r2, fs_ce_r3; |
reg [2:0] fs_state, fs_next_state; |
reg rx_valid_r; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
assign RxActive_o = rx_active; |
assign RxValid_o = rx_valid; |
assign RxError_o = 0; |
assign DataIn_o = hold_reg; |
assign LineState = {rxdp_s1, rxdn_s1}; |
|
always @(posedge clk) |
rx_en <= #1 RxEn_i; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Synchronize Inputs |
// |
|
// First synchronize to the local system clock to |
// avoid metastability outside the sync block (*_s1) |
// Second synchronise to the internal bit clock (*_s) |
always @(posedge clk) |
rxd_t1 <= #1 rxd; |
|
always @(posedge clk) |
rxd_s1 <= #1 rxd_t1; |
|
always @(posedge clk) |
rxd_s <= #1 rxd_s1; |
|
always @(posedge clk) |
rxdp_t1 <= #1 rxdp; |
|
always @(posedge clk) |
rxdp_s1 <= #1 rxdp_t1; |
|
always @(posedge clk) |
rxdp_s <= #1 rxdp_s1; |
|
always @(posedge clk) |
rxdn_t1 <= #1 rxdn; |
|
always @(posedge clk) |
rxdn_s1 <= #1 rxdn_t1; |
|
always @(posedge clk) |
rxdn_s <= #1 rxdn_s1; |
|
assign k = !rxdp_s & rxdn_s; |
assign j = rxdp_s & !rxdn_s; |
assign se0 = !rxdp_s & !rxdn_s; |
|
/////////////////////////////////////////////////////////////////// |
// |
// DPLL |
// |
|
// This design uses a clock enable to do 12Mhz timing and not a |
// real 12Mhz clock. Everything always runs at 48Mhz. We want to |
// make sure however, that the clock enable is always exactly in |
// the middle between two virtual 12Mhz rising edges. |
// We monitor rxdp and rxdn for any changes and do the appropiate |
// adjustments. |
// In addition to the locking done in the dpll FSM, we adjust the |
// final latch enable to compensate for various sync registers ... |
|
// Allow lockinf only when we are receiving |
assign lock_en = rx_en; |
|
// Edge detector |
always @(posedge clk) |
rxdp_s1r <= #1 rxdp_s1; |
|
always @(posedge clk) |
rxdn_s1r <= #1 rxdn_s1; |
|
assign change = (rxdp_s1r != rxdp_s1) | (rxdn_s1r != rxdn_s1); |
|
// DPLL FSM |
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) dpll_state <= #1 2'h1; |
else dpll_state <= #1 dpll_next_state; |
|
always @(dpll_state or lock_en or change) |
begin |
fs_ce_d = 1'b0; |
case(dpll_state) // synopsys full_case parallel_case |
2'h0: |
if(lock_en & change) dpll_next_state = 3'h0; |
else dpll_next_state = 3'h1; |
2'h1:begin |
fs_ce_d = 1'b1; |
//if(lock_en & change) dpll_next_state = 3'h0; |
if(lock_en & change) dpll_next_state = 3'h3; |
else dpll_next_state = 3'h2; |
end |
2'h2: |
if(lock_en & change) dpll_next_state = 3'h0; |
else dpll_next_state = 3'h3; |
2'h3: |
if(lock_en & change) dpll_next_state = 3'h0; |
else dpll_next_state = 3'h0; |
endcase |
end |
|
// Compensate for sync registers at the input - allign full speed |
// clock enable to be in the middle between two bit changes ... |
always @(posedge clk) |
fs_ce_r1 <= #1 fs_ce_d; |
|
always @(posedge clk) |
fs_ce_r2 <= #1 fs_ce_r1; |
|
always @(posedge clk) |
fs_ce_r3 <= #1 fs_ce_r2; |
|
always @(posedge clk) |
fs_ce <= #1 fs_ce_r3; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Find Sync Pattern FSM |
// |
|
parameter FS_IDLE = 3'h0, |
K1 = 3'h1, |
J1 = 3'h2, |
K2 = 3'h3, |
J2 = 3'h4, |
K3 = 3'h5, |
J3 = 3'h6, |
K4 = 3'h7; |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) fs_state <= #1 FS_IDLE; |
else fs_state <= #1 fs_next_state; |
|
always @(fs_state or fs_ce or k or j or rx_en) |
begin |
synced_d = 1'b0; |
fs_next_state = fs_state; |
if(fs_ce) |
case(fs_state) // synopsys full_case parallel_case |
FS_IDLE: |
begin |
if(k & rx_en) fs_next_state = K1; |
end |
K1: |
begin |
if(j & rx_en) fs_next_state = J1; |
else fs_next_state = FS_IDLE; |
end |
J1: |
begin |
if(k & rx_en) fs_next_state = K2; |
else fs_next_state = FS_IDLE; |
end |
K2: |
begin |
if(j & rx_en) fs_next_state = J2; |
else fs_next_state = FS_IDLE; |
end |
J2: |
begin |
if(k & rx_en) fs_next_state = K3; |
else fs_next_state = FS_IDLE; |
end |
K3: |
begin |
if(j & rx_en) fs_next_state = J3; |
else |
if(k & rx_en) fs_next_state = K4; // Allow missing one J |
else fs_next_state = FS_IDLE; |
end |
J3: |
begin |
if(k & rx_en) fs_next_state = K4; |
else fs_next_state = FS_IDLE; |
end |
K4: |
begin |
if(k) synced_d = 1'b1; |
fs_next_state = FS_IDLE; |
end |
endcase |
end |
|
/////////////////////////////////////////////////////////////////// |
// |
// Generate RxActive |
// |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) rx_active <= #1 1'b0; |
else |
if(synced_d & rx_en) rx_active <= #1 1'b1; |
else |
if(se0 & rx_valid_r ) rx_active <= #1 1'b0; |
|
always @(posedge clk) |
if(rx_valid) rx_valid_r <= #1 1'b1; |
else |
if(fs_ce) rx_valid_r <= #1 1'b0; |
|
/////////////////////////////////////////////////////////////////// |
// |
// NRZI Decoder |
// |
|
always @(posedge clk) |
if(fs_ce) sd_r <= #1 rxd_s; |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) sd_nrzi <= #1 1'b0; |
else |
if(rx_active & fs_ce) sd_nrzi <= #1 !(rxd_s ^ sd_r); |
|
/////////////////////////////////////////////////////////////////// |
// |
// Bit Stuff Detect |
// |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) one_cnt <= #1 3'h0; |
else |
if(!shift_en) one_cnt <= #1 3'h0; |
else |
if(fs_ce) |
begin |
if(!sd_nrzi | drop_bit) one_cnt <= #1 3'h0; |
else one_cnt <= #1 one_cnt + 3'h1; |
end |
|
assign drop_bit = (one_cnt==3'h6); |
|
/////////////////////////////////////////////////////////////////// |
// |
// Serial => Parallel converter |
// |
|
always @(posedge clk) |
if(fs_ce) shift_en <= #1 synced_d | rx_active; |
|
always @(posedge clk) |
if(fs_ce & shift_en & !drop_bit) |
hold_reg <= #1 {sd_nrzi, hold_reg[7:1]}; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Generate RxValid |
// |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) bit_cnt <= #1 3'b0; |
else |
if(!shift_en) bit_cnt <= #1 3'h0; |
else |
if(fs_ce & !drop_bit) bit_cnt <= #1 bit_cnt + 3'h1; |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) rx_valid1 <= #1 1'b0; |
else |
if(fs_ce & !drop_bit & (bit_cnt==3'h7)) rx_valid1 <= #1 1'b1; |
else |
if(rx_valid1 & fs_ce & !drop_bit) rx_valid1 <= #1 1'b0; |
|
always @(posedge clk) |
rx_valid <= #1 !drop_bit & rx_valid1 & fs_ce; |
|
endmodule |
|
/verilog/usb_tx_phy.v
0,0 → 1,451
///////////////////////////////////////////////////////////////////// |
//// //// |
//// USB 1.1 PHY //// |
//// TX //// |
//// //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// rudi@asics.ws //// |
//// //// |
//// //// |
//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// 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: usb_tx_phy.v,v 1.1.1.1 2002-09-16 14:27:02 rudi Exp $ |
// |
// $Date: 2002-09-16 14:27:02 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
|
`include "timescale.v" |
|
module usb_tx_phy( |
clk, rst, fs_ce, phy_mode, |
|
// Transciever Interface |
txdp, txdn, txoe, |
|
// UTMI Interface |
DataOut_i, TxValid_i, TxReady_o |
); |
|
input clk; |
input rst; |
input fs_ce; |
input phy_mode; |
output txdp, txdn, txoe; |
input [7:0] DataOut_i; |
input TxValid_i; |
output TxReady_o; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Local Wires and Registers |
// |
|
parameter IDLE = 3'd0, |
SOP = 3'h1, |
DATA = 3'h2, |
EOP1 = 3'h3, |
EOP2 = 3'h4, |
WAIT = 3'h5; |
|
reg TxReady_o; |
reg [2:0] state, next_state; |
reg tx_ready; |
reg tx_ready_d; |
reg ld_sop_d; |
reg ld_data_d; |
reg ld_eop_d; |
reg tx_ip; |
reg tx_ip_sync; |
reg [2:0] bit_cnt; |
reg [7:0] hold_reg; |
reg sd_raw_o; |
wire hold; |
reg data_done; |
reg sft_done; |
reg sft_done_r; |
wire sft_done_e; |
reg ld_data; |
wire eop_done; |
reg [2:0] one_cnt; |
wire stuff; |
reg sd_bs_o; |
reg sd_nrzi_o; |
reg append_eop; |
reg append_eop_sync1; |
reg append_eop_sync2; |
reg append_eop_sync3; |
reg txdp, txdn; |
reg txoe_r1, txoe_r2; |
reg txoe; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
always @(posedge clk) |
tx_ready <= #1 tx_ready_d; |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) TxReady_o <= #1 1'b0; |
else TxReady_o <= #1 tx_ready_d & TxValid_i; |
|
always @(posedge clk) |
ld_data <= #1 ld_data_d; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Transmit in progress indicator |
// |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) tx_ip <= #1 1'b0; |
else |
if(ld_sop_d) tx_ip <= #1 1'b1; |
else |
if(eop_done) tx_ip <= #1 1'b0; |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) tx_ip_sync <= #1 1'b0; |
else |
if(fs_ce) tx_ip_sync <= #1 tx_ip; |
|
// data_done helps us to catch cases where TxValid drops due to |
// packet end and then gets re-asserted as a new packet starts. |
// We might not see this because we are still transmitting. |
// data_done should solve those cases ... |
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) data_done <= #1 1'b0; |
else |
if(TxValid_i & ! tx_ip) data_done <= #1 1'b1; |
else |
if(!TxValid_i) data_done <= #1 1'b0; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Shift Register |
// |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) bit_cnt <= #1 3'h0; |
else |
if(!tx_ip_sync) bit_cnt <= #1 3'h0; |
else |
if(fs_ce & !hold) bit_cnt <= #1 bit_cnt + 3'h1; |
|
assign hold = stuff; |
|
always @(posedge clk) |
if(!tx_ip_sync) sd_raw_o <= #1 1'b0; |
else |
case(bit_cnt) // synopsys full_case parallel_case |
3'h0: sd_raw_o <= #1 hold_reg[0]; |
3'h1: sd_raw_o <= #1 hold_reg[1]; |
3'h2: sd_raw_o <= #1 hold_reg[2]; |
3'h3: sd_raw_o <= #1 hold_reg[3]; |
3'h4: sd_raw_o <= #1 hold_reg[4]; |
3'h5: sd_raw_o <= #1 hold_reg[5]; |
3'h6: sd_raw_o <= #1 hold_reg[6]; |
3'h7: sd_raw_o <= #1 hold_reg[7]; |
endcase |
|
always @(posedge clk) |
sft_done <= #1 !hold & (bit_cnt == 3'h7); |
|
always @(posedge clk) |
sft_done_r <= #1 sft_done; |
|
assign sft_done_e = sft_done & !sft_done_r; |
|
// Out Data Hold Register |
always @(posedge clk) |
if(ld_sop_d) hold_reg <= #1 8'h80; |
else |
if(ld_data) hold_reg <= #1 DataOut_i; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Bit Stuffer |
// |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) one_cnt <= #1 3'h0; |
else |
if(!tx_ip_sync) one_cnt <= #1 3'h0; |
else |
if(fs_ce) |
begin |
if(!sd_raw_o | stuff) one_cnt <= #1 3'h0; |
else one_cnt <= #1 one_cnt + 3'h1; |
end |
|
assign stuff = (one_cnt==3'h6); |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) sd_bs_o <= #1 1'h0; |
else |
if(fs_ce) sd_bs_o <= #1 !tx_ip_sync ? 1'b0 : |
(stuff ? 1'b0 : sd_raw_o); |
|
/////////////////////////////////////////////////////////////////// |
// |
// NRZI Encoder |
// |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) sd_nrzi_o <= #1 1'b1; |
else |
if(!tx_ip_sync | !txoe_r1) sd_nrzi_o <= #1 1'b1; |
else |
if(fs_ce) sd_nrzi_o <= #1 sd_bs_o ? sd_nrzi_o : ~sd_nrzi_o; |
|
/////////////////////////////////////////////////////////////////// |
// |
// EOP append logic |
// |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) append_eop <= #1 1'b0; |
else |
if(ld_eop_d) append_eop <= #1 1'b1; |
else |
if(append_eop_sync2) append_eop <= #1 1'b0; |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) append_eop_sync1 <= #1 1'b0; |
else |
if(fs_ce) append_eop_sync1 <= #1 append_eop; |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) append_eop_sync2 <= #1 1'b0; |
else |
if(fs_ce) append_eop_sync2 <= #1 append_eop_sync1; |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) append_eop_sync3 <= #1 1'b0; |
else |
if(fs_ce) append_eop_sync3 <= #1 append_eop_sync2; |
|
assign eop_done = append_eop_sync3; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Output Enable Logic |
// |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) txoe_r1 <= #1 1'b0; |
else |
if(fs_ce) txoe_r1 <= #1 tx_ip_sync; |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) txoe_r2 <= #1 1'b0; |
else |
if(fs_ce) txoe_r2 <= #1 txoe_r1; |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) txoe <= #1 1'b1; |
else |
if(fs_ce) txoe <= #1 !(txoe_r1 | txoe_r2); |
|
/////////////////////////////////////////////////////////////////// |
// |
// Output Registers |
// |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) txdp <= #1 1'b1; |
else |
if(fs_ce) txdp <= #1 phy_mode ? |
(!append_eop_sync3 & sd_nrzi_o) : |
sd_nrzi_o; |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) txdn <= #1 1'b0; |
else |
if(fs_ce) txdn <= #1 phy_mode ? |
(!append_eop_sync3 & ~sd_nrzi_o) : |
append_eop_sync3; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Tx Statemashine |
// |
|
`ifdef USB_ASYNC_REST |
always @(posedge clk or negedge rst) |
`else |
always @(posedge clk) |
`endif |
if(!rst) state <= #1 IDLE; |
else state <= #1 next_state; |
|
always @(state or TxValid_i or data_done or sft_done_e or eop_done or fs_ce) |
begin |
next_state = state; |
tx_ready_d = 1'b0; |
|
ld_sop_d = 1'b0; |
ld_data_d = 1'b0; |
ld_eop_d = 1'b0; |
|
case(state) // synopsys full_case parallel_case |
IDLE: |
begin |
if(TxValid_i) |
begin |
ld_sop_d = 1'b1; |
next_state = SOP; |
end |
end |
SOP: |
begin |
if(sft_done_e) |
begin |
tx_ready_d = 1'b1; |
ld_data_d = 1'b1; |
next_state = DATA; |
end |
end |
DATA: |
begin |
if(!data_done & sft_done_e) |
begin |
ld_eop_d = 1'b1; |
next_state = EOP1; |
end |
|
if(data_done & sft_done_e) |
begin |
tx_ready_d = 1'b1; |
ld_data_d = 1'b1; |
end |
end |
EOP1: |
begin |
if(eop_done) next_state = EOP2; |
end |
EOP2: |
begin |
if(!eop_done & fs_ce) next_state = WAIT; |
end |
WAIT: |
begin |
if(fs_ce) next_state = IDLE; |
end |
endcase |
|
end |
|
endmodule |
|
/verilog/timescale.v
0,0 → 1,451
`timescale 1ns / 10ps |
/verilog/usb_phy.v
0,0 → 1,165
///////////////////////////////////////////////////////////////////// |
//// //// |
//// USB 1.1 PHY //// |
//// //// |
//// //// |
//// Author: Rudolf Usselmann //// |
//// rudi@asics.ws //// |
//// //// |
//// //// |
//// Downloaded from: http://www.opencores.org/cores/usb_phy/ //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// 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: usb_phy.v,v 1.1.1.1 2002-09-16 14:26:59 rudi Exp $ |
// |
// $Date: 2002-09-16 14:26:59 $ |
// $Revision: 1.1.1.1 $ |
// $Author: rudi $ |
// $Locker: $ |
// $State: Exp $ |
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// |
// |
// |
// |
// |
// |
// |
|
`include "timescale.v" |
|
module usbf_phy(clk, rst, phy_tx_mode, usb_rst, |
|
// Transciever Interface |
txdp, txdn, txoe, |
rxd, rxdp, rxdn, |
|
// UTMI Interface |
DataOut_i, TxValid_i, TxReady_o, RxValid_o, |
RxActive_o, RxError_o, DataIn_o, LineState_o |
); |
|
input clk; |
input rst; |
input phy_tx_mode; |
output usb_rst; |
output txdp, txdn, txoe; |
input rxd, rxdp, rxdn; |
input [7:0] DataOut_i; |
input TxValid_i; |
output TxReady_o; |
output [7:0] DataIn_o; |
output RxValid_o; |
output RxActive_o; |
output RxError_o; |
output [1:0] LineState_o; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Local Wires and Registers |
// |
|
reg [5:0] rst_cnt; |
reg usb_rst; |
wire reset; |
|
/////////////////////////////////////////////////////////////////// |
// |
// Misc Logic |
// |
|
assign reset = rst & ~usb_rst; |
|
/////////////////////////////////////////////////////////////////// |
// |
// TX Phy |
// |
|
usb_tx_phy i_tx_phy( |
.clk( clk ), |
.rst( reset ), |
.fs_ce( fs_ce ), |
.phy_mode( phy_tx_mode ), |
|
// Transciever Interface |
.txdp( txdp ), |
.txdn( txdn ), |
.txoe( txoe ), |
|
// UTMI Interface |
.DataOut_i( DataOut_i ), |
.TxValid_i( TxValid_i ), |
.TxReady_o( TxReady_o ) |
); |
|
/////////////////////////////////////////////////////////////////// |
// |
// RX Phy and DPLL |
// |
|
usb_rx_phy i_rx_phy( |
.clk( clk ), |
.rst( reset ), |
.fs_ce( fs_ce ), |
|
// Transciever Interface |
.rxd( rxd ), |
.rxdp( rxdp ), |
.rxdn( rxdn ), |
|
// UTMI Interface |
.DataIn_o( DataIn_o ), |
.RxValid_o( RxValid_o ), |
.RxActive_o( RxActive_o ), |
.RxError_o( RxError_o ), |
.RxEn_i( txoe ), |
.LineState( LineState_o ) |
); |
|
/////////////////////////////////////////////////////////////////// |
// |
// Generate an USB Reset is we see SE0 for at least 2.5uS |
// |
|
always @(posedge clk) |
if(!rst) rst_cnt <= #1 5'h0; |
else |
if(LineState_o != 2'h0) rst_cnt <= #1 5'h0; |
else |
if(!usb_rst & fs_ce) rst_cnt <= #1 rst_cnt + 5'h1; |
|
always @(posedge clk) |
usb_rst <= #1 (rst_cnt == 5'd31); |
|
endmodule |
|