##// END OF EJS Templates
temp
temp

File last commit:

r100:fc97c34d69e3 martin
r249:279a122aaba5 JC
Show More
usbsim.vhd
1544 lines | 56.5 KiB | text/x-vhdl | VhdlLexer
------------------------------------------------------------------------------
-- 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;