usbsim.vhd
1544 lines
| 56.5 KiB
| text/x-vhdl
|
VhdlLexer
martin
|
r100 | ------------------------------------------------------------------------------ | ||
-- This file is a part of the GRLIB VHDL IP LIBRARY | ||||
-- Copyright (C) 2003 - 2008, Gaisler Research | ||||
-- Copyright (C) 2008 - 2010, Aeroflex Gaisler | ||||
-- | ||||
-- This program is free software; you can redistribute it and/or modify | ||||
-- it under the terms of the GNU General Public License as published by | ||||
-- the Free Software Foundation; either version 2 of the License, or | ||||
-- (at your option) any later version. | ||||
-- | ||||
-- This program is distributed in the hope that it will be useful, | ||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
-- GNU General Public License for more details. | ||||
-- | ||||
-- You should have received a copy of the GNU General Public License | ||||
-- along with this program; if not, write to the Free Software | ||||
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
----------------------------------------------------------------------------- | ||||
-- Package: usbsim | ||||
-- File: usbsim.vhd | ||||
-- Author: Jonas Ekergarn - Aeroflex Gaisler | ||||
-- Description: Types, constants and procedures used when simulating both | ||||
-- GRUSBDC and GRUSB_DCL | ||||
------------------------------------------------------------------------------ | ||||
-- pragma translate_off | ||||
library ieee; | ||||
use ieee.std_logic_1164.all; | ||||
use std.textio.all; | ||||
library grlib; | ||||
use grlib.stdlib.all; | ||||
package usbsim is | ||||
type octet_vector is array (natural range <>) of std_logic_vector(7 downto 0); | ||||
type grusb_in_type is record | ||||
datain : std_logic_vector(15 downto 0); | ||||
rxactive : std_ulogic; | ||||
rxvalid : std_ulogic; | ||||
rxvalidh : std_ulogic; | ||||
rxerror : std_ulogic; | ||||
txready : std_ulogic; | ||||
linestate : std_logic_vector(1 downto 0); | ||||
nxt : std_ulogic; | ||||
dir : std_ulogic; | ||||
vbusvalid : std_ulogic; | ||||
hostdisconnect : std_ulogic; | ||||
functesten : std_ulogic; | ||||
end record; | ||||
type grusb_out_type is record | ||||
dataout : std_logic_vector(15 downto 0); | ||||
txvalid : std_ulogic; | ||||
txvalidh : std_ulogic; | ||||
opmode : std_logic_vector(1 downto 0); | ||||
xcvrselect : std_logic_vector(1 downto 0); | ||||
termselect : std_ulogic; | ||||
suspendm : std_ulogic; | ||||
reset : std_ulogic; | ||||
stp : std_ulogic; | ||||
oen : std_ulogic; | ||||
databus16_8 : std_ulogic; | ||||
dppulldown : std_ulogic; | ||||
dmpulldown : std_ulogic; | ||||
idpullup : std_ulogic; | ||||
drvvbus : std_ulogic; | ||||
dischrgvbus : std_ulogic; | ||||
chrgvbus : std_ulogic; | ||||
txbitstuffenable : std_ulogic; | ||||
txbitstuffenableh : std_ulogic; | ||||
fslsserialmode : std_ulogic; | ||||
tx_enable_n : std_ulogic; | ||||
tx_dat : std_ulogic; | ||||
tx_se0 : std_ulogic; | ||||
end record; | ||||
----------------------------------------------------------------------------- | ||||
-- various test procedures for usb. | ||||
----------------------------------------------------------------------------- | ||||
--Endpoint numbers | ||||
constant EP0 : std_logic_vector(3 downto 0) := "0000"; | ||||
constant EP1 : std_logic_vector(3 downto 0) := "0001"; | ||||
constant EP2 : std_logic_vector(3 downto 0) := "0010"; | ||||
constant EP3 : std_logic_vector(3 downto 0) := "0011"; | ||||
constant EP4 : std_logic_vector(3 downto 0) := "0100"; | ||||
constant EP5 : std_logic_vector(3 downto 0) := "0101"; | ||||
constant EP6 : std_logic_vector(3 downto 0) := "0110"; | ||||
constant EP7 : std_logic_vector(3 downto 0) := "0111"; | ||||
constant EP8 : std_logic_vector(3 downto 0) := "1000"; | ||||
constant EP9 : std_logic_vector(3 downto 0) := "1001"; | ||||
constant EP10 : std_logic_vector(3 downto 0) := "1010"; | ||||
constant EP11 : std_logic_vector(3 downto 0) := "1011"; | ||||
constant EP12 : std_logic_vector(3 downto 0) := "1100"; | ||||
constant EP13 : std_logic_vector(3 downto 0) := "1101"; | ||||
constant EP14 : std_logic_vector(3 downto 0) := "1110"; | ||||
constant EP15 : std_logic_vector(3 downto 0) := "1111"; | ||||
------------------------------------------------------------------------------- | ||||
--usb pid constants | ||||
constant TOUT : std_logic_vector( 3 downto 0) := "0001"; | ||||
constant TIN : std_logic_vector( 3 downto 0) := "1001"; | ||||
constant SOF : std_logic_vector( 3 downto 0) := "0101"; | ||||
constant SETUP : std_logic_vector( 3 downto 0) := "1101"; | ||||
--data | ||||
constant DATA0 : std_logic_vector( 3 downto 0) := "0011"; | ||||
constant DATA1 : std_logic_vector( 3 downto 0) := "1011"; | ||||
constant DATA2 : std_logic_vector( 3 downto 0) := "0111"; | ||||
constant MDATA : std_logic_vector( 3 downto 0) := "1111"; | ||||
--handshake | ||||
constant TACK : std_logic_vector( 3 downto 0) := "0010"; | ||||
constant TNAK : std_logic_vector( 3 downto 0) := "1010"; | ||||
constant TSTALL : std_logic_vector( 3 downto 0) := "1110"; | ||||
constant TNYET : std_logic_vector( 3 downto 0) := "0110"; | ||||
--special | ||||
constant PRE : std_logic_vector( 3 downto 0) := "1100"; | ||||
constant ERR : std_logic_vector( 3 downto 0) := "1100"; | ||||
constant SPLIT : std_logic_vector( 3 downto 0) := "1000"; | ||||
constant PING : std_logic_vector( 3 downto 0) := "0100"; | ||||
constant RESERVED : std_logic_vector( 3 downto 0) := "0000"; | ||||
-- line states | ||||
constant SE0 : std_logic_vector(1 downto 0) := "00"; | ||||
constant J_STATE : std_logic_vector(1 downto 0) := "01"; | ||||
constant K_STATE : std_logic_vector(1 downto 0) := "10"; | ||||
constant SE1 : std_logic_vector(1 downto 0) := "11"; | ||||
-- opcode | ||||
constant NORM_OP : std_logic_vector(1 downto 0) := "00"; | ||||
constant NON_DRIV : std_logic_vector(1 downto 0) := "01"; | ||||
constant NO_NRZI : std_logic_vector(1 downto 0) := "10"; | ||||
-- ULPI PHY registers combined with regwrite bits | ||||
constant FCTRL_WADDR : std_logic_vector(7 downto 0) := X"84"; | ||||
constant FCTRL_SADDR : std_logic_vector(7 downto 0) := X"85"; | ||||
constant FCTRL_CADDR : std_logic_vector(7 downto 0) := X"86"; | ||||
-- ULPI RXCMDs | ||||
constant RXCMD_novbus : std_logic_vector(7 downto 0) := "00000000"; | ||||
constant RXCMD_fsidle : std_logic_vector(7 downto 0) := "00001101"; | ||||
constant RXCMD_hsidle : std_logic_vector(7 downto 0) := "00001100"; | ||||
constant RXCMD_jstate : std_logic_vector(7 downto 0) := "00001101"; | ||||
constant RXCMD_kstate : std_logic_vector(7 downto 0) := "00001110"; | ||||
constant RXCMD_se0state : std_logic_vector(7 downto 0) := "00001100"; | ||||
constant RXCMD_fsrxactive : std_logic_vector(7 downto 0) := "00011110"; | ||||
constant RXCMD_hsrxactive : std_logic_vector(7 downto 0) := "00011101"; | ||||
constant RXCMD_eopj : std_logic_vector(7 downto 0) := "00011101"; | ||||
constant RXCMD_eopse0 : std_logic_vector(7 downto 0) := "00011100"; | ||||
type uctrl_type is record | ||||
termselect : std_ulogic; | ||||
xcvrselect : std_logic_vector(1 downto 0); | ||||
opmode : std_logic_vector(1 downto 0); | ||||
suspendm : std_ulogic; | ||||
end record; | ||||
-- init usb signals | ||||
constant usbi_none : grusb_in_type := ( | ||||
datain => "ZZZZZZZZ" & "00000000", | ||||
rxactive => '0', | ||||
rxvalid => '0', | ||||
rxvalidh => 'Z', | ||||
rxerror => '0', | ||||
txready => '0', | ||||
linestate => "00", | ||||
nxt => '0', | ||||
dir => '0', | ||||
vbusvalid => '1', | ||||
hostdisconnect => '0', | ||||
functesten => '1'); | ||||
constant usbo_none : grusb_out_type := ( | ||||
dataout => "ZZZZZZZZ" & "00000000", | ||||
txvalid => '0', | ||||
txvalidh => 'Z', | ||||
opmode => "00", | ||||
xcvrselect => "00", | ||||
termselect => '0', | ||||
suspendm => '0', | ||||
reset => '0', | ||||
stp => '0', | ||||
oen => '0', | ||||
databus16_8 => '0', | ||||
dppulldown => '0', | ||||
dmpulldown => '0', | ||||
idpullup => '0', | ||||
drvvbus => '0', | ||||
dischrgvbus => '0', | ||||
chrgvbus => '0', | ||||
txbitstuffenable => '0', | ||||
txbitstuffenableh => '0', | ||||
fslsserialmode => '0', | ||||
tx_enable_n => '0', | ||||
tx_dat => '0', | ||||
tx_se0 => '0' | ||||
); | ||||
function crc5 ( | ||||
constant din : std_logic_vector(10 downto 0)) | ||||
return std_logic_vector; | ||||
function crc16 ( | ||||
constant din : std_logic_vector(7 downto 0); | ||||
constant crc16in : std_logic_vector(15 downto 0)) | ||||
return std_logic_vector; | ||||
function pidtostr( | ||||
constant pid : std_logic_vector(3 downto 0)) | ||||
return string; | ||||
procedure uprint( | ||||
constant Comment: in String := "-"; | ||||
constant Severe: in Severity_Level := Note; | ||||
constant Screen: in Boolean := True); | ||||
procedure gen_rxcmd ( | ||||
signal clk : in std_ulogic; | ||||
signal usbi : out grusb_in_type; | ||||
constant rxcmd : in std_logic_vector(7 downto 0)); | ||||
procedure accept_regwrite ( | ||||
signal clk : in std_ulogic; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
signal uctrl : out uctrl_type); | ||||
procedure accept_regread ( | ||||
signal clk : in std_ulogic; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
constant vbus : in std_ulogic); | ||||
procedure ulpi_reset ( | ||||
signal clk : in std_ulogic; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
signal uctrl : out uctrl_type; | ||||
constant pullup : in boolean; | ||||
constant keepclk : in boolean); | ||||
procedure sendpacket( | ||||
signal clk : in std_ulogic; | ||||
constant len : in integer; | ||||
constant data : in octet_vector; | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
signal usbi : out grusb_in_type; | ||||
signal hs : in std_ulogic); | ||||
procedure receivepacket( | ||||
signal clk : in std_ulogic; | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
variable len : out integer; | ||||
variable data : out octet_vector; | ||||
variable TP : inout boolean; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
signal hs : in std_ulogic; | ||||
variable timeout : out boolean); | ||||
procedure ttoken( | ||||
signal clk : in std_ulogic; | ||||
constant len : in integer range 0 to 16:= 3; | ||||
constant pid : in std_logic_vector(3 downto 0); | ||||
constant piderr : in boolean := false; | ||||
constant crcerr : in boolean := false; | ||||
constant device_address : in std_logic_vector(6 downto 0); | ||||
constant endpoint_number : in std_logic_vector(3 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
signal usbi : out grusb_in_type; | ||||
signal hs : in std_ulogic); | ||||
procedure tsof( | ||||
signal clk : in std_ulogic; | ||||
constant len : in integer range 0 to 16 := 3; | ||||
constant fno : in std_logic_vector(10 downto 0); | ||||
constant piderr : in boolean; | ||||
constant crcerr : in boolean; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal hs : in std_ulogic); | ||||
procedure tdata ( | ||||
signal clk : in std_ulogic; | ||||
constant pid : in std_logic_vector(3 downto 0); | ||||
constant piderr : in boolean := false; | ||||
constant crcerr : in boolean := false; | ||||
constant data : in octet_vector; | ||||
constant len : in integer range 0 to 3072; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal hs : in std_ulogic); | ||||
procedure rhandshake ( | ||||
signal clk : in std_ulogic; | ||||
constant expected : in std_logic_vector(3 downto 0); | ||||
constant nyet : in boolean := false; | ||||
constant nak : in boolean := false; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
variable TP : inout boolean; | ||||
variable gotnak : out boolean; | ||||
signal hs : in std_ulogic; | ||||
variable timeout : out boolean); | ||||
procedure rhandshake ( | ||||
signal clk : in std_ulogic; | ||||
constant expected : in std_logic_vector(3 downto 0); | ||||
constant nyet : in boolean := false; | ||||
constant nak : in boolean := false; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
variable TP : inout boolean; | ||||
variable gotnak : out boolean; | ||||
variable gotnyet : out boolean; | ||||
signal hs : in std_ulogic; | ||||
variable timeout : out boolean); | ||||
procedure rdata( | ||||
signal clk : in std_ulogic; | ||||
constant expected : in std_logic_vector(3 downto 0); | ||||
constant nak : in boolean := false; | ||||
constant nbytes : in integer; | ||||
constant expdata : in octet_vector; | ||||
constant ep : in integer; | ||||
constant device_address : in std_logic_vector(6 downto 0); | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
variable TP : inout boolean; | ||||
constant verbose : in boolean; | ||||
signal hs : in std_ulogic; | ||||
constant retryiso : in boolean; | ||||
variable timeout : out boolean); | ||||
procedure rdata( | ||||
signal clk : in std_ulogic; | ||||
constant expected : in std_logic_vector(3 downto 0); | ||||
constant nak : in boolean := false; | ||||
constant nbytes : in integer; | ||||
constant expdata : in octet_vector; | ||||
constant ep : in integer; | ||||
constant device_address : in std_logic_vector(6 downto 0); | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
variable TP : inout boolean; | ||||
constant verbose : in boolean; | ||||
signal hs : in std_ulogic; | ||||
constant retryiso : in boolean; | ||||
variable timeout : out boolean; | ||||
variable recdata : out octet_vector; | ||||
constant checkdata : in boolean); | ||||
procedure shandshake ( | ||||
signal clk : in std_ulogic; | ||||
constant hpid : in std_logic_vector(3 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
signal usbi : out grusb_in_type; | ||||
signal hs : in std_ulogic); | ||||
procedure getstatus ( | ||||
constant dir : in std_logic_vector(3 downto 0); | ||||
constant stall : in boolean := false; | ||||
constant nak : in boolean := true; | ||||
signal clk : in std_ulogic; | ||||
signal usbo : in grusb_out_type; | ||||
signal usbi : out grusb_in_type; | ||||
constant ep : in integer; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
constant device_address : in std_logic_vector(6 downto 0); | ||||
variable TP : inout boolean; | ||||
signal hs : in std_ulogic; | ||||
variable timeout : out boolean); | ||||
procedure hs_handshake ( | ||||
signal clk : in std_ulogic; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
signal uctrl : out uctrl_type; | ||||
signal hs : in std_ulogic; | ||||
constant uiface : in integer); | ||||
end usbsim; | ||||
package body usbsim is | ||||
----------------------------------------------------------------------------- | ||||
--usb crc5 calculator. | ||||
--in: std_logic_vector(10 downto 0) | ||||
--out: std_logic_vector(4 downto 0) | ||||
--desrciption: calculates the inverted usb crc5 value on argument. | ||||
----------------------------------------------------------------------------- | ||||
function crc5 ( | ||||
constant din : std_logic_vector(10 downto 0)) | ||||
return std_logic_vector is | ||||
variable dout : std_logic_vector(4 downto 0); | ||||
begin | ||||
dout(4) := din(0) xor din(1) xor din(4) xor din(5) xor din(7) xor din(10); | ||||
dout(3) := din(0) xor din(3) xor din(4) xor din(6) xor din (9); | ||||
dout(2) := din(0) xor din(1) xor din(2) xor din(3) xor din(4) xor din(7) xor din(8) xor din(10); | ||||
dout(1) := din(0) xor din(1) xor din(2) xor din(3) xor din(6) xor din(7) xor din(9) xor '1'; | ||||
dout(0) := din(0) xor din(1) xor din(2) xor din(5) xor din(6) xor din(8); | ||||
return dout; | ||||
end function crc5; | ||||
----------------------------------------------------------------------------- | ||||
--usb crc16 calculator | ||||
--in: old crc16, din(7 downto 0) | ||||
--out new crc16 value | ||||
--descripton: calculates the usb crc16 value from earlier crc16 value and din | ||||
--crc16in set to X"FFFF" for first calculation. | ||||
----------------------------------------------------------------------------- | ||||
function crc16 ( | ||||
constant din : std_logic_vector(7 downto 0); | ||||
constant crc16in : std_logic_vector(15 downto 0)) | ||||
return std_logic_vector is | ||||
variable dout : std_logic_vector(15 downto 0); | ||||
begin | ||||
dout(15) := din(0) xor din(1) xor din(2) xor din(3) xor din(4) xor din(5) xor din(6) xor din(7) xor | ||||
crc16in(7) xor crc16in(6) xor crc16in(5) xor crc16in(4) xor crc16in(3) xor crc16in(2) xor | ||||
crc16in(1) xor crc16in(0); | ||||
dout(14) := din(0) xor din(1) xor din(2) xor din(3) xor din(4) xor din(5) xor din(6) xor | ||||
crc16in(6) xor crc16in(5) xor crc16in(4) xor crc16in(3) xor crc16in(2) xor | ||||
crc16in(1) xor crc16in(0); | ||||
dout(13) := din(6) xor din(7) xor crc16in(7) xor crc16in(6); | ||||
dout(12) := din(5) xor din(6) xor crc16in(6) xor crc16in(5); | ||||
dout(11) := din(4) xor din(5) xor crc16in(5) xor crc16in(4); | ||||
dout(10) := din(3) xor din(4) xor crc16in(4) xor crc16in(3); | ||||
dout(9) := din(2) xor din(3) xor crc16in(3) xor crc16in(2); | ||||
dout(8) := din(1) xor din(2) xor crc16in(2) xor crc16in(1); | ||||
dout(7) := din(0) xor din(1) xor crc16in(15) xor crc16in(1) xor crc16in(0); | ||||
dout(6) := din(0) xor crc16in(14) xor crc16in(0); | ||||
dout(5) := crc16in(13); | ||||
dout(4) := crc16in(12); | ||||
dout(3) := crc16in(11); | ||||
dout(2) := crc16in(10); | ||||
dout(1) := crc16in(9); | ||||
dout(0) := din(0) xor din(1) xor din(2) xor din(3) xor din(4) xor din(5) xor din(6) xor din(7) xor | ||||
crc16in(8) xor crc16in(7) xor crc16in(6) xor crc16in(5) xor crc16in(4) xor crc16in(3) xor crc16in(2) xor | ||||
crc16in(1) xor crc16in(0); | ||||
return dout; | ||||
end function crc16; | ||||
function pidtostr( | ||||
constant pid : std_logic_vector(3 downto 0)) | ||||
return string is | ||||
variable s : string(1 to 8); | ||||
begin | ||||
case pid is | ||||
when TOUT => | ||||
s := "OUT "; | ||||
when TIN => | ||||
s := "IN "; | ||||
when SOF => | ||||
s := "SOF "; | ||||
when SETUP => | ||||
s := "SETUP "; | ||||
when DATA0 => | ||||
s := "DATA0 "; | ||||
when DATA1 => | ||||
s := "DATA1 "; | ||||
when DATA2 => | ||||
s := "DATA2 "; | ||||
when MDATA => | ||||
s := "MDATA "; | ||||
when TACK => | ||||
s := "ACK "; | ||||
when TNAK => | ||||
s := "NAK "; | ||||
when TSTALL => | ||||
s := "STALL "; | ||||
when TNYET => | ||||
s := "NYET "; | ||||
when PRE => | ||||
s := "PRE "; | ||||
when SPLIT => | ||||
s := "SPLIT "; | ||||
when PING => | ||||
s := "PING "; | ||||
when RESERVED => | ||||
s := "RESERVED"; | ||||
when others => | ||||
s := "Illegal "; | ||||
end case; | ||||
return s; | ||||
end function; | ||||
----------------------------------------------------------------------------- | ||||
-- This procedure prints a message to standard output | ||||
----------------------------------------------------------------------------- | ||||
procedure uprint( | ||||
constant Comment: in String := "-"; | ||||
constant Severe: in Severity_Level := Note; | ||||
constant Screen: in Boolean := True) is | ||||
variable L: Line; | ||||
begin | ||||
if Screen then | ||||
Write(L, Now, Right, 15); | ||||
Write(L, " : " & Comment); | ||||
if Severe = Warning then | ||||
Write(L, String'(" # Warning, ")); | ||||
elsif Severe = Error then | ||||
Write(L, String'(" # Error, ")); | ||||
elsif Severe = Failure then | ||||
Write(L, String'(" # Failure, ")); | ||||
end if; | ||||
WriteLine(Output, L); | ||||
end if; | ||||
end procedure uprint; | ||||
----------------------------------------------------------------------------- | ||||
-- ULPI procedures | ||||
----------------------------------------------------------------------------- | ||||
procedure gen_rxcmd ( | ||||
signal clk : in std_ulogic; | ||||
signal usbi : out grusb_in_type; | ||||
constant rxcmd : in std_logic_vector(7 downto 0)) is | ||||
begin | ||||
wait until rising_edge(clk); | ||||
usbi.dir <= '1'; usbi.nxt <= '0'; | ||||
wait until rising_edge(clk); | ||||
usbi.datain(7 downto 0) <= rxcmd; | ||||
wait until rising_edge(clk); | ||||
usbi.dir <= '0'; usbi.datain(7 downto 0) <= X"00"; | ||||
end procedure; | ||||
procedure accept_regwrite ( | ||||
signal clk : in std_ulogic; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
signal uctrl : out uctrl_type) is | ||||
variable fw, fs, fc : boolean := false; | ||||
variable suspend : std_ulogic := '1'; | ||||
begin | ||||
-- if usbo.dataout(7 downto 6) /= "10" then | ||||
-- wait until usbo.dataout(7 downto 6) = "10"; | ||||
-- end if; | ||||
while usbo.dataout(7 downto 6) /= "10" loop | ||||
wait for 1 ns; | ||||
end loop; | ||||
wait until rising_edge(clk); | ||||
wait for 1 ps; | ||||
usbi.nxt <= '1'; | ||||
if usbo.dataout(7 downto 0) = FCTRL_WADDR then fw := true; end if; | ||||
if usbo.dataout(7 downto 0) = FCTRL_SADDR then fs := true; end if; | ||||
if usbo.dataout(7 downto 0) = FCTRL_CADDR then fc := true; end if; | ||||
wait until falling_edge(clk); | ||||
wait until falling_edge(clk); | ||||
if fw then | ||||
uctrl.xcvrselect(0) <= usbo.dataout(0); | ||||
uctrl.termselect <= usbo.dataout(2); | ||||
uctrl.opmode(0) <= usbo.dataout(3); | ||||
uctrl.opmode(1) <= usbo.dataout(4); | ||||
suspend := usbo.dataout(6); | ||||
end if; | ||||
if fs then | ||||
if usbo.dataout(0) = '1' then uctrl.xcvrselect(0) <= '1'; end if; | ||||
if usbo.dataout(2) = '1' then uctrl.termselect <= '1'; end if; | ||||
if usbo.dataout(3) = '1' then uctrl.opmode(0) <= '1'; end if; | ||||
if usbo.dataout(4) = '1' then uctrl.opmode(1) <= '1'; end if; | ||||
if usbo.dataout(6) = '1' then suspend := '1'; end if; | ||||
end if; | ||||
if fc then | ||||
if usbo.dataout(0) = '1' then uctrl.xcvrselect(0) <= '0'; end if; | ||||
if usbo.dataout(2) = '1' then uctrl.termselect <= '0'; end if; | ||||
if usbo.dataout(3) = '1' then uctrl.opmode(0) <= '0'; end if; | ||||
if usbo.dataout(4) = '1' then uctrl.opmode(1) <= '0'; end if; | ||||
if usbo.dataout(6) = '1' then suspend := '0'; end if; | ||||
end if; | ||||
wait until rising_edge(usbo.stp); | ||||
usbi.nxt <= '0'; | ||||
if suspend = '0' then | ||||
wait until rising_edge(clk); | ||||
usbi.dir <= '1'; | ||||
wait until rising_edge(clk); | ||||
usbi.datain(7 downto 0) <= "000000" & J_STATE; | ||||
for i in 0 to 4 loop | ||||
wait until rising_edge(clk); | ||||
end loop; -- i | ||||
wait until falling_edge(clk); | ||||
uctrl.suspendm <= '0'; | ||||
else | ||||
wait until rising_edge(clk); | ||||
end if; | ||||
end procedure; | ||||
procedure accept_regread ( | ||||
signal clk : in std_ulogic; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
constant vbus : in std_ulogic) is | ||||
begin | ||||
-- if usbo.dataout(7 downto 6) /= "11" then | ||||
-- wait until usbo.dataout(7 downto 6) = "11"; | ||||
-- end if; | ||||
while usbo.dataout(7 downto 6) /= "11" loop | ||||
wait for 1 ns; | ||||
end loop; | ||||
wait until rising_edge(clk); | ||||
usbi.nxt <= '1'; | ||||
wait until rising_edge(clk); | ||||
usbi.nxt <= '0'; usbi.dir <= '1'; | ||||
wait until rising_edge(clk); | ||||
usbi.datain(7 downto 0) <= "000000" & vbus & '0'; | ||||
wait until rising_edge(clk); | ||||
usbi.dir <= '0'; | ||||
end procedure; | ||||
procedure ulpi_reset ( | ||||
signal clk : in std_ulogic; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
signal uctrl : out uctrl_type; | ||||
constant pullup : in boolean; | ||||
constant keepclk : in boolean) is | ||||
begin | ||||
usbi.dir <= '0'; | ||||
-- Wait for first txcmd (ulpi reset) | ||||
accept_regwrite(clk,usbi,usbo,uctrl); | ||||
-- Assert dir and then generate an rxcmd | ||||
wait until rising_edge(clk); | ||||
usbi.dir <= '1'; | ||||
for i in 0 to 4 loop | ||||
wait until rising_edge(clk); | ||||
end loop; | ||||
usbi.dir <= '0'; | ||||
gen_rxcmd(clk,usbi,RXCMD_novbus); | ||||
-- Wait for second txcmd (otg register write) | ||||
accept_regwrite(clk,usbi,usbo,uctrl); | ||||
-- Wait for third txcmd (interrupt register write) | ||||
accept_regwrite(clk,usbi,usbo,uctrl); | ||||
-- Wait for fourth txcmd (interrupt register write) | ||||
accept_regwrite(clk,usbi,usbo,uctrl); | ||||
-- Wait for fifth txcmd (ulpi reset) | ||||
accept_regwrite(clk,usbi,usbo,uctrl); | ||||
-- Assert dir and then generate an rxcmd | ||||
wait until rising_edge(clk); | ||||
usbi.dir <= '1'; | ||||
for i in 0 to 4 loop | ||||
wait until rising_edge(clk); | ||||
end loop; | ||||
usbi.dir <= '0'; | ||||
gen_rxcmd(clk,usbi,RXCMD_novbus); | ||||
-- If pull-up bit is enabled an extra register write will occur | ||||
if pullup then | ||||
accept_regwrite(clk,usbi,usbo,uctrl); | ||||
end if; | ||||
if not keepclk then | ||||
accept_regwrite(clk,usbi,usbo,uctrl); | ||||
if usbo.suspendm = '1' then | ||||
if usbo.xcvrselect /= "00" or usbo.termselect /= '0' or | ||||
usbo.opmode /= "00" then | ||||
-- Wait for suspend (due to no vbus) | ||||
wait until usbo.suspendm = '0'; | ||||
end if; | ||||
end if; | ||||
end if; | ||||
end procedure; | ||||
procedure sendpacket( | ||||
signal clk : in std_ulogic; | ||||
constant len : in integer; | ||||
constant data : in octet_vector; | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
signal usbi : out grusb_in_type; | ||||
signal hs : in std_ulogic) is | ||||
variable i : integer; | ||||
variable ws : integer; | ||||
begin | ||||
wait until rising_edge(clk); | ||||
if uiface = 0 then | ||||
usbi.linestate <= K_STATE; | ||||
if hs = '0' then | ||||
wait until rising_edge(clk); | ||||
end if; | ||||
usbi.rxactive <= '1'; | ||||
if (dwidth = 8) then --8-bit UTMI mode | ||||
i := 0; | ||||
while i < len loop | ||||
ws := conv_integer(rand(1 downto 0)); | ||||
if ws /= 0 then | ||||
for i in 0 to ws-1 loop | ||||
wait until rising_edge(clk); | ||||
end loop; | ||||
end if; | ||||
usbi.rxvalid <= '1'; usbi.datain(7 downto 0) <= data(i); | ||||
wait until rising_edge(clk); | ||||
usbi.rxvalid <= '0'; | ||||
i := i + 1; | ||||
end loop; | ||||
else --16-bit UTMI mode | ||||
i := 0; | ||||
while i < len loop | ||||
ws := conv_integer(rand(1 downto 0)); | ||||
if ws /= 0 then | ||||
for i in 0 to ws-1 loop | ||||
wait until rising_edge(clk); | ||||
end loop; | ||||
end if; | ||||
usbi.rxvalid <= '1'; usbi.datain(7 downto 0) <= data(i); | ||||
i := i + 1; | ||||
if (rand(7) = '1') and (i < len) then | ||||
usbi.rxvalidh <= '1'; usbi.datain(15 downto 8) <= data(i); | ||||
i := i + 1; | ||||
end if; | ||||
wait until rising_edge(clk); | ||||
usbi.rxvalid <= '0'; usbi.rxvalidh <= '0'; | ||||
end loop; | ||||
end if; | ||||
ws := conv_integer(rand(1 downto 0)); | ||||
if ws /= 0 then | ||||
for i in 0 to ws-1 loop | ||||
wait until rising_edge(clk); | ||||
end loop; | ||||
end if; | ||||
usbi.rxactive <= '0'; | ||||
if hs = '0' then | ||||
usbi.linestate <= SE0; | ||||
wait until clk = '1'; | ||||
usbi.linestate <= J_STATE; | ||||
end if; | ||||
else | ||||
if hs = '0' then | ||||
gen_rxcmd(clk,usbi,RXCMD_kstate); | ||||
wait until rising_edge(clk); | ||||
end if; | ||||
usbi.dir <= '1'; usbi.nxt <= '1'; | ||||
wait until rising_edge(clk); | ||||
usbi.nxt <= '0'; | ||||
if hs = '0' then | ||||
usbi.datain(7 downto 0) <= RXCMD_hsrxactive; | ||||
else | ||||
usbi.datain(7 downto 0) <= RXCMD_fsrxactive; | ||||
end if; | ||||
i := 0; | ||||
while i < len loop | ||||
ws := conv_integer(rand(1 downto 0)); | ||||
if ws /= 0 then | ||||
for i in 0 to ws-1 loop | ||||
wait until rising_edge(clk); | ||||
end loop; | ||||
end if; | ||||
usbi.nxt <= '1'; usbi.datain(7 downto 0) <= data(i); | ||||
wait until rising_edge(clk); | ||||
usbi.nxt <= '0'; | ||||
if hs = '0' then | ||||
usbi.datain(7 downto 0) <= RXCMD_hsrxactive; | ||||
else | ||||
usbi.datain(7 downto 0) <= RXCMD_fsrxactive; | ||||
end if; | ||||
i := i + 1; | ||||
end loop; | ||||
ws := conv_integer(rand(1 downto 0)); | ||||
if ws /= 0 then | ||||
for i in 0 to ws-1 loop | ||||
wait until rising_edge(clk); | ||||
end loop; | ||||
end if; | ||||
if hs = '1' then | ||||
usbi.datain(7 downto 0) <= RXCMD_eopse0; | ||||
else | ||||
usbi.datain(7 downto 0) <= RXCMD_eopse0; | ||||
wait until rising_edge(clk); | ||||
usbi.datain(7 downto 0) <= RXCMD_eopj; | ||||
end if; | ||||
wait until rising_edge(clk); | ||||
usbi.dir <= '0'; usbi.datain(7 downto 0) <= (others=>'0'); | ||||
end if; | ||||
wait until rising_edge(clk); | ||||
end procedure; | ||||
procedure receivepacket( | ||||
signal clk : in std_ulogic; | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
variable len : out integer; | ||||
variable data : out octet_vector; | ||||
variable TP : inout boolean; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
signal hs : in std_ulogic; | ||||
variable timeout : out boolean) is | ||||
variable ws : integer; | ||||
variable i : integer; | ||||
variable pvalid : std_ulogic; | ||||
variable stp : std_ulogic; | ||||
begin | ||||
stp := '0'; | ||||
if uiface = 0 then | ||||
usbi.linestate <= K_STATE; | ||||
if usbo.txvalid = '0' then | ||||
wait until usbo.txvalid = '1'; | ||||
end if; | ||||
i := 0; | ||||
pvalid := '1'; | ||||
while usbo.txvalid = '1' loop | ||||
ws := conv_integer(rand(1 downto 0)); | ||||
if ws /= 0 then | ||||
for i in 0 to ws-1 loop | ||||
wait until rising_edge(clk); | ||||
end loop; | ||||
end if; | ||||
usbi.txready <= '1'; | ||||
wait until rising_edge(clk); | ||||
if usbo.txvalid = '1' then | ||||
data(i) := usbo.dataout(7 downto 0); i := i + 1; | ||||
if (dwidth = 16) then | ||||
if usbo.txvalidh = '1' then | ||||
if pvalid = '0' then | ||||
uprint("ERROR: txvalidh asserted irregularly"); | ||||
TP := False; | ||||
end if; | ||||
pvalid := '1'; | ||||
data(i) := usbo.dataout(15 downto 8); i := i + 1; | ||||
else | ||||
pvalid := '0'; | ||||
end if; | ||||
end if; | ||||
end if; | ||||
usbi.txready <= '0'; | ||||
wait until falling_edge(clk); | ||||
if usbo.txvalid = '0' then | ||||
end if; | ||||
end loop; | ||||
usbi.txready <= '0'; len := i; | ||||
if hs = '0' then | ||||
wait until rising_edge(clk); | ||||
usbi.linestate <= SE0; | ||||
wait until rising_edge(clk); | ||||
usbi.linestate <= J_STATE; | ||||
end if; | ||||
else | ||||
i := 0; | ||||
-- if usbo.dataout(7 downto 6) /= "01" then | ||||
-- wait until usbo.dataout(7 downto 6) = "01" for 500 ns; | ||||
-- end if; | ||||
while usbo.dataout(7 downto 6) /= "01" loop | ||||
wait for 1 ns; | ||||
end loop; | ||||
if usbo.dataout(7 downto 6) /= "01" then | ||||
timeout := true; | ||||
else | ||||
timeout := false; | ||||
wait until rising_edge(clk); | ||||
while stp = '0' loop | ||||
usbi.nxt <= '1'; | ||||
wait until rising_edge(clk); | ||||
data(i) := usbo.dataout(7 downto 0); | ||||
if i = 0 then | ||||
data(i)(7 downto 4) := not usbo.dataout(3 downto 0); | ||||
end if; | ||||
i := i+1; | ||||
wait until falling_edge(clk); | ||||
stp := usbo.stp; | ||||
end loop; | ||||
wait until rising_edge(clk); | ||||
usbi.nxt <= '0'; | ||||
len := i; | ||||
if hs = '1' then | ||||
gen_rxcmd(clk,usbi,RXCMD_jstate); | ||||
gen_rxcmd(clk,usbi,RXCMD_se0state); | ||||
else | ||||
gen_rxcmd(clk,usbi,RXCMD_se0state); | ||||
gen_rxcmd(clk,usbi,RXCMD_jstate); | ||||
end if; | ||||
end if; | ||||
end if; | ||||
end procedure; | ||||
----------------------------------------------------------------------------- | ||||
-- usb token packet procedure. | ||||
-- transmits a token packet, as specified by the input signals | ||||
----------------------------------------------------------------------------- | ||||
procedure ttoken( | ||||
signal clk : in std_ulogic; | ||||
constant len : in integer range 0 to 16:= 3; | ||||
constant pid : in std_logic_vector(3 downto 0); | ||||
constant piderr : in boolean := false; | ||||
constant crcerr : in boolean := false; | ||||
constant device_address : in std_logic_vector(6 downto 0); | ||||
constant endpoint_number : in std_logic_vector(3 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
signal usbi : out grusb_in_type; | ||||
signal hs : in std_ulogic) is | ||||
variable p : octet_vector(0 to 15); | ||||
variable tmp : std_logic_vector(10 downto 0); | ||||
variable i : integer; | ||||
variable ws : integer; | ||||
begin | ||||
--build packet | ||||
for i in 0 to len-1 loop | ||||
case i is | ||||
when 0 => --PID | ||||
p(0) := not PID & PID; | ||||
--generate pid error | ||||
if piderr then | ||||
p(0)(conv_integer(rand(2 downto 0))) := | ||||
not p(0)(conv_integer(rand(2 downto 0))); | ||||
end if; | ||||
when 1 => --ADDR & EP | ||||
p(1) := endpoint_number(0) & device_address; | ||||
when 2 => --EP & CRC | ||||
tmp := endpoint_number & device_address; | ||||
p(2) := crc5(tmp) & endpoint_number(3 downto 1); | ||||
if crcerr then | ||||
p(2)(3+conv_integer(rand(1 downto 0))) := | ||||
not p(2)(3+conv_integer(rand(1 downto 0))); | ||||
end if; | ||||
when others => --EXCESSIVE DATA | ||||
p(i) := rand; | ||||
end case; | ||||
end loop; | ||||
--packet transmission | ||||
sendpacket(clk, len, p, uiface, dwidth, rand, usbi, hs); | ||||
end ttoken; | ||||
----------------------------------------------------------------------------- | ||||
-- usb sof packet procedure. | ||||
-- transmit specified framenumber | ||||
procedure tsof( | ||||
signal clk : in std_ulogic; | ||||
constant len : in integer range 0 to 16 := 3; | ||||
constant fno : in std_logic_vector(10 downto 0); | ||||
constant piderr : in boolean; | ||||
constant crcerr : in boolean; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal hs : in std_ulogic) is | ||||
variable ws : integer; | ||||
variable p : octet_vector(0 to 15); | ||||
begin | ||||
--build packet | ||||
for i in 0 to len-1 loop | ||||
case i is | ||||
when 0 => --PID | ||||
p(0) := not SOF & SOF; | ||||
--generate pid error | ||||
if piderr then | ||||
p(0)(conv_integer(rand(2 downto 0))) := | ||||
not p(0)(conv_integer(rand(2 downto 0))); | ||||
end if; | ||||
when 1 => --fno | ||||
p(1) := fno(7 downto 0); | ||||
when 2 => --EP & CRC | ||||
p(2) := crc5(fno) & fno(10 downto 8); | ||||
if crcerr then | ||||
p(2)(3+conv_integer(rand(1 downto 0))) := | ||||
not p(2)(3+conv_integer(rand(1 downto 0))); | ||||
end if; | ||||
when others => --EXCESSIVE DATA | ||||
p(i) := rand; | ||||
end case; | ||||
end loop; | ||||
--packet transmission | ||||
sendpacket(clk, len, p, uiface, dwidth, rand, usbi, hs); | ||||
end tsof; | ||||
----------------------------------------------------------------------------- | ||||
-- usb data packet procedure | ||||
-- transmits the number of bytes provided. | ||||
-- calculates and transmits crc16 value | ||||
procedure tdata ( | ||||
signal clk : in std_ulogic; | ||||
constant pid : in std_logic_vector(3 downto 0); | ||||
constant piderr : in boolean := false; | ||||
constant crcerr : in boolean := false; | ||||
constant data : in octet_vector; | ||||
constant len : in integer range 0 to 3072; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal hs : in std_ulogic) is | ||||
variable crc : std_logic_vector(15 downto 0) := X"FFFF"; | ||||
variable p : octet_vector(0 to len+2); | ||||
variable ws : integer; | ||||
begin | ||||
--build packet | ||||
for i in 0 to len loop | ||||
case i is | ||||
when 0 => -- PID | ||||
p(0) := not pid & pid; | ||||
if piderr then | ||||
p(0)(conv_integer(rand(2 downto 0))) := | ||||
not p(0)(conv_integer(rand(2 downto 0))); | ||||
end if; | ||||
when others => | ||||
p(i) := data(data'low+i-1); | ||||
crc := crc16(p(i), crc); | ||||
end case; | ||||
end loop; | ||||
crc := not crc; | ||||
if crcerr then | ||||
crc(conv_integer(rand(2 downto 0))) := | ||||
not crc(conv_integer(rand(2 downto 0))); | ||||
end if; | ||||
p(len+1) := crc(7 downto 0); | ||||
p(len+2) := crc(15 downto 8); | ||||
--packet transmission | ||||
sendpacket(clk, len+3, p, uiface, dwidth, rand, usbi, hs); | ||||
end tdata; | ||||
--------------------------------------------------------------------------- | ||||
-- usb receive handshake procedure | ||||
-- checks if the expected handshake was received properly | ||||
procedure rhandshake ( | ||||
signal clk : in std_ulogic; | ||||
constant expected : in std_logic_vector(3 downto 0); | ||||
constant nyet : in boolean := false; | ||||
constant nak : in boolean := false; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
variable TP : inout boolean; | ||||
variable gotnak : out boolean; | ||||
signal hs : in std_ulogic; | ||||
variable timeout : out boolean) is | ||||
variable res : boolean := false; | ||||
variable data : octet_vector(0 to 3071); | ||||
variable len : integer; | ||||
variable timeoutv : boolean; | ||||
begin | ||||
--receive packet | ||||
receivepacket(clk, uiface, dwidth, rand, len, data, TP, usbi, usbo, hs, timeoutv); | ||||
timeout := timeoutv; | ||||
if not timeoutv then | ||||
--check packet | ||||
if (len /= 1) then | ||||
uprint("ERROR: Handshake of illegal length(" & tost(len) &") received"); | ||||
TP := False; | ||||
elsif (not data(0)(7 downto 4)) /= data(0)(3 downto 0) then | ||||
uprint("ERROR: PID and inverted PID fields do not match"); | ||||
TP := False; | ||||
end if; | ||||
gotnak := (data(0)(3 downto 0) = TNAK) and TP; | ||||
if not ((data(0)(3 downto 0) = expected) or | ||||
((data(0)(3 downto 0) = TNYET) and nyet) or | ||||
((data(0)(3 downto 0) = TNAK) and nak)) then | ||||
uprint("ERROR: PIDs do not match"); | ||||
uprint("Expected: " & pidtostr(expected) & " Received: " & pidtostr(data(0)(3 downto 0))); | ||||
TP := False; | ||||
end if; | ||||
end if; | ||||
end rhandshake; | ||||
procedure rhandshake ( | ||||
signal clk : in std_ulogic; | ||||
constant expected : in std_logic_vector(3 downto 0); | ||||
constant nyet : in boolean := false; | ||||
constant nak : in boolean := false; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
variable TP : inout boolean; | ||||
variable gotnak : out boolean; | ||||
variable gotnyet : out boolean; | ||||
signal hs : in std_ulogic; | ||||
variable timeout : out boolean) is | ||||
variable res : boolean := false; | ||||
variable data : octet_vector(0 to 3071); | ||||
variable len : integer; | ||||
variable timeoutv : boolean; | ||||
begin | ||||
--receive packet | ||||
receivepacket(clk, uiface, dwidth, rand, len, data, TP, usbi, usbo, hs, timeoutv); | ||||
timeout := timeoutv; | ||||
if not timeoutv then | ||||
--check packet | ||||
if (len /= 1) then | ||||
uprint("ERROR: Handshake of illegal length(" & tost(len) &") received"); | ||||
TP := False; | ||||
elsif (not data(0)(7 downto 4)) /= data(0)(3 downto 0) then | ||||
uprint("ERROR: PID and inverted PID fields do not match"); | ||||
TP := False; | ||||
end if; | ||||
gotnak := (data(0)(3 downto 0) = TNAK) and TP; | ||||
gotnyet := (data(0)(3 downto 0) = TNYET) and TP; | ||||
if not ((data(0)(3 downto 0) = expected) or | ||||
((data(0)(3 downto 0) = TNYET) and nyet) or | ||||
((data(0)(3 downto 0) = TNAK) and nak)) then | ||||
uprint("ERROR: PIDs do not match"); | ||||
uprint("Expected: " & pidtostr(expected) & " Received: " & pidtostr(data(0)(3 downto 0))); | ||||
TP := False; | ||||
end if; | ||||
end if; | ||||
end rhandshake; | ||||
----------------------------------------------------------------------------- | ||||
-- usb receive data packet procedure | ||||
-- calculates and compare crc16 value | ||||
procedure rdata( | ||||
signal clk : in std_ulogic; | ||||
constant expected : in std_logic_vector(3 downto 0); | ||||
constant nak : in boolean := false; | ||||
constant nbytes : in integer; | ||||
constant expdata : in octet_vector; | ||||
constant ep : in integer; | ||||
constant device_address : in std_logic_vector(6 downto 0); | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
variable TP : inout boolean; | ||||
constant verbose : in boolean; | ||||
signal hs : in std_ulogic; | ||||
constant retryiso : in boolean; -- set to true only when a | ||||
-- zero byte DATA0 response | ||||
-- from a isochronous ep | ||||
-- should lead to a retry of | ||||
-- the IN | ||||
variable timeout : out boolean) is | ||||
variable res : boolean := false; | ||||
variable crc : std_logic_vector(15 downto 0) := X"FFFF"; | ||||
variable s : line; | ||||
variable bytes : integer := 0; | ||||
variable msg : boolean := false; | ||||
variable dout : std_logic_vector(7 downto 0); | ||||
variable err : boolean := false; | ||||
constant str : string := ", "; | ||||
variable data : octet_vector(0 to 3071); | ||||
variable len : integer; | ||||
begin | ||||
usbi <= usbi_none; usbi.linestate <= K_STATE; | ||||
while true loop | ||||
ttoken(clk, 3, TIN, false, false, device_address, conv_std_logic_vector(ep, 4), uiface, dwidth, rand, usbi, hs); | ||||
receivepacket(clk, uiface, dwidth, rand, len, data, TP, usbi, usbo, hs, timeout); | ||||
if (len > 0) then | ||||
if (data(0)(3 downto 0) = not data(0)(7 downto 4)) then | ||||
if (nak and (data(0)(3 downto 0) = TNAK)) or (retryiso and data(0)(3 downto 0) = DATA0 and len = 3) then | ||||
if not msg then | ||||
if (retryiso and data(0)(3 downto 0) = DATA0 and len = 3) then | ||||
if verbose then | ||||
uprint("Zero byte DATA0 received from isochornous endpoint, retry IN"); | ||||
end if; | ||||
else | ||||
if verbose then | ||||
uprint("NAK received. Device not ready to send data. Trying new IN"); | ||||
end if; | ||||
end if; | ||||
msg := true; | ||||
end if; | ||||
next; | ||||
else | ||||
if (data(0)(3 downto 0) = expected) then | ||||
case expected is | ||||
when TNAK => | ||||
if not msg then | ||||
uprint("NAK received. Device not ready to send data. Trying new IN"); | ||||
msg := true; | ||||
end if; | ||||
next; | ||||
when TSTALL => | ||||
uprint("STALL PID received. Aborting receive"); | ||||
err := true; | ||||
exit; | ||||
when TNYET => | ||||
uprint("NYET PID received. Should not be returned for IN tokens. Aborting Receive"); | ||||
TP := false; err := true; | ||||
exit; | ||||
when DATA0 => | ||||
exit; | ||||
when DATA1 => | ||||
exit; | ||||
when DATA2 => | ||||
exit; | ||||
when others => | ||||
uprint("Illegal PID returned for this stage. Aborting Receive"); | ||||
TP := false; err := true; | ||||
exit; | ||||
end case; | ||||
else | ||||
uprint("ERROR: Incorrect PID received. Got: " & pidtostr(data(0)(3 downto 0)) & " Expected: " & pidtostr(expected)); | ||||
TP := false; err := true; | ||||
exit; | ||||
end if; | ||||
end if; | ||||
else | ||||
uprint("ERROR: PID and Inverted PID fields do not match"); | ||||
TP := False; err := true; | ||||
exit; | ||||
end if; | ||||
else | ||||
uprint("ERROR: Zero length packet received"); | ||||
TP := False; err := true; | ||||
exit; | ||||
end if; | ||||
end loop; | ||||
if not err then | ||||
if verbose then | ||||
uprint("Total amount of received bytes: " & tost(len)); | ||||
end if; | ||||
if (len-3 /= nbytes) then | ||||
uprint("ERROR: Wrong amount of data accepted. Expected: " & tost(nbytes) & " Got: " & tost(len-3)); | ||||
TP := False; | ||||
end if; | ||||
for i in 0 to len-1 loop | ||||
if (i > 0) and (i < len-2) then | ||||
crc := crc16(data(data'low+i), crc); | ||||
if data(data'low+i) /= expdata(expdata'low+i-1) then | ||||
uprint("ERROR in received data. Index: " & tost(i) & " Expected: " & tost(expdata(expdata'low+i-1)) & " got: " & tost(data(data'low+i))); | ||||
TP := false; | ||||
end if; | ||||
end if; | ||||
if verbose then | ||||
uprint(tost(data(data'low+i))); | ||||
end if; | ||||
end loop; | ||||
if ((not crc(7 downto 0)) /= data(data'low+len-2)) or | ||||
((not crc(15 downto 8)) /= data(data'low+len-1)) then | ||||
uprint("ERROR: CRC16 checksum do not match"); | ||||
TP := False; | ||||
end if; | ||||
end if; | ||||
end rdata; | ||||
----------------------------------------------------------------------------- | ||||
-- usb receive data packet procedure | ||||
-- calculates and compare crc16 value | ||||
procedure rdata( | ||||
signal clk : in std_ulogic; | ||||
constant expected : in std_logic_vector(3 downto 0); | ||||
constant nak : in boolean := false; | ||||
constant nbytes : in integer; | ||||
constant expdata : in octet_vector; | ||||
constant ep : in integer; | ||||
constant device_address : in std_logic_vector(6 downto 0); | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
variable TP : inout boolean; | ||||
constant verbose : in boolean; | ||||
signal hs : in std_ulogic; | ||||
constant retryiso : in boolean; -- set to true only when a | ||||
-- zero byte DATA0 response | ||||
-- from a isochronous ep | ||||
-- should lead to a retry of | ||||
-- the IN | ||||
variable timeout : out boolean; | ||||
variable recdata : out octet_vector; | ||||
constant checkdata : in boolean) is | ||||
variable res : boolean := false; | ||||
variable crc : std_logic_vector(15 downto 0) := X"FFFF"; | ||||
variable s : line; | ||||
variable bytes : integer := 0; | ||||
variable msg : boolean := false; | ||||
variable dout : std_logic_vector(7 downto 0); | ||||
variable err : boolean := false; | ||||
constant str : string := ", "; | ||||
variable data : octet_vector(0 to 3071); | ||||
variable len : integer; | ||||
begin | ||||
usbi <= usbi_none; usbi.linestate <= K_STATE; | ||||
while true loop | ||||
ttoken(clk, 3, TIN, false, false, device_address, conv_std_logic_vector(ep, 4), uiface, dwidth, rand, usbi, hs); | ||||
receivepacket(clk, uiface, dwidth, rand, len, data, TP, usbi, usbo, hs, timeout); | ||||
if (len > 0) then | ||||
if (data(0)(3 downto 0) = not data(0)(7 downto 4)) then | ||||
if (nak and (data(0)(3 downto 0) = TNAK)) or (retryiso and data(0)(3 downto 0) = DATA0 and len = 3) then | ||||
if not msg then | ||||
if (retryiso and data(0)(3 downto 0) = DATA0 and len = 3) then | ||||
if verbose then | ||||
uprint("Zero byte DATA0 received from isochornous endpoint, retry IN"); | ||||
end if; | ||||
else | ||||
if verbose then | ||||
uprint("NAK received. Device not ready to send data. Trying new IN"); | ||||
end if; | ||||
end if; | ||||
msg := true; | ||||
end if; | ||||
next; | ||||
else | ||||
if (data(0)(3 downto 0) = expected) then | ||||
case expected is | ||||
when TNAK => | ||||
if not msg then | ||||
uprint("NAK received. Device not ready to send data. Trying new IN"); | ||||
msg := true; | ||||
end if; | ||||
next; | ||||
when TSTALL => | ||||
uprint("STALL PID received. Aborting receive"); | ||||
err := true; | ||||
exit; | ||||
when TNYET => | ||||
uprint("NYET PID received. Should not be returned for IN tokens. Aborting Receive"); | ||||
TP := false; err := true; | ||||
exit; | ||||
when DATA0 => | ||||
exit; | ||||
when DATA1 => | ||||
exit; | ||||
when DATA2 => | ||||
exit; | ||||
when others => | ||||
uprint("Illegal PID returned for this stage. Aborting Receive"); | ||||
TP := false; err := true; | ||||
exit; | ||||
end case; | ||||
else | ||||
uprint("ERROR: Incorrect PID received. Got: " & pidtostr(data(0)(3 downto 0)) & " Expected: " & pidtostr(expected)); | ||||
TP := false; err := true; | ||||
exit; | ||||
end if; | ||||
end if; | ||||
else | ||||
uprint("ERROR: PID and Inverted PID fields do not match"); | ||||
TP := False; err := true; | ||||
exit; | ||||
end if; | ||||
else | ||||
uprint("ERROR: Zero length packet received"); | ||||
TP := False; err := true; | ||||
exit; | ||||
end if; | ||||
end loop; | ||||
if not err then | ||||
if verbose then | ||||
uprint("Total amount of received bytes: " & tost(len)); | ||||
end if; | ||||
if (len-3 /= nbytes) then | ||||
uprint("ERROR: Wrong amount of data accepted. Expected: " & tost(nbytes) & " Got: " & tost(len-3)); | ||||
TP := False; | ||||
end if; | ||||
for i in 0 to len-1 loop | ||||
if (i > 0) and (i < len-2) then | ||||
crc := crc16(data(data'low+i), crc); | ||||
if checkdata then | ||||
if data(data'low+i) /= expdata(expdata'low+i-1) then | ||||
uprint("ERROR in received data. Index: " & tost(i) & " Expected: " & tost(expdata(expdata'low+i-1)) & " got: " & tost(data(data'low+i))); | ||||
TP := false; | ||||
end if; | ||||
end if; | ||||
recdata(recdata'low+i-1) := data(data'low+i); | ||||
end if; | ||||
if verbose then | ||||
uprint(tost(data(data'low+i))); | ||||
end if; | ||||
end loop; | ||||
if ((not crc(7 downto 0)) /= data(data'low+len-2)) or | ||||
((not crc(15 downto 8)) /= data(data'low+len-1)) then | ||||
uprint("ERROR: CRC16 checksum do not match"); | ||||
TP := False; | ||||
end if; | ||||
end if; | ||||
end rdata; | ||||
--------------------------------------------------------------------------- | ||||
-- usb transmit handshake procedure | ||||
-- sends specified handshake packet | ||||
procedure shandshake ( | ||||
signal clk : in std_ulogic; | ||||
constant hpid : in std_logic_vector(3 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
signal usbi : out grusb_in_type; | ||||
signal hs : in std_ulogic) is | ||||
variable p : octet_vector(0 to 0); | ||||
begin | ||||
p(0) := not hpid & hpid; | ||||
sendpacket(clk, 1, p, uiface, dwidth, rand, usbi, hs); | ||||
end shandshake; | ||||
----------------------------------------------------------------------------- | ||||
-- get device status | ||||
procedure getstatus ( | ||||
constant dir : in std_logic_vector(3 downto 0); | ||||
constant stall : in boolean := false; | ||||
constant nak : in boolean := true; | ||||
signal clk : in std_ulogic; | ||||
signal usbo : in grusb_out_type; | ||||
signal usbi : out grusb_in_type; | ||||
constant ep : in integer; | ||||
signal rand : in std_logic_vector(7 downto 0); | ||||
constant uiface : in integer; | ||||
constant dwidth : in integer; | ||||
constant device_address : in std_logic_vector(6 downto 0); | ||||
variable TP : inout boolean; | ||||
signal hs : in std_ulogic; | ||||
variable timeout : out boolean) is | ||||
variable pid : std_logic_vector(3 downto 0); | ||||
variable data : octet_vector(0 to 0); | ||||
variable gotnak : boolean; | ||||
begin | ||||
if dir = TIN then | ||||
if stall then | ||||
pid := TSTALL; | ||||
else | ||||
pid := DATA1; | ||||
end if; | ||||
rdata(clk, pid, nak, 0, data, ep, device_address, rand, | ||||
uiface, dwidth, usbi, usbo, TP, false, hs, false, timeout); | ||||
shandshake(clk, TACK, uiface, dwidth, rand, usbi, hs); | ||||
elsif dir = TOUT then | ||||
if stall then | ||||
pid := TSTALL; | ||||
else | ||||
pid := TACK; | ||||
end if; | ||||
gotnak := true; | ||||
while gotnak loop | ||||
ttoken(clk, 3, TOUT, false, false, device_address, conv_std_logic_vector(ep, 4), uiface, dwidth, rand, usbi, hs); | ||||
tdata(clk, DATA1, false, false, data(0 to 0), 0, rand, uiface, dwidth, usbi, hs); | ||||
rhandshake (clk, pid, false, nak, rand, uiface, dwidth, usbi, usbo, TP, gotnak, hs, timeout); | ||||
end loop; | ||||
end if; | ||||
end getstatus; | ||||
procedure hs_handshake ( | ||||
signal clk : in std_ulogic; | ||||
signal usbi : out grusb_in_type; | ||||
signal usbo : in grusb_out_type; | ||||
signal uctrl : out uctrl_type; | ||||
signal hs : in std_ulogic; | ||||
constant uiface : in integer) is | ||||
begin | ||||
usbi.linestate <= SE0; | ||||
if uiface = 1 then | ||||
gen_rxcmd(clk,usbi,RXCMD_se0state); | ||||
accept_regwrite(clk,usbi,usbo,uctrl); | ||||
if usbo.xcvrselect(0) = '1' then | ||||
wait until usbo.xcvrselect(0) = '0'; | ||||
end if; | ||||
else | ||||
wait until usbo.xcvrselect(0) = '0'; | ||||
end if; | ||||
if uiface = 0 then | ||||
if usbo.txvalid = '0' then wait until usbo.txvalid = '1'; end if; | ||||
else | ||||
if usbo.dataout(7 downto 0) = "00000000" then | ||||
wait until usbo.dataout(7 downto 0) /= "00000000"; | ||||
end if; | ||||
end if; | ||||
if uiface = 0 then | ||||
usbi.txready <= '1'; usbi.linestate <= K_STATE; | ||||
wait until usbo.txvalid = '0'; | ||||
usbi.linestate <= K_STATE; | ||||
usbi.txready <= '0'; | ||||
else | ||||
wait until rising_edge(clk); | ||||
usbi.nxt <= '1'; | ||||
wait until rising_edge(usbo.stp); | ||||
wait until rising_edge(clk); | ||||
usbi.nxt <= '0'; | ||||
end if; | ||||
wait for 50 us; | ||||
for i in 0 to 5 loop | ||||
if (i mod 2) = 0 then | ||||
usbi.linestate <= K_STATE; | ||||
if uiface = 1 then | ||||
gen_rxcmd(clk,usbi,RXCMD_kstate); | ||||
end if; | ||||
else | ||||
usbi.linestate <= J_STATE; | ||||
if uiface = 1 then | ||||
gen_rxcmd(clk,usbi,RXCMD_jstate); | ||||
end if; | ||||
end if; | ||||
if uiface = 1 then | ||||
if i = 5 then | ||||
accept_regwrite(clk,usbi,usbo,uctrl); | ||||
end if; | ||||
end if; | ||||
wait for 45 us; | ||||
end loop; | ||||
usbi.linestate <= SE0; | ||||
if uiface = 1 then | ||||
gen_rxcmd(clk,usbi,RXCMD_se0state); | ||||
else | ||||
if usbo.termselect /= '0' then | ||||
wait until usbo.termselect = '0'; | ||||
end if; | ||||
end if; | ||||
end hs_handshake; | ||||
end usbsim; | ||||