|
|
`timescale 1 ns/ 1 ns
|
`timescale 1 ns/ 1 ns
|
module usb_agent (
|
module usb_agent (
|
dpls,
|
dpls,
|
dmns
|
dmns
|
);
|
);
|
|
|
inout dpls, dmns;
|
inout dpls, dmns;
|
wire [24:0] ControlPkt;
|
wire [24:0] ControlPkt;
|
|
|
|
|
|
|
assign dpls = 1'bz;
|
assign dpls = 1'bz;
|
assign dmns = 1'bz;
|
assign dmns = 1'bz;
|
|
|
pullup(dpls);
|
pullup(dpls);
|
pulldown(dmns);
|
pulldown(dmns);
|
|
|
|
|
// ------------------------------
|
// ------------------------------
|
// Module Instantiations.---------------
|
// Module Instantiations.---------------
|
// ------------------------------
|
// ------------------------------
|
|
|
|
|
// a. Host Bus Model Instantiation.
|
// a. Host Bus Model Instantiation.
|
|
|
host_usb_bfm bfm_inst( .DPLS( dpls ),
|
host_usb_bfm bfm_inst( .DPLS( dpls ),
|
.DMNS( dmns ),
|
.DMNS( dmns ),
|
.ControlPkt( ControlPkt)
|
.ControlPkt( ControlPkt)
|
);
|
);
|
|
|
|
|
|
|
|
|
|
|
endmodule
|
endmodule
|
|
|
module host_usb_bfm(
|
module host_usb_bfm(
|
DPLS,
|
DPLS,
|
DMNS,
|
DMNS,
|
ControlPkt
|
ControlPkt
|
);
|
);
|
|
|
inout DPLS;
|
inout DPLS;
|
inout DMNS;
|
inout DMNS;
|
output [24:0] ControlPkt;
|
output [24:0] ControlPkt;
|
|
|
wire DPLS;
|
wire DPLS;
|
wire DMNS;
|
wire DMNS;
|
|
|
reg zDPLS; // this register is driven in host_usb_drvr.v
|
reg zDPLS; // this register is driven in host_usb_drvr.v
|
reg zDMNS; // this register is driven in host_usb_drvr.v
|
reg zDMNS; // this register is driven in host_usb_drvr.v
|
|
|
wire clk; // clock
|
wire clk; // clock
|
|
|
// encoder signals
|
// encoder signals
|
reg enc_enbl; // signal to enable encoder block
|
reg enc_enbl; // signal to enable encoder block
|
reg enc_reset_n; // signal to reset encoder block
|
reg enc_reset_n; // signal to reset encoder block
|
reg [7:0] enc_data_in; // byte wide data being pumped into the encoder
|
reg [7:0] enc_data_in; // byte wide data being pumped into the encoder
|
wire enc_count_out; // wire for encoder count_out signal
|
wire enc_count_out; // wire for encoder count_out signal
|
wire enc_data_out_valid; // wire for encoder data_out_valid signal
|
wire enc_data_out_valid; // wire for encoder data_out_valid signal
|
reg enc_last_byte;
|
reg enc_last_byte;
|
wire [3:0] enc_bit_count_out;
|
wire [3:0] enc_bit_count_out;
|
|
|
// decoder signals
|
// decoder signals
|
reg dec_enbl; // signal to enable decoder block
|
reg dec_enbl; // signal to enable decoder block
|
reg dec_reset_n; // signal to reset decoder block
|
reg dec_reset_n; // signal to reset decoder block
|
wire dec_ser_data_rdy; // signal to indicate serial data is ready
|
wire dec_ser_data_rdy; // signal to indicate serial data is ready
|
wire dec_par_data_rdy; // signal to indicate parallel data is ready
|
wire dec_par_data_rdy; // signal to indicate parallel data is ready
|
wire [7:0] dec_par_data_out; // parallel data out from decoder
|
wire [7:0] dec_par_data_out; // parallel data out from decoder
|
wire [31:0] dec_recv_bit_count; // gives the number of bits received so far
|
wire [31:0] dec_recv_bit_count; // gives the number of bits received so far
|
wire dec_bit_stuff_err; // goes high if there is a bit stuff error in
|
wire dec_bit_stuff_err; // goes high if there is a bit stuff error in
|
// the present data stream
|
// the present data stream
|
// dpll signals
|
// dpll signals
|
reg clk48;
|
reg clk48;
|
reg clk6;
|
reg clk6;
|
reg dpll_reset_n;
|
reg dpll_reset_n;
|
wire dpll_clk;
|
wire dpll_clk;
|
reg rec_clk;
|
reg rec_clk;
|
wire clk4x;
|
wire clk4x;
|
|
|
// Jitter control registers
|
// Jitter control registers
|
|
|
integer tmpJitterPeriod;
|
integer tmpJitterPeriod;
|
integer tmpJitterCount;
|
integer tmpJitterCount;
|
|
|
// clock related registers
|
// clock related registers
|
reg HSClkComp; // compensation when generating the 4x clock
|
reg HSClkComp; // compensation when generating the 4x clock
|
reg HSClkCompToggle;
|
reg HSClkCompToggle;
|
|
|
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
// //
|
// //
|
// Added to accomodate 1 ms slots and files //
|
// Added to accomodate 1 ms slots and files //
|
// //
|
// //
|
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
|
|
// reg [24:0] ControlPkt;
|
// reg [24:0] ControlPkt;
|
|
|
// Control Packet format;
|
// Control Packet format;
|
|
|
// [0] : 1 - Assert BufOk/0 - Donot assert BufOk.
|
// [0] : 1 - Assert BufOk/0 - Donot assert BufOk.
|
// [1] : 1 - Create BufOk Error/0 - Donot Create BufOk Error.
|
// [1] : 1 - Create BufOk Error/0 - Donot Create BufOk Error.
|
// [9:2] : Start Byte for In Transfers.
|
// [9:2] : Start Byte for In Transfers.
|
// [10] : 1 - Create a 4 Clock Protocol violation/0 - donot create vio.
|
// [10] : 1 - Create a 4 Clock Protocol violation/0 - donot create vio.
|
// [20:11]: Errors after num transfers.
|
// [20:11]: Errors after num transfers.
|
// [21] : Stalled or Not.
|
// [21] : Stalled or Not.
|
// [22] : Check for data on Application Bus during Writes.
|
// [22] : Check for data on Application Bus during Writes.
|
// [23] : Check for the Hshk on the Application Bus.
|
// [23] : Check for the Hshk on the Application Bus.
|
// [24] : If check for hshkis true, 1'b1 = XfrAck, 1'b0 = XfrNack.
|
// [24] : If check for hshkis true, 1'b1 = XfrAck, 1'b0 = XfrNack.
|
|
|
// integer ByteCount;
|
// integer ByteCount;
|
// integer Status ;
|
// integer Status ;
|
|
|
reg [6:0] dutAddr;
|
reg [6:0] dutAddr;
|
reg sofOnFlag ;
|
reg sofOnFlag ;
|
integer sofPeriod ;
|
integer sofPeriod ;
|
reg interruptOnFlag ;
|
reg interruptOnFlag ;
|
reg interruptRequest ;
|
reg interruptRequest ;
|
integer interruptTimer ;
|
integer interruptTimer ;
|
integer interruptPeriod ;
|
integer interruptPeriod ;
|
reg controlRequest ;
|
reg controlRequest ;
|
reg controlGrant ;
|
reg controlGrant ;
|
reg bulkInOnFlag ;
|
reg bulkInOnFlag ;
|
reg bulkOutOnFlag ;
|
reg bulkOutOnFlag ;
|
|
|
parameter DumpToFile = 1;
|
parameter DumpToFile = 1;
|
|
|
parameter IN_OUT_BUF_SIZE = 2048, // outgoing buffer data size
|
parameter IN_OUT_BUF_SIZE = 2048, // outgoing buffer data size
|
IN_OUT_BUF_PTR_SIZE = 12, // number of bits in out buff pointer
|
IN_OUT_BUF_PTR_SIZE = 12, // number of bits in out buff pointer
|
|
|
XMIT_BUF_SIZE = 1028, // Xmitbuffer size
|
XMIT_BUF_SIZE = 1028, // Xmitbuffer size
|
RECV_BUF_SIZE = 1028; // Recvbuffer size
|
RECV_BUF_SIZE = 1028; // Recvbuffer size
|
|
|
parameter OUT_TOKEN = 4'b0001,
|
parameter OUT_TOKEN = 4'b0001,
|
IN_TOKEN = 4'b1001,
|
IN_TOKEN = 4'b1001,
|
SOF_TOKEN = 4'b0101,
|
SOF_TOKEN = 4'b0101,
|
SETUP_TOKEN = 4'b1101,
|
SETUP_TOKEN = 4'b1101,
|
DATA0 = 4'b0011,
|
DATA0 = 4'b0011,
|
DATA1 = 4'b1011,
|
DATA1 = 4'b1011,
|
ACK = 4'b0010,
|
ACK = 4'b0010,
|
NAK = 4'b1010,
|
NAK = 4'b1010,
|
STALL = 4'b1110,
|
STALL = 4'b1110,
|
PREAMBLE = 4'b1100;
|
PREAMBLE = 4'b1100;
|
|
|
parameter GET_CONFIGURATION = 01, // Standard Request Codes for end points
|
parameter GET_CONFIGURATION = 01, // Standard Request Codes for end points
|
GET_DESCRIPTOR = 02,
|
GET_DESCRIPTOR = 02,
|
GET_INTERFACE = 03,
|
GET_INTERFACE = 03,
|
GET_MAX_PACKET = 04,
|
GET_MAX_PACKET = 04,
|
GET_STATUS = 05,
|
GET_STATUS = 05,
|
SET_ADDRESS = 06,
|
SET_ADDRESS = 06,
|
SET_CONFIGURATION = 07,
|
SET_CONFIGURATION = 07,
|
SET_DESCRIPTOR = 08,
|
SET_DESCRIPTOR = 08,
|
SET_IDLE = 09,
|
SET_IDLE = 09,
|
SET_INTERFACE = 10,
|
SET_INTERFACE = 10,
|
SET_MAX_PACKET = 11,
|
SET_MAX_PACKET = 11,
|
SET_REMOTE_WAKEUP = 12,
|
SET_REMOTE_WAKEUP = 12,
|
SET_STATUS = 13;
|
SET_STATUS = 13;
|
|
|
parameter DEVICE = 1, // Descriptor Types
|
parameter DEVICE = 1, // Descriptor Types
|
CONFIGURATION = 2,
|
CONFIGURATION = 2,
|
STRING = 3,
|
STRING = 3,
|
INTERFACE = 4,
|
INTERFACE = 4,
|
ENDPOINT = 5;
|
ENDPOINT = 5;
|
|
|
parameter GET_HUB_STATUS = 0, // Hub class request codes
|
parameter GET_HUB_STATUS = 0, // Hub class request codes
|
GET_PORT_STATUS = 0,
|
GET_PORT_STATUS = 0,
|
CLEAR_FEATURE = 1,
|
CLEAR_FEATURE = 1,
|
GET_STATE = 2,
|
GET_STATE = 2,
|
SET_FEATURE = 3,
|
SET_FEATURE = 3,
|
// reserved for future use 4-5
|
// reserved for future use 4-5
|
GET_HUB_DESCRIPTOR = 6,
|
GET_HUB_DESCRIPTOR = 6,
|
SET_HUB_DESCRIPTOR = 7;
|
SET_HUB_DESCRIPTOR = 7;
|
|
|
parameter C_HUB_LOCAL_POWER = 00, // Hub class feature selectors
|
parameter C_HUB_LOCAL_POWER = 00, // Hub class feature selectors
|
C_HUB_OVER_CURRENT = 01,
|
C_HUB_OVER_CURRENT = 01,
|
PORT_CONNECTION = 00,
|
PORT_CONNECTION = 00,
|
PORT_ENABLE = 01,
|
PORT_ENABLE = 01,
|
PORT_SUSPEND = 02,
|
PORT_SUSPEND = 02,
|
PORT_OVER_CURRENT = 03,
|
PORT_OVER_CURRENT = 03,
|
PORT_RESET = 04,
|
PORT_RESET = 04,
|
PORT_POWER = 08,
|
PORT_POWER = 08,
|
PORT_LOW_SPEED = 09,
|
PORT_LOW_SPEED = 09,
|
C_PORT_CONNECTION = 16,
|
C_PORT_CONNECTION = 16,
|
C_PORT_ENABLE = 17,
|
C_PORT_ENABLE = 17,
|
C_PORT_SUSPEND = 18,
|
C_PORT_SUSPEND = 18,
|
C_PORT_OVER_CURRENT = 19,
|
C_PORT_OVER_CURRENT = 19,
|
C_PORT_RESET = 20;
|
C_PORT_RESET = 20;
|
|
|
parameter true = 1'b1,
|
parameter true = 1'b1,
|
True = 1'b1,
|
True = 1'b1,
|
TRUE = 1'b1,
|
TRUE = 1'b1,
|
false = 1'b0,
|
false = 1'b0,
|
False = 1'b0,
|
False = 1'b0,
|
FALSE = 1'b0;
|
FALSE = 1'b0;
|
|
|
parameter HIGH_SPEED = 1'b1,
|
parameter HIGH_SPEED = 1'b1,
|
LOW_SPEED = 1'b0;
|
LOW_SPEED = 1'b0;
|
|
|
parameter J = 2'b10, // high speed idle state {DPLS, DMNS}
|
parameter J = 2'b10, // high speed idle state {DPLS, DMNS}
|
K = 2'b01, // low speed idle state {DPLS, DMNS}
|
K = 2'b01, // low speed idle state {DPLS, DMNS}
|
SE0 = 2'b00, // single ended zero {DPLS, DMNS}
|
SE0 = 2'b00, // single ended zero {DPLS, DMNS}
|
SE1 = 2'b11; // single ended 1 {DPLS, DMNS}
|
SE1 = 2'b11; // single ended 1 {DPLS, DMNS}
|
|
|
parameter MAX_CNTRL_INTERLEAVE= 6; // number of control transactions that can
|
parameter MAX_CNTRL_INTERLEAVE= 6; // number of control transactions that can
|
// interleaved
|
// interleaved
|
|
|
parameter NUM_ENDPT_FILES = 12; // number of transmit files associtated
|
parameter NUM_ENDPT_FILES = 12; // number of transmit files associtated
|
// with endpoints
|
// with endpoints
|
|
|
parameter READ = 2'b10;
|
parameter READ = 2'b10;
|
parameter WRITE = 2'b11;
|
parameter WRITE = 2'b11;
|
|
|
parameter BINARY = 1'b0;
|
parameter BINARY = 1'b0;
|
parameter HEX = 1'b1;
|
parameter HEX = 1'b1;
|
|
|
parameter XMIT_BUF = 4'b0000;
|
parameter XMIT_BUF = 4'b0000;
|
parameter OUT_BUFF = 4'b0001;
|
parameter OUT_BUFF = 4'b0001;
|
|
|
parameter NumCharsInFileName = 20; // number of characters in a file name
|
parameter NumCharsInFileName = 20; // number of characters in a file name
|
parameter CharByte = 8; // number of bits for a character
|
parameter CharByte = 8; // number of bits for a character
|
parameter MaxFileSize = 9 * 1024; // 9k file size
|
parameter MaxFileSize = 9 * 1024; // 9k file size
|
|
|
reg [7:0] in_out_buf [0 : IN_OUT_BUF_SIZE - 1];
|
reg [7:0] in_out_buf [0 : IN_OUT_BUF_SIZE - 1];
|
reg [11:0] in_out_buf_ptr;
|
reg [11:0] in_out_buf_ptr;
|
|
|
reg [7:0] XmitBuffer [0 : XMIT_BUF_SIZE]; // Xmit buffer
|
reg [7:0] XmitBuffer [0 : XMIT_BUF_SIZE]; // Xmit buffer
|
reg [7:0] RecvBuffer [0 : RECV_BUF_SIZE]; // Recv buffer
|
reg [7:0] RecvBuffer [0 : RECV_BUF_SIZE]; // Recv buffer
|
|
|
reg [10:0] FrameNumber; // frame number
|
reg [10:0] FrameNumber; // frame number
|
|
|
reg [15:0] InDataToggle [127:0]; // set\unset Data0/Data1 for data Xfers
|
reg [15:0] InDataToggle [127:0]; // set\unset Data0/Data1 for data Xfers
|
reg [15:0] OutDataToggle [127:0]; // set\unset Data0/Data1 for data Xfers
|
reg [15:0] OutDataToggle [127:0]; // set\unset Data0/Data1 for data Xfers
|
|
|
reg TimeOut; // register to specify timeout
|
reg TimeOut; // register to specify timeout
|
integer TimeOutVal; // value to specify for how many bit times
|
integer TimeOutVal; // value to specify for how many bit times
|
// to wait for before time out
|
// to wait for before time out
|
|
|
reg [31:0] ResponseLatency; // turnaround time for the host before
|
reg [31:0] ResponseLatency; // turnaround time for the host before
|
// responding
|
// responding
|
reg IsoHeadGen; // specifies if a header is generated for an
|
reg IsoHeadGen; // specifies if a header is generated for an
|
// isochronous transfer or not
|
// isochronous transfer or not
|
|
|
reg GenCrc16Err; // specifies if a crc error is to be generated or not
|
reg GenCrc16Err; // specifies if a crc error is to be generated or not
|
reg [15:0] Crc16ErrMask; // a particular crc bit is inverted according to the
|
reg [15:0] Crc16ErrMask; // a particular crc bit is inverted according to the
|
// bit in the Mask is high
|
// bit in the Mask is high
|
|
|
reg GenCrc5Err; // specifies if a crc error is to be generated or not
|
reg GenCrc5Err; // specifies if a crc error is to be generated or not
|
reg [4:0] Crc5ErrMask; // a particular crc bit is inverted according to the
|
reg [4:0] Crc5ErrMask; // a particular crc bit is inverted according to the
|
// bit in the Mask is high
|
// bit in the Mask is high
|
|
|
reg ReportResults; // reports results to a file
|
reg ReportResults; // reports results to a file
|
reg [NumCharsInFileName * CharByte : 1] ResultsFile; // reports file name
|
reg [NumCharsInFileName * CharByte : 1] ResultsFile; // reports file name
|
integer ResultsFp; // filepointer for reults file
|
integer ResultsFp; // filepointer for reults file
|
|
|
reg ReportErrors;
|
reg ReportErrors;
|
|
|
integer PulseWidth; // PulseWidth of USB clock
|
integer PulseWidth; // PulseWidth of USB clock
|
|
|
reg SyncField; // specifies if a correct/incorrect sync field is to
|
reg SyncField; // specifies if a correct/incorrect sync field is to
|
// be sent
|
// be sent
|
reg [31:0] SyncLevel; // at which point in a task to corrupt the SyncField
|
reg [31:0] SyncLevel; // at which point in a task to corrupt the SyncField
|
reg [31:0] SetSyncLevel; // set this value before calling SendData
|
reg [31:0] SetSyncLevel; // set this value before calling SendData
|
reg [7:0] SyncFieldMask; // specifies how the sync field is to be corrupted
|
reg [7:0] SyncFieldMask; // specifies how the sync field is to be corrupted
|
|
|
reg GenSE0Error; // generate a SE0 error
|
reg GenSE0Error; // generate a SE0 error
|
reg [31:0] SE0BitTimes; // generate SE0 for this many bit times
|
reg [31:0] SE0BitTimes; // generate SE0 for this many bit times
|
reg [31:0] SE0ErrorLevel; // = 0 : generates a SE0 error after a sync field
|
reg [31:0] SE0ErrorLevel; // = 0 : generates a SE0 error after a sync field
|
// = 1 : generates a SE0 error after data
|
// = 1 : generates a SE0 error after data
|
// = 2 : generates a SE0 error after a handshake
|
// = 2 : generates a SE0 error after a handshake
|
|
|
|
|
reg HshkPidIntegrity; // specifies if correct ACKs should be sent
|
reg HshkPidIntegrity; // specifies if correct ACKs should be sent
|
reg [7:0] HshkPidIntegrityMask; // Mask according to which ACK's are corrupted
|
reg [7:0] HshkPidIntegrityMask; // Mask according to which ACK's are corrupted
|
|
|
reg BitStuffErr;
|
reg BitStuffErr;
|
|
|
integer RespTimeOutVal; // bit times to wait for when no response is to be
|
integer RespTimeOutVal; // bit times to wait for when no response is to be
|
// sent
|
// sent
|
|
|
integer tmpCounter; // a scratch variable to be used any where
|
integer tmpCounter; // a scratch variable to be used any where
|
|
|
event DoesNotOccur; // an event which will not be triggered to
|
event DoesNotOccur; // an event which will not be triggered to
|
// used to suspend threads
|
// used to suspend threads
|
|
|
reg [31:0] StartTime; // start time of a transaction
|
reg [31:0] StartTime; // start time of a transaction
|
reg [31:0] StopTime; // stop time of a transaction
|
reg [31:0] StopTime; // stop time of a transaction
|
reg [31:0] SE0StartTime; // start time of a single ended 0
|
reg [31:0] SE0StartTime; // start time of a single ended 0
|
reg [31:0] SE0StopTime; // stop of a single ended 0
|
reg [31:0] SE0StopTime; // stop of a single ended 0
|
|
|
reg [31:0] SelfName; // 4 byte wide register to differentiate between
|
reg [31:0] SelfName; // 4 byte wide register to differentiate between
|
// instantiations
|
// instantiations
|
|
|
|
|
// info about a current control transaction
|
// info about a current control transaction
|
|
|
reg [1:0] CntrlTransType [1 : MAX_CNTRL_INTERLEAVE];
|
reg [1:0] CntrlTransType [1 : MAX_CNTRL_INTERLEAVE];
|
// type of control transaction
|
// type of control transaction
|
// 00 no control transaction in progress
|
// 00 no control transaction in progress
|
// 01 control_rd transaction in progress
|
// 01 control_rd transaction in progress
|
// 11 control_wr transaction in progress
|
// 11 control_wr transaction in progress
|
reg [6:0] CntrlTransAddr [1 : MAX_CNTRL_INTERLEAVE];
|
reg [6:0] CntrlTransAddr [1 : MAX_CNTRL_INTERLEAVE];
|
// address to which a cntrl trans is in progress
|
// address to which a cntrl trans is in progress
|
reg [3:0] CntrlTransEndP [1 : MAX_CNTRL_INTERLEAVE];
|
reg [3:0] CntrlTransEndP [1 : MAX_CNTRL_INTERLEAVE];
|
// End Pnt to which a cntrl trans is in progress
|
// End Pnt to which a cntrl trans is in progress
|
reg [15:0] CntrlTransDlen [1 : MAX_CNTRL_INTERLEAVE];
|
reg [15:0] CntrlTransDlen [1 : MAX_CNTRL_INTERLEAVE];
|
// data length for this control transaction
|
// data length for this control transaction
|
|
|
|
|
reg [NumCharsInFileName * CharByte : 1] SendDataFileName;
|
reg [NumCharsInFileName * CharByte : 1] SendDataFileName;
|
// File from which data to be sent is taken from, format is 1 byte per line
|
// File from which data to be sent is taken from, format is 1 byte per line
|
// in hex format
|
// in hex format
|
|
|
reg [NumCharsInFileName * CharByte : 1] RecvDataFileName;
|
reg [NumCharsInFileName * CharByte : 1] RecvDataFileName;
|
// File to which received data is logged to, format is 1 byte per line in
|
// File to which received data is logged to, format is 1 byte per line in
|
// hex format
|
// hex format
|
|
|
reg [NumCharsInFileName * CharByte : 1] ErrorFileName;
|
reg [NumCharsInFileName * CharByte : 1] ErrorFileName;
|
// file name to report errors
|
// file name to report errors
|
|
|
reg [31:0] RecvDataFp; // file pointer to RecvDataFileName
|
reg [31:0] RecvDataFp; // file pointer to RecvDataFileName
|
|
|
reg [31:0] SendDataOfst; // offset into SendDataFileName
|
reg [31:0] SendDataOfst; // offset into SendDataFileName
|
|
|
reg [31:0] ErrorFileFp; // file pointer of the error file
|
reg [31:0] ErrorFileFp; // file pointer of the error file
|
|
|
|
|
reg [NumCharsInFileName * CharByte : 1] EndPtFileName [1 : NUM_ENDPT_FILES];
|
reg [NumCharsInFileName * CharByte : 1] EndPtFileName [1 : NUM_ENDPT_FILES];
|
// array to store file names associated with end points
|
// array to store file names associated with end points
|
reg [1:0] EndPtFileMode [1 : NUM_ENDPT_FILES];
|
reg [1:0] EndPtFileMode [1 : NUM_ENDPT_FILES];
|
// array to store read/write mode info for each file
|
// array to store read/write mode info for each file
|
reg [31:0] EndPtFp [1 : NUM_ENDPT_FILES];
|
reg [31:0] EndPtFp [1 : NUM_ENDPT_FILES];
|
reg [10:0] EndPtFileInfo [1 : NUM_ENDPT_FILES];
|
reg [10:0] EndPtFileInfo [1 : NUM_ENDPT_FILES];
|
reg [31:0] EndPtFileOfst [1 : NUM_ENDPT_FILES];
|
reg [31:0] EndPtFileOfst [1 : NUM_ENDPT_FILES];
|
// offset into the file if it is in write mode
|
// offset into the file if it is in write mode
|
|
|
|
|
reg Debug; // debugging messages are turned on if set to true
|
reg Debug; // debugging messages are turned on if set to true
|
|
|
|
|
reg GenDataPidErr; // generates a data pid integrity error
|
reg GenDataPidErr; // generates a data pid integrity error
|
reg [7:0] DataPidErrMask; // error mask for generating
|
reg [7:0] DataPidErrMask; // error mask for generating
|
reg GenTokenErr; // generates a token pid integrity error
|
reg GenTokenErr; // generates a token pid integrity error
|
reg [7:0] TokenErrMask; // token error mask
|
reg [7:0] TokenErrMask; // token error mask
|
|
|
reg DeviceSpeed; // low speed or high speed
|
reg DeviceSpeed; // low speed or high speed
|
|
|
reg GenByteBoundary; // generate a byte boundary error
|
reg GenByteBoundary; // generate a byte boundary error
|
|
|
reg SendPreamble;
|
reg SendPreamble;
|
|
|
// registers to log simulation results
|
// registers to log simulation results
|
|
|
reg [31:0] NumBulkInTrans; // number of bulk in transactions
|
reg [31:0] NumBulkInTrans; // number of bulk in transactions
|
reg [31:0] NumSucBulkInTrans; // number of successful bulk in transctions
|
reg [31:0] NumSucBulkInTrans; // number of successful bulk in transctions
|
reg [31:0] NumBulkOutTrans; // number of bulk out transactions
|
reg [31:0] NumBulkOutTrans; // number of bulk out transactions
|
reg [31:0] NumSucBulkOutTrans; // number of successful bulk out transactions
|
reg [31:0] NumSucBulkOutTrans; // number of successful bulk out transactions
|
reg [31:0] NumIsoInTrans; // number of iso in transactions
|
reg [31:0] NumIsoInTrans; // number of iso in transactions
|
reg [31:0] NumSucIsoInTrans; // number of successful iso in transactions
|
reg [31:0] NumSucIsoInTrans; // number of successful iso in transactions
|
reg [31:0] NumIsoOutTrans; // number of iso out transactions
|
reg [31:0] NumIsoOutTrans; // number of iso out transactions
|
reg [31:0] NumSOF; // number of SOF's sent
|
reg [31:0] NumSOF; // number of SOF's sent
|
reg [31:0] NumCntrlRdTrans; // number of control reads
|
reg [31:0] NumCntrlRdTrans; // number of control reads
|
reg [31:0] NumSucCntrlRdTrans; // number of successful control reads
|
reg [31:0] NumSucCntrlRdTrans; // number of successful control reads
|
reg [31:0] NumCntrlWrTrans; // number of control writes
|
reg [31:0] NumCntrlWrTrans; // number of control writes
|
reg [31:0] NumSucCntrlWrTrans; // number of successful control writes
|
reg [31:0] NumSucCntrlWrTrans; // number of successful control writes
|
reg [31:0] NumIntrptTrans; // number of interrupt transactions
|
reg [31:0] NumIntrptTrans; // number of interrupt transactions
|
reg [31:0] NumSucIntrptTrans; // number of successful interrupt transactions
|
reg [31:0] NumSucIntrptTrans; // number of successful interrupt transactions
|
reg [31:0] NumIntrOutTrans; // number of interrupt out transactions
|
reg [31:0] NumIntrOutTrans; // number of interrupt out transactions
|
reg [31:0] NumSucIntrOutTrans; // number of successful interrupt out transactions
|
reg [31:0] NumSucIntrOutTrans; // number of successful interrupt out transactions
|
reg [31:0] NumResets; // number of resets
|
reg [31:0] NumResets; // number of resets
|
|
|
|
|
// registers to store jitter information
|
// registers to store jitter information
|
|
|
integer HighJitterTime; // time by which high time pulse width is modified
|
integer HighJitterTime; // time by which high time pulse width is modified
|
integer LowJitterTime; // time by which low time pulse width is modified
|
integer LowJitterTime; // time by which low time pulse width is modified
|
integer JitterPeriod; // specifies in pulse numbers when the Jitter is
|
integer JitterPeriod; // specifies in pulse numbers when the Jitter is
|
// to be repeated
|
// to be repeated
|
integer JitterCount; // number of pulses for which jitter is induced
|
integer JitterCount; // number of pulses for which jitter is induced
|
reg JitterOnOff; // specifies if jitter is being induced or not
|
reg JitterOnOff; // specifies if jitter is being induced or not
|
|
|
reg task_in_progress;
|
reg task_in_progress;
|
|
|
// SOF's
|
// SOF's
|
reg hs_clk; // high speed clock
|
reg hs_clk; // high speed clock
|
reg ls_clk; // low-speed clock
|
reg ls_clk; // low-speed clock
|
reg clk_swtch; // clock switch
|
reg clk_swtch; // clock switch
|
|
|
|
|
reg [31:0] SetupDataLen;
|
reg [31:0] SetupDataLen;
|
|
|
reg GenByteBoundaryPos;
|
reg GenByteBoundaryPos;
|
reg BoundaryBitVal;
|
reg BoundaryBitVal;
|
|
|
integer ModifyGran;
|
integer ModifyGran;
|
|
|
|
|
|
|
task DispErrMsg;
|
task DispErrMsg;
|
|
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
input [31:0] ErrMsgNo;
|
input [31:0] ErrMsgNo;
|
|
|
begin
|
begin
|
if (ReportErrors == FALSE) disable DispErrMsg;
|
if (ReportErrors == FALSE) disable DispErrMsg;
|
if ((ErrorFileFp == 0) & (ErrorFileName == "")) begin
|
if ((ErrorFileFp == 0) & (ErrorFileName == "")) begin
|
$display("No file name specified to log errors.");
|
$display("No file name specified to log errors.");
|
disable DispErrMsg;
|
disable DispErrMsg;
|
end
|
end
|
if (ErrorFileFp == 0) ErrorFileFp = $fopen(ErrorFileName);
|
if (ErrorFileFp == 0) ErrorFileFp = $fopen(ErrorFileName);
|
if ((ErrMsgNo >= 0) & (ErrMsgNo <= 32)) $fwrite(ErrorFileFp, "Error %0d :", (500 + ErrMsgNo));
|
if ((ErrMsgNo >= 0) & (ErrMsgNo <= 32)) $fwrite(ErrorFileFp, "Error %0d :", (500 + ErrMsgNo));
|
case (ErrMsgNo)
|
case (ErrMsgNo)
|
0: $fdisplay(ErrorFileFp, "Time out for bulk in transfer at address %h for End Point %h at time %0t", address, EndPt, $time);
|
0: $fdisplay(ErrorFileFp, "Time out for bulk in transfer at address %h for End Point %h at time %0t", address, EndPt, $time);
|
1: $fdisplay(ErrorFileFp, "Time out for iso in transfer at address %h for End Point %h at time %0t", address, EndPt, $time);
|
1: $fdisplay(ErrorFileFp, "Time out for iso in transfer at address %h for End Point %h at time %0t", address, EndPt, $time);
|
2: $fdisplay(ErrorFileFp, "Time out for interrupt transfer at address %h for End Point %h at time %0t", address, EndPt, $time);
|
2: $fdisplay(ErrorFileFp, "Time out for interrupt transfer at address %h for End Point %h at time %0t", address, EndPt, $time);
|
3: $fdisplay(ErrorFileFp, "Time out for control transfer at address %h for End Point %h at time %0t", address, EndPt, $time); //this EndPt value should be zero
|
3: $fdisplay(ErrorFileFp, "Time out for control transfer at address %h for End Point %h at time %0t", address, EndPt, $time); //this EndPt value should be zero
|
4: $fdisplay(ErrorFileFp, "Time out for bulk out transfer at address %h for End Point %h at time %0t", address, EndPt, $time);
|
4: $fdisplay(ErrorFileFp, "Time out for bulk out transfer at address %h for End Point %h at time %0t", address, EndPt, $time);
|
5: $fdisplay(ErrorFileFp, "Pid error at address %h for End Point %h at time %0t", address, EndPt, $time);
|
5: $fdisplay(ErrorFileFp, "Pid error at address %h for End Point %h at time %0t", address, EndPt, $time);
|
6: $fdisplay(ErrorFileFp, "Short packet at address %h for End Point %h at time %0t", address, EndPt, $time);
|
6: $fdisplay(ErrorFileFp, "Short packet at address %h for End Point %h at time %0t", address, EndPt, $time);
|
7: $fdisplay(ErrorFileFp, "CRC error for token packet at address %h for End Point %h at time %0t", address, EndPt, $time);
|
7: $fdisplay(ErrorFileFp, "CRC error for token packet at address %h for End Point %h at time %0t", address, EndPt, $time);
|
8: $fdisplay(ErrorFileFp, "CRC error for data at address %h for End Point %h at time %0t", address, EndPt, $time);
|
8: $fdisplay(ErrorFileFp, "CRC error for data at address %h for End Point %h at time %0t", address, EndPt, $time);
|
9: $fdisplay(ErrorFileFp, "Incorrect token received at address %h for End Point %h at time %0t", address, EndPt, $time);
|
9: $fdisplay(ErrorFileFp, "Incorrect token received at address %h for End Point %h at time %0t", address, EndPt, $time);
|
10: $fdisplay(ErrorFileFp, "Incorrect Data0/Data1 toggle received at address %h for End Point %h at time %0t", address, EndPt, $time);
|
10: $fdisplay(ErrorFileFp, "Incorrect Data0/Data1 toggle received at address %h for End Point %h at time %0t", address, EndPt, $time);
|
11: $fdisplay(ErrorFileFp, "NAK recevied at address %h for End Point %h at time %0t", address, EndPt, $time);
|
11: $fdisplay(ErrorFileFp, "NAK recevied at address %h for End Point %h at time %0t", address, EndPt, $time);
|
12: $fdisplay(ErrorFileFp, "STALL received at address %h for End Point %h at time %0t", address, EndPt, $time);
|
12: $fdisplay(ErrorFileFp, "STALL received at address %h for End Point %h at time %0t", address, EndPt, $time);
|
13: $fdisplay(ErrorFileFp, "Incorrect handshake received at address %h for End Point %h at time %0t", address, EndPt, $time);
|
13: $fdisplay(ErrorFileFp, "Incorrect handshake received at address %h for End Point %h at time %0t", address, EndPt, $time);
|
14: $fdisplay(ErrorFileFp, "Long packet at address %h for End Point %h at time %0t", address, EndPt, $time);
|
14: $fdisplay(ErrorFileFp, "Long packet at address %h for End Point %h at time %0t", address, EndPt, $time);
|
15: $fdisplay(ErrorFileFp, "Corrupted handshake received at address %h for End Point %h at time %0t", address, EndPt, $time);
|
15: $fdisplay(ErrorFileFp, "Corrupted handshake received at address %h for End Point %h at time %0t", address, EndPt, $time);
|
16: $fdisplay(ErrorFileFp, "Device error at address %h for End Point %h at time %0t", address, EndPt, $time);
|
16: $fdisplay(ErrorFileFp, "Device error at address %h for End Point %h at time %0t", address, EndPt, $time);
|
17: $fdisplay(ErrorFileFp, "Invalid wIndex value for control transfer to address %h at time %0t", address, $time);
|
17: $fdisplay(ErrorFileFp, "Invalid wIndex value for control transfer to address %h at time %0t", address, $time);
|
18: $fdisplay(ErrorFileFp, "Invalid RequestType for control transfer to address %h at time %0t", address, $time);
|
18: $fdisplay(ErrorFileFp, "Invalid RequestType for control transfer to address %h at time %0t", address, $time);
|
19: $fdisplay(ErrorFileFp, "Invalid wValue value for control transfer to address %h at time %0t", address, $time);
|
19: $fdisplay(ErrorFileFp, "Invalid wValue value for control transfer to address %h at time %0t", address, $time);
|
20: $fdisplay(ErrorFileFp, "Invalid data length during data phase for control transfer to address %0h and End Point %0h at time %0t", address, EndPt, $time);
|
20: $fdisplay(ErrorFileFp, "Invalid data length during data phase for control transfer to address %0h and End Point %0h at time %0t", address, EndPt, $time);
|
21: $fdisplay(ErrorFileFp, "No setup transaction in progress to do a control_in or a control_out or a status transaction at time %0t", $time);
|
21: $fdisplay(ErrorFileFp, "No setup transaction in progress to do a control_in or a control_out or a status transaction at time %0t", $time);
|
22: $fdisplay(ErrorFileFp, "Doing a control_in when a control_out is expected and vice-versa at time %0t", $time);
|
22: $fdisplay(ErrorFileFp, "Doing a control_in when a control_out is expected and vice-versa at time %0t", $time);
|
23: $fdisplay(ErrorFileFp, "Doing a control_in or control_out when the number of bytes specified by wLength have been received or sent at time %0t", $time);
|
23: $fdisplay(ErrorFileFp, "Doing a control_in or control_out when the number of bytes specified by wLength have been received or sent at time %0t", $time);
|
24: $fdisplay(ErrorFileFp, "Doing a status_in when a status_out is expected and vice-versa at time %0t", $time);
|
24: $fdisplay(ErrorFileFp, "Doing a status_in when a status_out is expected and vice-versa at time %0t", $time);
|
25: $fdisplay(ErrorFileFp, "Received a DATA0 token during the status phase of a control transaction at address %0h, EndPt %0h, at time %0t", address, EndPt, $time);
|
25: $fdisplay(ErrorFileFp, "Received a DATA0 token during the status phase of a control transaction at address %0h, EndPt %0h, at time %0t", address, EndPt, $time);
|
26: $fdisplay(ErrorFileFp, "Incorrect sync field at time %0t", $time);
|
26: $fdisplay(ErrorFileFp, "Incorrect sync field at time %0t", $time);
|
27: $fdisplay(ErrorFileFp, "Bit Stuffing error at time %0t", $time);
|
27: $fdisplay(ErrorFileFp, "Bit Stuffing error at time %0t", $time);
|
28: $fdisplay(ErrorFileFp, "Eop incorrect at time %0t", $time);
|
28: $fdisplay(ErrorFileFp, "Eop incorrect at time %0t", $time);
|
29: $fdisplay(ErrorFileFp, "Null File Name passed to command at time %0t", $time);
|
29: $fdisplay(ErrorFileFp, "Null File Name passed to command at time %0t", $time);
|
30: $fdisplay(ErrorFileFp, "Offset into file greater than size of file at time %0t", $time);
|
30: $fdisplay(ErrorFileFp, "Offset into file greater than size of file at time %0t", $time);
|
31: $fdisplay(ErrorFileFp, "Command not supported by a low speed device issued at time %0t.", $time);
|
31: $fdisplay(ErrorFileFp, "Command not supported by a low speed device issued at time %0t.", $time);
|
32: $fdisplay(ErrorFileFp, "Command not supported by command line interface issued at time %0t.", $time);
|
32: $fdisplay(ErrorFileFp, "Command not supported by command line interface issued at time %0t.", $time);
|
endcase
|
endcase
|
end
|
end
|
endtask
|
endtask
|
|
|
//bit 0 has the IN DataToggle and bit 1 has the OUT DataToggle
|
//bit 0 has the IN DataToggle and bit 1 has the OUT DataToggle
|
function [1:0] CheckDataToggle;
|
function [1:0] CheckDataToggle;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
|
|
reg [15:0] tmpReg1;
|
reg [15:0] tmpReg1;
|
reg [15:0] tmpReg2;
|
reg [15:0] tmpReg2;
|
|
|
begin
|
begin
|
tmpReg1 = InDataToggle[address];
|
tmpReg1 = InDataToggle[address];
|
tmpReg2 = OutDataToggle[address];
|
tmpReg2 = OutDataToggle[address];
|
if ((EndPt < 16) & (EndPt >= 0)) begin
|
if ((EndPt < 16) & (EndPt >= 0)) begin
|
CheckDataToggle[0] = tmpReg1[EndPt];
|
CheckDataToggle[0] = tmpReg1[EndPt];
|
CheckDataToggle[1] = tmpReg2[EndPt];
|
CheckDataToggle[1] = tmpReg2[EndPt];
|
end
|
end
|
else CheckDataToggle = 0; // default
|
else CheckDataToggle = 0; // default
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function CheckDataToggleIN;
|
function CheckDataToggleIN;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
|
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
|
|
begin
|
begin
|
tmpReg = InDataToggle[address];
|
tmpReg = InDataToggle[address];
|
if ((EndPt < 16) & (EndPt >= 0)) CheckDataToggleIN = tmpReg[EndPt];
|
if ((EndPt < 16) & (EndPt >= 0)) CheckDataToggleIN = tmpReg[EndPt];
|
else CheckDataToggleIN = 0; // default
|
else CheckDataToggleIN = 0; // default
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function CheckDataToggleOUT;
|
function CheckDataToggleOUT;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
|
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
|
|
begin
|
begin
|
tmpReg = OutDataToggle[address];
|
tmpReg = OutDataToggle[address];
|
if ((EndPt < 16) & (EndPt >= 0)) CheckDataToggleOUT = tmpReg[EndPt];
|
if ((EndPt < 16) & (EndPt >= 0)) CheckDataToggleOUT = tmpReg[EndPt];
|
else CheckDataToggleOUT = 0; // default
|
else CheckDataToggleOUT = 0; // default
|
end
|
end
|
endfunction
|
endfunction
|
|
|
task SetDataToggle;
|
task SetDataToggle;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
input [1:0] SetVal; //value to which the toggle value should be changed to
|
input [1:0] SetVal; //value to which the toggle value should be changed to
|
// index 0 has the IN value and index 1 has the OUT value
|
// index 0 has the IN value and index 1 has the OUT value
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
begin
|
begin
|
tmpReg = InDataToggle[address];
|
tmpReg = InDataToggle[address];
|
if ((SetVal[0] == 0) | (SetVal[0] == 1)) tmpReg[EndPt] = SetVal;
|
if ((SetVal[0] == 0) | (SetVal[0] == 1)) tmpReg[EndPt] = SetVal;
|
else tmpReg[EndPt] = 0; // default
|
else tmpReg[EndPt] = 0; // default
|
InDataToggle[address] = tmpReg;
|
InDataToggle[address] = tmpReg;
|
tmpReg = OutDataToggle[address];
|
tmpReg = OutDataToggle[address];
|
if ((SetVal[1] == 0) | (SetVal[1] == 1)) tmpReg[EndPt] = SetVal;
|
if ((SetVal[1] == 0) | (SetVal[1] == 1)) tmpReg[EndPt] = SetVal;
|
else tmpReg[EndPt] = 0; // default
|
else tmpReg[EndPt] = 0; // default
|
OutDataToggle[address] = tmpReg;
|
OutDataToggle[address] = tmpReg;
|
end
|
end
|
endtask
|
endtask
|
|
|
task SetDataToggleIN;
|
task SetDataToggleIN;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
input SetVal; //value to which the toggle value should be changed to
|
input SetVal; //value to which the toggle value should be changed to
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
begin
|
begin
|
tmpReg = InDataToggle[address];
|
tmpReg = InDataToggle[address];
|
if ((SetVal == 0) | (SetVal == 1)) tmpReg[EndPt] = SetVal;
|
if ((SetVal == 0) | (SetVal == 1)) tmpReg[EndPt] = SetVal;
|
else tmpReg[EndPt] = 0; // default
|
else tmpReg[EndPt] = 0; // default
|
InDataToggle[address] = tmpReg;
|
InDataToggle[address] = tmpReg;
|
end
|
end
|
endtask
|
endtask
|
|
|
task SetDataToggleOUT;
|
task SetDataToggleOUT;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
input SetVal; //value to which the toggle value should be changed to
|
input SetVal; //value to which the toggle value should be changed to
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
begin
|
begin
|
tmpReg = OutDataToggle[address];
|
tmpReg = OutDataToggle[address];
|
if ((SetVal == 0) | (SetVal == 1)) tmpReg[EndPt] = SetVal;
|
if ((SetVal == 0) | (SetVal == 1)) tmpReg[EndPt] = SetVal;
|
else tmpReg[EndPt] = 0; // default
|
else tmpReg[EndPt] = 0; // default
|
OutDataToggle[address] = tmpReg;
|
OutDataToggle[address] = tmpReg;
|
end
|
end
|
endtask
|
endtask
|
|
|
function [7:0] CorruptHshk;
|
function [7:0] CorruptHshk;
|
input [7:0] funHshk;
|
input [7:0] funHshk;
|
reg [7:0] tmpReg;
|
reg [7:0] tmpReg;
|
reg [4:0] i;
|
reg [4:0] i;
|
begin
|
begin
|
tmpReg = funHshk;
|
tmpReg = funHshk;
|
if (HshkPidIntegrity == TRUE) begin
|
if (HshkPidIntegrity == TRUE) begin
|
for (i = 0; i < 8; i = i + 1) begin
|
for (i = 0; i < 8; i = i + 1) begin
|
if (HshkPidIntegrityMask[i] == 1'b1) tmpReg[i] = ~tmpReg[i];
|
if (HshkPidIntegrityMask[i] == 1'b1) tmpReg[i] = ~tmpReg[i];
|
end
|
end
|
end
|
end
|
CorruptHshk = tmpReg;
|
CorruptHshk = tmpReg;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// swap2 : swaps around the bits in half a nibble
|
// swap2 : swaps around the bits in half a nibble
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
function [1:0] swap2;
|
function [1:0] swap2;
|
input [1:0] SwapBits;
|
input [1:0] SwapBits;
|
begin
|
begin
|
swap2 = {SwapBits[0], SwapBits[1]};
|
swap2 = {SwapBits[0], SwapBits[1]};
|
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// swap8 : swaps around the bits in a byte and returns the swapped byte
|
// swap8 : swaps around the bits in a byte and returns the swapped byte
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
function [7:0] swap8;
|
function [7:0] swap8;
|
input [7:0] SwapByte;
|
input [7:0] SwapByte;
|
begin
|
begin
|
swap8 = {SwapByte[0], SwapByte[1], SwapByte[2], SwapByte[3], SwapByte[4], SwapByte[5], SwapByte[6], SwapByte[7]};
|
swap8 = {SwapByte[0], SwapByte[1], SwapByte[2], SwapByte[3], SwapByte[4], SwapByte[5], SwapByte[6], SwapByte[7]};
|
end
|
end
|
endfunction
|
endfunction
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// DumpData : dumps the data received into in_out_buf to a file
|
// DumpData : dumps the data received into in_out_buf to a file
|
// Inputs : address : device address to which data is dumped to the
|
// Inputs : address : device address to which data is dumped to the
|
// associated file, 7 bits
|
// associated file, 7 bits
|
// EndPt : End Point number, 4 bits
|
// EndPt : End Point number, 4 bits
|
// ByteCount : number of bytes to dump from in_out_buf to the file
|
// ByteCount : number of bytes to dump from in_out_buf to the file
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task DumpData;
|
task DumpData;
|
|
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
input [3:0] DataToggle;
|
input [3:0] DataToggle;
|
input [31:0] ByteCount;
|
input [31:0] ByteCount;
|
|
|
integer i;
|
integer i;
|
integer j;
|
integer j;
|
|
|
reg [39:0] DataToggleString;
|
reg [39:0] DataToggleString;
|
reg Match;
|
reg Match;
|
|
|
begin
|
begin
|
DataToggleString = (DataToggle == DATA0) ? "DATA0" : "DATA1" ;
|
DataToggleString = (DataToggle == DATA0) ? "DATA0" : "DATA1" ;
|
Match = FALSE;
|
Match = FALSE;
|
for (i = 1; i <= NUM_ENDPT_FILES; i = i + 1) begin
|
for (i = 1; i <= NUM_ENDPT_FILES; i = i + 1) begin
|
if (EndPtFileInfo[i] == {EndPt, address}) begin
|
if (EndPtFileInfo[i] == {EndPt, address}) begin
|
if ((EndPtFp[i] > 0) & (EndPtFileMode[i] == WRITE)) begin
|
if ((EndPtFp[i] > 0) & (EndPtFileMode[i] == WRITE)) begin
|
$fdisplay (EndPtFp[i], "//address = %b, EndPt = %b, Data Toggle = %0s at time = %0t", address, EndPt, DataToggleString, $time);
|
$fdisplay (EndPtFp[i], "//address = %b, EndPt = %b, Data Toggle = %0s at time = %0t", address, EndPt, DataToggleString, $time);
|
//for (j = 1; j <= ByteCount; j = j + 1) $fwrite (EndPtFp[i], "%h, ", in_out_buf [j]);
|
//for (j = 1; j <= ByteCount; j = j + 1) $fwrite (EndPtFp[i], "%h, ", in_out_buf [j]);
|
for (j = 1; j <= ByteCount; j = j + 1) $fdisplay (EndPtFp[i], "%h", in_out_buf[j]);
|
for (j = 1; j <= ByteCount; j = j + 1) $fdisplay (EndPtFp[i], "%h", in_out_buf[j]);
|
$fdisplay(EndPtFp[i], "\n");
|
$fdisplay(EndPtFp[i], "\n");
|
Match = TRUE;
|
Match = TRUE;
|
end
|
end
|
i = NUM_ENDPT_FILES + 1;
|
i = NUM_ENDPT_FILES + 1;
|
end
|
end
|
end
|
end
|
|
|
if (Match == FALSE) begin // no file name associated with this address
|
if (Match == FALSE) begin // no file name associated with this address
|
// dump data into the common bucket(file)
|
// dump data into the common bucket(file)
|
if (RecvDataFp == 0) RecvDataFp = $fopen(RecvDataFileName);
|
if (RecvDataFp == 0) RecvDataFp = $fopen(RecvDataFileName);
|
$fdisplay (RecvDataFp, "//address = %b, EndPt = %b, Data Toggle = %0s at time = %0t", address, EndPt, DataToggleString, $time);
|
$fdisplay (RecvDataFp, "//address = %b, EndPt = %b, Data Toggle = %0s at time = %0t", address, EndPt, DataToggleString, $time);
|
//for (j = 1; j <= ByteCount; j = j + 1) $fwrite (RecvDataFp, "%h, ", in_out_buf[j]);
|
//for (j = 1; j <= ByteCount; j = j + 1) $fwrite (RecvDataFp, "%h, ", in_out_buf[j]);
|
for (j = 1; j <= ByteCount; j = j + 1) $fdisplay (RecvDataFp, "%h", in_out_buf[j]);
|
for (j = 1; j <= ByteCount; j = j + 1) $fdisplay (RecvDataFp, "%h", in_out_buf[j]);
|
$fdisplay(RecvDataFp, "\n");
|
$fdisplay(RecvDataFp, "\n");
|
end
|
end
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
function [7:0] CorruptDataPid;
|
function [7:0] CorruptDataPid;
|
input [7:0] funDataPid;
|
input [7:0] funDataPid;
|
integer i;
|
integer i;
|
reg [7:0] tmpReg;
|
reg [7:0] tmpReg;
|
begin
|
begin
|
tmpReg = funDataPid;
|
tmpReg = funDataPid;
|
if (GenDataPidErr == TRUE) begin
|
if (GenDataPidErr == TRUE) begin
|
for ( i = 0; i < 8; i = i + 1) begin
|
for ( i = 0; i < 8; i = i + 1) begin
|
if (DataPidErrMask[i] == 1'b1) tmpReg[i] = ~tmpReg[i];
|
if (DataPidErrMask[i] == 1'b1) tmpReg[i] = ~tmpReg[i];
|
end
|
end
|
end
|
end
|
CorruptDataPid = tmpReg;
|
CorruptDataPid = tmpReg;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
function [7:0] CorruptToken;
|
function [7:0] CorruptToken;
|
input [7:0] funToken;
|
input [7:0] funToken;
|
integer i;
|
integer i;
|
reg [7:0] tmpReg;
|
reg [7:0] tmpReg;
|
begin
|
begin
|
tmpReg = funToken;
|
tmpReg = funToken;
|
if (GenTokenErr == TRUE) begin
|
if (GenTokenErr == TRUE) begin
|
for ( i = 0; i < 8; i = i + 1) begin
|
for ( i = 0; i < 8; i = i + 1) begin
|
if (TokenErrMask[i] == 1'b1) tmpReg[i] = ~tmpReg[i];
|
if (TokenErrMask[i] == 1'b1) tmpReg[i] = ~tmpReg[i];
|
end
|
end
|
end
|
end
|
CorruptToken = tmpReg;
|
CorruptToken = tmpReg;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// WriteResults : writes out the results to the file pointed to by ResultsFp
|
// WriteResults : writes out the results to the file pointed to by ResultsFp
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task WriteResults;
|
task WriteResults;
|
|
|
begin
|
begin
|
|
|
if (ResultsFile == "") disable WriteResults;
|
if (ResultsFile == "") disable WriteResults;
|
|
|
if (ResultsFp != 0) $fclose(ResultsFp);
|
if (ResultsFp != 0) $fclose(ResultsFp);
|
|
|
ResultsFp = $fopen(ResultsFile);
|
ResultsFp = $fopen(ResultsFile);
|
|
|
$fdisplay(ResultsFp, "\n");
|
$fdisplay(ResultsFp, "\n");
|
$fdisplay(ResultsFp, "--------------------------------------------------------------------------------");
|
$fdisplay(ResultsFp, "--------------------------------------------------------------------------------");
|
$fdisplay(ResultsFp, "-------------------- Transfer Statistics for the HOST model --------------------");
|
$fdisplay(ResultsFp, "-------------------- Transfer Statistics for the HOST model --------------------");
|
$fdisplay(ResultsFp, "--------------------------------------------------------------------------------");
|
$fdisplay(ResultsFp, "--------------------------------------------------------------------------------");
|
$fdisplay(ResultsFp, "\n");
|
$fdisplay(ResultsFp, "\n");
|
|
|
|
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Simulation Start Time ------------------------------ : 0",);
|
" Simulation Start Time ------------------------------ : 0",);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Bulk In transactions --------------------- : %0d",
|
" Number of Bulk In transactions --------------------- : %0d",
|
NumBulkInTrans);
|
NumBulkInTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Successful Bulk In transactions ---------- : %0d",
|
" Number of Successful Bulk In transactions ---------- : %0d",
|
NumSucBulkInTrans);
|
NumSucBulkInTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Bulk Out transactions -------------------- : %0d",
|
" Number of Bulk Out transactions -------------------- : %0d",
|
NumBulkOutTrans);
|
NumBulkOutTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Successful Bulk Out transactions --------- : %0d",
|
" Number of Successful Bulk Out transactions --------- : %0d",
|
NumSucBulkOutTrans);
|
NumSucBulkOutTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Iso In transactions ---------------------- : %0d",
|
" Number of Iso In transactions ---------------------- : %0d",
|
NumIsoInTrans);
|
NumIsoInTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Successful Iso In transactions ----------- : %0d",
|
" Number of Successful Iso In transactions ----------- : %0d",
|
NumSucIsoInTrans);
|
NumSucIsoInTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Iso Out transactions --------------------- : %0d",
|
" Number of Iso Out transactions --------------------- : %0d",
|
NumIsoOutTrans);
|
NumIsoOutTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Interrupt transactions ------------------- : %0d",
|
" Number of Interrupt transactions ------------------- : %0d",
|
NumIntrptTrans);
|
NumIntrptTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Successful Interrupt transactions -------- : %0d",
|
" Number of Successful Interrupt transactions -------- : %0d",
|
NumSucIntrptTrans);
|
NumSucIntrptTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of resets ----------------------------------- : %0d",
|
" Number of resets ----------------------------------- : %0d",
|
NumResets);
|
NumResets);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of SOF's sent ------------------------------- : %0d",
|
" Number of SOF's sent ------------------------------- : %0d",
|
NumSOF);
|
NumSOF);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Control Read transactions ---------------- : %0d",
|
" Number of Control Read transactions ---------------- : %0d",
|
NumCntrlRdTrans);
|
NumCntrlRdTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Successful Control Read transactions ----- : %0d",
|
" Number of Successful Control Read transactions ----- : %0d",
|
NumSucCntrlRdTrans);
|
NumSucCntrlRdTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Control Write transactions --------------- : %0d",
|
" Number of Control Write transactions --------------- : %0d",
|
NumCntrlWrTrans);
|
NumCntrlWrTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Number of Successful Control Write transactions ---- : %0d",
|
" Number of Successful Control Write transactions ---- : %0d",
|
NumSucCntrlWrTrans);
|
NumSucCntrlWrTrans);
|
$fdisplay(ResultsFp,
|
$fdisplay(ResultsFp,
|
" Simulation End Time -------------------------------- : %0t",
|
" Simulation End Time -------------------------------- : %0t",
|
$time);
|
$time);
|
$fdisplay(ResultsFp, "\n");
|
$fdisplay(ResultsFp, "\n");
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// CorruptCrc16 : Corrupts the crc16 value passed on to it according to the
|
// CorruptCrc16 : Corrupts the crc16 value passed on to it according to the
|
// present crc16 error generation status
|
// present crc16 error generation status
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
function [15:0] CorruptCrc16;
|
function [15:0] CorruptCrc16;
|
input [15:0] funCrc16;
|
input [15:0] funCrc16;
|
reg [5:0] i;
|
reg [5:0] i;
|
begin
|
begin
|
if (GenCrc16Err == TRUE) begin
|
if (GenCrc16Err == TRUE) begin
|
for (i = 0; i < 16; i = i + 1) begin
|
for (i = 0; i < 16; i = i + 1) begin
|
if (Crc16ErrMask[i] == 1'b1) funCrc16[i] = ~funCrc16[i];
|
if (Crc16ErrMask[i] == 1'b1) funCrc16[i] = ~funCrc16[i];
|
end
|
end
|
end
|
end
|
CorruptCrc16 = funCrc16;
|
CorruptCrc16 = funCrc16;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// CorruptCrc5 : Corrupts the crc5 value passed on to it according to the
|
// CorruptCrc5 : Corrupts the crc5 value passed on to it according to the
|
// present crc5 error generation status
|
// present crc5 error generation status
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
function [4:0] CorruptCrc5;
|
function [4:0] CorruptCrc5;
|
input [4:0] funCrc5;
|
input [4:0] funCrc5;
|
reg [5:0] i;
|
reg [5:0] i;
|
begin
|
begin
|
if (GenCrc5Err == TRUE) begin
|
if (GenCrc5Err == TRUE) begin
|
for (i = 0; i < 5; i = i + 1) begin
|
for (i = 0; i < 5; i = i + 1) begin
|
if (Crc5ErrMask[i] == 1'b1) funCrc5[i] = ~funCrc5[i];
|
if (Crc5ErrMask[i] == 1'b1) funCrc5[i] = ~funCrc5[i];
|
end
|
end
|
end
|
end
|
CorruptCrc5 = funCrc5;
|
CorruptCrc5 = funCrc5;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// modify_device_speed : modifies the device speed
|
// modify_device_speed : modifies the device speed
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task modify_device_speed;
|
task modify_device_speed;
|
input tskDeviceSpeed;
|
input tskDeviceSpeed;
|
begin
|
begin
|
DeviceSpeed = (tskDeviceSpeed == LOW_SPEED) ? LOW_SPEED:HIGH_SPEED;
|
DeviceSpeed = (tskDeviceSpeed == LOW_SPEED) ? LOW_SPEED:HIGH_SPEED;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// CorruptSyncField : corrupts the sync field according to SyncFieldMask
|
// CorruptSyncField : corrupts the sync field according to SyncFieldMask
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
function [7:0] CorruptSyncField;
|
function [7:0] CorruptSyncField;
|
input [7:0] funSyncField;
|
input [7:0] funSyncField;
|
reg [7:0] tmpReg;
|
reg [7:0] tmpReg;
|
reg [4:0] i;
|
reg [4:0] i;
|
begin
|
begin
|
tmpReg = funSyncField;
|
tmpReg = funSyncField;
|
if ((SyncField == TRUE) & (SyncLevel == SetSyncLevel)) begin
|
if ((SyncField == TRUE) & (SyncLevel == SetSyncLevel)) begin
|
for (i = 0; i < 8; i = i + 1) begin
|
for (i = 0; i < 8; i = i + 1) begin
|
if (SyncFieldMask[i] == 1'b1) tmpReg[i] = ~tmpReg[i];
|
if (SyncFieldMask[i] == 1'b1) tmpReg[i] = ~tmpReg[i];
|
end
|
end
|
end
|
end
|
CorruptSyncField = tmpReg;
|
CorruptSyncField = tmpReg;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// SendData : serialises and puts out the data in in_out_buf onto DPLS(D+)
|
// SendData : serialises and puts out the data in in_out_buf onto DPLS(D+)
|
// and DMNS(D-)
|
// and DMNS(D-)
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task SendData;
|
task SendData;
|
integer i;
|
integer i;
|
reg [31:0] SE0Counter; // Single Ended Zero Counter
|
reg [31:0] SE0Counter; // Single Ended Zero Counter
|
reg [31:0] SE0Terminate;
|
reg [31:0] SE0Terminate;
|
event SE0Event;
|
event SE0Event;
|
begin
|
begin
|
i = 0;
|
i = 0;
|
SE0Counter = 2'b00;
|
SE0Counter = 2'b00;
|
if (in_out_buf_ptr > 0) begin
|
if (in_out_buf_ptr > 0) begin
|
@(posedge clk);
|
@(posedge clk);
|
@(posedge clk) begin // synchronise to positive edge of clock
|
@(posedge clk) begin // synchronise to positive edge of clock
|
enc_enbl = 1'b1; // active high
|
enc_enbl = 1'b1; // active high
|
enc_reset_n = 1'b1; // active low
|
enc_reset_n = 1'b1; // active low
|
enc_last_byte = 1'b0;
|
enc_last_byte = 1'b0;
|
enc_data_in = CorruptSyncField(8'h80);
|
enc_data_in = CorruptSyncField(8'h80);
|
end
|
end
|
fork
|
fork
|
forever @(posedge clk) begin
|
forever @(posedge clk) begin
|
if (GenByteBoundary == TRUE) begin
|
if (GenByteBoundary == TRUE) begin
|
if ((i == in_out_buf_ptr) & (enc_bit_count_out == 6)) begin
|
if ((i == in_out_buf_ptr) & (enc_bit_count_out == 6)) begin
|
enc_enbl = 1'b0;
|
enc_enbl = 1'b0;
|
enc_reset_n = 1'b0;
|
enc_reset_n = 1'b0;
|
in_out_buf_ptr = 0;
|
in_out_buf_ptr = 0;
|
-> SE0Event;
|
-> SE0Event;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
forever @(posedge clk) begin
|
forever @(posedge clk) begin
|
if (GenByteBoundaryPos == TRUE) begin
|
if (GenByteBoundaryPos == TRUE) begin
|
in_out_buf[in_out_buf_ptr + 1] = {BoundaryBitVal, BoundaryBitVal, BoundaryBitVal, BoundaryBitVal, BoundaryBitVal, BoundaryBitVal, BoundaryBitVal, BoundaryBitVal};
|
in_out_buf[in_out_buf_ptr + 1] = {BoundaryBitVal, BoundaryBitVal, BoundaryBitVal, BoundaryBitVal, BoundaryBitVal, BoundaryBitVal, BoundaryBitVal, BoundaryBitVal};
|
if ((i == (in_out_buf_ptr + 1)) & (enc_bit_count_out == 0)) begin
|
if ((i == (in_out_buf_ptr + 1)) & (enc_bit_count_out == 0)) begin
|
enc_enbl = 1'b0;
|
enc_enbl = 1'b0;
|
enc_reset_n = 1'b0;
|
enc_reset_n = 1'b0;
|
in_out_buf_ptr = 0;
|
in_out_buf_ptr = 0;
|
-> SE0Event;
|
-> SE0Event;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
forever @(negedge enc_count_out) begin
|
forever @(negedge enc_count_out) begin
|
if ((i == in_out_buf_ptr) & (GenByteBoundaryPos == FALSE)) begin
|
if ((i == in_out_buf_ptr) & (GenByteBoundaryPos == FALSE)) begin
|
//@(posedge clk);
|
//@(posedge clk);
|
enc_enbl = 1'b0; // active high
|
enc_enbl = 1'b0; // active high
|
enc_reset_n = 1'b0; // active low
|
enc_reset_n = 1'b0; // active low
|
in_out_buf_ptr = 0; // reset output buffer pointer
|
in_out_buf_ptr = 0; // reset output buffer pointer
|
-> SE0Event;
|
-> SE0Event;
|
end
|
end
|
else begin
|
else begin
|
enc_data_in = in_out_buf[i];
|
enc_data_in = in_out_buf[i];
|
if (i == in_out_buf_ptr - 1) enc_last_byte = 1'b1;
|
if (i == in_out_buf_ptr - 1) enc_last_byte = 1'b1;
|
else enc_last_byte = 1'b0;
|
else enc_last_byte = 1'b0;
|
//if (Debug) $display("in_out_buf[%h] = %h at time %0t",i, in_out_buf[i], $time);
|
//if (Debug) $display("in_out_buf[%h] = %h at time %0t",i, in_out_buf[i], $time);
|
i = i + 1;
|
i = i + 1;
|
end
|
end
|
end
|
end
|
|
|
forever @(SE0Event) begin // drive a SE0 for 2 bit times
|
forever @(SE0Event) begin // drive a SE0 for 2 bit times
|
SE0Terminate = ((GenSE0Error == TRUE) & (SE0ErrorLevel == SetSyncLevel)) ? (SE0BitTimes) : 2;
|
SE0Terminate = ((GenSE0Error == TRUE) & (SE0ErrorLevel == SetSyncLevel)) ? (SE0BitTimes) : 2;
|
if (ModifyGran < -8) ModifyGran = -8;
|
if (ModifyGran < -8) ModifyGran = -8;
|
// SE0Terminate = (SE0Terminate * 4) + ModifyGran;
|
// SE0Terminate = (SE0Terminate * 4) + ModifyGran;
|
// @(posedge clk);
|
// @(posedge clk);
|
// forever @(posedge clk4x) begin
|
// forever @(posedge clk4x) begin
|
forever @(posedge clk) begin
|
forever @(posedge clk) begin
|
if (SE0Counter >= SE0Terminate) begin
|
if (SE0Counter >= SE0Terminate) begin
|
zDPLS = #1 1'bZ;
|
zDPLS = #1 1'bZ;
|
zDMNS = 1'bZ;
|
zDMNS = 1'bZ;
|
@(posedge clk); // wait for one idle state after pulls
|
@(posedge clk); // wait for one idle state after pulls
|
disable SendData;
|
disable SendData;
|
end
|
end
|
if (i >= in_out_buf_ptr) begin
|
if (i >= in_out_buf_ptr) begin
|
zDPLS = #1 1'b0;
|
zDPLS = #1 1'b0;
|
zDMNS = 1'b0;
|
zDMNS = 1'b0;
|
SE0Counter = SE0Counter + 1;
|
SE0Counter = SE0Counter + 1;
|
end
|
end
|
end
|
end
|
end
|
end
|
join
|
join
|
end
|
end
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// WaitForResp : collects the data from DPLS(D+) and DMNS(D-) and fills in_out_buf
|
// WaitForResp : collects the data from DPLS(D+) and DMNS(D-) and fills in_out_buf
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task WaitForResp;
|
task WaitForResp;
|
|
|
output [31:0] recv_bit_count;
|
output [31:0] recv_bit_count;
|
|
|
reg [31:0] recv_bit_count;
|
reg [31:0] recv_bit_count;
|
integer EopDetect;
|
integer EopDetect;
|
reg [4:0] ClkCount;
|
reg [4:0] ClkCount;
|
reg [3:0] DplsCount;
|
reg [3:0] DplsCount;
|
reg FltrSyncFld;
|
reg FltrSyncFld;
|
integer tmpTimeOutCounter;
|
integer tmpTimeOutCounter;
|
reg tmpTimeOut;
|
reg tmpTimeOut;
|
reg OnlyOnce;
|
reg OnlyOnce;
|
reg SyncDetect;
|
reg SyncDetect;
|
time SyncPulseT1;
|
time SyncPulseT1;
|
time SyncPulseT2;
|
time SyncPulseT2;
|
time SyncPulseDuration;
|
time SyncPulseDuration;
|
|
|
begin
|
begin
|
if (Debug) $display("In %0s --> In task wait for response at time %0t", SelfName, $time);
|
if (Debug) $display("In %0s --> In task wait for response at time %0t", SelfName, $time);
|
EopDetect = 0;
|
EopDetect = 0;
|
in_out_buf_ptr = 0;
|
in_out_buf_ptr = 0;
|
DplsCount = 0;
|
DplsCount = 0;
|
ClkCount = 0;
|
ClkCount = 0;
|
FltrSyncFld = 1'b1;
|
FltrSyncFld = 1'b1;
|
tmpTimeOutCounter = 0;
|
tmpTimeOutCounter = 0;
|
tmpTimeOut = TRUE;
|
tmpTimeOut = TRUE;
|
recv_bit_count = 0;
|
recv_bit_count = 0;
|
OnlyOnce = TRUE;
|
OnlyOnce = TRUE;
|
SyncDetect = FALSE;
|
SyncDetect = FALSE;
|
|
|
// dec_enbl = 1'b1; // active high
|
// dec_enbl = 1'b1; // active high
|
// dec_reset_n = 1'b1; // active low
|
// dec_reset_n = 1'b1; // active low
|
begin : TimeOutBlock
|
begin : TimeOutBlock
|
forever @(posedge dpll_clk) begin
|
forever @(posedge dpll_clk) begin
|
//if (Debug) $display("In %0s --> waiting for event in WaitForResp %0t", SelfName, $time);
|
//if (Debug) $display("In %0s --> waiting for event in WaitForResp %0t", SelfName, $time);
|
if (TimeOut == TRUE) begin
|
if (TimeOut == TRUE) begin
|
if (tmpTimeOutCounter == TimeOutVal) begin
|
if (tmpTimeOutCounter == TimeOutVal) begin
|
if (Debug) $display("In %0s --> Time out at time %0t", SelfName, $time);
|
if (Debug) $display("In %0s --> Time out at time %0t", SelfName, $time);
|
disable WaitForResp;
|
disable WaitForResp;
|
end
|
end
|
tmpTimeOutCounter = tmpTimeOutCounter + 1;
|
tmpTimeOutCounter = tmpTimeOutCounter + 1;
|
end
|
end
|
//if (Debug) $display("In %0s --> DeviceSpeed = %b at time %0t", SelfName, DeviceSpeed, $time);
|
//if (Debug) $display("In %0s --> DeviceSpeed = %b at time %0t", SelfName, DeviceSpeed, $time);
|
//if (DPLS === 1'b0) begin
|
//if (DPLS === 1'b0) begin
|
if (DPLS === ~DeviceSpeed) begin
|
if (DPLS === ~DeviceSpeed) begin
|
if (Debug) $display("In %0s --> DPLS = %b , DeviceSpeed = %b at time %0t", SelfName, DPLS, DeviceSpeed, $time);
|
if (Debug) $display("In %0s --> DPLS = %b , DeviceSpeed = %b at time %0t", SelfName, DPLS, DeviceSpeed, $time);
|
if (DMNS === DeviceSpeed) begin // differential data
|
if (DMNS === DeviceSpeed) begin // differential data
|
|
|
@DPLS
|
@DPLS
|
StartTime = $time;
|
StartTime = $time;
|
SyncPulseT1 = $time;
|
SyncPulseT1 = $time;
|
@DPLS
|
@DPLS
|
SyncPulseT2 = $time;
|
SyncPulseT2 = $time;
|
@DPLS
|
@DPLS
|
SyncPulseDuration = SyncPulseT2 - SyncPulseT1;
|
SyncPulseDuration = SyncPulseT2 - SyncPulseT1;
|
@DPLS
|
@DPLS
|
SyncPulseT1 = $time;
|
SyncPulseT1 = $time;
|
@DPLS
|
@DPLS
|
SyncPulseT2 = $time;
|
SyncPulseT2 = $time;
|
@DPLS
|
@DPLS
|
#SyncPulseDuration
|
#SyncPulseDuration
|
#SyncPulseDuration
|
#SyncPulseDuration
|
#SyncPulseDuration
|
#SyncPulseDuration
|
|
|
dec_enbl = 1'b1; // active high
|
dec_enbl = 1'b1; // active high
|
dec_reset_n = 1'b1; // active low
|
dec_reset_n = 1'b1; // active low
|
// StartTime = $time; this time should be start of syncpulse
|
// StartTime = $time; this time should be start of syncpulse
|
disable TimeOutBlock;
|
disable TimeOutBlock;
|
end
|
end
|
else if ((DMNS === 1'b0) & (DPLS === 1'b0)) begin
|
else if ((DMNS === 1'b0) & (DPLS === 1'b0)) begin
|
EopDetect = 1;
|
EopDetect = 1;
|
disable TimeOutBlock;
|
disable TimeOutBlock;
|
end
|
end
|
end
|
end
|
end
|
end
|
end // TimeOutBlock
|
end // TimeOutBlock
|
|
|
if (Debug) $display("In %0s --> Decoder enabled at time %0t in host", SelfName, $time);
|
if (Debug) $display("In %0s --> Decoder enabled at time %0t in host", SelfName, $time);
|
fork
|
fork
|
begin : DataSink
|
begin : DataSink
|
forever @(posedge dec_par_data_rdy) begin
|
forever @(posedge dec_par_data_rdy) begin
|
if (FltrSyncFld == 1'b1) begin // filter out the sync field
|
if (FltrSyncFld == 1'b1) begin // filter out the sync field
|
in_out_buf[in_out_buf_ptr] = dec_par_data_out;
|
in_out_buf[in_out_buf_ptr] = dec_par_data_out;
|
in_out_buf_ptr = in_out_buf_ptr + 1;
|
in_out_buf_ptr = in_out_buf_ptr + 1;
|
end
|
end
|
if (dec_par_data_out == {~PREAMBLE, PREAMBLE} &
|
if (dec_par_data_out == {~PREAMBLE, PREAMBLE} &
|
in_out_buf_ptr == 1) begin
|
in_out_buf_ptr == 1) begin
|
dec_enbl = 1'b0;
|
dec_enbl = 1'b0;
|
dec_reset_n = 1'b0;
|
dec_reset_n = 1'b0;
|
StopTime = $time;
|
StopTime = $time;
|
disable WaitForResp;
|
disable WaitForResp;
|
end
|
end
|
if (Debug) $display("In %0s --> receive data = %h", SelfName, dec_par_data_out);
|
if (Debug) $display("In %0s --> receive data = %h", SelfName, dec_par_data_out);
|
if (FltrSyncFld == 1'b0) begin
|
if (FltrSyncFld == 1'b0) begin
|
/*
|
/*
|
if (dec_par_data_out != 8'h80) begin
|
if (dec_par_data_out != 8'h80) begin
|
if (Debug) $display("In %0s --> Incorrect sync field %0h received at time %0t, ...discarding packet", SelfName, dec_par_data_out, $time);
|
if (Debug) $display("In %0s --> Incorrect sync field %0h received at time %0t, ...discarding packet", SelfName, dec_par_data_out, $time);
|
in_out_buf_ptr = 0; // equivalent to a time out
|
in_out_buf_ptr = 0; // equivalent to a time out
|
dec_enbl = 1'b0;
|
dec_enbl = 1'b0;
|
dec_reset_n = 1'b0;
|
dec_reset_n = 1'b0;
|
wait(1==0); // wait while the other block detects a EOP and disables task
|
wait(1==0); // wait while the other block detects a EOP and disables task
|
end
|
end
|
*/
|
*/
|
end
|
end
|
FltrSyncFld = 1'b1;
|
FltrSyncFld = 1'b1;
|
end
|
end
|
end
|
end
|
|
|
forever @(posedge dpll_clk) begin
|
forever @(posedge dpll_clk) begin
|
if (dec_bit_stuff_err == 1'b1) begin
|
if (dec_bit_stuff_err == 1'b1) begin
|
if (OnlyOnce == TRUE) begin
|
if (OnlyOnce == TRUE) begin
|
DispErrMsg(0, 0, 27);
|
DispErrMsg(0, 0, 27);
|
OnlyOnce = FALSE;
|
OnlyOnce = FALSE;
|
in_out_buf_ptr = 0; // reset data pointer
|
in_out_buf_ptr = 0; // reset data pointer
|
end
|
end
|
disable DataSink;
|
disable DataSink;
|
end
|
end
|
if((DPLS == DMNS) & (DPLS == 1'b0)) begin
|
if((DPLS == DMNS) & (DPLS == 1'b0)) begin
|
EopDetect = EopDetect + 1;
|
EopDetect = EopDetect + 1;
|
recv_bit_count = dec_recv_bit_count - 1;
|
recv_bit_count = dec_recv_bit_count - 1;
|
if (StopTime == 0) StopTime = $time;
|
if (StopTime == 0) StopTime = $time;
|
if (SE0StartTime == 0) SE0StartTime = $time;
|
if (SE0StartTime == 0) SE0StartTime = $time;
|
if (Debug) $display("In %0s --> StopTime = %0d, SE0StartTime = %0d", SelfName, StopTime, SE0StartTime);
|
if (Debug) $display("In %0s --> StopTime = %0d, SE0StartTime = %0d", SelfName, StopTime, SE0StartTime);
|
end
|
end
|
if (EopDetect == 1) begin
|
if (EopDetect == 1) begin
|
if (DPLS == ~DMNS) begin // SE0 seen for only 1 bit time
|
if (DPLS == ~DMNS) begin // SE0 seen for only 1 bit time
|
if (Debug) $display("In %0s --> EOP asserted for 1 bit time at time %0t", SelfName, $time);
|
if (Debug) $display("In %0s --> EOP asserted for 1 bit time at time %0t", SelfName, $time);
|
dec_enbl = 1'b0; // disable the decoder
|
dec_enbl = 1'b0; // disable the decoder
|
dec_reset_n = 1'b0; // reset the decoder
|
dec_reset_n = 1'b0; // reset the decoder
|
SE0StopTime = $time;
|
SE0StopTime = $time;
|
disable WaitForResp; // incorrect EOP was received
|
disable WaitForResp; // incorrect EOP was received
|
end
|
end
|
end
|
end
|
if (EopDetect == 2) begin
|
if (EopDetect == 2) begin
|
dec_enbl = 1'b0; // disable the decoder
|
dec_enbl = 1'b0; // disable the decoder
|
dec_reset_n = 1'b0; // reset the decoder
|
dec_reset_n = 1'b0; // reset the decoder
|
if (DPLS == ~DMNS) begin
|
if (DPLS == ~DMNS) begin
|
if (Debug) $display("In %0s --> EOP asserted for 2 bit time at time %0t", SelfName, $time);
|
if (Debug) $display("In %0s --> EOP asserted for 2 bit time at time %0t", SelfName, $time);
|
dec_enbl = 1'b0; // disable the decoder
|
dec_enbl = 1'b0; // disable the decoder
|
dec_reset_n = 1'b0; // reset the decoder
|
dec_reset_n = 1'b0; // reset the decoder
|
SE0StopTime = $time;
|
SE0StopTime = $time;
|
disable WaitForResp; // correct EOP was received
|
disable WaitForResp; // correct EOP was received
|
end
|
end
|
end
|
end
|
if ((EopDetect > 2) & (EopDetect < 32)) begin // incorrect EOP received
|
if ((EopDetect > 2) & (EopDetect < 32)) begin // incorrect EOP received
|
if (DPLS == ~DMNS) begin
|
if (DPLS == ~DMNS) begin
|
if (Debug) $display("In %0s --> EOP asserted for %h bit times at time ", SelfName, EopDetect, $time);
|
if (Debug) $display("In %0s --> EOP asserted for %h bit times at time ", SelfName, EopDetect, $time);
|
SE0StopTime = $time;
|
SE0StopTime = $time;
|
disable WaitForResp;
|
disable WaitForResp;
|
end
|
end
|
end
|
end
|
if (EopDetect >= 32) begin
|
if (EopDetect >= 32) begin
|
if (DPLS == ~DMNS) begin
|
if (DPLS == ~DMNS) begin
|
if (Debug) $display("In %0s --> Reset at time ", SelfName, $time);
|
if (Debug) $display("In %0s --> Reset at time ", SelfName, $time);
|
SE0StopTime = $time;
|
SE0StopTime = $time;
|
in_out_buf_ptr = 0;
|
in_out_buf_ptr = 0;
|
disable WaitForResp;
|
disable WaitForResp;
|
end
|
end
|
end
|
end
|
end
|
end
|
join
|
join
|
|
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// SendReset : asserts a SE0 on the USB for the number of bit times specified
|
// SendReset : asserts a SE0 on the USB for the number of bit times specified
|
// by ResetTime.
|
// by ResetTime.
|
// Input : ResetTime, number of bit times for which to drive a reset on
|
// Input : ResetTime, number of bit times for which to drive a reset on
|
// the USB
|
// the USB
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
task SendReset;
|
task SendReset;
|
|
|
input [7:0] ResetTime;
|
input [7:0] ResetTime;
|
reg [7:0] tskResetTime;
|
reg [7:0] tskResetTime;
|
reg [7:0] tskResetTimeCounter;
|
reg [7:0] tskResetTimeCounter;
|
|
|
begin
|
begin
|
tskResetTime = ResetTime;
|
tskResetTime = ResetTime;
|
//if (tskResetTime <= 32) tskResetTime = 7'b0100000;
|
//if (tskResetTime <= 32) tskResetTime = 7'b0100000;
|
//if (tskResetTime >= 64) tskResetTime = 7'b1000000;
|
//if (tskResetTime >= 64) tskResetTime = 7'b1000000;
|
tskResetTimeCounter = 7'b0000000;
|
tskResetTimeCounter = 7'b0000000;
|
forever @(posedge clk) begin
|
forever @(posedge clk) begin
|
zDPLS = 1'b0;
|
zDPLS = 1'b0;
|
zDMNS = 1'b0;
|
zDMNS = 1'b0;
|
tskResetTimeCounter = tskResetTimeCounter + 1'b1;
|
tskResetTimeCounter = tskResetTimeCounter + 1'b1;
|
if (tskResetTimeCounter > tskResetTime) begin
|
if (tskResetTimeCounter > tskResetTime) begin
|
zDPLS = 1'bz;
|
zDPLS = 1'bz;
|
zDMNS = 1'bz;
|
zDMNS = 1'bz;
|
@(posedge clk);
|
@(posedge clk);
|
@(posedge clk);
|
@(posedge clk);
|
disable SendReset;
|
disable SendReset;
|
end
|
end
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
|
|
|
|
parameter M16 = 16'h8005; //mask value to calculate 16 bit crc
|
parameter M16 = 16'h8005; //mask value to calculate 16 bit crc
|
parameter M05 = 8'h05; //mask value to calculate 5 bit crc
|
parameter M05 = 8'h05; //mask value to calculate 5 bit crc
|
|
|
function [15:0] crc16;
|
function [15:0] crc16;
|
input [7:0] DataByte;
|
input [7:0] DataByte;
|
input [15:0] PrevCrc;
|
input [15:0] PrevCrc;
|
|
|
reg [15:0] TempPrevCrc;
|
reg [15:0] TempPrevCrc;
|
integer i;
|
integer i;
|
|
|
begin
|
begin
|
TempPrevCrc = PrevCrc;
|
TempPrevCrc = PrevCrc;
|
for (i = 0; i < 8; i = i + 1)
|
for (i = 0; i < 8; i = i + 1)
|
begin
|
begin
|
if (DataByte[i] ^ TempPrevCrc[15] )
|
if (DataByte[i] ^ TempPrevCrc[15] )
|
TempPrevCrc = {TempPrevCrc[14:0],1'b0} ^ M16;
|
TempPrevCrc = {TempPrevCrc[14:0],1'b0} ^ M16;
|
else
|
else
|
TempPrevCrc = {TempPrevCrc[14:0], 1'b0};
|
TempPrevCrc = {TempPrevCrc[14:0], 1'b0};
|
end
|
end
|
crc16 = TempPrevCrc;
|
crc16 = TempPrevCrc;
|
end
|
end
|
|
|
endfunction
|
endfunction
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//function crc5 calculates a 5 bit crc
|
//function crc5 calculates a 5 bit crc
|
//inputs :
|
//inputs :
|
// PrevCrc : 5 bit value, initially set to zero by the
|
// PrevCrc : 5 bit value, initially set to zero by the
|
// calling module, from the next call onwards
|
// calling module, from the next call onwards
|
// it is the previous CRC value returned by
|
// it is the previous CRC value returned by
|
// the function.
|
// the function.
|
//
|
//
|
// DataByte : 8 bit value for which crc is to calculated
|
// DataByte : 8 bit value for which crc is to calculated
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
function [4:0] crc5;
|
function [4:0] crc5;
|
input [10:0] DataByte;
|
input [10:0] DataByte;
|
input [4:0] PrevCrc;
|
input [4:0] PrevCrc;
|
|
|
reg [4:0] TempPrevCrc;
|
reg [4:0] TempPrevCrc;
|
integer i;
|
integer i;
|
begin
|
begin
|
TempPrevCrc = PrevCrc;
|
TempPrevCrc = PrevCrc;
|
for (i = 0; i < 11; i = i + 1)
|
for (i = 0; i < 11; i = i + 1)
|
begin
|
begin
|
if (DataByte[i] ^ TempPrevCrc[4] )
|
if (DataByte[i] ^ TempPrevCrc[4] )
|
TempPrevCrc = {TempPrevCrc[3:0],1'b0} ^ M05;
|
TempPrevCrc = {TempPrevCrc[3:0],1'b0} ^ M05;
|
else
|
else
|
TempPrevCrc = {TempPrevCrc[3:0], 1'b0};
|
TempPrevCrc = {TempPrevCrc[3:0], 1'b0};
|
end
|
end
|
crc5 = TempPrevCrc[4:0];
|
crc5 = TempPrevCrc[4:0];
|
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// FillCrc5 : fills with crc5 given a 11 bit value
|
// FillCrc5 : fills with crc5 given a 11 bit value
|
// input : InVal, in value for which crc5 has to be appended
|
// input : InVal, in value for which crc5 has to be appended
|
// this is a 11 bit value for which the 7 LSB bits are address and
|
// this is a 11 bit value for which the 7 LSB bits are address and
|
// 4 MSB bits are end point number
|
// 4 MSB bits are end point number
|
// returns : 16 bit value for which is InVal with crc5 appended to it.
|
// returns : 16 bit value for which is InVal with crc5 appended to it.
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
function [15:0] FillCrc5;
|
function [15:0] FillCrc5;
|
input [10:0] InVal;
|
input [10:0] InVal;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
begin
|
begin
|
tmpReg[10:0] = InVal; // put address and EndPt into consecutive bits
|
tmpReg[10:0] = InVal; // put address and EndPt into consecutive bits
|
tmpReg[15:11] = crc5(InVal, 5'b11111); // calculate crc5 for the first 8 bits
|
tmpReg[15:11] = crc5(InVal, 5'b11111); // calculate crc5 for the first 8 bits
|
|
|
tmpReg[15:11] ={tmpReg[11], tmpReg[12], tmpReg[13], tmpReg[14], tmpReg[15]};
|
tmpReg[15:11] ={tmpReg[11], tmpReg[12], tmpReg[13], tmpReg[14], tmpReg[15]};
|
tmpReg[6:0] = InVal[6:0]; // address
|
tmpReg[6:0] = InVal[6:0]; // address
|
tmpReg[10:7] = InVal[10:7]; // End Point
|
tmpReg[10:7] = InVal[10:7]; // End Point
|
if (GenCrc5Err == FALSE) tmpReg[15:11] = ~tmpReg[15:11];
|
if (GenCrc5Err == FALSE) tmpReg[15:11] = ~tmpReg[15:11];
|
// invert the bits in the crc
|
// invert the bits in the crc
|
tmpReg[15:11] = CorruptCrc5(tmpReg[15:11]); // crc5 corruption
|
tmpReg[15:11] = CorruptCrc5(tmpReg[15:11]); // crc5 corruption
|
FillCrc5 = tmpReg;
|
FillCrc5 = tmpReg;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// FillCrc16 : Calculates the crc16 value from in_out_buf
|
// FillCrc16 : Calculates the crc16 value from in_out_buf
|
// input : StartAddr : start address of in_out_buf, 32 bits
|
// input : StartAddr : start address of in_out_buf, 32 bits
|
// StopAddr : stop address of in_out_buf, 32 bits
|
// StopAddr : stop address of in_out_buf, 32 bits
|
// returns : 16 bit value which is the crc16 for this segment of memory
|
// returns : 16 bit value which is the crc16 for this segment of memory
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
function [16:0] FillCrc16;
|
function [16:0] FillCrc16;
|
|
|
input [31:0] StartAddr;
|
input [31:0] StartAddr;
|
input [31:0] StopAddr;
|
input [31:0] StopAddr;
|
|
|
reg [16:0] tmpCrc;
|
reg [16:0] tmpCrc;
|
integer i;
|
integer i;
|
|
|
begin
|
begin
|
tmpCrc = 16'hffff;
|
tmpCrc = 16'hffff;
|
for (i = StartAddr; i <= StopAddr; i = i + 1) begin
|
for (i = StartAddr; i <= StopAddr; i = i + 1) begin
|
tmpCrc = crc16(in_out_buf[i], tmpCrc);
|
tmpCrc = crc16(in_out_buf[i], tmpCrc);
|
end
|
end
|
FillCrc16 = tmpCrc;
|
FillCrc16 = tmpCrc;
|
end
|
end
|
endfunction
|
endfunction
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// SendAck : sends an ack
|
// SendAck : sends an ack
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task SendAck;
|
task SendAck;
|
|
|
begin
|
begin
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
in_out_buf[0] = CorruptHshk({~ACK, ACK});
|
in_out_buf[0] = CorruptHshk({~ACK, ACK});
|
in_out_buf_ptr = 1;
|
in_out_buf_ptr = 1;
|
SetSyncLevel = 2;
|
SetSyncLevel = 2;
|
usb_idle(ResponseLatency - 3);
|
usb_idle(ResponseLatency - 3);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
SendData;
|
SendData;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// reset : performs a reset on the USB bus by driving SE0
|
// reset : performs a reset on the USB bus by driving SE0
|
//
|
//
|
// input : Reset Time in bit times
|
// input : Reset Time in bit times
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task usb_reset;
|
task usb_reset;
|
|
|
input [7:0] tskResetTime;
|
input [7:0] tskResetTime;
|
|
|
begin
|
begin
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
NumResets = NumResets + 1;
|
NumResets = NumResets + 1;
|
SendReset(tskResetTime);
|
SendReset(tskResetTime);
|
WriteResults;
|
WriteResults;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
// usb_idle : idles the USB.
|
// usb_idle : idles the USB.
|
// input : IdleTime, which is the number of bit times for which to idle the
|
// input : IdleTime, which is the number of bit times for which to idle the
|
// bus.
|
// bus.
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task usb_idle;
|
task usb_idle;
|
input [31:0] IdleTime;
|
input [31:0] IdleTime;
|
reg [31:0] tskIdleTime;
|
reg [31:0] tskIdleTime;
|
|
|
begin : usb_idle
|
begin : usb_idle
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
tskIdleTime = 0;
|
tskIdleTime = 0;
|
forever @(posedge clk) begin
|
forever @(posedge clk) begin
|
if (tskIdleTime >= IdleTime) begin
|
if (tskIdleTime >= IdleTime) begin
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable usb_idle;
|
disable usb_idle;
|
end
|
end
|
tskIdleTime = tskIdleTime + 1;
|
tskIdleTime = tskIdleTime + 1;
|
end
|
end
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// task usb_idle_nolock : same as usb_idle except that there is no lock
|
// task usb_idle_nolock : same as usb_idle except that there is no lock
|
// that is there is no assertion of the task_in_progress
|
// that is there is no assertion of the task_in_progress
|
// flag
|
// flag
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
task usb_idle_nolock;
|
task usb_idle_nolock;
|
input [31:0] IdleTime;
|
input [31:0] IdleTime;
|
reg [31:0] tskIdleTime;
|
reg [31:0] tskIdleTime;
|
begin : usb_idle_nolock
|
begin : usb_idle_nolock
|
tskIdleTime = 0;
|
tskIdleTime = 0;
|
forever @(posedge clk) begin
|
forever @(posedge clk) begin
|
if (tskIdleTime >= IdleTime) begin
|
if (tskIdleTime >= IdleTime) begin
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable usb_idle_nolock;
|
disable usb_idle_nolock;
|
end
|
end
|
tskIdleTime = tskIdleTime + 1;
|
tskIdleTime = tskIdleTime + 1;
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// setup : issues a setup token with the corresponding data
|
// setup : issues a setup token with the corresponding data
|
// inputs : address : address of the device, 7 bits
|
// inputs : address : address of the device, 7 bits
|
// EndPt : end point number, 4 bits
|
// EndPt : end point number, 4 bits
|
// outputs : Status : returns the status of the transaction, 4 bits
|
// outputs : Status : returns the status of the transaction, 4 bits
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task setup;
|
task setup;
|
|
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
|
|
output [3:0] Status; // 0 : ack received
|
output [3:0] Status; // 0 : ack received
|
// 3 : no response
|
// 3 : no response
|
// 4 : invalid response
|
// 4 : invalid response
|
// 6 : another control transaction in progress
|
// 6 : another control transaction in progress
|
// 8 : invalid control data
|
// 8 : invalid control data
|
reg [3:0] Status;
|
reg [3:0] Status;
|
reg [15:0] tmpCrc;
|
reg [15:0] tmpCrc;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
integer i;
|
integer i;
|
integer CntrlNum; // number of the control transaction
|
integer CntrlNum; // number of the control transaction
|
reg [31:0] recv_bit_count;
|
reg [31:0] recv_bit_count;
|
reg Match;
|
reg Match;
|
reg [31:0] tmpPulseWidth;
|
reg [31:0] tmpPulseWidth;
|
|
|
// eight bytes of setup data is assumed to be in Xmitbuffer
|
// eight bytes of setup data is assumed to be in Xmitbuffer
|
begin : setup
|
begin : setup
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
tmpPulseWidth = PulseWidth;
|
tmpPulseWidth = PulseWidth;
|
Match = FALSE;
|
Match = FALSE;
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
if ((address == CntrlTransAddr[i]) & (EndPt == CntrlTransEndP[i])) begin
|
if ((address == CntrlTransAddr[i]) & (EndPt == CntrlTransEndP[i])) begin
|
Status = 4'b0110;
|
Status = 4'b0110;
|
disable setup;
|
disable setup;
|
end
|
end
|
end
|
end
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
if (CntrlTransType[i] == 2'b00) begin
|
if (CntrlTransType[i] == 2'b00) begin
|
Match = TRUE;
|
Match = TRUE;
|
CntrlTransAddr[i] = address;
|
CntrlTransAddr[i] = address;
|
CntrlTransEndP[i] = EndPt;
|
CntrlTransEndP[i] = EndPt;
|
CntrlTransDlen[i] = {XmitBuffer[7], XmitBuffer[6]};
|
CntrlTransDlen[i] = {XmitBuffer[7], XmitBuffer[6]};
|
CntrlNum = i;
|
CntrlNum = i;
|
i = MAX_CNTRL_INTERLEAVE + 1;
|
i = MAX_CNTRL_INTERLEAVE + 1;
|
end
|
end
|
end
|
end
|
if (Match == FALSE) begin
|
if (Match == FALSE) begin
|
Status = 6; // only one control transaction in progress
|
Status = 6; // only one control transaction in progress
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable setup;
|
disable setup;
|
end
|
end
|
|
|
usb_idle(ResponseLatency - 3); // #27
|
usb_idle(ResponseLatency - 3); // #27
|
if ((SendPreamble == TRUE) & (DeviceSpeed == HIGH_SPEED)) begin
|
if ((SendPreamble == TRUE) & (DeviceSpeed == HIGH_SPEED)) begin
|
send_preamble; // a high speed preamble is sent only when a high speed
|
send_preamble; // a high speed preamble is sent only when a high speed
|
// hub is connected to the host model so in this case
|
// hub is connected to the host model so in this case
|
// switch clock speeds
|
// switch clock speeds
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
usb_idle(4); // idle for 4 high speed clock times after a preamble
|
usb_idle(4); // idle for 4 high speed clock times after a preamble
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
// PulseWidth = PulseWidth * 8; // decrease the clock frequency
|
// PulseWidth = PulseWidth * 8; // decrease the clock frequency
|
clk_swtch = LOW_SPEED;
|
clk_swtch = LOW_SPEED;
|
end
|
end
|
|
|
in_out_buf[0] = CorruptToken({~SETUP_TOKEN, SETUP_TOKEN});
|
in_out_buf[0] = CorruptToken({~SETUP_TOKEN, SETUP_TOKEN});
|
|
|
tmpReg = FillCrc5({EndPt, address});
|
tmpReg = FillCrc5({EndPt, address});
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf_ptr = 3;
|
in_out_buf_ptr = 3;
|
SetSyncLevel = 0;
|
SetSyncLevel = 0;
|
// usb_idle(ResponseLatency - 3); #27
|
// usb_idle(ResponseLatency - 3); #27
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
|
|
SendData;
|
SendData;
|
|
|
usb_idle(ResponseLatency - 3); // #27
|
usb_idle(ResponseLatency - 3); // #27
|
|
|
send_high_speed_preamble;
|
send_high_speed_preamble;
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
in_out_buf[0] = CorruptDataPid({~DATA0, DATA0});
|
in_out_buf[0] = CorruptDataPid({~DATA0, DATA0});
|
tmpCrc = 16'hffff;
|
tmpCrc = 16'hffff;
|
for (i = 1; i <= SetupDataLen; i = i + 1) begin
|
for (i = 1; i <= SetupDataLen; i = i + 1) begin
|
in_out_buf[i] = XmitBuffer[i - 1];
|
in_out_buf[i] = XmitBuffer[i - 1];
|
tmpCrc = crc16(in_out_buf[i], tmpCrc);
|
tmpCrc = crc16(in_out_buf[i], tmpCrc);
|
end
|
end
|
//if (Debug) $display("In %0s raw crc is %h at time %0t", SelfName, tmpCrc, $time);
|
//if (Debug) $display("In %0s raw crc is %h at time %0t", SelfName, tmpCrc, $time);
|
tmpCrc = CorruptCrc16(~{swap8(tmpCrc[15:8]), swap8(tmpCrc[7:0])});
|
tmpCrc = CorruptCrc16(~{swap8(tmpCrc[15:8]), swap8(tmpCrc[7:0])});
|
in_out_buf[9] = tmpCrc[15:8];
|
in_out_buf[9] = tmpCrc[15:8];
|
in_out_buf[10] = tmpCrc[7:0];
|
in_out_buf[10] = tmpCrc[7:0];
|
//if (Debug) $display("In %0s bus crc is %h at time %0t", SelfName, {in_out_buf[9], in_out_buf[10]}, $time);
|
//if (Debug) $display("In %0s bus crc is %h at time %0t", SelfName, {in_out_buf[9], in_out_buf[10]}, $time);
|
in_out_buf_ptr = SetupDataLen + 3;
|
in_out_buf_ptr = SetupDataLen + 3;
|
SetSyncLevel = 1;
|
SetSyncLevel = 1;
|
// usb_idle(ResponseLatency - 3); #27
|
// usb_idle(ResponseLatency - 3); #27
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
SendData;
|
SendData;
|
tmpReg[7:0] = XmitBuffer[0];
|
tmpReg[7:0] = XmitBuffer[0];
|
//if (Debug) $display("In %0s --> tmpReg = %b at time %0t", SelfName, tmpReg[7:0], $time);
|
//if (Debug) $display("In %0s --> tmpReg = %b at time %0t", SelfName, tmpReg[7:0], $time);
|
case(tmpReg[7])
|
case(tmpReg[7])
|
1'b1 : CntrlTransType[CntrlNum] = READ;
|
1'b1 : CntrlTransType[CntrlNum] = READ;
|
1'b0 : CntrlTransType[CntrlNum] = WRITE;
|
1'b0 : CntrlTransType[CntrlNum] = WRITE;
|
default : begin
|
default : begin
|
Status = 8; // invalid control data
|
Status = 8; // invalid control data
|
in_out_buf_ptr = 0;
|
in_out_buf_ptr = 0;
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable setup;
|
disable setup;
|
end
|
end
|
endcase
|
endcase
|
|
|
if (tmpReg[7] == 1'b1) NumCntrlRdTrans = NumCntrlRdTrans + 1;
|
if (tmpReg[7] == 1'b1) NumCntrlRdTrans = NumCntrlRdTrans + 1;
|
else NumCntrlWrTrans = NumCntrlWrTrans + 1;
|
else NumCntrlWrTrans = NumCntrlWrTrans + 1;
|
|
|
if (Debug) $display("CntrlTransType = %b", CntrlTransType[CntrlNum]);
|
if (Debug) $display("CntrlTransType = %b", CntrlTransType[CntrlNum]);
|
|
|
|
|
WaitForResp(recv_bit_count);
|
WaitForResp(recv_bit_count);
|
if (Debug) $display("In %0s --> in_out_buf[0] = %b, in_out_buf_ptr = %d", SelfName, in_out_buf[0], in_out_buf_ptr);
|
if (Debug) $display("In %0s --> in_out_buf[0] = %b, in_out_buf_ptr = %d", SelfName, in_out_buf[0], in_out_buf_ptr);
|
case (in_out_buf_ptr)
|
case (in_out_buf_ptr)
|
0 : begin // time out
|
0 : begin // time out
|
if (dec_bit_stuff_err == TRUE) begin
|
if (dec_bit_stuff_err == TRUE) begin
|
usb_idle(RespTimeOutVal);
|
usb_idle(RespTimeOutVal);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
end
|
end
|
Status = 3;
|
Status = 3;
|
CntrlTransType[CntrlNum] = 2'b00; // clear the transaction in progress flag
|
CntrlTransType[CntrlNum] = 2'b00; // clear the transaction in progress flag
|
CntrlTransAddr[CntrlNum] = 7'b1111111;
|
CntrlTransAddr[CntrlNum] = 7'b1111111;
|
CntrlTransEndP[CntrlNum] = 4'b1111;
|
CntrlTransEndP[CntrlNum] = 4'b1111;
|
CntrlTransDlen[CntrlNum] = 0;
|
CntrlTransDlen[CntrlNum] = 0;
|
end
|
end
|
1 : begin
|
1 : begin
|
if (in_out_buf[0] == {~ACK, ACK}) begin
|
if (in_out_buf[0] == {~ACK, ACK}) begin
|
Status = 0; //setup initiated successfully
|
Status = 0; //setup initiated successfully
|
SetDataToggle(address, EndPt, 2'b11);
|
SetDataToggle(address, EndPt, 2'b11);
|
end
|
end
|
else begin
|
else begin
|
Status = 4; // invalid response
|
Status = 4; // invalid response
|
CntrlTransType[CntrlNum] = 2'b00;
|
CntrlTransType[CntrlNum] = 2'b00;
|
// clear the transaction in progress flag
|
// clear the transaction in progress flag
|
CntrlTransAddr[CntrlNum] = 7'b1111111;
|
CntrlTransAddr[CntrlNum] = 7'b1111111;
|
CntrlTransEndP[CntrlNum] = 4'b1111;
|
CntrlTransEndP[CntrlNum] = 4'b1111;
|
CntrlTransDlen[CntrlNum] = 0;
|
CntrlTransDlen[CntrlNum] = 0;
|
end
|
end
|
end
|
end
|
default : begin
|
default : begin
|
Status = 4; // invalid response
|
Status = 4; // invalid response
|
CntrlTransType[CntrlNum] = 2'b00;
|
CntrlTransType[CntrlNum] = 2'b00;
|
// clear the transaction in progress flag
|
// clear the transaction in progress flag
|
CntrlTransAddr[CntrlNum] = 7'b1111111;
|
CntrlTransAddr[CntrlNum] = 7'b1111111;
|
CntrlTransEndP[CntrlNum] = 4'b1111;
|
CntrlTransEndP[CntrlNum] = 4'b1111;
|
CntrlTransDlen[CntrlNum] = 0;
|
CntrlTransDlen[CntrlNum] = 0;
|
end
|
end
|
endcase
|
endcase
|
WriteResults;
|
WriteResults;
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// control_IN : does the data phase in a control transaction initiated by
|
// control_IN : does the data phase in a control transaction initiated by
|
// a call to setup
|
// a call to setup
|
// output : ByteCount : number of bytes received during this control_in
|
// output : ByteCount : number of bytes received during this control_in
|
// Status : Exit Status of this task
|
// Status : Exit Status of this task
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
task control_IN;
|
task control_IN;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
output [31:0] ByteCount;
|
output [31:0] ByteCount;
|
output [3:0] Status;
|
output [3:0] Status;
|
|
|
reg [3:0] Status;
|
reg [3:0] Status;
|
reg [31:0] tskByteCount;
|
reg [31:0] tskByteCount;
|
reg [31:0] recv_bit_count;
|
reg [31:0] recv_bit_count;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpCrc;
|
reg [15:0] tmpCrc;
|
integer i;
|
integer i;
|
integer CntrlNum;
|
integer CntrlNum;
|
reg tmpDataToggle;
|
reg tmpDataToggle;
|
reg [31:0] tmpPulseWidth;
|
reg [31:0] tmpPulseWidth;
|
|
|
begin : control_IN
|
begin : control_IN
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
ByteCount = 0;
|
ByteCount = 0;
|
tmpPulseWidth = PulseWidth;
|
tmpPulseWidth = PulseWidth;
|
CntrlNum = 0;
|
CntrlNum = 0;
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
if ((CntrlTransType[i] != 2'b00) & (CntrlTransAddr[i] == address) & (CntrlTransEndP[i] == EndPt)) begin
|
if ((CntrlTransType[i] != 2'b00) & (CntrlTransAddr[i] == address) & (CntrlTransEndP[i] == EndPt)) begin
|
CntrlNum = i;
|
CntrlNum = i;
|
i = MAX_CNTRL_INTERLEAVE + 1;
|
i = MAX_CNTRL_INTERLEAVE + 1;
|
end
|
end
|
end
|
end
|
if (Debug) $display("CntrlTransType = %b", CntrlTransType[CntrlNum]);
|
if (Debug) $display("CntrlTransType = %b", CntrlTransType[CntrlNum]);
|
if (CntrlNum == 0) begin
|
if (CntrlNum == 0) begin
|
DispErrMsg(0, 0, 21);
|
DispErrMsg(0, 0, 21);
|
Status = 7;
|
Status = 7;
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable control_IN;
|
disable control_IN;
|
end
|
end
|
if (CntrlTransType[CntrlNum] == 2'b00) begin // redundant ??
|
if (CntrlTransType[CntrlNum] == 2'b00) begin // redundant ??
|
DispErrMsg(0, 0, 21);
|
DispErrMsg(0, 0, 21);
|
Status = 7; // no setup transaction in progress to do a control_in xfer
|
Status = 7; // no setup transaction in progress to do a control_in xfer
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable control_IN;
|
disable control_IN;
|
end
|
end
|
|
|
if (CntrlTransType[CntrlNum] != READ) begin
|
if (CntrlTransType[CntrlNum] != READ) begin
|
DispErrMsg(0, 0, 22);
|
DispErrMsg(0, 0, 22);
|
Status = 9; // wrong type of control transaction
|
Status = 9; // wrong type of control transaction
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable control_IN;
|
disable control_IN;
|
end
|
end
|
|
|
|
|
if ((SendPreamble == TRUE) & (DeviceSpeed == HIGH_SPEED)) begin
|
if ((SendPreamble == TRUE) & (DeviceSpeed == HIGH_SPEED)) begin
|
clk_swtch = LOW_SPEED; // #27
|
clk_swtch = LOW_SPEED; // #27
|
usb_idle(ResponseLatency - 3); // #27
|
usb_idle(ResponseLatency - 3); // #27
|
clk_swtch = HIGH_SPEED; // #27
|
clk_swtch = HIGH_SPEED; // #27
|
send_preamble; // a high speed preamble is sent only when a high speed
|
send_preamble; // a high speed preamble is sent only when a high speed
|
// hub is connected to the host model so in this case
|
// hub is connected to the host model so in this case
|
// switch clock speeds
|
// switch clock speeds
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
usb_idle(4); // idle for 4 high speed clock times after a preamble
|
usb_idle(4); // idle for 4 high speed clock times after a preamble
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
// PulseWidth = PulseWidth * 8;
|
// PulseWidth = PulseWidth * 8;
|
clk_swtch = LOW_SPEED;
|
clk_swtch = LOW_SPEED;
|
end
|
end
|
|
|
in_out_buf[0] = CorruptToken({~IN_TOKEN, IN_TOKEN});
|
in_out_buf[0] = CorruptToken({~IN_TOKEN, IN_TOKEN});
|
in_out_buf_ptr = 1;
|
in_out_buf_ptr = 1;
|
|
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
|
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf_ptr = 3;
|
in_out_buf_ptr = 3;
|
SetSyncLevel = 0;
|
SetSyncLevel = 0;
|
// usb_idle(ResponseLatency - 3); #27
|
// usb_idle(ResponseLatency - 3); #27
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
SendData; //serialises, encodes and sends the data in in_out_buf,
|
SendData; //serialises, encodes and sends the data in in_out_buf,
|
|
|
WaitForResp(recv_bit_count);
|
WaitForResp(recv_bit_count);
|
@(posedge dpll_clk); // 10/10/97
|
@(posedge dpll_clk); // 10/10/97
|
case(in_out_buf_ptr)
|
case(in_out_buf_ptr)
|
0 : begin // no response from device abort control transaction
|
0 : begin // no response from device abort control transaction
|
Status = 3;
|
Status = 3;
|
if (Debug) $display("In %0s --> time out for control_in transaction at time %0t", SelfName, $time);
|
if (Debug) $display("In %0s --> time out for control_in transaction at time %0t", SelfName, $time);
|
end
|
end
|
1 : begin
|
1 : begin
|
tmpReg[7:0] = in_out_buf[0]; //should contain the pid
|
tmpReg[7:0] = in_out_buf[0]; //should contain the pid
|
if (tmpReg[7:4] != (~tmpReg[3:0])) begin
|
if (tmpReg[7:4] != (~tmpReg[3:0])) begin
|
DispErrMsg(address, EndPt, 5);
|
DispErrMsg(address, EndPt, 5);
|
end
|
end
|
if (tmpReg[3:0] == NAK) begin
|
if (tmpReg[3:0] == NAK) begin
|
DispErrMsg(address, EndPt, 11);
|
DispErrMsg(address, EndPt, 11);
|
Status = 1; //NAK received from end point
|
Status = 1; //NAK received from end point
|
end
|
end
|
if (tmpReg[3:0] == STALL) begin
|
if (tmpReg[3:0] == STALL) begin
|
DispErrMsg(address, EndPt, 12);
|
DispErrMsg(address, EndPt, 12);
|
Status = 2; //STALL received from end point
|
Status = 2; //STALL received from end point
|
end
|
end
|
end
|
end
|
2 : begin
|
2 : begin
|
DispErrMsg(address, EndPt, 6); // invalid number of data bytes received
|
DispErrMsg(address, EndPt, 6); // invalid number of data bytes received
|
Status = 4; //invalid response
|
Status = 4; //invalid response
|
end
|
end
|
default : begin
|
default : begin
|
tmpReg[7:0] = in_out_buf[0]; //should contain the pid
|
tmpReg[7:0] = in_out_buf[0]; //should contain the pid
|
if (tmpReg[7:4] != (~tmpReg[3:0])) begin
|
if (tmpReg[7:4] != (~tmpReg[3:0])) begin
|
DispErrMsg(address, EndPt, 5);
|
DispErrMsg(address, EndPt, 5);
|
end
|
end
|
if (Debug) $display("In %0s --> Data toggle recevied is %0b at time %0t", SelfName, tmpReg[7:0], $time);
|
if (Debug) $display("In %0s --> Data toggle recevied is %0b at time %0t", SelfName, tmpReg[7:0], $time);
|
ByteCount = 0;
|
ByteCount = 0;
|
tmpCrc = 16'hffff;
|
tmpCrc = 16'hffff;
|
//if (Debug) $display("In %0s --> calculating crc for in_out_buf[%0d] = %0h", SelfName, i, in_out_buf[i]);
|
//if (Debug) $display("In %0s --> calculating crc for in_out_buf[%0d] = %0h", SelfName, i, in_out_buf[i]);
|
for (i = 1; i < (in_out_buf_ptr - 2); i = i + 1) begin
|
for (i = 1; i < (in_out_buf_ptr - 2); i = i + 1) begin
|
tmpCrc = crc16(in_out_buf[i], tmpCrc);
|
tmpCrc = crc16(in_out_buf[i], tmpCrc);
|
RecvBuffer[i - 1] = in_out_buf[i];
|
RecvBuffer[i - 1] = in_out_buf[i];
|
ByteCount = ByteCount + 1;
|
ByteCount = ByteCount + 1;
|
if (Debug) $display("In %0s --> received byte[%0d] = %b", SelfName, i, in_out_buf[i]);
|
if (Debug) $display("In %0s --> received byte[%0d] = %b", SelfName, i, in_out_buf[i]);
|
end
|
end
|
if (Debug) $display("In %0s --> calculated crc is %0h at time %0t.", SelfName, tmpCrc, $time);
|
if (Debug) $display("In %0s --> calculated crc is %0h at time %0t.", SelfName, tmpCrc, $time);
|
if (Debug) $display("In %0s --> received raw crc is %0h at time %0t.", SelfName, {swap8(~in_out_buf[in_out_buf_ptr - 2]), swap8(~in_out_buf[in_out_buf_ptr - 1])}, $time);
|
if (Debug) $display("In %0s --> received raw crc is %0h at time %0t.", SelfName, {swap8(~in_out_buf[in_out_buf_ptr - 2]), swap8(~in_out_buf[in_out_buf_ptr - 1])}, $time);
|
tmpCrc = CorruptCrc16(~{swap8(tmpCrc[15:8]), swap8(tmpCrc[7:0])});
|
tmpCrc = CorruptCrc16(~{swap8(tmpCrc[15:8]), swap8(tmpCrc[7:0])});
|
if (Debug) $display("In %0s --> received crc is %0h at time %0t.", SelfName, {in_out_buf[in_out_buf_ptr - 2], in_out_buf[in_out_buf_ptr - 1]}, $time);
|
if (Debug) $display("In %0s --> received crc is %0h at time %0t.", SelfName, {in_out_buf[in_out_buf_ptr - 2], in_out_buf[in_out_buf_ptr - 1]}, $time);
|
|
|
//ByteCount = ByteCount + 1;
|
//ByteCount = ByteCount + 1;
|
if (Debug) $display("In %0s --> tmpCrc %0h, at time %0t", SelfName, tmpCrc, $time);
|
if (Debug) $display("In %0s --> tmpCrc %0h, at time %0t", SelfName, tmpCrc, $time);
|
if (tmpCrc != {in_out_buf[in_out_buf_ptr - 2], in_out_buf[in_out_buf_ptr - 1]}) begin
|
if (tmpCrc != {in_out_buf[in_out_buf_ptr - 2], in_out_buf[in_out_buf_ptr - 1]}) begin
|
DispErrMsg(address, EndPt, 8); //CRC Error, send no response
|
DispErrMsg(address, EndPt, 8); //CRC Error, send no response
|
Status = 5;
|
Status = 5;
|
usb_idle(RespTimeOutVal);
|
usb_idle(RespTimeOutVal);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
end
|
end
|
else begin
|
else begin
|
case (tmpReg[3:0]) //check the token
|
case (tmpReg[3:0]) //check the token
|
DATA0 : begin
|
DATA0 : begin
|
if(CheckDataToggleIN(address, EndPt) != 0) begin
|
if(CheckDataToggleIN(address, EndPt) != 0) begin
|
DispErrMsg(address, EndPt, 10);
|
DispErrMsg(address, EndPt, 10);
|
ByteCount = 0; // discard data
|
ByteCount = 0; // discard data
|
end
|
end
|
SetDataToggle(address, EndPt, 2'b11);
|
SetDataToggle(address, EndPt, 2'b11);
|
//usb_idle(ResponseLatency - 3); // #27
|
//usb_idle(ResponseLatency - 3); // #27
|
send_high_speed_preamble;
|
send_high_speed_preamble;
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
SendAck;
|
SendAck;
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
Status = 0;
|
Status = 0;
|
if (Debug) $display("In %0s --> sending ACK at time %0t", SelfName, $time);
|
if (Debug) $display("In %0s --> sending ACK at time %0t", SelfName, $time);
|
end
|
end
|
DATA1 : begin
|
DATA1 : begin
|
if(CheckDataToggleIN(address, EndPt) != 1) begin
|
if(CheckDataToggleIN(address, EndPt) != 1) begin
|
DispErrMsg(address, EndPt, 10);
|
DispErrMsg(address, EndPt, 10);
|
ByteCount = 0; // discard data
|
ByteCount = 0; // discard data
|
end
|
end
|
SetDataToggle(address, EndPt, 2'b00);
|
SetDataToggle(address, EndPt, 2'b00);
|
//usb_idle(ResponseLatency - 3);
|
//usb_idle(ResponseLatency - 3);
|
send_high_speed_preamble;
|
send_high_speed_preamble;
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
SendAck;
|
SendAck;
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
Status = 0;
|
Status = 0;
|
if (Debug) $display("In %0s --> sending ACK at time %0t", SelfName, $time);
|
if (Debug) $display("In %0s --> sending ACK at time %0t", SelfName, $time);
|
end
|
end
|
default : begin
|
default : begin
|
Status = 4;
|
Status = 4;
|
ByteCount = 0; // discard data
|
ByteCount = 0; // discard data
|
DispErrMsg(address, EndPt, 9); //incorrect token
|
DispErrMsg(address, EndPt, 9); //incorrect token
|
end
|
end
|
endcase
|
endcase
|
end //if (tmpCrc ...
|
end //if (tmpCrc ...
|
end // default :
|
end // default :
|
endcase
|
endcase
|
|
|
if (ByteCount > CntrlTransDlen[CntrlNum]) begin
|
if (ByteCount > CntrlTransDlen[CntrlNum]) begin
|
CntrlTransDlen[CntrlNum] = 0;
|
CntrlTransDlen[CntrlNum] = 0;
|
DispErrMsg(address, EndPt, 20);
|
DispErrMsg(address, EndPt, 20);
|
end
|
end
|
if (Status == 0) CntrlTransDlen[CntrlNum] = CntrlTransDlen[CntrlNum] - ByteCount;
|
if (Status == 0) CntrlTransDlen[CntrlNum] = CntrlTransDlen[CntrlNum] - ByteCount;
|
WriteResults;
|
WriteResults;
|
// PulseWidth = tmpPulseWidth;
|
// PulseWidth = tmpPulseWidth;
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// control_OUT : does the data phase in control transaction intiated by a setup
|
// control_OUT : does the data phase in control transaction intiated by a setup
|
// input : ByteCount, number of bytes from XmitBuffer to send
|
// input : ByteCount, number of bytes from XmitBuffer to send
|
// Status : exit status
|
// Status : exit status
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task control_OUT;
|
task control_OUT;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
input [31:0] ByteCount;
|
input [31:0] ByteCount;
|
output [3:0] Status;
|
output [3:0] Status;
|
|
|
reg [3:0] Status;
|
reg [3:0] Status;
|
reg [31:0] tskByteCount;
|
reg [31:0] tskByteCount;
|
reg [31:0] recv_bit_count;
|
reg [31:0] recv_bit_count;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpCrc;
|
reg [15:0] tmpCrc;
|
integer i;
|
integer i;
|
integer CntrlNum;
|
integer CntrlNum;
|
reg tmpDataToggle;
|
reg tmpDataToggle;
|
reg [31:0] tmpPulseWidth;
|
reg [31:0] tmpPulseWidth;
|
|
|
begin : control_OUT
|
begin : control_OUT
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
tmpPulseWidth = PulseWidth;
|
tmpPulseWidth = PulseWidth;
|
CntrlNum = 0;
|
CntrlNum = 0;
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
if ((CntrlTransType[i] != 2'b00) & (CntrlTransAddr[i] == address) & (CntrlTransEndP[i] == EndPt)) begin
|
if ((CntrlTransType[i] != 2'b00) & (CntrlTransAddr[i] == address) & (CntrlTransEndP[i] == EndPt)) begin
|
CntrlNum = i;
|
CntrlNum = i;
|
i = MAX_CNTRL_INTERLEAVE + 1;
|
i = MAX_CNTRL_INTERLEAVE + 1;
|
end
|
end
|
end
|
end
|
if (CntrlNum == 0) begin
|
if (CntrlNum == 0) begin
|
DispErrMsg(0, 0, 21);
|
DispErrMsg(0, 0, 21);
|
Status = 7;
|
Status = 7;
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable control_OUT;
|
disable control_OUT;
|
end
|
end
|
|
|
if (CntrlTransType[CntrlNum] == 2'b00) begin
|
if (CntrlTransType[CntrlNum] == 2'b00) begin
|
DispErrMsg(0, 0, 21);
|
DispErrMsg(0, 0, 21);
|
Status = 7; // no setup transaction in progress to do a control_in xfer
|
Status = 7; // no setup transaction in progress to do a control_in xfer
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable control_OUT;
|
disable control_OUT;
|
end
|
end
|
|
|
if (CntrlTransType[CntrlNum] != WRITE) begin
|
if (CntrlTransType[CntrlNum] != WRITE) begin
|
DispErrMsg(0, 0, 22);
|
DispErrMsg(0, 0, 22);
|
Status = 9; // wrong type of control transaction
|
Status = 9; // wrong type of control transaction
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable control_OUT;
|
disable control_OUT;
|
end
|
end
|
|
|
if (CntrlTransDlen[CntrlNum] == 0) begin
|
if (CntrlTransDlen[CntrlNum] == 0) begin
|
DispErrMsg(0, 0, 23);
|
DispErrMsg(0, 0, 23);
|
Status = 10; // doing a control transaction when wLength is 0
|
Status = 10; // doing a control transaction when wLength is 0
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable control_OUT;
|
disable control_OUT;
|
end
|
end
|
// no setup transaction in progress so start a control_in transaction
|
// no setup transaction in progress so start a control_in transaction
|
|
|
usb_idle(ResponseLatency - 3);
|
usb_idle(ResponseLatency - 3);
|
|
|
if ((DeviceSpeed == HIGH_SPEED) & (SendPreamble == TRUE)) begin
|
if ((DeviceSpeed == HIGH_SPEED) & (SendPreamble == TRUE)) begin
|
clk_swtch = LOW_SPEED; // #27
|
clk_swtch = LOW_SPEED; // #27
|
usb_idle(ResponseLatency - 3); // #27
|
usb_idle(ResponseLatency - 3); // #27
|
clk_swtch = HIGH_SPEED; // #27
|
clk_swtch = HIGH_SPEED; // #27
|
send_preamble; // a high speed preamble is sent only when a high speed
|
send_preamble; // a high speed preamble is sent only when a high speed
|
// hub is connected to the host model so in this case
|
// hub is connected to the host model so in this case
|
// switch clock speeds
|
// switch clock speeds
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
// PulseWidth = PulseWidth * 8;
|
// PulseWidth = PulseWidth * 8;
|
clk_swtch = LOW_SPEED;
|
clk_swtch = LOW_SPEED;
|
end
|
end
|
|
|
|
|
tskByteCount = ByteCount;
|
tskByteCount = ByteCount;
|
if (tskByteCount > CntrlTransDlen[CntrlNum]) begin
|
if (tskByteCount > CntrlTransDlen[CntrlNum]) begin
|
if (Debug) $display("In %0s --> more data is being requested than specified by wLength, ignoring the extra bytes at time %0t", SelfName, $time);
|
if (Debug) $display("In %0s --> more data is being requested than specified by wLength, ignoring the extra bytes at time %0t", SelfName, $time);
|
tskByteCount = CntrlTransDlen[CntrlNum];
|
tskByteCount = CntrlTransDlen[CntrlNum];
|
end
|
end
|
// else CntrlTransDlen[CntrlNum] = CntrlTransDlen[CntrlNum] - tskByteCount;
|
// else CntrlTransDlen[CntrlNum] = CntrlTransDlen[CntrlNum] - tskByteCount;
|
// decrement data count
|
// decrement data count
|
|
|
in_out_buf[0] = CorruptToken({~OUT_TOKEN, OUT_TOKEN});
|
in_out_buf[0] = CorruptToken({~OUT_TOKEN, OUT_TOKEN});
|
in_out_buf_ptr = 1;
|
in_out_buf_ptr = 1;
|
|
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
|
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf_ptr = 3;
|
in_out_buf_ptr = 3;
|
if (Debug) $display("In host --> address = %h, EndPt = %h, crc5 = %h, tmpReg = %h", address, EndPt, tmpReg[15:11], tmpReg);
|
if (Debug) $display("In host --> address = %h, EndPt = %h, crc5 = %h, tmpReg = %h", address, EndPt, tmpReg[15:11], tmpReg);
|
|
|
SetSyncLevel = 0;
|
SetSyncLevel = 0;
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
SendData; //serialises, encodes and sends the data in in_out_buf
|
SendData; //serialises, encodes and sends the data in in_out_buf
|
|
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
tmpDataToggle = CheckDataToggleIN(address, EndPt);
|
tmpDataToggle = CheckDataToggleIN(address, EndPt);
|
if (Debug) $display("In %0s --> DataToggle is %0h", SelfName, tmpDataToggle);
|
if (Debug) $display("In %0s --> DataToggle is %0h", SelfName, tmpDataToggle);
|
|
|
case (tmpDataToggle)
|
case (tmpDataToggle)
|
0 : in_out_buf[0] = CorruptDataPid({~DATA0, DATA0});
|
0 : in_out_buf[0] = CorruptDataPid({~DATA0, DATA0});
|
1 : in_out_buf[0] = CorruptDataPid({~DATA1, DATA1});
|
1 : in_out_buf[0] = CorruptDataPid({~DATA1, DATA1});
|
default : in_out_buf[0] = CorruptDataPid({~DATA0, DATA0});
|
default : in_out_buf[0] = CorruptDataPid({~DATA0, DATA0});
|
endcase
|
endcase
|
in_out_buf_ptr = 1;
|
in_out_buf_ptr = 1;
|
if (Debug) $display("In %0s --> DataToggle is %0h at time %0t.", SelfName, in_out_buf[0], $time);
|
if (Debug) $display("In %0s --> DataToggle is %0h at time %0t.", SelfName, in_out_buf[0], $time);
|
|
|
tmpCrc = 16'hffff;
|
tmpCrc = 16'hffff;
|
for (i = 1; i <= ByteCount; i = i + 1) begin
|
for (i = 1; i <= ByteCount; i = i + 1) begin
|
in_out_buf[i] = XmitBuffer[i - 1];
|
in_out_buf[i] = XmitBuffer[i - 1];
|
tmpCrc = crc16(in_out_buf[i], tmpCrc);
|
tmpCrc = crc16(in_out_buf[i], tmpCrc);
|
in_out_buf_ptr = in_out_buf_ptr + 1;
|
in_out_buf_ptr = in_out_buf_ptr + 1;
|
if (Debug) $display("In %0s --> sending byte[%0d] = %b", SelfName, i, in_out_buf[i]);
|
if (Debug) $display("In %0s --> sending byte[%0d] = %b", SelfName, i, in_out_buf[i]);
|
end
|
end
|
if (Debug) $display("In %0s --> raw crc is %0h at time", SelfName, tmpCrc, $time);
|
if (Debug) $display("In %0s --> raw crc is %0h at time", SelfName, tmpCrc, $time);
|
tmpCrc = CorruptCrc16(~{swap8(tmpCrc[15:8]), swap8(tmpCrc[7:0])});
|
tmpCrc = CorruptCrc16(~{swap8(tmpCrc[15:8]), swap8(tmpCrc[7:0])});
|
if (Debug) $display("In %0s --> sent crc is %0h at time", SelfName, tmpCrc, $time);
|
if (Debug) $display("In %0s --> sent crc is %0h at time", SelfName, tmpCrc, $time);
|
in_out_buf[ByteCount + 2] = tmpCrc[7:0];
|
in_out_buf[ByteCount + 2] = tmpCrc[7:0];
|
in_out_buf[ByteCount + 1] = tmpCrc[15:8];
|
in_out_buf[ByteCount + 1] = tmpCrc[15:8];
|
in_out_buf_ptr = in_out_buf_ptr + 2;
|
in_out_buf_ptr = in_out_buf_ptr + 2;
|
SetSyncLevel = 1;
|
SetSyncLevel = 1;
|
usb_idle(ResponseLatency - 3);
|
usb_idle(ResponseLatency - 3);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
send_high_speed_preamble;
|
send_high_speed_preamble;
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
SendData; //send the contents of in_out_buf
|
SendData; //send the contents of in_out_buf
|
|
|
WaitForResp(recv_bit_count); //wait for a response for this transfer
|
WaitForResp(recv_bit_count); //wait for a response for this transfer
|
if (Debug) $display("In %0s --> bits received are %0h", SelfName, recv_bit_count);
|
if (Debug) $display("In %0s --> bits received are %0h", SelfName, recv_bit_count);
|
|
|
case (in_out_buf_ptr)
|
case (in_out_buf_ptr)
|
0 : begin
|
0 : begin
|
if (dec_bit_stuff_err == TRUE) begin
|
if (dec_bit_stuff_err == TRUE) begin
|
usb_idle(RespTimeOutVal);
|
usb_idle(RespTimeOutVal);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
end
|
end
|
Status = 3;
|
Status = 3;
|
DispErrMsg(address, EndPt, 4);
|
DispErrMsg(address, EndPt, 4);
|
end
|
end
|
1 : begin
|
1 : begin
|
tmpReg[7:0] = in_out_buf[0];
|
tmpReg[7:0] = in_out_buf[0];
|
case (tmpReg[3:0])
|
case (tmpReg[3:0])
|
ACK : begin
|
ACK : begin
|
case (tmpDataToggle) //change the data toggle
|
case (tmpDataToggle) //change the data toggle
|
0 : SetDataToggle(address, EndPt, 2'b11);
|
0 : SetDataToggle(address, EndPt, 2'b11);
|
1 : SetDataToggle(address, EndPt, 2'b00);
|
1 : SetDataToggle(address, EndPt, 2'b00);
|
default : SetDataToggle(address, EndPt, 0);
|
default : SetDataToggle(address, EndPt, 0);
|
endcase
|
endcase
|
Status = 0;
|
Status = 0;
|
if (Debug) $display("In %0s --> ACK received at time %0t.", SelfName, $time);
|
if (Debug) $display("In %0s --> ACK received at time %0t.", SelfName, $time);
|
end
|
end
|
NAK : begin
|
NAK : begin
|
DispErrMsg(address, EndPt, 11);
|
DispErrMsg(address, EndPt, 11);
|
Status = 1; // nak received
|
Status = 1; // nak received
|
end
|
end
|
STALL : begin
|
STALL : begin
|
DispErrMsg(address, EndPt, 12);
|
DispErrMsg(address, EndPt, 12);
|
Status = 2; // stall received
|
Status = 2; // stall received
|
end
|
end
|
default : begin
|
default : begin
|
DispErrMsg(address, EndPt, 13);
|
DispErrMsg(address, EndPt, 13);
|
Status = 4; // invalid response
|
Status = 4; // invalid response
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
default : DispErrMsg(address, EndPt, 14);
|
default : DispErrMsg(address, EndPt, 14);
|
endcase
|
endcase
|
if (Status == 0) CntrlTransDlen[CntrlNum] = CntrlTransDlen[CntrlNum] - tskByteCount;
|
if (Status == 0) CntrlTransDlen[CntrlNum] = CntrlTransDlen[CntrlNum] - tskByteCount;
|
WriteResults;
|
WriteResults;
|
// PulseWidth = tmpPulseWidth;
|
// PulseWidth = tmpPulseWidth;
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask //control_out
|
endtask //control_out
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// status_in : does the status phase in a control transaction
|
// status_in : does the status phase in a control transaction
|
// output : Status : exit status of the transaction
|
// output : Status : exit status of the transaction
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task status_IN;
|
task status_IN;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
output Status;
|
output Status;
|
reg [3:0] Status;
|
reg [3:0] Status;
|
reg [31:0] recv_bit_count;
|
reg [31:0] recv_bit_count;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
integer i;
|
integer i;
|
reg tmpDataToggle;
|
reg tmpDataToggle;
|
integer CntrlNum;
|
integer CntrlNum;
|
reg [31:0] tmpPulseWidth;
|
reg [31:0] tmpPulseWidth;
|
|
|
begin : status_IN
|
begin : status_IN
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
tmpPulseWidth = PulseWidth;
|
tmpPulseWidth = PulseWidth;
|
CntrlNum = 0;
|
CntrlNum = 0;
|
$display("Input Address:%x, EndPt:%x",address,EndPt);
|
$display("Input Address:%x, EndPt:%x",address,EndPt);
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
$display("i :%d, CntrlTransType:%x; CntrlTransAddr:%x;CntrlTransEndP:%x ",
|
$display("i :%d, CntrlTransType:%x; CntrlTransAddr:%x;CntrlTransEndP:%x ",
|
i,CntrlTransType[i],CntrlTransAddr[i],CntrlTransEndP[i]);
|
i,CntrlTransType[i],CntrlTransAddr[i],CntrlTransEndP[i]);
|
if ((CntrlTransType[i] != 2'b00) & (CntrlTransAddr[i] == address) & (CntrlTransEndP[i] == EndPt)) begin
|
if ((CntrlTransType[i] != 2'b00) & (CntrlTransAddr[i] == address) & (CntrlTransEndP[i] == EndPt)) begin
|
CntrlNum = i;
|
CntrlNum = i;
|
i = MAX_CNTRL_INTERLEAVE + 1;
|
i = MAX_CNTRL_INTERLEAVE + 1;
|
end
|
end
|
end
|
end
|
if (CntrlNum == 0) begin
|
if (CntrlNum == 0) begin
|
DispErrMsg(0, 0, 21);
|
DispErrMsg(0, 0, 21);
|
Status = 7;
|
Status = 7;
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable status_IN;
|
disable status_IN;
|
end
|
end
|
if (CntrlTransType[CntrlNum] == 2'b00) begin
|
if (CntrlTransType[CntrlNum] == 2'b00) begin
|
DispErrMsg(0, 0, 24);
|
DispErrMsg(0, 0, 24);
|
Status = 7; // no setup transaction in progress to do a control_in xfer
|
Status = 7; // no setup transaction in progress to do a control_in xfer
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable status_IN;
|
disable status_IN;
|
end
|
end
|
if (Debug) $display("In %0s CntrlTransType = %b, WRITE = %b", SelfName, CntrlTransType[CntrlNum], WRITE);
|
if (Debug) $display("In %0s CntrlTransType = %b, WRITE = %b", SelfName, CntrlTransType[CntrlNum], WRITE);
|
if (CntrlTransType[CntrlNum] != WRITE) begin
|
if (CntrlTransType[CntrlNum] != WRITE) begin
|
DispErrMsg(0, 0, 22);
|
DispErrMsg(0, 0, 22);
|
Status = 9; // wrong type of control transaction
|
Status = 9; // wrong type of control transaction
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable status_IN;
|
disable status_IN;
|
end
|
end
|
|
|
usb_idle(ResponseLatency - 3);
|
usb_idle(ResponseLatency - 3);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
if ((DeviceSpeed == HIGH_SPEED) & (SendPreamble == TRUE)) begin
|
if ((DeviceSpeed == HIGH_SPEED) & (SendPreamble == TRUE)) begin
|
clk_swtch = LOW_SPEED; // #27
|
clk_swtch = LOW_SPEED; // #27
|
usb_idle(ResponseLatency - 3); // #27
|
usb_idle(ResponseLatency - 3); // #27
|
clk_swtch = HIGH_SPEED; // #27
|
clk_swtch = HIGH_SPEED; // #27
|
send_preamble; // a high speed preamble is sent only when a high speed
|
send_preamble; // a high speed preamble is sent only when a high speed
|
// hub is connected to the host model so in this case
|
// hub is connected to the host model so in this case
|
// switch clock speeds
|
// switch clock speeds
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
// PulseWidth = PulseWidth * 8;
|
// PulseWidth = PulseWidth * 8;
|
clk_swtch = LOW_SPEED;
|
clk_swtch = LOW_SPEED;
|
end
|
end
|
in_out_buf[0] = CorruptToken({~IN_TOKEN, IN_TOKEN});
|
in_out_buf[0] = CorruptToken({~IN_TOKEN, IN_TOKEN});
|
in_out_buf_ptr = 1;
|
in_out_buf_ptr = 1;
|
|
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
|
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf_ptr = 3;
|
in_out_buf_ptr = 3;
|
SetSyncLevel = 0;
|
SetSyncLevel = 0;
|
SendData; //serialises, encodes and sends the data in in_out_buf,
|
SendData; //serialises, encodes and sends the data in in_out_buf,
|
|
|
WaitForResp(recv_bit_count);
|
WaitForResp(recv_bit_count);
|
case (in_out_buf_ptr)
|
case (in_out_buf_ptr)
|
0 : begin // timeout
|
0 : begin // timeout
|
if (dec_bit_stuff_err == TRUE) begin
|
if (dec_bit_stuff_err == TRUE) begin
|
usb_idle(RespTimeOutVal);
|
usb_idle(RespTimeOutVal);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
end
|
end
|
Status = 3;
|
Status = 3;
|
end
|
end
|
1 : begin
|
1 : begin
|
tmpReg[7:0] = in_out_buf[0]; //should contain the pid
|
tmpReg[7:0] = in_out_buf[0]; //should contain the pid
|
if (tmpReg[7:4] != (~tmpReg[3:0])) begin
|
if (tmpReg[7:4] != (~tmpReg[3:0])) begin
|
DispErrMsg(address, EndPt, 5);
|
DispErrMsg(address, EndPt, 5);
|
end
|
end
|
if (tmpReg[3:0] == NAK) begin
|
if (tmpReg[3:0] == NAK) begin
|
DispErrMsg(address, EndPt, 11);
|
DispErrMsg(address, EndPt, 11);
|
Status = 1; //NAK received from end point
|
Status = 1; //NAK received from end point
|
end
|
end
|
else if (tmpReg[3:0] == STALL) begin
|
else if (tmpReg[3:0] == STALL) begin
|
DispErrMsg(address, EndPt, 12);
|
DispErrMsg(address, EndPt, 12);
|
Status = 2; //STALL received from end point
|
Status = 2; //STALL received from end point
|
end
|
end
|
else begin
|
else begin
|
Status = 4; // invalid response
|
Status = 4; // invalid response
|
end
|
end
|
end
|
end
|
3 : begin
|
3 : begin
|
tmpReg[7:0] = in_out_buf[0]; //should contain the pid
|
tmpReg[7:0] = in_out_buf[0]; //should contain the pid
|
if (tmpReg[7:4] != (~tmpReg[3:0])) begin
|
if (tmpReg[7:4] != (~tmpReg[3:0])) begin
|
DispErrMsg(address, EndPt, 5);
|
DispErrMsg(address, EndPt, 5);
|
end
|
end
|
if ({in_out_buf[1], in_out_buf[2]} != 16'h0000) begin
|
if ({in_out_buf[1], in_out_buf[2]} != 16'h0000) begin
|
DispErrMsg(address, EndPt, 8);
|
DispErrMsg(address, EndPt, 8);
|
usb_idle(RespTimeOutVal);
|
usb_idle(RespTimeOutVal);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
Status = 5;
|
Status = 5;
|
end
|
end
|
else begin
|
else begin
|
if (tmpReg[3:0] == DATA1) begin
|
if (tmpReg[3:0] == DATA1) begin
|
NumSucCntrlWrTrans = NumSucCntrlWrTrans + 1;
|
NumSucCntrlWrTrans = NumSucCntrlWrTrans + 1;
|
//usb_idle(ResponseLatency - 3); // #27
|
//usb_idle(ResponseLatency - 3); // #27
|
send_high_speed_preamble;
|
send_high_speed_preamble;
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
SendAck;
|
SendAck;
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
Status = 0;
|
Status = 0;
|
end
|
end
|
else begin
|
else begin
|
DispErrMsg(address, EndPt, 25);
|
DispErrMsg(address, EndPt, 25);
|
usb_idle(RespTimeOutVal);
|
usb_idle(RespTimeOutVal);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
end
|
end
|
end
|
end
|
end
|
end
|
default : begin
|
default : begin
|
Status = 4; // invalid response
|
Status = 4; // invalid response
|
end
|
end
|
endcase
|
endcase
|
|
|
//reset control transaction flags
|
//reset control transaction flags
|
if (Status != 1) begin
|
if (Status != 1) begin
|
CntrlTransEndP[CntrlNum] = 4'b1111;
|
CntrlTransEndP[CntrlNum] = 4'b1111;
|
CntrlTransAddr[CntrlNum] = 7'b1111111;
|
CntrlTransAddr[CntrlNum] = 7'b1111111;
|
CntrlTransDlen[CntrlNum] = 0;
|
CntrlTransDlen[CntrlNum] = 0;
|
CntrlTransType[CntrlNum] = 0;
|
CntrlTransType[CntrlNum] = 0;
|
end
|
end
|
WriteResults;
|
WriteResults;
|
// PulseWidth = tmpPulseWidth;
|
// PulseWidth = tmpPulseWidth;
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// status_out : does the status phase of a control transaction
|
// status_out : does the status phase of a control transaction
|
// output : Status : Exit Status
|
// output : Status : Exit Status
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task status_OUT;
|
task status_OUT;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
output Status;
|
output Status;
|
reg [3:0] Status;
|
reg [3:0] Status;
|
reg [31:0] recv_bit_count;
|
reg [31:0] recv_bit_count;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
integer i;
|
integer i;
|
reg tmpDataToggle;
|
reg tmpDataToggle;
|
integer CntrlNum;
|
integer CntrlNum;
|
reg [31:0] tmpPulseWidth;
|
reg [31:0] tmpPulseWidth;
|
|
|
begin : status_OUT
|
begin : status_OUT
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
tmpPulseWidth = PulseWidth;
|
tmpPulseWidth = PulseWidth;
|
CntrlNum = 0;
|
CntrlNum = 0;
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
for (i = 1; i <= MAX_CNTRL_INTERLEAVE; i = i + 1) begin
|
if ((CntrlTransType[i] != 2'b00) & (CntrlTransAddr[i] == address) & (CntrlTransEndP[i] == EndPt)) begin
|
if ((CntrlTransType[i] != 2'b00) & (CntrlTransAddr[i] == address) & (CntrlTransEndP[i] == EndPt)) begin
|
CntrlNum = i;
|
CntrlNum = i;
|
i = MAX_CNTRL_INTERLEAVE + 1;
|
i = MAX_CNTRL_INTERLEAVE + 1;
|
end
|
end
|
end
|
end
|
if (CntrlNum == 0) begin
|
if (CntrlNum == 0) begin
|
DispErrMsg(0, 0, 21);
|
DispErrMsg(0, 0, 21);
|
Status = 7;
|
Status = 7;
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable status_OUT;
|
disable status_OUT;
|
end
|
end
|
if (CntrlTransType [CntrlNum]== 2'b00) begin
|
if (CntrlTransType [CntrlNum]== 2'b00) begin
|
DispErrMsg(0, 0, 24);
|
DispErrMsg(0, 0, 24);
|
Status = 7; // no setup transaction in progress to do a control_in xfer
|
Status = 7; // no setup transaction in progress to do a control_in xfer
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable status_OUT;
|
disable status_OUT;
|
end
|
end
|
|
|
if (CntrlTransType[CntrlNum] != READ) begin
|
if (CntrlTransType[CntrlNum] != READ) begin
|
DispErrMsg(0, 0, 22);
|
DispErrMsg(0, 0, 22);
|
Status = 9; // wrong type of control transaction
|
Status = 9; // wrong type of control transaction
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable status_OUT;
|
disable status_OUT;
|
end
|
end
|
|
|
usb_idle(ResponseLatency - 3);
|
usb_idle(ResponseLatency - 3);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
if ((DeviceSpeed == HIGH_SPEED) & (SendPreamble == TRUE)) begin
|
if ((DeviceSpeed == HIGH_SPEED) & (SendPreamble == TRUE)) begin
|
clk_swtch = LOW_SPEED; // #27
|
clk_swtch = LOW_SPEED; // #27
|
usb_idle(ResponseLatency - 3); // #27
|
usb_idle(ResponseLatency - 3); // #27
|
clk_swtch = HIGH_SPEED; // #27
|
clk_swtch = HIGH_SPEED; // #27
|
send_preamble; // a high speed preamble is sent only when a high speed
|
send_preamble; // a high speed preamble is sent only when a high speed
|
// hub is connected to the host model so in this case
|
// hub is connected to the host model so in this case
|
// switch clock speeds
|
// switch clock speeds
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
usb_idle(4); // idle for 4 high speed clock times after a preamble
|
usb_idle(4); // idle for 4 high speed clock times after a preamble
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
// PulseWidth = PulseWidth * 8;
|
// PulseWidth = PulseWidth * 8;
|
clk_swtch = LOW_SPEED;
|
clk_swtch = LOW_SPEED;
|
end
|
end
|
in_out_buf[0] = CorruptToken({~OUT_TOKEN, OUT_TOKEN});
|
in_out_buf[0] = CorruptToken({~OUT_TOKEN, OUT_TOKEN});
|
in_out_buf_ptr = 1;
|
in_out_buf_ptr = 1;
|
|
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
|
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf_ptr = 3;
|
in_out_buf_ptr = 3;
|
SetSyncLevel = 0;
|
SetSyncLevel = 0;
|
SendData;
|
SendData;
|
|
|
usb_idle(ResponseLatency - 3);
|
usb_idle(ResponseLatency - 3);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
send_high_speed_preamble;
|
send_high_speed_preamble;
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
in_out_buf[0] = CorruptDataPid({~DATA1, DATA1});
|
in_out_buf[0] = CorruptDataPid({~DATA1, DATA1});
|
in_out_buf[1] = 0;
|
in_out_buf[1] = 0;
|
in_out_buf[2] = 0;
|
in_out_buf[2] = 0;
|
in_out_buf_ptr = 3;
|
in_out_buf_ptr = 3;
|
SetSyncLevel = 1;
|
SetSyncLevel = 1;
|
SendData;
|
SendData;
|
|
|
WaitForResp(recv_bit_count);
|
WaitForResp(recv_bit_count);
|
|
|
case (in_out_buf_ptr)
|
case (in_out_buf_ptr)
|
0 : begin
|
0 : begin
|
if (dec_bit_stuff_err == TRUE) begin
|
if (dec_bit_stuff_err == TRUE) begin
|
usb_idle(RespTimeOutVal);
|
usb_idle(RespTimeOutVal);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
end
|
end
|
Status = 3; // time out
|
Status = 3; // time out
|
end
|
end
|
1 : begin
|
1 : begin
|
tmpReg[7:0] = in_out_buf[0]; //should contain the pid
|
tmpReg[7:0] = in_out_buf[0]; //should contain the pid
|
if (tmpReg[7:4] != (~tmpReg[3:0])) begin
|
if (tmpReg[7:4] != (~tmpReg[3:0])) begin
|
DispErrMsg(address, EndPt, 5);
|
DispErrMsg(address, EndPt, 5);
|
end
|
end
|
if (tmpReg[3:0] == NAK) begin
|
if (tmpReg[3:0] == NAK) begin
|
DispErrMsg(address, EndPt, 11);
|
DispErrMsg(address, EndPt, 11);
|
Status = 1; //NAK received from end point
|
Status = 1; //NAK received from end point
|
end
|
end
|
else if (tmpReg[3:0] == STALL) begin
|
else if (tmpReg[3:0] == STALL) begin
|
DispErrMsg(address, EndPt, 12);
|
DispErrMsg(address, EndPt, 12);
|
Status = 2; //STALL received from end point
|
Status = 2; //STALL received from end point
|
end
|
end
|
else if (tmpReg[3:0] == ACK) begin
|
else if (tmpReg[3:0] == ACK) begin
|
NumSucCntrlRdTrans = NumSucCntrlRdTrans + 1;
|
NumSucCntrlRdTrans = NumSucCntrlRdTrans + 1;
|
Status = 0;
|
Status = 0;
|
end
|
end
|
else begin
|
else begin
|
Status = 4; // invalid response
|
Status = 4; // invalid response
|
end
|
end
|
end
|
end
|
default : begin
|
default : begin
|
Status = 4; // invalid response
|
Status = 4; // invalid response
|
end
|
end
|
endcase
|
endcase
|
|
|
//reset control transaction flags
|
//reset control transaction flags
|
if (Status != 1) begin
|
if (Status != 1) begin
|
CntrlTransEndP[CntrlNum] = 0;
|
CntrlTransEndP[CntrlNum] = 0;
|
CntrlTransAddr[CntrlNum] = 7'b1111111;
|
CntrlTransAddr[CntrlNum] = 7'b1111111;
|
CntrlTransDlen[CntrlNum] = 4'b1111;
|
CntrlTransDlen[CntrlNum] = 4'b1111;
|
CntrlTransType[CntrlNum] = 0;
|
CntrlTransType[CntrlNum] = 0;
|
end
|
end
|
// PulseWidth = tmpPulseWidth;
|
// PulseWidth = tmpPulseWidth;
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
WriteResults;
|
WriteResults;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// usb_resume : drives a K state on the bus for ResumeTime number of bit times
|
// usb_resume : drives a K state on the bus for ResumeTime number of bit times
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task usb_resume;
|
task usb_resume;
|
input [31:0] ResumeTime;
|
input [31:0] ResumeTime;
|
reg [31:0] tskResumeTime;
|
reg [31:0] tskResumeTime;
|
|
|
begin : usb_resume
|
begin : usb_resume
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
tskResumeTime = 0;
|
tskResumeTime = 0;
|
forever @(posedge clk) begin
|
forever @(posedge clk) begin
|
if (tskResumeTime >= ResumeTime) begin
|
if (tskResumeTime >= ResumeTime) begin
|
zDPLS = 1'b0;
|
zDPLS = 1'b0;
|
zDMNS = 1'b0;
|
zDMNS = 1'b0;
|
if (DeviceSpeed == HIGH_SPEED) begin // wait for two low speed bit times
|
if (DeviceSpeed == HIGH_SPEED) begin // wait for two low speed bit times
|
#667;
|
#667;
|
#667;
|
#667;
|
end
|
end
|
else begin
|
else begin
|
@(posedge clk);
|
@(posedge clk);
|
@(posedge clk);
|
@(posedge clk);
|
end
|
end
|
zDPLS = 1'bZ;
|
zDPLS = 1'bZ;
|
zDMNS = 1'bZ;
|
zDMNS = 1'bZ;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
disable usb_resume;
|
disable usb_resume;
|
end
|
end
|
if (DeviceSpeed == HIGH_SPEED) begin
|
if (DeviceSpeed == HIGH_SPEED) begin
|
zDPLS = 1'b0;
|
zDPLS = 1'b0;
|
zDMNS = 1'b1;
|
zDMNS = 1'b1;
|
end
|
end
|
else begin
|
else begin
|
zDPLS = 1'b1;
|
zDPLS = 1'b1;
|
zDMNS = 1'b0;
|
zDMNS = 1'b0;
|
end
|
end
|
tskResumeTime = tskResumeTime + 1;
|
tskResumeTime = tskResumeTime + 1;
|
end
|
end
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// send_preamble : sends a Preamble token and idles the bus for the required
|
// send_preamble : sends a Preamble token and idles the bus for the required
|
// 4 bit times which is the hub setup time for low speed devices
|
// 4 bit times which is the hub setup time for low speed devices
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task send_preamble;
|
task send_preamble;
|
|
|
reg tskGenSE0Error;
|
reg tskGenSE0Error;
|
reg [31:0] tskSE0BitTimes;
|
reg [31:0] tskSE0BitTimes;
|
reg [31:0] tskSE0ErrorLevel;
|
reg [31:0] tskSE0ErrorLevel;
|
|
|
begin
|
begin
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
// SE0 should not be generated after sending a preamble 10/03/1996
|
// SE0 should not be generated after sending a preamble 10/03/1996
|
// modify SE0 error generation logic
|
// modify SE0 error generation logic
|
tskGenSE0Error = GenSE0Error;
|
tskGenSE0Error = GenSE0Error;
|
tskSE0BitTimes = SE0BitTimes;
|
tskSE0BitTimes = SE0BitTimes;
|
tskSE0ErrorLevel = SE0ErrorLevel;
|
tskSE0ErrorLevel = SE0ErrorLevel;
|
|
|
GenSE0Error = TRUE;
|
GenSE0Error = TRUE;
|
SE0BitTimes = 0;
|
SE0BitTimes = 0;
|
SE0ErrorLevel = SetSyncLevel;
|
SE0ErrorLevel = SetSyncLevel;
|
|
|
in_out_buf[0] = {~PREAMBLE, PREAMBLE};
|
in_out_buf[0] = {~PREAMBLE, PREAMBLE};
|
in_out_buf_ptr = 1;
|
in_out_buf_ptr = 1;
|
SendData;
|
SendData;
|
|
|
// restore SE0 error generation logic 10/03/1996
|
// restore SE0 error generation logic 10/03/1996
|
GenSE0Error = tskGenSE0Error;
|
GenSE0Error = tskGenSE0Error;
|
SE0BitTimes = tskSE0BitTimes;
|
SE0BitTimes = tskSE0BitTimes;
|
SE0ErrorLevel = tskSE0ErrorLevel;
|
SE0ErrorLevel = tskSE0ErrorLevel;
|
|
|
usb_idle(4); // hub setup time
|
usb_idle(4); // hub setup time
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// transfer_buf : transfers whatever data from the xmit buffer with a sync
|
// transfer_buf : transfers whatever data from the xmit buffer with a sync
|
// field in the front
|
// field in the front
|
// input : ByteCount : number of bytes to be transferred from buffer, 32 bits
|
// input : ByteCount : number of bytes to be transferred from buffer, 32 bits
|
// FromFile : TRUE/FALSE, if TRUE data is taken from host_usb_recv.dat
|
// FromFile : TRUE/FALSE, if TRUE data is taken from host_usb_recv.dat
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task transfer_buf;
|
task transfer_buf;
|
|
|
input [31:0] ByteCount;
|
input [31:0] ByteCount;
|
input FromFile;
|
input FromFile;
|
input [160:1] FileName;
|
input [160:1] FileName;
|
reg [3:0] Status;
|
reg [3:0] Status;
|
integer i;
|
integer i;
|
|
|
begin : transfer_buf
|
begin : transfer_buf
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
for (i = 0; i < ByteCount; i = i + 1) begin
|
for (i = 0; i < ByteCount; i = i + 1) begin
|
in_out_buf[i] = XmitBuffer[i]; // addition 5/29/1996
|
in_out_buf[i] = XmitBuffer[i]; // addition 5/29/1996
|
end
|
end
|
in_out_buf_ptr = ByteCount;
|
in_out_buf_ptr = ByteCount;
|
SendData;
|
SendData;
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// receive_buf : receives the data from the bus and puts in RecvBuf
|
// receive_buf : receives the data from the bus and puts in RecvBuf
|
// input : DumpToFile : if true data is dumped to a file
|
// input : DumpToFile : if true data is dumped to a file
|
// output : ByteCount : number of bytes received
|
// output : ByteCount : number of bytes received
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task receive_buf;
|
task receive_buf;
|
|
|
input DumpToFile;
|
input DumpToFile;
|
output [31:0] ByteCount;
|
output [31:0] ByteCount;
|
reg [31:0] recv_bit_count;
|
reg [31:0] recv_bit_count;
|
integer i;
|
integer i;
|
|
|
begin
|
begin
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
WaitForResp(recv_bit_count);
|
WaitForResp(recv_bit_count);
|
for (i = 0; i < in_out_buf_ptr; i = i + 1) begin
|
for (i = 0; i < in_out_buf_ptr; i = i + 1) begin
|
RecvBuffer[i] = in_out_buf[i];
|
RecvBuffer[i] = in_out_buf[i];
|
end
|
end
|
ByteCount = in_out_buf_ptr;
|
ByteCount = in_out_buf_ptr;
|
if (DumpToFile == TRUE && ByteCount > 0) DumpData(7'b1111111, 4'b1111, DATA0, ByteCount-1);
|
if (DumpToFile == TRUE && ByteCount > 0) DumpData(7'b1111111, 4'b1111, DATA0, ByteCount-1);
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
|
|
endtask
|
endtask
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// task send_high_speed_preamble : sends a preamble by switching clock
|
// task send_high_speed_preamble : sends a preamble by switching clock
|
// during a low speed transaction
|
// during a low speed transaction
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
task send_high_speed_preamble;
|
task send_high_speed_preamble;
|
begin
|
begin
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
if ((SendPreamble == TRUE) & (DeviceSpeed == HIGH_SPEED)) begin
|
if ((SendPreamble == TRUE) & (DeviceSpeed == HIGH_SPEED)) begin
|
// PulseWidth = PulseWidth / 8;
|
// PulseWidth = PulseWidth / 8;
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
send_preamble;
|
send_preamble;
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
// a high speed preamble is sent only when a high speed
|
// a high speed preamble is sent only when a high speed
|
// hub is connected to the host model so in this case
|
// hub is connected to the host model so in this case
|
// switch clock speeds
|
// switch clock speeds
|
usb_idle(4);
|
usb_idle(4);
|
task_in_progress = TRUE;
|
task_in_progress = TRUE;
|
// idle for 4 high speed clock times after a preamble
|
// idle for 4 high speed clock times after a preamble
|
// PulseWidth = PulseWidth * 8;
|
// PulseWidth = PulseWidth * 8;
|
clk_swtch = LOW_SPEED;
|
clk_swtch = LOW_SPEED;
|
end
|
end
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
initial begin // initilaise the input and output buffers
|
initial begin // initilaise the input and output buffers
|
for(tmpCounter = 0; tmpCounter <= 2048; tmpCounter = tmpCounter + 1) begin
|
for(tmpCounter = 0; tmpCounter <= 2048; tmpCounter = tmpCounter + 1) begin
|
XmitBuffer[tmpCounter] = 8'b00000000;
|
XmitBuffer[tmpCounter] = 8'b00000000;
|
end
|
end
|
for(tmpCounter = 0; tmpCounter <= RECV_BUF_SIZE; tmpCounter = tmpCounter + 1) begin
|
for(tmpCounter = 0; tmpCounter <= RECV_BUF_SIZE; tmpCounter = tmpCounter + 1) begin
|
RecvBuffer[tmpCounter] = 8'b00000000;
|
RecvBuffer[tmpCounter] = 8'b00000000;
|
end
|
end
|
for (tmpCounter = 0; tmpCounter < IN_OUT_BUF_SIZE; tmpCounter = tmpCounter + 1) begin
|
for (tmpCounter = 0; tmpCounter < IN_OUT_BUF_SIZE; tmpCounter = tmpCounter + 1) begin
|
in_out_buf[tmpCounter] = 0;
|
in_out_buf[tmpCounter] = 0;
|
end
|
end
|
//for (tmpCounter = 0; tmpCounter < OUT_BUF_SIZE; tmpCounter = tmpCounter + 1) begin
|
//for (tmpCounter = 0; tmpCounter < OUT_BUF_SIZE; tmpCounter = tmpCounter + 1) begin
|
//out_buf[tmpCounter] = 0;
|
//out_buf[tmpCounter] = 0;
|
//end
|
//end
|
for (tmpCounter = 0; tmpCounter < 128; tmpCounter = tmpCounter + 1)
|
for (tmpCounter = 0; tmpCounter < 128; tmpCounter = tmpCounter + 1)
|
begin
|
begin
|
InDataToggle[tmpCounter] = 16'h0000;
|
InDataToggle[tmpCounter] = 16'h0000;
|
OutDataToggle[tmpCounter] = 16'h0000;
|
OutDataToggle[tmpCounter] = 16'h0000;
|
end
|
end
|
|
|
TimeOut = TRUE;
|
TimeOut = TRUE;
|
TimeOutVal = 16; // timeout after 16 bit times
|
TimeOutVal = 16; // timeout after 16 bit times
|
RespTimeOutVal = 16;
|
RespTimeOutVal = 16;
|
|
|
ResponseLatency = 3;
|
ResponseLatency = 3;
|
|
|
GenCrc16Err = FALSE;
|
GenCrc16Err = FALSE;
|
Crc16ErrMask = 16'hffff;
|
Crc16ErrMask = 16'hffff;
|
|
|
GenCrc5Err = FALSE;
|
GenCrc5Err = FALSE;
|
Crc5ErrMask = 5'b00000;
|
Crc5ErrMask = 5'b00000;
|
|
|
ReportResults = TRUE; // default : turned on
|
ReportResults = TRUE; // default : turned on
|
ResultsFile = "host_usb_res.log"; // default file name
|
ResultsFile = "host_usb_res.log"; // default file name
|
ResultsFp = 0; // initially log file pointer is 0
|
ResultsFp = 0; // initially log file pointer is 0
|
|
|
PulseWidth = 42;
|
PulseWidth = 42;
|
|
|
SyncField = FALSE; // default : sync field corruption is turned off
|
SyncField = FALSE; // default : sync field corruption is turned off
|
SyncFieldMask = 8'hf0; // default no sync field corruption specified
|
SyncFieldMask = 8'hf0; // default no sync field corruption specified
|
SyncLevel = 0;
|
SyncLevel = 0;
|
SetSyncLevel = 0;
|
SetSyncLevel = 0;
|
|
|
GenSE0Error = FALSE;
|
GenSE0Error = FALSE;
|
SE0BitTimes = 2; // default conforms to the spec
|
SE0BitTimes = 2; // default conforms to the spec
|
SE0ErrorLevel = 0;
|
SE0ErrorLevel = 0;
|
|
|
HshkPidIntegrity = FALSE; // no corruption
|
HshkPidIntegrity = FALSE; // no corruption
|
HshkPidIntegrityMask = 8'hf0; // corruption mask for ACK's
|
HshkPidIntegrityMask = 8'hf0; // corruption mask for ACK's
|
|
|
BitStuffErr = FALSE; // changed TRUE to FALSE 02/18/97
|
BitStuffErr = FALSE; // changed TRUE to FALSE 02/18/97
|
|
|
for (tmpCounter = 1; tmpCounter <= MAX_CNTRL_INTERLEAVE; tmpCounter = tmpCounter + 1) begin
|
for (tmpCounter = 1; tmpCounter <= MAX_CNTRL_INTERLEAVE; tmpCounter = tmpCounter + 1) begin
|
CntrlTransType[tmpCounter] = 2'b00;
|
CntrlTransType[tmpCounter] = 2'b00;
|
// no control transaction in progress
|
// no control transaction in progress
|
CntrlTransAddr[tmpCounter] = 7'b1111111;
|
CntrlTransAddr[tmpCounter] = 7'b1111111;
|
// address of a control transaction
|
// address of a control transaction
|
CntrlTransEndP[tmpCounter] = 4'b1111;
|
CntrlTransEndP[tmpCounter] = 4'b1111;
|
// endpoint number of a control transaction
|
// endpoint number of a control transaction
|
CntrlTransDlen[tmpCounter] = 16'h0000;
|
CntrlTransDlen[tmpCounter] = 16'h0000;
|
// data length for this control transaction
|
// data length for this control transaction
|
end
|
end
|
|
|
SendDataFileName = "host_usb_xmit.dat";
|
SendDataFileName = "host_usb_xmit.dat";
|
RecvDataFileName = "host_usb_recv.dat";
|
RecvDataFileName = "host_usb_recv.dat";
|
RecvDataFp = 0;
|
RecvDataFp = 0;
|
ReportErrors = TRUE;
|
ReportErrors = TRUE;
|
ErrorFileName = "host_usb_err.log";
|
ErrorFileName = "host_usb_err.log";
|
ErrorFileFp = 0;
|
ErrorFileFp = 0;
|
|
|
for ( tmpCounter = 1; tmpCounter <= NUM_ENDPT_FILES; tmpCounter = tmpCounter + 1) begin
|
for ( tmpCounter = 1; tmpCounter <= NUM_ENDPT_FILES; tmpCounter = tmpCounter + 1) begin
|
EndPtFileName[tmpCounter] = "";
|
EndPtFileName[tmpCounter] = "";
|
EndPtFileMode[tmpCounter] = 2'b00; // no mode is assigned to it
|
EndPtFileMode[tmpCounter] = 2'b00; // no mode is assigned to it
|
EndPtFileInfo[tmpCounter] = 11'b00000000000;
|
EndPtFileInfo[tmpCounter] = 11'b00000000000;
|
EndPtFp[tmpCounter] = 0;
|
EndPtFp[tmpCounter] = 0;
|
EndPtFileOfst[tmpCounter] = 0;
|
EndPtFileOfst[tmpCounter] = 0;
|
end
|
end
|
|
|
SendDataOfst = 0;
|
SendDataOfst = 0;
|
|
|
Debug = FALSE;
|
Debug = FALSE;
|
|
|
GenDataPidErr = FALSE;
|
GenDataPidErr = FALSE;
|
DataPidErrMask = 8'hff;
|
DataPidErrMask = 8'hff;
|
GenTokenErr = FALSE;
|
GenTokenErr = FALSE;
|
TokenErrMask = 8'hff;
|
TokenErrMask = 8'hff;
|
|
|
//DeviceSpeed = LOW_SPEED;
|
//DeviceSpeed = LOW_SPEED;
|
DeviceSpeed = HIGH_SPEED;
|
DeviceSpeed = HIGH_SPEED;
|
GenByteBoundary = FALSE;
|
GenByteBoundary = FALSE;
|
|
|
SendPreamble = FALSE; // assumes a low speed device is connected to the
|
SendPreamble = FALSE; // assumes a low speed device is connected to the
|
// host
|
// host
|
|
|
FrameNumber = 0;
|
FrameNumber = 0;
|
|
|
NumBulkInTrans = 0; // number of bulk in transactions
|
NumBulkInTrans = 0; // number of bulk in transactions
|
NumSucBulkInTrans = 0; // number of successful bulk in transctions
|
NumSucBulkInTrans = 0; // number of successful bulk in transctions
|
NumBulkOutTrans = 0; // number of bulk out transactions
|
NumBulkOutTrans = 0; // number of bulk out transactions
|
NumSucBulkOutTrans = 0; // number of successful bulk out transactions
|
NumSucBulkOutTrans = 0; // number of successful bulk out transactions
|
NumIsoInTrans = 0; // number of iso in transactions
|
NumIsoInTrans = 0; // number of iso in transactions
|
NumSucIsoInTrans = 0; // number of successful iso in transactions
|
NumSucIsoInTrans = 0; // number of successful iso in transactions
|
NumIsoOutTrans = 0; // number of iso out transactions
|
NumIsoOutTrans = 0; // number of iso out transactions
|
NumSOF = 0; // number of SOF's sent
|
NumSOF = 0; // number of SOF's sent
|
NumCntrlRdTrans = 0; // number of control reads
|
NumCntrlRdTrans = 0; // number of control reads
|
NumSucCntrlRdTrans = 0; // number of successful control reads
|
NumSucCntrlRdTrans = 0; // number of successful control reads
|
NumCntrlWrTrans = 0; // number of control writes
|
NumCntrlWrTrans = 0; // number of control writes
|
NumSucCntrlWrTrans = 0; // number of successful control writes
|
NumSucCntrlWrTrans = 0; // number of successful control writes
|
NumIntrptTrans = 0; // number of interrupts
|
NumIntrptTrans = 0; // number of interrupts
|
NumSucIntrptTrans = 0; // number of successful interrupts
|
NumSucIntrptTrans = 0; // number of successful interrupts
|
NumIntrOutTrans = 0; // number of interrupt out transactions
|
NumIntrOutTrans = 0; // number of interrupt out transactions
|
NumSucIntrOutTrans = 0; // number of successful interrupt out transactions
|
NumSucIntrOutTrans = 0; // number of successful interrupt out transactions
|
NumResets = 0; // number of resets
|
NumResets = 0; // number of resets
|
|
|
// intialize Jitter registers
|
// intialize Jitter registers
|
HighJitterTime = 0;
|
HighJitterTime = 0;
|
LowJitterTime = 0;
|
LowJitterTime = 0;
|
JitterPeriod = 0;
|
JitterPeriod = 0;
|
JitterCount = 0;
|
JitterCount = 0;
|
JitterOnOff = FALSE; // Jitter generation is off by default;
|
JitterOnOff = FALSE; // Jitter generation is off by default;
|
|
|
task_in_progress = FALSE;
|
task_in_progress = FALSE;
|
|
|
clk_swtch = HIGH_SPEED;
|
clk_swtch = HIGH_SPEED;
|
|
|
SetupDataLen = 8;
|
SetupDataLen = 8;
|
|
|
GenByteBoundaryPos = FALSE;
|
GenByteBoundaryPos = FALSE;
|
BoundaryBitVal = 1'b0;
|
BoundaryBitVal = 1'b0;
|
|
|
ModifyGran = 0;
|
ModifyGran = 0;
|
|
|
end
|
end
|
|
|
|
|
assign clk = (clk_swtch == LOW_SPEED) ? ls_clk : hs_clk;
|
assign clk = (clk_swtch == LOW_SPEED) ? ls_clk : hs_clk;
|
assign clk4x = (clk_swtch == LOW_SPEED) ? clk6 : clk48;
|
assign clk4x = (clk_swtch == LOW_SPEED) ? clk6 : clk48;
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// task in_token : sends an in token on to the bus.
|
// task in_token : sends an in token on to the bus.
|
// inputs : address : 7 bits : endpoint address
|
// inputs : address : 7 bits : endpoint address
|
// EndPt : 4 bits : endpoint number
|
// EndPt : 4 bits : endpoint number
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
task in_token;
|
task in_token;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
begin
|
begin
|
in_out_buf[0] = CorruptToken({~IN_TOKEN, IN_TOKEN});
|
in_out_buf[0] = CorruptToken({~IN_TOKEN, IN_TOKEN});
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf_ptr = 3;
|
in_out_buf_ptr = 3;
|
SendData;
|
SendData;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// task out_token : sends an out token on to the bus.
|
// task out_token : sends an out token on to the bus.
|
// inputs : address : 7 bits : endpoint address
|
// inputs : address : 7 bits : endpoint address
|
// EndPt : 4 bits : endpoint number
|
// EndPt : 4 bits : endpoint number
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
task out_token;
|
task out_token;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
begin
|
begin
|
in_out_buf[0] = CorruptToken({~OUT_TOKEN, OUT_TOKEN});
|
in_out_buf[0] = CorruptToken({~OUT_TOKEN, OUT_TOKEN});
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf_ptr = 3;
|
in_out_buf_ptr = 3;
|
SendData;
|
SendData;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// task setup_token : sends an setup token on to the bus
|
// task setup_token : sends an setup token on to the bus
|
// inputs : address : 7 bits : endpoint address
|
// inputs : address : 7 bits : endpoint address
|
// EndPt : 4 bits : endpoint number
|
// EndPt : 4 bits : endpoint number
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
task setup_token;
|
task setup_token;
|
input [6:0] address;
|
input [6:0] address;
|
input [3:0] EndPt;
|
input [3:0] EndPt;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
begin
|
begin
|
in_out_buf[0] = CorruptToken({~SETUP_TOKEN, SETUP_TOKEN});
|
in_out_buf[0] = CorruptToken({~SETUP_TOKEN, SETUP_TOKEN});
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
tmpReg[15:0] = FillCrc5({EndPt, address});
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[1] = tmpReg[7:0];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf[2] = tmpReg[15:8];
|
in_out_buf_ptr = 3;
|
in_out_buf_ptr = 3;
|
SendData;
|
SendData;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// task send_ack : sends an ACK on to the bus
|
// task send_ack : sends an ACK on to the bus
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
task send_ack;
|
task send_ack;
|
begin
|
begin
|
in_out_buf[0] = CorruptHshk({~ACK, ACK});
|
in_out_buf[0] = CorruptHshk({~ACK, ACK});
|
in_out_buf_ptr = 1;
|
in_out_buf_ptr = 1;
|
SendData;
|
SendData;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// task send_nak : sends a NAK on the bus (though an host is not supposed
|
// task send_nak : sends a NAK on the bus (though an host is not supposed
|
// to send a NAK)
|
// to send a NAK)
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
task send_nak;
|
task send_nak;
|
begin
|
begin
|
in_out_buf[0] = CorruptHshk({~NAK, NAK});
|
in_out_buf[0] = CorruptHshk({~NAK, NAK});
|
in_out_buf_ptr = 1;
|
in_out_buf_ptr = 1;
|
SendData;
|
SendData;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// task send_stall : sends a STALL on to the bus (though an host is not
|
// task send_stall : sends a STALL on to the bus (though an host is not
|
// supposed to send a STALL)
|
// supposed to send a STALL)
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
task send_stall;
|
task send_stall;
|
begin
|
begin
|
in_out_buf[0] = CorruptHshk({~STALL, STALL});
|
in_out_buf[0] = CorruptHshk({~STALL, STALL});
|
in_out_buf_ptr = 1;
|
in_out_buf_ptr = 1;
|
SendData;
|
SendData;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// task wait_for_data : waits for a response on the bus and decodes the
|
// task wait_for_data : waits for a response on the bus and decodes the
|
// data packet and returns a status indicating what
|
// data packet and returns a status indicating what
|
// type of packet was received.
|
// type of packet was received.
|
// Output : PackType : 4'b0010 : ACK
|
// Output : PackType : 4'b0010 : ACK
|
// 4'b1010 : NAK
|
// 4'b1010 : NAK
|
// 4'b1110 : STALL
|
// 4'b1110 : STALL
|
// 4'b0011 : DATA0
|
// 4'b0011 : DATA0
|
// 4'b1011 : DATA1
|
// 4'b1011 : DATA1
|
// 4'b1111 : Unknown
|
// 4'b1111 : Unknown
|
// ByteCount : indicates the number of bytes of data present if
|
// ByteCount : indicates the number of bytes of data present if
|
// PackType is of DATA0 or DATA1
|
// PackType is of DATA0 or DATA1
|
// Status : 0 : command executed successfully.
|
// Status : 0 : command executed successfully.
|
// 3 : time out, no response.
|
// 3 : time out, no response.
|
// 4 : invalid response, unknown packet type
|
// 4 : invalid response, unknown packet type
|
// 5 : CRC error on received data
|
// 5 : CRC error on received data
|
// 11 : corrupted ACK/NAK/STALL
|
// 11 : corrupted ACK/NAK/STALL
|
// 12 : corrupted DATA0/DATA1 pid, CRC correct
|
// 12 : corrupted DATA0/DATA1 pid, CRC correct
|
// 13 : corrupted DATA0/DATA1 pid, CRC incorrect
|
// 13 : corrupted DATA0/DATA1 pid, CRC incorrect
|
//
|
//
|
//
|
//
|
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
task wait_for_data;
|
task wait_for_data;
|
output [31:0] ByteCount;
|
output [31:0] ByteCount;
|
output [3:0] PackType;
|
output [3:0] PackType;
|
output [3:0] Status;
|
output [3:0] Status;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpReg;
|
reg [15:0] tmpCrc;
|
reg [15:0] tmpCrc;
|
reg [31:0] recv_bit_count;
|
reg [31:0] recv_bit_count;
|
integer i;
|
integer i;
|
begin
|
begin
|
WaitForResp(recv_bit_count);
|
WaitForResp(recv_bit_count);
|
PackType = 4'b1111;
|
PackType = 4'b1111;
|
Status = 0;
|
Status = 0;
|
case (in_out_buf_ptr)
|
case (in_out_buf_ptr)
|
0 : begin
|
0 : begin
|
Status = 3; // timeout
|
Status = 3; // timeout
|
if (dec_bit_stuff_err == TRUE) usb_idle(RespTimeOutVal);
|
if (dec_bit_stuff_err == TRUE) usb_idle(RespTimeOutVal);
|
end
|
end
|
1 : begin
|
1 : begin
|
tmpReg[7:0] = in_out_buf[0];
|
tmpReg[7:0] = in_out_buf[0];
|
case (tmpReg[3:0])
|
case (tmpReg[3:0])
|
ACK : PackType = ACK;
|
ACK : PackType = ACK;
|
NAK : PackType = NAK;
|
NAK : PackType = NAK;
|
STALL : PackType = STALL;
|
STALL : PackType = STALL;
|
default : PackType = 4'b1111;
|
default : PackType = 4'b1111;
|
endcase
|
endcase
|
if (((tmpReg == ACK) | (tmpReg == NAK) | (tmpReg == STALL)) & (~tmpReg[7:4] != tmpReg[3:0])) Status = 11;
|
if (((tmpReg == ACK) | (tmpReg == NAK) | (tmpReg == STALL)) & (~tmpReg[7:4] != tmpReg[3:0])) Status = 11;
|
end
|
end
|
2 : begin
|
2 : begin
|
Status = 4;
|
Status = 4;
|
PackType = 4'b1111;
|
PackType = 4'b1111;
|
end
|
end
|
default : begin // since the number of bytes received is greater than 2 this
|
default : begin // since the number of bytes received is greater than 2 this
|
// obviously should be a data packet
|
// obviously should be a data packet
|
tmpReg[7:0] = in_out_buf[0];
|
tmpReg[7:0] = in_out_buf[0];
|
ByteCount = 0;
|
ByteCount = 0;
|
tmpCrc = 16'hffff;
|
tmpCrc = 16'hffff;
|
if ((tmpReg[3:0] == DATA0) | (tmpReg[3:0] == DATA1)) begin
|
if ((tmpReg[3:0] == DATA0) | (tmpReg[3:0] == DATA1)) begin
|
for ( i = 1; i < (in_out_buf_ptr - 2); i = i + 1) begin
|
for ( i = 1; i < (in_out_buf_ptr - 2); i = i + 1) begin
|
tmpCrc = crc16(in_out_buf[i], tmpCrc);
|
tmpCrc = crc16(in_out_buf[i], tmpCrc);
|
RecvBuffer[i - 1] = in_out_buf[i];
|
RecvBuffer[i - 1] = in_out_buf[i];
|
ByteCount = ByteCount + 1;
|
ByteCount = ByteCount + 1;
|
end
|
end
|
tmpCrc = ~{swap8(tmpCrc[15:8]), swap8(tmpCrc[7:0])};
|
tmpCrc = ~{swap8(tmpCrc[15:8]), swap8(tmpCrc[7:0])};
|
if (tmpCrc != {in_out_buf[in_out_buf_ptr - 2], in_out_buf[in_out_buf_ptr - 1]}) Status = 5;
|
if (tmpCrc != {in_out_buf[in_out_buf_ptr - 2], in_out_buf[in_out_buf_ptr - 1]}) Status = 5;
|
if (~tmpReg[7:4] != tmpReg[3:0]) begin
|
if (~tmpReg[7:4] != tmpReg[3:0]) begin
|
if (Status == 5) Status = 13;
|
if (Status == 5) Status = 13;
|
else Status = 12;
|
else Status = 12;
|
end
|
end
|
PackType = tmpReg[3:0];
|
PackType = tmpReg[3:0];
|
end
|
end
|
else PackType = 4'b1111;
|
else PackType = 4'b1111;
|
end
|
end
|
endcase
|
endcase
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
|
|
parameter MYACK = 4'b0000,
|
parameter MYACK = 4'b0000,
|
MYNAK = 4'b0001,
|
MYNAK = 4'b0001,
|
MYSTALL = 4'b0010,
|
MYSTALL = 4'b0010,
|
MYTOUT = 4'b0011,
|
MYTOUT = 4'b0011,
|
MYIVRES = 4'b0100,
|
MYIVRES = 4'b0100,
|
MYCRCER = 4'b0101;
|
MYCRCER = 4'b0101;
|
|
|
|
|
|
|
parameter OUT = 2'b00,
|
parameter OUT = 2'b00,
|
IN = 2'b10,
|
IN = 2'b10,
|
SOF = 2'b01,
|
SOF = 2'b01,
|
SETUP=2'b11;
|
SETUP=2'b11;
|
|
|
|
|
// Control Packet format;
|
// Control Packet format;
|
|
|
reg [24:0] ControlPkt;
|
reg [24:0] ControlPkt;
|
reg [3:0] Status;
|
reg [3:0] Status;
|
integer ByteCount;
|
integer ByteCount;
|
|
|
|
|
task printstatus;
|
task printstatus;
|
input [3:0] RecvdStatus;
|
input [3:0] RecvdStatus;
|
input [3:0] ExpStatus;
|
input [3:0] ExpStatus;
|
begin
|
begin
|
$display("");
|
$display("");
|
$display(" #######################################################");
|
$display(" #######################################################");
|
if(RecvdStatus !== ExpStatus ) begin
|
if(RecvdStatus !== ExpStatus ) begin
|
$display(" ERROR: Expected Status and Observed Status didn't match at %0d", $time);
|
$display(" ERROR: Expected Status and Observed Status didn't match at %0d", $time);
|
if(ExpStatus==4'b0000)
|
if(ExpStatus==4'b0000)
|
$display(" Expected Status is ACK at %0d", $time);
|
$display(" Expected Status is ACK at %0d", $time);
|
else if(ExpStatus==4'b0001)
|
else if(ExpStatus==4'b0001)
|
$display(" Expected Status is NACK at %0d", $time);
|
$display(" Expected Status is NACK at %0d", $time);
|
else if(ExpStatus==4'b0010)
|
else if(ExpStatus==4'b0010)
|
$display(" Expected Status is STALL at %0d", $time);
|
$display(" Expected Status is STALL at %0d", $time);
|
else if(ExpStatus==4'b0011)
|
else if(ExpStatus==4'b0011)
|
$display(" Expected Status is TIMEOUT at %0d", $time);
|
$display(" Expected Status is TIMEOUT at %0d", $time);
|
else if(ExpStatus==4'b0100)
|
else if(ExpStatus==4'b0100)
|
$display(" Expected Status is INVALID RESPONSE at %0d", $time);
|
$display(" Expected Status is INVALID RESPONSE at %0d", $time);
|
else if(ExpStatus==4'b0101)
|
else if(ExpStatus==4'b0101)
|
$display(" Expected Status is CRC ERROR at %0d", $time);
|
$display(" Expected Status is CRC ERROR at %0d", $time);
|
end
|
end
|
|
|
if(RecvdStatus==4'b0000)
|
if(RecvdStatus==4'b0000)
|
$display(" Received Status is ACK at %0d", $time);
|
$display(" Received Status is ACK at %0d", $time);
|
else if(RecvdStatus==4'b0001)
|
else if(RecvdStatus==4'b0001)
|
$display(" Received Status is NACK at %0d", $time);
|
$display(" Received Status is NACK at %0d", $time);
|
else if(RecvdStatus==4'b0010)
|
else if(RecvdStatus==4'b0010)
|
$display(" Received Status is STALL at %0d", $time);
|
$display(" Received Status is STALL at %0d", $time);
|
else if(RecvdStatus==4'b011)
|
else if(RecvdStatus==4'b011)
|
$display(" Received Status is TIMEOUT at %0d", $time);
|
$display(" Received Status is TIMEOUT at %0d", $time);
|
else if(RecvdStatus==4'b0100)
|
else if(RecvdStatus==4'b0100)
|
$display(" Received Status is INVALID RESPONSE at %0d", $time);
|
$display(" Received Status is INVALID RESPONSE at %0d", $time);
|
else if(RecvdStatus==4'b0101)
|
else if(RecvdStatus==4'b0101)
|
$display(" Received Status is CRC ERROR at %0d", $time);
|
$display(" Received Status is CRC ERROR at %0d", $time);
|
$display(" #######################################################");
|
$display(" #######################################################");
|
$display("");
|
$display("");
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
|
|
task dump_recv_buffer;
|
task dump_recv_buffer;
|
|
|
input [31:0] NumBytes;
|
input [31:0] NumBytes;
|
integer i;
|
integer i;
|
begin
|
begin
|
|
|
|
|
for(i=0; i < NumBytes; i=i+1)
|
for(i=0; i < NumBytes; i=i+1)
|
$display("RecvBuffer[%0d] = %b : %0d", i, RecvBuffer[i], RecvBuffer[i]);
|
$display("RecvBuffer[%0d] = %b : %0d", i, RecvBuffer[i], RecvBuffer[i]);
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
task send_token;
|
task send_token;
|
input [1:0] tkn;
|
input [1:0] tkn;
|
input [6:0] adr;
|
input [6:0] adr;
|
input [3:0] ep;
|
input [3:0] ep;
|
|
|
reg [2:0] Status;
|
reg [2:0] Status;
|
reg [15:0] tmpreg;
|
reg [15:0] tmpreg;
|
begin
|
begin
|
|
|
XmitBuffer[0] = {~tkn,2'b10, tkn, 2'b01};
|
XmitBuffer[0] = {~tkn,2'b10, tkn, 2'b01};
|
tmpreg = FillCrc5({ep, adr});
|
tmpreg = FillCrc5({ep, adr});
|
XmitBuffer[1] = tmpreg[7:0];
|
XmitBuffer[1] = tmpreg[7:0];
|
XmitBuffer[2] = tmpreg[15:8];
|
XmitBuffer[2] = tmpreg[15:8];
|
transfer_buf(3, 0, Status);
|
transfer_buf(3, 0, Status);
|
end
|
end
|
endtask
|
endtask
|
|
|
task send_datapkt;
|
task send_datapkt;
|
input datatgl;
|
input datatgl;
|
input [10:0] numbytes;
|
input [10:0] numbytes;
|
|
|
integer i;
|
integer i;
|
reg [15:0] tmpcrc;
|
reg [15:0] tmpcrc;
|
reg [2:0] Status;
|
reg [2:0] Status;
|
begin
|
begin
|
|
|
// Shifting the XmitBuffer Values to put the DataTkn in Byte0.
|
// Shifting the XmitBuffer Values to put the DataTkn in Byte0.
|
for(i=numbytes; i > 0; i=i-1) begin
|
for(i=numbytes; i > 0; i=i-1) begin
|
XmitBuffer[i] = XmitBuffer[i-1];
|
XmitBuffer[i] = XmitBuffer[i-1];
|
end
|
end
|
|
|
XmitBuffer[0] = {!datatgl, 3'b100, datatgl, 3'b011};
|
XmitBuffer[0] = {!datatgl, 3'b100, datatgl, 3'b011};
|
|
|
tmpcrc = crc16(XmitBuffer[1], 16'hffff);
|
tmpcrc = crc16(XmitBuffer[1], 16'hffff);
|
for(i=1; i < numbytes; i=i+1) begin
|
for(i=1; i < numbytes; i=i+1) begin
|
tmpcrc = crc16(XmitBuffer[i+1], tmpcrc);
|
tmpcrc = crc16(XmitBuffer[i+1], tmpcrc);
|
end
|
end
|
|
|
if(numbytes > 0) begin
|
if(numbytes > 0) begin
|
XmitBuffer[numbytes+1] = ~swap8(tmpcrc[15:8]);
|
XmitBuffer[numbytes+1] = ~swap8(tmpcrc[15:8]);
|
XmitBuffer[numbytes+2] = ~swap8(tmpcrc[7:0]);
|
XmitBuffer[numbytes+2] = ~swap8(tmpcrc[7:0]);
|
end
|
end
|
else begin
|
else begin
|
XmitBuffer[numbytes+1] = 8'b0000_0000;
|
XmitBuffer[numbytes+1] = 8'b0000_0000;
|
XmitBuffer[numbytes+2] = 8'b0000_0000;
|
XmitBuffer[numbytes+2] = 8'b0000_0000;
|
end
|
end
|
|
|
transfer_buf(numbytes+3, 0, Status);
|
transfer_buf(numbytes+3, 0, Status);
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task SetAddress;
|
task SetAddress;
|
input [6:0] address;
|
input [6:0] address;
|
begin
|
begin
|
XmitBuffer[0] = 8'b0000_0000;
|
XmitBuffer[0] = 8'b0000_0000;
|
XmitBuffer[1] = 8'b0000_0101; // SetAddress
|
XmitBuffer[1] = 8'b0000_0101; // SetAddress
|
XmitBuffer[2] = {1'b0, address};
|
XmitBuffer[2] = {1'b0, address};
|
XmitBuffer[3] = 8'b0000_0000;
|
XmitBuffer[3] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[6] = 8'b0000_0000;
|
XmitBuffer[6] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task GetConfiguration;
|
task GetConfiguration;
|
begin
|
begin
|
XmitBuffer[0] = 8'b1000_0000;
|
XmitBuffer[0] = 8'b1000_0000;
|
XmitBuffer[1] = 8'b0000_1000; // get config.
|
XmitBuffer[1] = 8'b0000_1000; // get config.
|
XmitBuffer[2] = 8'b0000_0000;
|
XmitBuffer[2] = 8'b0000_0000;
|
XmitBuffer[3] = 8'b0000_0000;
|
XmitBuffer[3] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[6] = 8'b0000_0001;
|
XmitBuffer[6] = 8'b0000_0001;
|
XmitBuffer[7] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task SetConfiguration;
|
task SetConfiguration;
|
input [1:0] cfg_val;
|
input [1:0] cfg_val;
|
begin
|
begin
|
XmitBuffer[0] = 8'b0000_0000;
|
XmitBuffer[0] = 8'b0000_0000;
|
XmitBuffer[1] = 8'b0000_1001; // Set Configuration
|
XmitBuffer[1] = 8'b0000_1001; // Set Configuration
|
XmitBuffer[2] = {6'b000_000, cfg_val};
|
XmitBuffer[2] = {6'b000_000, cfg_val};
|
XmitBuffer[3] = 8'b0000_0000;
|
XmitBuffer[3] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[6] = 8'b0000_0000;
|
XmitBuffer[6] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
end
|
end
|
endtask
|
endtask
|
|
|
task GetDescriptor;
|
task GetDescriptor;
|
input [2:0] des_type_new;
|
input [2:0] des_type_new;
|
input [2:0] des_index;
|
input [2:0] des_index;
|
input [15:0] des_size;
|
input [15:0] des_size;
|
begin
|
begin
|
XmitBuffer[0] = 8'b1000_0000;
|
XmitBuffer[0] = 8'b1000_0000;
|
XmitBuffer[1] = 8'b0000_0110;
|
XmitBuffer[1] = 8'b0000_0110;
|
XmitBuffer[2] = {5'b00000, des_index};
|
XmitBuffer[2] = {5'b00000, des_index};
|
XmitBuffer[3] = {5'b00000, des_type_new};
|
XmitBuffer[3] = {5'b00000, des_type_new};
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[6] = des_size[7:0];
|
XmitBuffer[6] = des_size[7:0];
|
XmitBuffer[7] = des_size[15:8];
|
XmitBuffer[7] = des_size[15:8];
|
end
|
end
|
endtask
|
endtask
|
|
|
task SetDescriptor;
|
task SetDescriptor;
|
input [2:0] des_type_new;
|
input [2:0] des_type_new;
|
input [2:0] des_index;
|
input [2:0] des_index;
|
input [15:0] des_size;
|
input [15:0] des_size;
|
begin
|
begin
|
XmitBuffer[0] = 8'b0000_0000;
|
XmitBuffer[0] = 8'b0000_0000;
|
XmitBuffer[1] = 8'b0000_0111;
|
XmitBuffer[1] = 8'b0000_0111;
|
XmitBuffer[2] = {5'b00000, des_index};
|
XmitBuffer[2] = {5'b00000, des_index};
|
XmitBuffer[3] = {5'b00000, des_type_new};
|
XmitBuffer[3] = {5'b00000, des_type_new};
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[6] = des_size[7:0];
|
XmitBuffer[6] = des_size[7:0];
|
XmitBuffer[7] = des_size[15:8];
|
XmitBuffer[7] = des_size[15:8];
|
end
|
end
|
endtask
|
endtask
|
|
|
task SynchFrame;
|
task SynchFrame;
|
begin
|
begin
|
XmitBuffer[0] = 8'b1000_0010;
|
XmitBuffer[0] = 8'b1000_0010;
|
XmitBuffer[1] = 8'b0000_1100;
|
XmitBuffer[1] = 8'b0000_1100;
|
XmitBuffer[2] = 8'b0000_0000;
|
XmitBuffer[2] = 8'b0000_0000;
|
XmitBuffer[3] = 8'b0000_0000;
|
XmitBuffer[3] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[6] = 8'b0000_0000;
|
XmitBuffer[6] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task VenRegWordWr;
|
task VenRegWordWr;
|
input [6:0] address;
|
input [6:0] address;
|
input [31:0] reg_address;
|
input [31:0] reg_address;
|
input [31:0] dataword;
|
input [31:0] dataword;
|
begin
|
begin
|
XmitBuffer[0] = 8'b0100_0000;
|
XmitBuffer[0] = 8'b0100_0000;
|
XmitBuffer[1] = 8'b0001_0000;
|
XmitBuffer[1] = 8'b0001_0000;
|
XmitBuffer[2] = reg_address[31:24];
|
XmitBuffer[2] = reg_address[31:24];
|
XmitBuffer[3] = reg_address[23:16];
|
XmitBuffer[3] = reg_address[23:16];
|
XmitBuffer[4] = reg_address[15:8];
|
XmitBuffer[4] = reg_address[15:8];
|
XmitBuffer[5] = reg_address[7:0];
|
XmitBuffer[5] = reg_address[7:0];
|
XmitBuffer[6] = 8'b0000_0100;
|
XmitBuffer[6] = 8'b0000_0100;
|
XmitBuffer[7] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
|
|
setup (address, 4'h0, Status);
|
setup (address, 4'h0, Status);
|
|
|
XmitBuffer[0] = dataword[31:24];
|
XmitBuffer[0] = dataword[31:24];
|
XmitBuffer[1] = dataword[23:16];
|
XmitBuffer[1] = dataword[23:16];
|
XmitBuffer[2] = dataword[15:8];
|
XmitBuffer[2] = dataword[15:8];
|
XmitBuffer[3] = dataword[7:0];
|
XmitBuffer[3] = dataword[7:0];
|
|
|
control_OUT(address, 4'h0, 4, Status);
|
control_OUT(address, 4'h0, 4, Status);
|
status_IN (address, 4'h0, Status);
|
status_IN (address, 4'h0, Status);
|
end
|
end
|
endtask
|
endtask
|
|
|
task VenRegWordRd;
|
task VenRegWordRd;
|
input [6:0] address;
|
input [6:0] address;
|
input [31:0] reg_address;
|
input [31:0] reg_address;
|
output [31:0] dataword;
|
output [31:0] dataword;
|
reg [31:0] ByteCount;
|
reg [31:0] ByteCount;
|
begin
|
begin
|
XmitBuffer[0] = 8'b1100_0000;
|
XmitBuffer[0] = 8'b1100_0000;
|
XmitBuffer[1] = 8'b0001_0001;
|
XmitBuffer[1] = 8'b0001_0001;
|
XmitBuffer[2] = reg_address[31:24];
|
XmitBuffer[2] = reg_address[31:24];
|
XmitBuffer[3] = reg_address[23:16];
|
XmitBuffer[3] = reg_address[23:16];
|
XmitBuffer[4] = reg_address[15:8];
|
XmitBuffer[4] = reg_address[15:8];
|
XmitBuffer[5] = reg_address[7:0];
|
XmitBuffer[5] = reg_address[7:0];
|
XmitBuffer[6] = 8'b0000_0100;
|
XmitBuffer[6] = 8'b0000_0100;
|
XmitBuffer[7] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
|
|
setup (address, 4'h0, Status);
|
setup (address, 4'h0, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
if (Status != MYACK)
|
if (Status != MYACK)
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
if (Status != MYACK)
|
if (Status != MYACK)
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
dataword[7:0] = RecvBuffer[3];
|
dataword[7:0] = RecvBuffer[3];
|
dataword[15:8] = RecvBuffer[2];
|
dataword[15:8] = RecvBuffer[2];
|
dataword[23:16] = RecvBuffer[1];
|
dataword[23:16] = RecvBuffer[1];
|
dataword[31:24] = RecvBuffer[0];
|
dataword[31:24] = RecvBuffer[0];
|
dump_recv_buffer(ByteCount);
|
dump_recv_buffer(ByteCount);
|
|
|
status_OUT (address, 4'h0, Status);
|
status_OUT (address, 4'h0, Status);
|
end
|
end
|
endtask
|
endtask
|
|
|
task VenRegWordRdCmp;
|
task VenRegWordRdCmp;
|
input [6:0] address;
|
input [6:0] address;
|
input [31:0] reg_address;
|
input [31:0] reg_address;
|
input [31:0] dataword;
|
input [31:0] dataword;
|
output [31:0] ByteCount;
|
output [31:0] ByteCount;
|
begin
|
begin
|
XmitBuffer[0] = 8'b1100_0000;
|
XmitBuffer[0] = 8'b1100_0000;
|
XmitBuffer[1] = 8'b0001_0001;
|
XmitBuffer[1] = 8'b0001_0001;
|
XmitBuffer[2] = reg_address[31:24];
|
XmitBuffer[2] = reg_address[31:24];
|
XmitBuffer[3] = reg_address[23:16];
|
XmitBuffer[3] = reg_address[23:16];
|
XmitBuffer[4] = reg_address[15:8];
|
XmitBuffer[4] = reg_address[15:8];
|
XmitBuffer[5] = reg_address[7:0];
|
XmitBuffer[5] = reg_address[7:0];
|
XmitBuffer[6] = 8'b0000_0100;
|
XmitBuffer[6] = 8'b0000_0100;
|
XmitBuffer[7] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
|
|
setup (address, 4'h0, Status);
|
setup (address, 4'h0, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
if (Status != MYACK)
|
if (Status != MYACK)
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
if (Status != MYACK)
|
if (Status != MYACK)
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
if ((RecvBuffer[3] !== dataword[7:0]) || (RecvBuffer[2] !== dataword[15:8])
|
if ((RecvBuffer[3] !== dataword[7:0]) || (RecvBuffer[2] !== dataword[15:8])
|
|| (RecvBuffer[1] !== dataword[23:16]) || (RecvBuffer[0] !== dataword[31:24]))
|
|| (RecvBuffer[1] !== dataword[23:16]) || (RecvBuffer[0] !== dataword[31:24]))
|
begin
|
begin
|
-> tb.test_control.error_detected;
|
-> tb.test_control.error_detected;
|
$display( "usb_agent check: Register Read Byte Mismatch !!! Exp: %x ; Rxd: %x",dataword[31:0], {RecvBuffer[0],RecvBuffer[1], RecvBuffer[2],RecvBuffer[3]} );
|
$display( "usb_agent check: Register Read Byte Mismatch !!! Exp: %x ; Rxd: %x",dataword[31:0], {RecvBuffer[0],RecvBuffer[1], RecvBuffer[2],RecvBuffer[3]} );
|
dump_recv_buffer(ByteCount);
|
dump_recv_buffer(ByteCount);
|
end
|
end
|
|
|
status_OUT (address, 4'h0, Status);
|
status_OUT (address, 4'h0, Status);
|
end
|
end
|
endtask
|
endtask
|
task VenRegHalfWordRd;
|
task VenRegHalfWordRd;
|
input [6:0] address;
|
input [6:0] address;
|
input [21:0] reg_address;
|
input [21:0] reg_address;
|
input [15:0] dataword;
|
input [15:0] dataword;
|
output [31:0] ByteCount;
|
output [31:0] ByteCount;
|
begin
|
begin
|
XmitBuffer[0] = 8'b1100_0000;
|
XmitBuffer[0] = 8'b1100_0000;
|
XmitBuffer[1] = {2'b00,reg_address[21:16]};
|
XmitBuffer[1] = {2'b00,reg_address[21:16]};
|
XmitBuffer[2] = reg_address[7:0];
|
XmitBuffer[2] = reg_address[7:0];
|
XmitBuffer[3] = reg_address[15:8];
|
XmitBuffer[3] = reg_address[15:8];
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[6] = 8'b0000_0010;
|
XmitBuffer[6] = 8'b0000_0010;
|
XmitBuffer[7] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
|
|
setup (address, 4'h0, Status);
|
setup (address, 4'h0, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
if (Status != MYACK)
|
if (Status != MYACK)
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
if (Status != MYACK)
|
if (Status != MYACK)
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
if ((RecvBuffer[0] !== dataword[7:0]) || (RecvBuffer[1] !== dataword[15:8]))
|
if ((RecvBuffer[0] !== dataword[7:0]) || (RecvBuffer[1] !== dataword[15:8]))
|
begin
|
begin
|
-> tb.test_control.error_detected;
|
-> tb.test_control.error_detected;
|
$display( "usb_agent check: Register Read Byte Mismatch !!!");
|
$display( "usb_agent check: Register Read Byte Mismatch !!!");
|
dump_recv_buffer(ByteCount);
|
dump_recv_buffer(ByteCount);
|
end
|
end
|
status_OUT (address, 4'h0, Status);
|
status_OUT (address, 4'h0, Status);
|
end
|
end
|
endtask
|
endtask
|
|
|
task VenRegByteRd;
|
task VenRegByteRd;
|
input [6:0] address;
|
input [6:0] address;
|
input [21:0] reg_address;
|
input [21:0] reg_address;
|
input [7:0] dataword;
|
input [7:0] dataword;
|
output [31:0] ByteCount;
|
output [31:0] ByteCount;
|
begin
|
begin
|
XmitBuffer[0] = 8'b1100_0000;
|
XmitBuffer[0] = 8'b1100_0000;
|
XmitBuffer[1] = {2'b00,reg_address[21:16]};
|
XmitBuffer[1] = {2'b00,reg_address[21:16]};
|
XmitBuffer[2] = reg_address[7:0];
|
XmitBuffer[2] = reg_address[7:0];
|
XmitBuffer[3] = reg_address[15:8];
|
XmitBuffer[3] = reg_address[15:8];
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[6] = 8'b0000_0001;
|
XmitBuffer[6] = 8'b0000_0001;
|
XmitBuffer[7] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
|
|
setup (address, 4'h0, Status);
|
setup (address, 4'h0, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
if (Status != MYACK)
|
if (Status != MYACK)
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
if (Status != MYACK)
|
if (Status != MYACK)
|
control_IN(address, 4'h0, ByteCount, Status);
|
control_IN(address, 4'h0, ByteCount, Status);
|
if ((RecvBuffer[0] !== dataword[7:0]))
|
if ((RecvBuffer[0] !== dataword[7:0]))
|
begin
|
begin
|
-> tb.test_control.error_detected;
|
-> tb.test_control.error_detected;
|
$display( "usb_agent check: Register Read Byte Mismatch !!!");
|
$display( "usb_agent check: Register Read Byte Mismatch !!!");
|
dump_recv_buffer(ByteCount);
|
dump_recv_buffer(ByteCount);
|
end
|
end
|
status_OUT (address, 4'h0, Status);
|
status_OUT (address, 4'h0, Status);
|
end
|
end
|
endtask
|
endtask
|
|
|
task VenRegWr;
|
task VenRegWr;
|
input [21:0] reg_address;
|
input [21:0] reg_address;
|
input [2:0] length;
|
input [2:0] length;
|
begin
|
begin
|
XmitBuffer[0] = 8'b0100_0000;
|
XmitBuffer[0] = 8'b0100_0000;
|
XmitBuffer[1] = {2'b00,reg_address[21:16]};
|
XmitBuffer[1] = {2'b00,reg_address[21:16]};
|
XmitBuffer[2] = reg_address[7:0];
|
XmitBuffer[2] = reg_address[7:0];
|
XmitBuffer[3] = reg_address[15:8];
|
XmitBuffer[3] = reg_address[15:8];
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[6] = {5'b0000_0,length};
|
XmitBuffer[6] = {5'b0000_0,length};
|
XmitBuffer[7] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
task VenRegRd;
|
task VenRegRd;
|
input [21:0] reg_address;
|
input [21:0] reg_address;
|
input [2:0] length;
|
input [2:0] length;
|
begin
|
begin
|
XmitBuffer[0] = 8'b1100_0000;
|
XmitBuffer[0] = 8'b1100_0000;
|
XmitBuffer[1] = {2'b00,reg_address[21:16]};
|
XmitBuffer[1] = {2'b00,reg_address[21:16]};
|
XmitBuffer[2] = reg_address[7:0];
|
XmitBuffer[2] = reg_address[7:0];
|
XmitBuffer[3] = reg_address[15:8];
|
XmitBuffer[3] = reg_address[15:8];
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[4] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[5] = 8'b0000_0000;
|
XmitBuffer[6] = {5'b0000_0,length};
|
XmitBuffer[6] = {5'b0000_0,length};
|
XmitBuffer[7] = 8'b0000_0000;
|
XmitBuffer[7] = 8'b0000_0000;
|
end
|
end
|
endtask
|
endtask
|
|
|
task VenRegWrWordData;
|
task VenRegWrWordData;
|
input [7:0] Byte0;
|
input [7:0] Byte0;
|
input [7:0] Byte1;
|
input [7:0] Byte1;
|
input [7:0] Byte2;
|
input [7:0] Byte2;
|
input [7:0] Byte3;
|
input [7:0] Byte3;
|
begin
|
begin
|
XmitBuffer[0] = Byte0;
|
XmitBuffer[0] = Byte0;
|
XmitBuffer[1] = Byte1;
|
XmitBuffer[1] = Byte1;
|
XmitBuffer[2] = Byte2;
|
XmitBuffer[2] = Byte2;
|
XmitBuffer[3] = Byte3;
|
XmitBuffer[3] = Byte3;
|
end
|
end
|
endtask
|
endtask
|
|
|
task VenRegWrHWordData;
|
task VenRegWrHWordData;
|
input [7:0] Byte0;
|
input [7:0] Byte0;
|
input [7:0] Byte1;
|
input [7:0] Byte1;
|
begin
|
begin
|
XmitBuffer[0] = Byte0;
|
XmitBuffer[0] = Byte0;
|
XmitBuffer[1] = Byte1;
|
XmitBuffer[1] = Byte1;
|
end
|
end
|
endtask
|
endtask
|
|
|
task VenRegWrByteData;
|
task VenRegWrByteData;
|
input [7:0] Byte0;
|
input [7:0] Byte0;
|
begin
|
begin
|
XmitBuffer[0] = Byte0;
|
XmitBuffer[0] = Byte0;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
/*****************************************/
|
/*****************************************/
|
|
|
assign DPLS = zDPLS;
|
assign DPLS = zDPLS;
|
assign DMNS = zDMNS;
|
assign DMNS = zDMNS;
|
|
|
//instantiate the encoder
|
//instantiate the encoder
|
usb_bfm_encoder u_usb_enc
|
usb_bfm_encoder u_usb_enc
|
(
|
(
|
.enable_in (enc_enbl),
|
.enable_in (enc_enbl),
|
.reset_n (enc_reset_n),
|
.reset_n (enc_reset_n),
|
.clk (clk),
|
.clk (clk),
|
.bit_count_out (enc_bit_count_out),
|
.bit_count_out (enc_bit_count_out),
|
.count_out (enc_count_out),
|
.count_out (enc_count_out),
|
.data_out_valid (enc_data_out_valid),
|
.data_out_valid (enc_data_out_valid),
|
.gen_bit_stuff_err (BitStuffErr),
|
.gen_bit_stuff_err (BitStuffErr),
|
.last_byte (enc_last_byte),
|
.last_byte (enc_last_byte),
|
.start_bit (DeviceSpeed),
|
.start_bit (DeviceSpeed),
|
.data_in (enc_data_in),
|
.data_in (enc_data_in),
|
.data_out (DPLS),
|
.data_out (DPLS),
|
.data_out_n (DMNS)
|
.data_out_n (DMNS)
|
);
|
);
|
|
|
//instantiate the decoder
|
//instantiate the decoder
|
usb_bfm_decoder u_usb_dec
|
usb_bfm_decoder u_usb_dec
|
(
|
(
|
.enable_in (dec_enbl),
|
.enable_in (dec_enbl),
|
.ser_data_rdy (dec_ser_data_rdy),
|
.ser_data_rdy (dec_ser_data_rdy),
|
.par_data_rdy (dec_par_data_rdy),
|
.par_data_rdy (dec_par_data_rdy),
|
.reset_n (dec_reset_n),
|
.reset_n (dec_reset_n),
|
.clk (dpll_clk),
|
.clk (dpll_clk),
|
.start_bit (DeviceSpeed), // 1'b1),
|
.start_bit (DeviceSpeed), // 1'b1),
|
.data_in (DPLS),
|
.data_in (DPLS),
|
.data_in_n (DMNS),
|
.data_in_n (DMNS),
|
.recv_bit_count (dec_recv_bit_count),
|
.recv_bit_count (dec_recv_bit_count),
|
.bit_stuff_err (dec_bit_stuff_err),
|
.bit_stuff_err (dec_bit_stuff_err),
|
.ser_data_out (),
|
.ser_data_out (),
|
.par_data_out (dec_par_data_out)
|
.par_data_out (dec_par_data_out)
|
);
|
);
|
|
|
usb_bfm_dpll dpll_inst
|
usb_bfm_dpll dpll_inst
|
(
|
(
|
.clk48 (clk4x),
|
.clk48 (clk4x),
|
.clk6 (clk4x),
|
.clk6 (clk4x),
|
.switch (~DeviceSpeed),
|
.switch (~DeviceSpeed),
|
.reset_n (dpll_reset_n),
|
.reset_n (dpll_reset_n),
|
.data_in (DPLS),
|
.data_in (DPLS),
|
.rec_clk (dpll_clk),
|
.rec_clk (dpll_clk),
|
.data_out ()
|
.data_out ()
|
);
|
);
|
|
|
|
|
always begin
|
always begin
|
if (JitterOnOff == TRUE) begin
|
if (JitterOnOff == TRUE) begin
|
if (tmpJitterCount > 0) begin
|
if (tmpJitterCount > 0) begin
|
#(PulseWidth - LowJitterTime) hs_clk = 1'b1;
|
#(PulseWidth - LowJitterTime) hs_clk = 1'b1;
|
#(PulseWidth - HighJitterTime) hs_clk = 1'b0;
|
#(PulseWidth - HighJitterTime) hs_clk = 1'b0;
|
tmpJitterCount = tmpJitterCount - 1;
|
tmpJitterCount = tmpJitterCount - 1;
|
if (tmpJitterCount == 0) begin
|
if (tmpJitterCount == 0) begin
|
tmpJitterPeriod = JitterPeriod;
|
tmpJitterPeriod = JitterPeriod;
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
#PulseWidth hs_clk = 1'b1;
|
#PulseWidth hs_clk = 1'b1;
|
#PulseWidth hs_clk = 1'b0;
|
#PulseWidth hs_clk = 1'b0;
|
if (tmpJitterPeriod == 0) begin
|
if (tmpJitterPeriod == 0) begin
|
tmpJitterCount = JitterCount;
|
tmpJitterCount = JitterCount;
|
end
|
end
|
tmpJitterPeriod = tmpJitterPeriod - 1;
|
tmpJitterPeriod = tmpJitterPeriod - 1;
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
#PulseWidth hs_clk = 1'b1;
|
#PulseWidth hs_clk = 1'b1;
|
#PulseWidth hs_clk = 1'b0;
|
#PulseWidth hs_clk = 1'b0;
|
end
|
end
|
end
|
end
|
|
|
always begin
|
always begin
|
if (JitterOnOff == TRUE) begin
|
if (JitterOnOff == TRUE) begin
|
if (tmpJitterCount > 0) begin
|
if (tmpJitterCount > 0) begin
|
#((PulseWidth * 8) - LowJitterTime) ls_clk = 1'b1;
|
#((PulseWidth * 8) - LowJitterTime) ls_clk = 1'b1;
|
#((PulseWidth * 8) - HighJitterTime) ls_clk = 1'b0;
|
#((PulseWidth * 8) - HighJitterTime) ls_clk = 1'b0;
|
tmpJitterCount = tmpJitterCount - 1;
|
tmpJitterCount = tmpJitterCount - 1;
|
if (tmpJitterCount == 0) begin
|
if (tmpJitterCount == 0) begin
|
tmpJitterPeriod = JitterPeriod;
|
tmpJitterPeriod = JitterPeriod;
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
#(PulseWidth * 8) ls_clk = 1'b1;
|
#(PulseWidth * 8) ls_clk = 1'b1;
|
#(PulseWidth * 8) ls_clk = 1'b0;
|
#(PulseWidth * 8) ls_clk = 1'b0;
|
if (tmpJitterPeriod == 0) begin
|
if (tmpJitterPeriod == 0) begin
|
tmpJitterCount = JitterCount;
|
tmpJitterCount = JitterCount;
|
end
|
end
|
tmpJitterPeriod = tmpJitterPeriod - 1;
|
tmpJitterPeriod = tmpJitterPeriod - 1;
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
#(PulseWidth * 8) ls_clk = 1'b1;
|
#(PulseWidth * 8) ls_clk = 1'b1;
|
#(PulseWidth * 8) ls_clk = 1'b0;
|
#(PulseWidth * 8) ls_clk = 1'b0;
|
end
|
end
|
end
|
end
|
|
|
initial // intialise pll clock signals
|
initial // intialise pll clock signals
|
begin
|
begin
|
tmpJitterPeriod = 0;
|
tmpJitterPeriod = 0;
|
tmpJitterCount = 0;
|
tmpJitterCount = 0;
|
dpll_reset_n = 1'b0;
|
dpll_reset_n = 1'b0;
|
#1 dpll_reset_n = 1'b1;
|
#1 dpll_reset_n = 1'b1;
|
end
|
end
|
|
|
initial // drive 6 MHz clock
|
initial // drive 6 MHz clock
|
begin
|
begin
|
clk6 = 1'b0;
|
clk6 = 1'b0;
|
forever #(PulseWidth * 2) clk6 = ~clk6;
|
forever #(PulseWidth * 2) clk6 = ~clk6;
|
end
|
end
|
|
|
initial // drive 48 MHz clock
|
initial // drive 48 MHz clock
|
begin
|
begin
|
clk48 = 1'b0;
|
clk48 = 1'b0;
|
HSClkComp = 1'b0;
|
HSClkComp = 1'b0;
|
HSClkCompToggle = 1'b0;
|
HSClkCompToggle = 1'b0;
|
case ((PulseWidth) % 4)
|
case ((PulseWidth) % 4)
|
0 : HSClkComp = 1'b0;
|
0 : HSClkComp = 1'b0;
|
1 : HSClkComp = 1'b0;
|
1 : HSClkComp = 1'b0;
|
2 : HSClkComp = 1'b1;
|
2 : HSClkComp = 1'b1;
|
3 : HSClkComp = 1'b1;
|
3 : HSClkComp = 1'b1;
|
default : HSClkComp = 1'b0;
|
default : HSClkComp = 1'b0;
|
endcase
|
endcase
|
forever begin
|
forever begin
|
#((PulseWidth / 4) + HSClkComp) clk48 = 1'b1;
|
#((PulseWidth / 4) + HSClkComp) clk48 = 1'b1;
|
case ((PulseWidth) % 4)
|
case ((PulseWidth) % 4)
|
0, 2 : begin
|
0, 2 : begin
|
#(PulseWidth / 4) clk48 = 1'b0;
|
#(PulseWidth / 4) clk48 = 1'b0;
|
HSClkComp = ((PulseWidth % 4) == 0) ? 1'b0 : 1'b1;
|
HSClkComp = ((PulseWidth % 4) == 0) ? 1'b0 : 1'b1;
|
end
|
end
|
1, 3 : begin
|
1, 3 : begin
|
if (HSClkCompToggle == 1'b0) begin
|
if (HSClkCompToggle == 1'b0) begin
|
#(PulseWidth / 4) clk48 = 1'b0;
|
#(PulseWidth / 4) clk48 = 1'b0;
|
HSClkCompToggle = 1'b1;
|
HSClkCompToggle = 1'b1;
|
end
|
end
|
else begin
|
else begin
|
#((PulseWidth / 4) + HSClkCompToggle) clk48 = 1'b0;
|
#((PulseWidth / 4) + HSClkCompToggle) clk48 = 1'b0;
|
HSClkCompToggle = 1'b0;
|
HSClkCompToggle = 1'b0;
|
end
|
end
|
HSClkComp = ((PulseWidth % 4) == 1) ? 1'b0 : 1'b1;
|
HSClkComp = ((PulseWidth % 4) == 1) ? 1'b0 : 1'b1;
|
end
|
end
|
default : clk48 = 1'b1;
|
default : clk48 = 1'b1;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
always @(dpll_clk) rec_clk = dpll_clk;
|
always @(dpll_clk) rec_clk = dpll_clk;
|
|
|
//initialise the encoder signals
|
//initialise the encoder signals
|
initial
|
initial
|
begin
|
begin
|
hs_clk = 1'b1;
|
hs_clk = 1'b1;
|
ls_clk = 1'b1;
|
ls_clk = 1'b1;
|
enc_enbl = 1'b0; // active high
|
enc_enbl = 1'b0; // active high
|
enc_reset_n = 1'b0; // active low
|
enc_reset_n = 1'b0; // active low
|
enc_data_in = 8'bZZZZZZZZ;
|
enc_data_in = 8'bZZZZZZZZ;
|
zDPLS = 1'bZ;
|
zDPLS = 1'bZ;
|
zDMNS = 1'bZ;
|
zDMNS = 1'bZ;
|
dec_enbl = 1'b0; // active high
|
dec_enbl = 1'b0; // active high
|
dec_reset_n = 1'b0; // active low
|
dec_reset_n = 1'b0; // active low
|
// dec_cnt;
|
// dec_cnt;
|
// user_commands; // Invoking the User Commands.
|
// user_commands; // Invoking the User Commands.
|
end
|
end
|
|
|
initial
|
initial
|
begin
|
begin
|
`ifdef USBF_DEBUG
|
`ifdef USBF_DEBUG
|
Debug = TRUE ;
|
Debug = TRUE ;
|
`else
|
`else
|
Debug = FALSE ;
|
Debug = FALSE ;
|
`endif
|
`endif
|
sofOnFlag = FALSE ;
|
sofOnFlag = FALSE ;
|
//sofPeriod = 1_000_000 ;
|
//sofPeriod = 1_000_000 ;
|
sofPeriod = 100_000 ;
|
sofPeriod = 100_000 ;
|
interruptOnFlag = FALSE ;
|
interruptOnFlag = FALSE ;
|
interruptRequest = FALSE ;
|
interruptRequest = FALSE ;
|
interruptTimer = 0 ;
|
interruptTimer = 0 ;
|
interruptPeriod = 0 ;
|
interruptPeriod = 0 ;
|
controlRequest = FALSE ;
|
controlRequest = FALSE ;
|
controlGrant = FALSE ;
|
controlGrant = FALSE ;
|
bulkInOnFlag = FALSE ;
|
bulkInOnFlag = FALSE ;
|
bulkOutOnFlag = FALSE ;
|
bulkOutOnFlag = FALSE ;
|
end
|
end
|
|
|
|
|
endmodule
|
endmodule
|
|
|
|
|
module usb_bfm_decoder(
|
module usb_bfm_decoder(
|
enable_in,
|
enable_in,
|
ser_data_rdy,
|
ser_data_rdy,
|
par_data_rdy,
|
par_data_rdy,
|
reset_n,
|
reset_n,
|
clk,
|
clk,
|
start_bit,
|
start_bit,
|
data_in,
|
data_in,
|
data_in_n,
|
data_in_n,
|
recv_bit_count,
|
recv_bit_count,
|
bit_stuff_err,
|
bit_stuff_err,
|
ser_data_out,
|
ser_data_out,
|
par_data_out
|
par_data_out
|
);
|
);
|
|
|
input enable_in;
|
input enable_in;
|
output ser_data_rdy;
|
output ser_data_rdy;
|
output par_data_rdy;
|
output par_data_rdy;
|
input clk;
|
input clk;
|
input start_bit;
|
input start_bit;
|
input data_in;
|
input data_in;
|
input data_in_n;
|
input data_in_n;
|
output recv_bit_count;
|
output [31:0] recv_bit_count;
|
output bit_stuff_err;
|
output bit_stuff_err;
|
output ser_data_out;
|
output ser_data_out;
|
output [7:0] par_data_out;
|
output [7:0] par_data_out;
|
input reset_n;
|
input reset_n;
|
|
|
reg enable_out;
|
reg enable_out;
|
reg [7:0] par_data_out;
|
reg [7:0] par_data_out;
|
reg ser_data_out;
|
reg ser_data_out;
|
reg prev_bit;
|
reg prev_bit;
|
reg prev_bit1;
|
reg prev_bit1;
|
reg tmpDataOut1;
|
reg tmpDataOut1;
|
reg [7:0] tmpDataOut;
|
reg [7:0] tmpDataOut;
|
reg [31:0] recv_bit_count;
|
reg [31:0] recv_bit_count;
|
reg bit_stuff_err;
|
reg bit_stuff_err;
|
reg ser_data_rdy;
|
reg ser_data_rdy;
|
reg par_data_rdy;
|
reg par_data_rdy;
|
reg JustEnabled;
|
reg JustEnabled;
|
|
|
reg [3:0] bit_count;
|
reg [3:0] bit_count;
|
reg [3:0] count;
|
reg [3:0] count;
|
reg SyncDetect;
|
reg SyncDetect;
|
|
|
initial begin
|
initial begin
|
enable_out = 1;
|
enable_out = 1;
|
ser_data_out = 1'bz;
|
ser_data_out = 1'bz;
|
ser_data_rdy = 1'b0;
|
ser_data_rdy = 1'b0;
|
par_data_out = 8'b0000_0000;
|
par_data_out = 8'b0000_0000;
|
bit_count = 0;
|
bit_count = 0;
|
count = 0;
|
count = 0;
|
tmpDataOut = 8'b00000000;
|
tmpDataOut = 8'b00000000;
|
tmpDataOut1 = 0;
|
tmpDataOut1 = 0;
|
JustEnabled = 1;
|
JustEnabled = 1;
|
par_data_rdy = 1'b0;
|
par_data_rdy = 1'b0;
|
recv_bit_count = 32'h0000_0000;
|
recv_bit_count = 32'h0000_0000;
|
bit_stuff_err = 1'b0;
|
bit_stuff_err = 1'b0;
|
end
|
end
|
|
|
|
|
|
|
always @(posedge clk) #1 prev_bit1 <= data_in;
|
always @(posedge clk) #1 prev_bit1 <= data_in;
|
|
|
always @(posedge clk) begin
|
always @(posedge clk) begin
|
|
|
if (!reset_n) begin
|
if (!reset_n) begin
|
count <= 0;
|
count <= 0;
|
recv_bit_count <= 1'b0;
|
recv_bit_count <= 1'b0;
|
bit_count <= 0;
|
bit_count <= 0;
|
par_data_out <= 8'b0000_0000;
|
par_data_out <= 8'b0000_0000;
|
end
|
end
|
|
|
if (enable_in) begin
|
if (enable_in) begin
|
if (count == 7 && !(bit_count==5 & (tmpDataOut1!=prev_bit))) begin
|
if (count == 7 && !(bit_count==5 & (tmpDataOut1!=prev_bit))) begin
|
par_data_rdy <= 1'b1;
|
par_data_rdy <= 1'b1;
|
end
|
end
|
if (bit_count < 5) begin
|
if (bit_count < 5) begin
|
if (count == 7) count <= 0;
|
if (count == 7) count <= 0;
|
else count <= count + 1;
|
else count <= count + 1;
|
par_data_out[count] <= tmpDataOut1;
|
par_data_out[count] <= tmpDataOut1;
|
recv_bit_count <= recv_bit_count + 1;
|
recv_bit_count <= recv_bit_count + 1;
|
ser_data_rdy <= 1'b1;
|
ser_data_rdy <= 1'b1;
|
ser_data_out <= tmpDataOut1;
|
ser_data_out <= tmpDataOut1;
|
end
|
end
|
else begin
|
else begin
|
if (tmpDataOut1 != 1'b0) begin
|
if (tmpDataOut1 != 1'b0) begin
|
bit_stuff_err <= 1'b1;
|
bit_stuff_err <= 1'b1;
|
end
|
end
|
ser_data_rdy <= 1'b0;
|
ser_data_rdy <= 1'b0;
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
bit_stuff_err <= 1'b0;
|
bit_stuff_err <= 1'b0;
|
par_data_rdy <= 1'b0;
|
par_data_rdy <= 1'b0;
|
end
|
end
|
|
|
prev_bit <= tmpDataOut1;
|
prev_bit <= tmpDataOut1;
|
|
|
if ((tmpDataOut1 == prev_bit) & (tmpDataOut1 == 1'b1)) begin
|
if ((tmpDataOut1 == prev_bit) & (tmpDataOut1 == 1'b1)) begin
|
bit_count <= bit_count + 1;
|
bit_count <= bit_count + 1;
|
end
|
end
|
else begin
|
else begin
|
bit_count <= 0;
|
bit_count <= 0;
|
end
|
end
|
|
|
if (bit_count == 5) bit_count <= 0;
|
if (bit_count == 5) bit_count <= 0;
|
|
|
if (prev_bit1 == data_in) tmpDataOut1 <= 1'b1;
|
if (prev_bit1 == data_in) tmpDataOut1 <= 1'b1;
|
else tmpDataOut1 <= 1'b0;
|
else tmpDataOut1 <= 1'b0;
|
|
|
if (par_data_rdy == 1'b1) par_data_rdy <= 1'b0;
|
if (par_data_rdy == 1'b1) par_data_rdy <= 1'b0;
|
|
|
end
|
end
|
|
|
|
|
endmodule
|
endmodule
|
|
|
module usb_bfm_encoder( enable_in,
|
module usb_bfm_encoder( enable_in,
|
reset_n,
|
reset_n,
|
clk,
|
clk,
|
bit_count_out,
|
bit_count_out,
|
count_out,
|
count_out,
|
data_out_valid,
|
data_out_valid,
|
gen_bit_stuff_err,
|
gen_bit_stuff_err,
|
last_byte,
|
last_byte,
|
start_bit,
|
start_bit,
|
data_in,
|
data_in,
|
data_out,
|
data_out,
|
data_out_n
|
data_out_n
|
);
|
);
|
|
|
//enable_in : 0 disables the block
|
//enable_in : 0 disables the block
|
// 1 enables the block
|
// 1 enables the block
|
//data_in : 8 bit wide register containing the parallel data
|
//data_in : 8 bit wide register containing the parallel data
|
//clk : Clock !!
|
//clk : Clock !!
|
//not used//data_in_valid : the data in data_in is a valid next block of data
|
//not used//data_in_valid : the data in data_in is a valid next block of data
|
//count_out : count[2]
|
//count_out : count[2]
|
//data_out : serial data out
|
//data_out : serial data out
|
//data_out_n : invert of data_out
|
//data_out_n : invert of data_out
|
//data_out_valid : the data on data_out is valid and can be sampled
|
//data_out_valid : the data on data_out is valid and can be sampled
|
//reset_n : synchronous reset of the block
|
//reset_n : synchronous reset of the block
|
|
|
input enable_in;
|
input enable_in;
|
input clk;
|
input clk;
|
input gen_bit_stuff_err;
|
input gen_bit_stuff_err;
|
input [7:0] data_in;
|
input [7:0] data_in;
|
input reset_n;
|
input reset_n;
|
input last_byte;
|
input last_byte;
|
input start_bit;
|
input start_bit;
|
|
|
output [3:0] bit_count_out;
|
output [3:0] bit_count_out;
|
output count_out;
|
output count_out;
|
output data_out;
|
output data_out;
|
output data_out_n;
|
output data_out_n;
|
output data_out_valid;
|
output data_out_valid;
|
|
|
reg [3:0] bit_count_out;
|
reg [3:0] bit_count_out;
|
reg count_out;
|
reg count_out;
|
reg data_out;
|
reg data_out;
|
reg data_out_n;
|
reg data_out_n;
|
reg data_out_valid;
|
reg data_out_valid;
|
reg tmpDataOut1;
|
reg tmpDataOut1;
|
reg tmpDataOut2;
|
reg tmpDataOut2;
|
reg prev_bit;
|
reg prev_bit;
|
reg tmpDataOut;
|
reg tmpDataOut;
|
|
|
reg [3:0] count;
|
reg [3:0] count;
|
reg [3:0] bit_count;
|
reg [3:0] bit_count;
|
reg [7:0] tmpDataIn;
|
reg [7:0] tmpDataIn;
|
|
|
initial begin
|
initial begin
|
data_out = 1'bZ;
|
data_out = 1'bZ;
|
data_out_n = 1'bZ;
|
data_out_n = 1'bZ;
|
count = 0;
|
count = 0;
|
bit_count = 0;
|
bit_count = 0;
|
bit_count_out = 0;
|
bit_count_out = 0;
|
count_out = 0;
|
count_out = 0;
|
data_out_valid = 0;
|
data_out_valid = 0;
|
tmpDataOut1 = start_bit;
|
tmpDataOut1 = start_bit;
|
tmpDataOut = 0;
|
tmpDataOut = 0;
|
prev_bit = 0;
|
prev_bit = 0;
|
end
|
end
|
|
|
always @(posedge clk) begin
|
always @(posedge clk) begin
|
if (enable_in) begin
|
if (enable_in) begin
|
if (count == 0) tmpDataIn = data_in;
|
if (count == 0) tmpDataIn = data_in;
|
if (count < 8) begin
|
if (count < 8) begin
|
tmpDataOut = tmpDataIn[count];
|
tmpDataOut = tmpDataIn[count];
|
if ((tmpDataOut) & (prev_bit)) begin
|
if ((tmpDataOut) & (prev_bit)) begin
|
bit_count = bit_count + 1;
|
bit_count = bit_count + 1;
|
end
|
end
|
else begin
|
else begin
|
if (tmpDataOut) bit_count = 1;
|
if (tmpDataOut) bit_count = 1;
|
else begin
|
else begin
|
if (bit_count == 6) bit_count = 7;
|
if (bit_count == 6) bit_count = 7;
|
else bit_count = 0;
|
else bit_count = 0;
|
end
|
end
|
end
|
end
|
if (bit_count == 7) begin
|
if (bit_count == 7) begin
|
if (gen_bit_stuff_err == 1'b0) begin
|
if (gen_bit_stuff_err == 1'b0) begin
|
|
|
tmpDataOut1 = ~tmpDataOut1;
|
tmpDataOut1 = ~tmpDataOut1;
|
prev_bit = 1'b0;
|
prev_bit = 1'b0;
|
end
|
end
|
else begin
|
else begin
|
tmpDataOut1 = tmpDataOut1;
|
tmpDataOut1 = tmpDataOut1;
|
prev_bit = 1'b1;
|
prev_bit = 1'b1;
|
end
|
end
|
bit_count = 0;
|
bit_count = 0;
|
end
|
end
|
else begin
|
else begin
|
if (tmpDataIn[count] == 0) tmpDataOut1 = ~tmpDataOut1;
|
if (tmpDataIn[count] == 0) tmpDataOut1 = ~tmpDataOut1;
|
count = count + 1;
|
count = count + 1;
|
prev_bit = tmpDataOut;
|
prev_bit = tmpDataOut;
|
end
|
end
|
data_out = #1 tmpDataOut1;
|
data_out = #1 tmpDataOut1;
|
data_out_n = ~tmpDataOut1;
|
data_out_n = ~tmpDataOut1;
|
data_out_valid = 1;
|
data_out_valid = 1;
|
end
|
end
|
if (count == 8) count = 0;
|
if (count == 8) count = 0;
|
if (bit_count != 6) count_out = count[2];
|
if (bit_count != 6) count_out = count[2];
|
bit_count_out = count;
|
bit_count_out = count;
|
end
|
end
|
else begin
|
else begin
|
data_out = #1 1'bz;
|
data_out = #1 1'bz;
|
data_out_n = 1'bz;
|
data_out_n = 1'bz;
|
data_out_valid = 0;
|
data_out_valid = 0;
|
end
|
end
|
|
|
if (!reset_n) begin
|
if (!reset_n) begin
|
count = 0;
|
count = 0;
|
count_out = 0;
|
count_out = 0;
|
bit_count = 0;
|
bit_count = 0;
|
data_out_valid = 0;
|
data_out_valid = 0;
|
tmpDataIn = 8'h00;
|
tmpDataIn = 8'h00;
|
tmpDataOut1 = start_bit;
|
tmpDataOut1 = start_bit;
|
tmpDataOut = 0;
|
tmpDataOut = 0;
|
prev_bit = 0;
|
prev_bit = 0;
|
data_out = #1 1'bz;
|
data_out = #1 1'bz;
|
data_out_n = 1'bz;
|
data_out_n = 1'bz;
|
end
|
end
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
module usb_bfm_dpll (clk48, clk6, switch, reset_n, data_in, rec_clk, data_out);
|
module usb_bfm_dpll (clk48, clk6, switch, reset_n, data_in, rec_clk, data_out);
|
|
|
input clk48, clk6, switch, reset_n, data_in;
|
input clk48, clk6, switch, reset_n, data_in;
|
|
|
output rec_clk, data_out;
|
output rec_clk, data_out;
|
|
|
wire rec_clk;
|
wire rec_clk;
|
wire data_out;
|
wire data_out;
|
wire nrz;
|
wire nrz;
|
wire dpll_clk;
|
wire dpll_clk;
|
|
|
assign data_out = nrz;
|
assign data_out = nrz;
|
|
|
wire diff_pulse;
|
wire diff_pulse;
|
|
|
// Instance of the clock switch
|
// Instance of the clock switch
|
usb_bfm_clk_switch clk_switch (.clk1 (clk48),
|
usb_bfm_clk_switch clk_switch (.clk1 (clk48),
|
.clk2 (clk6),
|
.clk2 (clk6),
|
.switch (switch),
|
.switch (switch),
|
.reset_n (reset_n),
|
.reset_n (reset_n),
|
.clk_out (dpll_clk));
|
.clk_out (dpll_clk));
|
|
|
// Instance of NRZI to NRZ converter
|
// Instance of NRZI to NRZ converter
|
usb_bfm_nrzi2nrz nrzi2nrz_inst (.nrzi (data_in),
|
usb_bfm_nrzi2nrz nrzi2nrz_inst (.nrzi (data_in),
|
.rec_clk (rec_clk),
|
.rec_clk (rec_clk),
|
.reset_n (reset_n),
|
.reset_n (reset_n),
|
.nrz (nrz));
|
.nrz (nrz));
|
|
|
// Instance of the phase detect
|
// Instance of the phase detect
|
usb_bfm_ph_detect ph_detect (.dpll_clk (dpll_clk),
|
usb_bfm_ph_detect ph_detect (.dpll_clk (dpll_clk),
|
.rst_n (reset_n),
|
.rst_n (reset_n),
|
.data_in (data_in),
|
.data_in (data_in),
|
.rec_clk (rec_clk),
|
.rec_clk (rec_clk),
|
.diff_pulse (diff_pulse));
|
.diff_pulse (diff_pulse));
|
|
|
// Instance of the pulse puller state machine
|
// Instance of the pulse puller state machine
|
usb_bfm_pulse_puller pulse_puller (.clk (dpll_clk),
|
usb_bfm_pulse_puller pulse_puller (.clk (dpll_clk),
|
.diff_pulse (diff_pulse),
|
.diff_pulse (diff_pulse),
|
.rst_n (reset_n),
|
.rst_n (reset_n),
|
.rec_clk (rec_clk));
|
.rec_clk (rec_clk));
|
|
|
endmodule
|
endmodule
|
|
|
|
|
// The clock switch module for selecting a low/high speed PLL
|
// The clock switch module for selecting a low/high speed PLL
|
|
|
module usb_bfm_clk_switch (clk1, clk2, switch, reset_n, clk_out);
|
module usb_bfm_clk_switch (clk1, clk2, switch, reset_n, clk_out);
|
|
|
input clk1, clk2, switch, reset_n;
|
input clk1, clk2, switch, reset_n;
|
output clk_out;
|
output clk_out;
|
|
|
wire ff1set, ff1clr, ff3clr, clk_out;
|
wire ff1set, ff1clr, ff3clr, clk_out;
|
reg ff1out, ff2out_bar, ff3out, ff3out_bar, ff4out_bar;
|
reg ff1out, ff2out_bar, ff3out, ff3out_bar, ff4out_bar;
|
|
|
assign ff1set = ff4out_bar;
|
assign ff1set = ff4out_bar;
|
assign ff1clr = reset_n;
|
assign ff1clr = reset_n;
|
assign ff3clr = ff2out_bar;
|
assign ff3clr = ff2out_bar;
|
assign clk_out = ((ff1out | clk1) & (ff3out_bar | clk2));
|
assign clk_out = ((ff1out | clk1) & (ff3out_bar | clk2));
|
|
|
parameter LOW = 1'b0;
|
parameter LOW = 1'b0;
|
parameter HIGH = 1'b1;
|
parameter HIGH = 1'b1;
|
|
|
//Filp Flop # 1
|
//Filp Flop # 1
|
|
|
always @ (posedge clk1 or negedge ff1set or negedge ff1clr) begin
|
always @ (posedge clk1 or negedge ff1set or negedge ff1clr) begin
|
|
|
if (ff1clr === LOW) begin
|
if (ff1clr === LOW) begin
|
ff1out = LOW;
|
ff1out = LOW;
|
end
|
end
|
else if (ff1set === LOW) begin
|
else if (ff1set === LOW) begin
|
ff1out = HIGH;
|
ff1out = HIGH;
|
end
|
end
|
else
|
else
|
ff1out <= switch;
|
ff1out <= switch;
|
end
|
end
|
|
|
//Flip Flop # 2
|
//Flip Flop # 2
|
|
|
always @ (posedge clk2) begin
|
always @ (posedge clk2) begin
|
ff2out_bar <= (ff1out);
|
ff2out_bar <= (ff1out);
|
end
|
end
|
|
|
//Flip Flop #3
|
//Flip Flop #3
|
|
|
always @ (posedge clk2 or negedge ff3clr) begin
|
always @ (posedge clk2 or negedge ff3clr) begin
|
|
|
if (ff3clr === LOW) begin
|
if (ff3clr === LOW) begin
|
ff3out <= LOW;
|
ff3out <= LOW;
|
ff3out_bar <= HIGH;
|
ff3out_bar <= HIGH;
|
end
|
end
|
else begin
|
else begin
|
ff3out <= switch;
|
ff3out <= switch;
|
ff3out_bar <= !switch;
|
ff3out_bar <= !switch;
|
end
|
end
|
end
|
end
|
|
|
//Flip Flop #4
|
//Flip Flop #4
|
|
|
always @ (posedge clk1) begin
|
always @ (posedge clk1) begin
|
ff4out_bar <= ! (ff3out);
|
ff4out_bar <= ! (ff3out);
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
// The NRZI to NRZ converter
|
// The NRZI to NRZ converter
|
|
|
module usb_bfm_nrzi2nrz (nrzi, rec_clk, reset_n, nrz);
|
module usb_bfm_nrzi2nrz (nrzi, rec_clk, reset_n, nrz);
|
|
|
input nrzi, rec_clk, reset_n;
|
input nrzi, rec_clk, reset_n;
|
output nrz;
|
output nrz;
|
|
|
wire nrz;
|
wire nrz;
|
|
|
wire D1, D2, D0;
|
wire D1, D2, D0;
|
reg Q1, Q2, Q0;
|
reg Q1, Q2, Q0;
|
reg del_rec_clk;
|
reg del_rec_clk;
|
|
|
assign D0 = nrzi;
|
assign D0 = nrzi;
|
assign D1 = Q0;
|
assign D1 = Q0;
|
assign D2 = !(Q0^Q1);
|
assign D2 = !(Q0^Q1);
|
assign nrz = Q2;
|
assign nrz = Q2;
|
|
|
//NRZI to NRZ converter
|
//NRZI to NRZ converter
|
|
|
always @ (reset_n) begin
|
always @ (reset_n) begin
|
if (!reset_n) begin
|
if (!reset_n) begin
|
Q0 <= 1'b0;
|
Q0 <= 1'b0;
|
Q1 <= 1'b0;
|
Q1 <= 1'b0;
|
Q2 <= 1'b0;
|
Q2 <= 1'b0;
|
end
|
end
|
end
|
end
|
|
|
always @ (rec_clk) begin
|
always @ (rec_clk) begin
|
del_rec_clk <= #21 rec_clk;
|
del_rec_clk <= #21 rec_clk;
|
end
|
end
|
|
|
always @(posedge del_rec_clk) begin
|
always @(posedge del_rec_clk) begin
|
Q0 <= D0;
|
Q0 <= D0;
|
Q1 <= D1;
|
Q1 <= D1;
|
Q2 <= D2;
|
Q2 <= D2;
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
// The Phase detector
|
// The Phase detector
|
|
|
module usb_bfm_ph_detect (dpll_clk, rst_n, data_in, rec_clk, diff_pulse);
|
module usb_bfm_ph_detect (dpll_clk, rst_n, data_in, rec_clk, diff_pulse);
|
|
|
input dpll_clk, rst_n, data_in, rec_clk;
|
input dpll_clk, rst_n, data_in, rec_clk;
|
output diff_pulse;
|
output diff_pulse;
|
|
|
wire diff_pulse;
|
wire diff_pulse;
|
|
|
reg Q0;
|
reg Q0;
|
reg rec_clk_neg_edge;
|
reg rec_clk_neg_edge;
|
reg gate_control;
|
reg gate_control;
|
|
|
assign diff_pulse = (Q0 ^ data_in) & gate_control;
|
assign diff_pulse = (Q0 ^ data_in) & gate_control;
|
|
|
always @ (posedge dpll_clk or negedge rst_n) begin
|
always @ (posedge dpll_clk or negedge rst_n) begin
|
if (rst_n) begin
|
if (rst_n) begin
|
if ((Q0 ^ data_in) & rec_clk_neg_edge) begin
|
if ((Q0 ^ data_in) & rec_clk_neg_edge) begin
|
gate_control <= 1'b0;
|
gate_control <= 1'b0;
|
rec_clk_neg_edge <= 1'b0;
|
rec_clk_neg_edge <= 1'b0;
|
end
|
end
|
end
|
end
|
else begin
|
else begin
|
gate_control <= 1'b1;
|
gate_control <= 1'b1;
|
rec_clk_neg_edge <= 1'b0;
|
rec_clk_neg_edge <= 1'b0;
|
end
|
end
|
rec_clk_neg_edge <= 1'b0;
|
rec_clk_neg_edge <= 1'b0;
|
end
|
end
|
|
|
always @ (negedge rec_clk or negedge rst_n) begin
|
always @ (negedge rec_clk or negedge rst_n) begin
|
if (rst_n) begin
|
if (rst_n) begin
|
Q0 <= data_in;
|
Q0 <= data_in;
|
rec_clk_neg_edge <= 1'b1;
|
rec_clk_neg_edge <= 1'b1;
|
gate_control <= 1'b1;
|
gate_control <= 1'b1;
|
end
|
end
|
else begin
|
else begin
|
Q0 <= 1'b0;
|
Q0 <= 1'b0;
|
end
|
end
|
end
|
end
|
endmodule
|
endmodule
|
|
|
// The State m/c which does the Phase Correction
|
// The State m/c which does the Phase Correction
|
|
|
module usb_bfm_pulse_puller (clk, diff_pulse, rst_n, rec_clk);
|
module usb_bfm_pulse_puller (clk, diff_pulse, rst_n, rec_clk);
|
|
|
input clk, rst_n, diff_pulse;
|
input clk, rst_n, diff_pulse;
|
output rec_clk;
|
output rec_clk;
|
|
|
reg rec_clk;
|
reg rec_clk;
|
|
|
reg [3:0] State;
|
reg [3:0] State;
|
|
|
reg correct_pulse;
|
reg correct_pulse;
|
|
|
reg Q0;
|
reg Q0;
|
|
|
parameter HIGH = 1'b1;
|
parameter HIGH = 1'b1;
|
parameter LOW = 1'b0;
|
parameter LOW = 1'b0;
|
|
|
parameter S0 = 3'b000;
|
parameter S0 = 3'b000;
|
parameter S1 = 3'b001;
|
parameter S1 = 3'b001;
|
parameter S2 = 3'b010;
|
parameter S2 = 3'b010;
|
parameter S3 = 3'b011;
|
parameter S3 = 3'b011;
|
parameter S4 = 3'b100;
|
parameter S4 = 3'b100;
|
|
|
// Generation of the correcting pulse from the Phase difference between the
|
// Generation of the correcting pulse from the Phase difference between the
|
// data transition and negative edge of recovered clock
|
// data transition and negative edge of recovered clock
|
|
|
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
Q0 <= diff_pulse;
|
Q0 <= diff_pulse;
|
correct_pulse <= Q0 & diff_pulse;
|
correct_pulse <= Q0 & diff_pulse;
|
end
|
end
|
|
|
// The pulse_puller state machine
|
// The pulse_puller state machine
|
|
|
always @ (posedge clk or negedge rst_n) begin
|
always @ (posedge clk or negedge rst_n) begin
|
|
|
if (!rst_n) begin
|
if (!rst_n) begin
|
State <= S0;
|
State <= S0;
|
rec_clk <= LOW;
|
rec_clk <= LOW;
|
end
|
end
|
else begin
|
else begin
|
|
|
case (State)
|
case (State)
|
|
|
S0 : begin
|
S0 : begin
|
State <= S1;
|
State <= S1;
|
rec_clk <= ~rec_clk;
|
rec_clk <= ~rec_clk;
|
end
|
end
|
|
|
S1 : if (correct_pulse) begin
|
S1 : if (correct_pulse) begin
|
rec_clk <= ~rec_clk;
|
rec_clk <= ~rec_clk;
|
State <= S3;
|
State <= S3;
|
end
|
end
|
else begin
|
else begin
|
rec_clk <= rec_clk;
|
rec_clk <= rec_clk;
|
State <= S2;
|
State <= S2;
|
end
|
end
|
|
|
S2 : begin
|
S2 : begin
|
if (correct_pulse) begin
|
if (correct_pulse) begin
|
State <= S4;
|
State <= S4;
|
end
|
end
|
else begin
|
else begin
|
State <= S3;
|
State <= S3;
|
end
|
end
|
rec_clk <= ~rec_clk;
|
rec_clk <= ~rec_clk;
|
end
|
end
|
|
|
S3 : if (correct_pulse) begin
|
S3 : if (correct_pulse) begin
|
State <= S1;
|
State <= S1;
|
rec_clk <= ~rec_clk;
|
rec_clk <= ~rec_clk;
|
end
|
end
|
else begin
|
else begin
|
rec_clk <= rec_clk;
|
rec_clk <= rec_clk;
|
State <= S4;
|
State <= S4;
|
end
|
end
|
|
|
S4 : begin
|
S4 : begin
|
if (correct_pulse) begin
|
if (correct_pulse) begin
|
State <= S2;
|
State <= S2;
|
end
|
end
|
else begin
|
else begin
|
State <= S1;
|
State <= S1;
|
end
|
end
|
rec_clk <= ~rec_clk;
|
rec_clk <= ~rec_clk;
|
end
|
end
|
|
|
default :
|
default :
|
$display ("Illegal State at ",$time);
|
$display ("Illegal State at ",$time);
|
|
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|
|
|
|
|