📄 usbf_utmi_ls.v
字号:
/////////////////////////////////////////////////////////////////////
//// ////
//// UTMI Line Status & Speed Negotiation block ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/usb/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000-2003 Rudolf Usselmann ////
//// www.asics.ws ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
// CVS Log
//
// $Id: usbf_utmi_ls.v,v 1.6 2003/11/11 07:15:16 rudi Exp $
//
// $Date: 2003/11/11 07:15:16 $
// $Revision: 1.6 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: usbf_utmi_ls.v,v $
// Revision 1.6 2003/11/11 07:15:16 rudi
// Fixed Resume signaling and initial attachment
//
// Revision 1.5 2003/10/17 02:36:57 rudi
// - Disabling bit stuffing and NRZI encoding during speed negotiation
// - Now the core can send zero size packets
// - Fixed register addresses for some of the higher endpoints
// (conversion between decimal/hex was wrong)
// - The core now does properly evaluate the function address to
// determine if the packet was intended for it.
// - Various other minor bugs and typos
//
// Revision 1.4 2001/11/04 12:22:45 rudi
//
// - Fixed previous fix (brocke something else ...)
// - Majore Synthesis cleanup
//
// Revision 1.3 2001/09/24 01:15:28 rudi
//
// Changed reset to be active high async.
//
// Revision 1.2 2001/08/10 08:48:33 rudi
//
// - Changed IO names to be more clear.
// - Uniquifyed define names to be core specific.
//
// Revision 1.1 2001/08/03 05:30:09 rudi
//
//
// 1) Reorganized directory structure
//
// Revision 1.2 2001/03/31 13:00:52 rudi
//
// - Added Core configuration
// - Added handling of OUT packets less than MAX_PL_SZ in DMA mode
// - Modified WISHBONE interface and sync logic
// - Moved SSRAM outside the core (added interface)
// - Many small bug fixes ...
//
// Revision 1.1 2001/03/07 09:08:13 rudi
//
// Added USB control signaling (Line Status) block. Fixed some minor
// typos, added resume bit and signal.
//
//
//
`include "usbf_defines.v"
module usbf_utmi_ls( clk, rst,
resume_req,
// UTMI Interface
rx_active, tx_ready, drive_k,
XcvSelect, TermSel, SuspendM, LineState, OpMode,
usb_vbus,
// Misc Interfaces
mode_hs, usb_reset, usb_suspend, usb_attached,
suspend_clr
);
input clk;
//input wclk;
input rst;
input resume_req;
input rx_active, tx_ready;
output drive_k;
output XcvSelect;
output TermSel;
output SuspendM;
input [1:0] LineState;
output [1:0] OpMode;
input usb_vbus;
output mode_hs; // High Speed Mode
output usb_reset; // USB Reset
output usb_suspend; // USB Suspend
output usb_attached; // Attached to USB
output suspend_clr;
///////////////////////////////////////////////////////////////////
//
// Parameters
//
parameter [14:0] // synopsys enum state
POR = 15'b000_0000_0000_0001,
NORMAL = 15'b000_0000_0000_0010,
RES_SUSP = 15'b000_0000_0000_0100,
SUSPEND = 15'b000_0000_0000_1000,
RESUME = 15'b000_0000_0001_0000,
RESUME_REQUEST = 15'b000_0000_0010_0000,
RESUME_WAIT = 15'b000_0000_0100_0000,
RESUME_SIG = 15'b000_0000_1000_0000,
ATTACH = 15'b000_0001_0000_0000,
RESET = 15'b000_0010_0000_0000,
SPEED_NEG = 15'b000_0100_0000_0000,
SPEED_NEG_K = 15'b000_1000_0000_0000,
SPEED_NEG_J = 15'b001_0000_0000_0000,
SPEED_NEG_HS = 15'b010_0000_0000_0000,
SPEED_NEG_FS = 15'b100_0000_0000_0000;
///////////////////////////////////////////////////////////////////
//
// Local Wires and Registers
//
reg [14:0] /* synopsys enum state */ state, next_state;
// synopsys state_vector state
reg [1:0] line_state_r;
reg mode_hs, mode_set_hs, mode_set_fs;
reg usb_suspend, suspend_set, suspend_clr;
reg usb_attached, attached_set, attached_clr;
reg TermSel, fs_term_on, fs_term_off;
reg XcvSelect, xcv_set_hs, xcv_set_fs;
reg [1:0] OpMode;
reg bit_stuff_on, bit_stuff_off;
reg usb_reset, usb_reset_d;
wire ls_se0, ls_j, ls_k, ls_se1;
reg ls_k_r, ls_j_r, ls_se0_r;
reg ls_idle_r;
wire ls_idle;
reg idle_long;
wire idle_long_set, idle_long_clr;
wire k_long, j_long, se0_long;
reg drive_k, drive_k_d;
reg [3:0] ps_cnt;
reg ps_cnt_clr;
reg idle_cnt_clr;
reg idle_cnt1_clr;
reg [7:0] idle_cnt1, idle_cnt1_next;
reg T1_gt_2_5_uS, T1_st_3_0_mS, T1_gt_3_0_mS;
reg T1_gt_3_125_mS, T1_gt_5_0_mS;
reg [7:0] me_ps;
reg me_cnt_clr;
reg me_ps_2_5_us;
reg [7:0] me_ps2;
reg me_ps2_0_5_ms;
reg [7:0] me_cnt;
reg me_cnt_100_ms;
reg T2_gt_100_uS, T2_wakeup, T2_gt_1_0_mS, T2_gt_1_2_mS;
reg [2:0] chirp_cnt;
reg chirp_cnt_clr, chirp_cnt_inc;
reg chirp_cnt_is_6;
reg resume_req_s1;
reg resume_req_s;
///////////////////////////////////////////////////////////////////
//
// Misc Logic
//
always @(posedge clk)
drive_k <= drive_k_d;
assign SuspendM = (usb_suspend & !resume_req_s) | (LineState == 2'b10);
always @(posedge clk)
resume_req_s1 <= resume_req;
always @(posedge clk)
resume_req_s <= resume_req_s1;
// ---------------------------------------------------------
// USB State/Operation Mode JK Flops
always @(posedge clk)
if(mode_set_fs) mode_hs <= 1'b0;
else
if(mode_set_hs) mode_hs <= 1'b1;
always @(posedge clk)
if(suspend_clr) usb_suspend <= 1'b0;
else
if(suspend_set) usb_suspend <= 1'b1;
always @(posedge clk)
if(attached_clr) usb_attached <= 1'b0;
else
if(attached_set) usb_attached <= 1'b1;
always @(posedge clk)
if(fs_term_off) TermSel <= 1'b0;
else
if(fs_term_on) TermSel <= 1'b1;
always @(posedge clk)
if(xcv_set_fs) XcvSelect <= 1'b1;
else
if(xcv_set_hs) XcvSelect <= 1'b0;
always @(posedge clk)
if(bit_stuff_off) OpMode <= 2'b10;
else
if(bit_stuff_on) OpMode <= 2'b00;
always @(posedge clk)
usb_reset <= usb_reset_d;
// ---------------------------------------------------------
// Line State Detector
always @(posedge clk)
line_state_r <= LineState;
assign ls_se0 = (line_state_r == 2'b00);
assign ls_j = (line_state_r == 2'b01);
assign ls_k = (line_state_r == 2'b10);
assign ls_se1 = (line_state_r == 2'b11);
assign ls_idle = mode_hs ? ls_se0 : ls_j;
// Idle Detection
// Idle Has to persist for at least two cycles in a roe in the
// same state to recognized
always @(posedge clk)
ls_idle_r <= ls_idle;
assign idle_long_set = ls_idle & ls_idle_r;
assign idle_long_clr = !ls_idle & !ls_idle_r;
`ifdef USBF_ASYNC_RESET
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) idle_long <= 1'b0;
else
if(idle_long_clr) idle_long <= 1'b0;
else
if(idle_long_set) idle_long <= 1'b1;
// Detect Signals for two cycles ina row before making a transaction ...
always @(posedge clk)
ls_k_r <= ls_k;
always @(posedge clk)
ls_j_r <= ls_j;
always @(posedge clk)
ls_se0_r <= ls_se0;
assign k_long = ls_k & ls_k_r;
assign j_long = ls_j & ls_j_r;
assign se0_long = ls_se0 & ls_se0_r;
///////////////////////////////////////////////////////////////////
//
// Counters
//
// ---------------------------------------------------------
// idle Counter
// Pre-Scaler
// Generates a 0.25 uS Count Enable (ps_cnt_clr)
always @(posedge clk)
if(!idle_long || idle_cnt_clr || ps_cnt_clr) ps_cnt <= 4'd0;
else ps_cnt <= ps_cnt + 4'd1;
always @(posedge clk) // Clear the pre-scaler in 250 nS intervals
ps_cnt_clr <= (ps_cnt == `USBF_T1_PS_250_NS);
// Count uS
always @(posedge clk)
if(!idle_long || idle_cnt1_clr || idle_cnt_clr) idle_cnt1 <= 8'h0;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -