OpenCores
URL https://opencores.org/ocsvn/usb11_sim_model/usb11_sim_model/trunk

Subversion Repositories usb11_sim_model

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /usb11_sim_model/trunk
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/USB_Stimuli.vhd
0,0 → 1,153
--==========================================================================================================--
-- --
-- Copyright (C) 2011 by Martin Neumann martin@neumanns-mail.de --
-- --
-- This source file may be used and distributed without restriction provided that this copyright statement --
-- is not removed from the file and that any derivative work contains the original copyright notice and --
-- the associated disclaimer. --
-- --
-- This software is provided ''as is'' and without any express or implied warranties, including, but not --
-- limited to, the implied warranties of merchantability and fitness for a particular purpose. in no event --
-- shall the author or contributors be liable for any direct, indirect, incidental, special, exemplary, or --
-- consequential damages (including, but not limited to, procurement of substitute goods or services; loss --
-- of use, data, or profits; or business interruption) however caused and on any theory of liability, --
-- whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way --
-- out of the use of this software, even if advised of the possibility of such damage. --
-- --
--==========================================================================================================--
-- --
-- File name : USB_tc_02.vhd --
-- Author : Martin Neumann martin@neumanns-mail.de --
-- Description : Copy and rename this file to usb_stimuli.vhd before running a new simulation! --
-- --
--==========================================================================================================--
-- --
-- Change history --
-- --
-- Version / date Description --
-- --
-- 01 05 Mar 2011 MN Initial version --
-- --
-- End change history --
--==========================================================================================================--
 
LIBRARY work, IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_arith.ALL;
USE work.usb_commands.ALL;
 
ENTITY USB_Stimuli IS PORT(
-- Test Control Interface --
USB : OUT usb_action;
t_no : OUT NATURAL;
-- Application Interface
clk : IN STD_LOGIC;
rst_neg_ext : OUT STD_LOGIC;
RXval : IN STD_LOGIC; -- RX bytes available
RXdat : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Received data bytes
RXrdy : OUT STD_LOGIC := '0'; -- Application ready for data
RXlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Number of bytes available
TXval : OUT STD_LOGIC := '0'; -- Application has valid data
TXdat : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Data byte to send
TXrdy : IN STD_LOGIC; -- Entity is ready for data
TXroom : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- No of free bytes in TX
TXcork : OUT STD_LOGIC := '1'); -- Hold TX transmission
END USB_Stimuli;
 
ARCHITECTURE sim OF usb_stimuli IS
 
SIGNAL rd_data : byte_array(0 TO 7);
SIGNAL TX_load : STD_LOGIC := '0';
 
BEGIN
 
p_stimuli_data : PROCESS
BEGIN
list("*****************************");
list("* Results of tc_02.vhd *");
list("*****************************");
list(" ");
list(T_No, 10);
rst_neg_ext <= '0';
WAIT FOR 301 ns;
rst_neg_ext <= '1';
WAIT FOR 40 ns;
list("Reset completed, initializing");
TX_load <= '1';
list(T_No, 20);
setup(usb, X"00", X"0"); --Send Setup to addr 0, endp 0 ..
send_D0(usb,(X"80",X"06",X"00",X"01",X"00",X"00",X"40",X"00")); -- .. 'Get Device descriptor'
wait_slv(usb); --Recv ACK
in_token(usb, X"00", X"0"); --Send IN-Token
wait_slv(usb); --Recv Data1 Device Discriptor
send_ack(usb); --Send ACK
out_token(usb, X"00", X"0");
send_D0(usb); --Send Zero Data
wait_slv(usb);
 
list(T_No, 30);
setup(usb, X"00", X"0"); --Setup to addr 0, endp 0 ..
send_D0(usb,(X"00",X"05",X"03",X"00",X"00",X"00",X"00",X"00")); -- .. 'Set Address'
wait_slv(usb); --Recv ACK
in_token(usb, X"00", X"0"); --Send IN-Token
wait_slv(usb); --Recv Data0 zero Length
send_ack(usb); --Send ACK
 
--Now we may use the new address :
list(T_No, 50);
out_token(usb, X"03", X"1"); --Send Out-Token to Endpoint 1
send_D0(usb, (X"11",X"22",X"33",X"44",X"55",X"66",X"77",X"88"));
wait_slv(usb);
list(T_No, 51);
out_token(usb, X"03", X"1"); --Send Out-Token to Endpoint 1
send_D0(usb, (X"11",X"12",X"13",X"14",X"15",X"16",X"17",X"18"));
wait_slv(usb);
TXcork <= '0'; --Release TX buffer
FOR i IN 0 TO 5 LOOP
list(T_No, 60+i);
in_token(usb, X"03", X"1"); --Send IN-Token to Endpoint 1
wait_slv(usb); --Recv Data ?
send_ack(usb); --Send ACK
END LOOP;
-- list(T_No, 70);
-- in_token(usb, X"03", X"1"); --Send IN-Token to Endpoint 1
-- wait_slv(usb); --Recv Data ?
-- send_ack(usb); --Send ACK
IF usb_busy THEN --is a usb_monitor signal
WAIT UNTIL NOT usb_busy;
END IF;
WAIT FOR 300 ns;
send_RES(usb);
WAIT FOR 1 us;
ASSERT FALSE REPORT"End of Test" SEVERITY FAILURE;
END PROCESS;
 
p_rd_data : PROCESS
VARIABLE i : NATURAL := 0;
BEGIN
WAIT UNTIL rising_edge(clk);
RXrdy <= '1';
IF i < 8 THEN
RXrdy <= '1';
IF RXval ='1' THEN
rd_data(i) <= RXdat;
END IF;
ELSE
RXrdy <= '0';
END IF;
END PROCESS;
 
p_wr_data : PROCESS
VARIABLE i : NATURAL := 0;
BEGIN
WAIT UNTIL rising_edge(clk);
IF i < 333 AND TXrdy ='1' and TX_load ='1' THEN
TXval <= '1';
TXdat <= CONV_STD_LOGIC_VECTOR(i,8);
i := i +1;
ELSE
TXval <= '0';
END IF;
END PROCESS;
 
END sim;
/usb_tc_02.vhd
0,0 → 1,153
--==========================================================================================================--
-- --
-- Copyright (C) 2011 by Martin Neumann martin@neumanns-mail.de --
-- --
-- This source file may be used and distributed without restriction provided that this copyright statement --
-- is not removed from the file and that any derivative work contains the original copyright notice and --
-- the associated disclaimer. --
-- --
-- This software is provided ''as is'' and without any express or implied warranties, including, but not --
-- limited to, the implied warranties of merchantability and fitness for a particular purpose. in no event --
-- shall the author or contributors be liable for any direct, indirect, incidental, special, exemplary, or --
-- consequential damages (including, but not limited to, procurement of substitute goods or services; loss --
-- of use, data, or profits; or business interruption) however caused and on any theory of liability, --
-- whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way --
-- out of the use of this software, even if advised of the possibility of such damage. --
-- --
--==========================================================================================================--
-- --
-- File name : USB_tc_02.vhd --
-- Author : Martin Neumann martin@neumanns-mail.de --
-- Description : Copy and rename this file to usb_stimuli.vhd before running a new simulation! --
-- --
--==========================================================================================================--
-- --
-- Change history --
-- --
-- Version / date Description --
-- --
-- 01 05 Mar 2011 MN Initial version --
-- --
-- End change history --
--==========================================================================================================--
 
LIBRARY work, IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_arith.ALL;
USE work.usb_commands.ALL;
 
ENTITY USB_Stimuli IS PORT(
-- Test Control Interface --
USB : OUT usb_action;
t_no : OUT NATURAL;
-- Application Interface
clk : IN STD_LOGIC;
rst_neg_ext : OUT STD_LOGIC;
RXval : IN STD_LOGIC; -- RX bytes available
RXdat : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Received data bytes
RXrdy : OUT STD_LOGIC := '0'; -- Application ready for data
RXlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Number of bytes available
TXval : OUT STD_LOGIC := '0'; -- Application has valid data
TXdat : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Data byte to send
TXrdy : IN STD_LOGIC; -- Entity is ready for data
TXroom : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- No of free bytes in TX
TXcork : OUT STD_LOGIC := '1'); -- Hold TX transmission
END USB_Stimuli;
 
ARCHITECTURE sim OF usb_stimuli IS
 
SIGNAL rd_data : byte_array(0 TO 7);
SIGNAL TX_load : STD_LOGIC := '0';
 
BEGIN
 
p_stimuli_data : PROCESS
BEGIN
list("*****************************");
list("* Results of tc_02.vhd *");
list("*****************************");
list(" ");
list(T_No, 10);
rst_neg_ext <= '0';
WAIT FOR 301 ns;
rst_neg_ext <= '1';
WAIT FOR 40 ns;
list("Reset completed, initializing");
TX_load <= '1';
list(T_No, 20);
setup(usb, X"00", X"0"); --Send Setup to addr 0, endp 0 ..
send_D0(usb,(X"80",X"06",X"00",X"01",X"00",X"00",X"40",X"00")); -- .. 'Get Device descriptor'
wait_slv(usb); --Recv ACK
in_token(usb, X"00", X"0"); --Send IN-Token
wait_slv(usb); --Recv Data1 Device Discriptor
send_ack(usb); --Send ACK
out_token(usb, X"00", X"0");
send_D0(usb); --Send Zero Data
wait_slv(usb);
 
list(T_No, 30);
setup(usb, X"00", X"0"); --Setup to addr 0, endp 0 ..
send_D0(usb,(X"00",X"05",X"03",X"00",X"00",X"00",X"00",X"00")); -- .. 'Set Address'
wait_slv(usb); --Recv ACK
in_token(usb, X"00", X"0"); --Send IN-Token
wait_slv(usb); --Recv Data0 zero Length
send_ack(usb); --Send ACK
 
--Now we may use the new address :
list(T_No, 50);
out_token(usb, X"03", X"1"); --Send Out-Token to Endpoint 1
send_D0(usb, (X"11",X"22",X"33",X"44",X"55",X"66",X"77",X"88"));
wait_slv(usb);
list(T_No, 51);
out_token(usb, X"03", X"1"); --Send Out-Token to Endpoint 1
send_D0(usb, (X"11",X"12",X"13",X"14",X"15",X"16",X"17",X"18"));
wait_slv(usb);
TXcork <= '0'; --Release TX buffer
FOR i IN 0 TO 5 LOOP
list(T_No, 60+i);
in_token(usb, X"03", X"1"); --Send IN-Token to Endpoint 1
wait_slv(usb); --Recv Data ?
send_ack(usb); --Send ACK
END LOOP;
-- list(T_No, 70);
-- in_token(usb, X"03", X"1"); --Send IN-Token to Endpoint 1
-- wait_slv(usb); --Recv Data ?
-- send_ack(usb); --Send ACK
IF usb_busy THEN --is a usb_monitor signal
WAIT UNTIL NOT usb_busy;
END IF;
WAIT FOR 300 ns;
send_RES(usb);
WAIT FOR 1 us;
ASSERT FALSE REPORT"End of Test" SEVERITY FAILURE;
END PROCESS;
 
p_rd_data : PROCESS
VARIABLE i : NATURAL := 0;
BEGIN
WAIT UNTIL rising_edge(clk);
RXrdy <= '1';
IF i < 8 THEN
RXrdy <= '1';
IF RXval ='1' THEN
rd_data(i) <= RXdat;
END IF;
ELSE
RXrdy <= '0';
END IF;
END PROCESS;
 
p_wr_data : PROCESS
VARIABLE i : NATURAL := 0;
BEGIN
WAIT UNTIL rising_edge(clk);
IF i < 333 AND TXrdy ='1' and TX_load ='1' THEN
TXval <= '1';
TXdat <= CONV_STD_LOGIC_VECTOR(i,8);
i := i +1;
ELSE
TXval <= '0';
END IF;
END PROCESS;
 
END sim;
/TC_Copy.bat
0,0 → 1,5
@ECHO Off
if exist USB_Stimuli.old erase USB_Stimuli.old
if exist USB_Stimuli.vhd rename USB_Stimuli.vhd USB_Stimuli.old
copy %1 USB_Stimuli.vhd
 
/usb_tc_02.out
0,0 → 1,77
*****************************
* Results of tc_02.vhd *
*****************************
Test_No 10
Reset completed, initializing
Test_No 20
1862.409 ns Send Setup: Address 0x00, Endpoint 0x0, CRC5 0x02
4862.328 ns Send Data0 0x80 0x06 0x00 0x01 0x00 0x00 0x40 0x00 0xDD 0x94
13599.797 ns Recv ACK
15452.206 ns Send IN-Token: Address 0x00, Endpoint 0x0, CRC5 0x02
18845.557 ns Recv Data1 0x12 0x01 0x10 0x01 0x02 0x00 0x00 0x40 0x9A 0xFB 0x9A 0xFB 0x20 0x00 0x00 0x00
29992.797 ns ..... 0x00 0x01 0xB4 0x2C
33861.545 ns Send ACK
35533.631 ns Send OUT-Token: Address 0x00, Endpoint 0x0, CRC5 0x02
38533.55 ns Send Data0 0x00 0x00
41926.901 ns Recv ACK
Test_No 30
43779.31 ns Send Setup: Address 0x00, Endpoint 0x0, CRC5 0x02
46779.229 ns Send Data0 0x00 0x05 0x03 0x00 0x00 0x00 0x00 0x00 0xEA 0xC7
55598.663 ns Recv ACK
57451.072 ns Send IN-Token: Address 0x00, Endpoint 0x0, CRC5 0x02
60844.423 ns Recv Data1 0x00 0x00
64024.665 ns Send ACK
Test_No 50
65696.751 ns Send OUT-Token: Address 0x03, Endpoint 0x1, CRC5 0x1C
68696.67 ns Send Data0 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x5E 0xBF
77516.104 ns Recv ACK
Test_No 51
79352.12 ns Send OUT-Token: Address 0x03, Endpoint 0x1, CRC5 0x1C
82352.039 ns Send Data0 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x95 0xA7
91089.508 ns Recv ACK
Test_No 60
92941.917 ns Send IN-Token: Address 0x03, Endpoint 0x1, CRC5 0x1C
96351.661 ns Recv Data0 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
107498.901 ns ..... 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F
117990.421 ns ..... 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2A 0x2B 0x2C 0x2D 0x2E 0x2F
128481.941 ns ..... 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3A 0x3B 0x3C 0x3D 0x3E 0x3F
139055.426 ns ..... 0x26 0xF7
141612.734 ns Send ACK
Test_No 61
143268.427 ns Send IN-Token: Address 0x03, Endpoint 0x1, CRC5 0x1C
146678.171 ns Recv Data1 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4A 0x4B 0x4C 0x4D 0x4E 0x4F
157825.411 ns ..... 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5A 0x5B 0x5C 0x5D 0x5E 0x5F
168316.931 ns ..... 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x6A 0x6B 0x6C 0x6D 0x6E 0x6F
178808.451 ns ..... 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77 0x78 0x79 0x7A 0x7B 0x7C 0x7D 0x7E 0x7F
189463.901 ns ..... 0x9B 0xBA
192021.209 ns Send ACK
Test_No 62
193693.295 ns Send IN-Token: Address 0x03, Endpoint 0x1, CRC5 0x1C
197103.039 ns Recv Data0 0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 0x88 0x89 0x8A 0x8B 0x8C 0x8D 0x8E 0x8F
208250.279 ns ..... 0x90 0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 0x99 0x9A 0x9B 0x9C 0x9D 0x9E 0x9F
218823.764 ns ..... 0xA0 0xA1 0xA2 0xA3 0xA4 0xA5 0xA6 0xA7 0xA8 0xA9 0xAA 0xAB 0xAC 0xAD 0xAE 0xAF
229315.284 ns ..... 0xB0 0xB1 0xB2 0xB3 0xB4 0xB5 0xB6 0xB7 0xB8 0xB9 0xBA 0xBB 0xBC 0xBD 0xBE 0xBF
239888.769 ns ..... 0x5C 0x6C
242446.077 ns Send ACK
Test_No 63
244101.77 ns Send IN-Token: Address 0x03, Endpoint 0x1, CRC5 0x1C
247511.514 ns Recv Data1 0xC0 0xC1 0xC2 0xC3 0xC4 0xC5 0xC6 0xC7 0xC8 0xC9 0xCA 0xCB 0xCC 0xCD 0xCE 0xCF
258740.719 ns ..... 0xD0 0xD1 0xD2 0xD3 0xD4 0xD5 0xD6 0xD7 0xD8 0xD9 0xDA 0xDB 0xDC 0xDD 0xDE 0xDF
269314.204 ns ..... 0xE0 0xE1 0xE2 0xE3 0xE4 0xE5 0xE6 0xE7 0xE8 0xE9 0xEA 0xEB 0xEC 0xED 0xEE 0xEF
279969.654 ns ..... 0xF0 0xF1 0xF2 0xF3 0xF4 0xF5 0xF6 0xF7 0xF8 0xF9 0xFA 0xFB 0xFC 0xFD 0xFE 0x00
291034.929 ns ..... 0xA1 0x61
293526.665 ns Send ACK
Test_No 64
295198.751 ns Send IN-Token: Address 0x03, Endpoint 0x1, CRC5 0x1C
298592.102 ns Recv Data0 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10
309739.342 ns ..... 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F 0x20
320230.862 ns ..... 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2A 0x2B 0x2C 0x2D 0x2E 0x2F 0x30
330722.382 ns ..... 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3A 0x3B 0x3C 0x3D 0x3E 0x3F 0x41
341295.867 ns ..... 0x98 0x8A
343853.175 ns Send ACK
Test_No 65
345525.261 ns Send IN-Token: Address 0x03, Endpoint 0x1, CRC5 0x1C
348935.005 ns Recv Data1 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4A 0x4B 0x4C 0x5A 0x87
359360.953 ns Send ACK
364950.966 ns USB Reset detected for 5098.223 ns
/usb_fs_slave.vhdl
0,0 → 1,181
 
--==========================================================================================================--
-- --
-- Copyright (C) 2011 by Martin Neumann martin@neumanns-mail.de --
-- --
-- This source file may be used and distributed without restriction provided that this copyright statement --
-- is not removed from the file and that any derivative work contains the original copyright notice and --
-- the associated disclaimer. --
-- --
-- This software is provided ''as is'' and without any express or implied warranties, including, but not --
-- limited to, the implied warranties of merchantability and fitness for a particular purpose. in no event --
-- shall the author or contributors be liable for any direct, indirect, incidental, special, exemplary, or --
-- consequential damages (including, but not limited to, procurement of substitute goods or services; loss --
-- of use, data, or profits; or business interruption) however caused and on any theory of liability, --
-- whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way --
-- out of the use of this software, even if advised of the possibility of such damage. --
-- --
--==========================================================================================================--
-- --
-- File name : usb_fs_slave.vhdl --
-- Author : Martin Neumann martin@neumanns-mail.de --
-- Description : Wrapper for a USB full speed slave operating at 60MHz clock frequency --
-- --
--==========================================================================================================--
-- --
-- Change history --
-- --
-- Version / date Description --
-- --
-- 01 05 Mar 2011 MN Initial version --
-- --
-- End change history --
--==========================================================================================================--
 
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
 
ENTITY usb_fs_slave IS
GENERIC (
VENDORID : STD_LOGIC_VECTOR(15 DOWNTO 0);
PRODUCTID : STD_LOGIC_VECTOR(15 DOWNTO 0);
VERSIONBCD : STD_LOGIC_VECTOR(15 DOWNTO 0);
SELFPOWERED : BOOLEAN := FALSE;
BUFSIZE_BITS : INTEGER RANGE 7 to 12 := 10);
PORT (
clk : IN STD_LOGIC;
rst_neg_ext : IN STD_LOGIC;
rst_neg_syc : OUT STD_LOGIC;
d_pos : INOUT STD_LOGIC;
d_neg : INOUT STD_LOGIC;
USB_rst : OUT STD_LOGIC; -- USB reset detected (SE0 > 2.5 us)
online : OUT STD_LOGIC; -- High when the device is in Config state.
RXval : OUT STD_LOGIC; -- High if a received byte available on RXDAT.
RXdat : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Received data byte, valid if RXVAL is high.
RXrdy : IN STD_LOGIC; -- High if application is ready to receive.
RXlen : OUT STD_LOGIC_VECTOR(BUFSIZE_BITS-1 DOWNTO 0); -- No of bytes available in receive buffer.
TXval : IN STD_LOGIC; -- High if the application has data to send.
TXdat : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Data byte to send, must be valid if TXVAL is high.
TXrdy : OUT STD_LOGIC; -- High if the entity is ready to accept the next byte.
TXroom : OUT STD_LOGIC_VECTOR(BUFSIZE_BITS-1 DOWNTO 0); -- No of free bytes in transmit buffer.
TXcork : IN STD_LOGIC; -- Temp. suppress transmissions at the outgoing endpoint.
FPGA_ready : OUT STD_LOGIC); -- connect FPGA_ready to the pullup resistor logic
END usb_fs_slave;
 
ARCHITECTURE rtl OF usb_fs_slave IS
 
CONSTANT DriverMode : STD_LOGIC := '1'; -- HIGH level for differential io mode (else single-ended)
CONSTANT tx_wait : STD_LOGIC := '0'; -- Don't suppress temporarily transmissions at the outgoing endpoint.
 
SIGNAL Phy_DataIn : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL Phy_DataOut : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL Phy_Linestate : STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL Phy_Opmode : STD_LOGIC_VECTOR(1 DOWNTO 0);
SIGNAL Phy_RxActive : STD_LOGIC;
SIGNAL Phy_RxError : STD_LOGIC;
SIGNAL Phy_RxValid : STD_LOGIC;
SIGNAL Phy_Termselect : STD_LOGIC := 'L';
SIGNAL Phy_TxReady : STD_LOGIC;
SIGNAL Phy_TxValid : STD_LOGIC;
SIGNAL Phy_XcvrSelect : STD_LOGIC := 'L';
SIGNAL usb_rst_phy : STD_LOGIC;
SIGNAL usb_rst_slv : STD_LOGIC;
SIGNAL rst_neg_int : STD_LOGIC;
SIGNAL rst_neg_tmp : STD_LOGIC;
SIGNAL rxd : STD_LOGIC;
SIGNAL txdn : STD_LOGIC;
SIGNAL txdp : STD_LOGIC;
SIGNAL txoe : STD_LOGIC;
 
FUNCTION neg(value : STD_LOGIC) RETURN STD_LOGIC IS
BEGIN
RETURN NOT value;
END neg;
 
BEGIN
 
p_rst_neg : PROCESS(rst_neg_ext, clk)
BEGIN
IF rst_neg_ext ='0' THEN
rst_neg_tmp <= '0';
rst_neg_int <= '0';
ELSIF clk'EVENT AND clk ='1' THEN
rst_neg_tmp <= rst_neg_ext;
rst_neg_int <= rst_neg_tmp;
END IF;
END PROCESS;
 
rst_neg_syc <= rst_neg_int;
 
rxd <= d_pos AND NOT d_neg;
usb_rst <= usb_rst_phy OR usb_rst_slv;
 
d_pos <= txdp WHEN txoe = '0' ELSE 'Z';
d_neg <= txdn WHEN txoe = '0' ELSE 'Z';
 
usb_phy_1 : ENTITY work.usb_phy --Open Cores USB Phy, designed by Rudolf Usselmanns
GENERIC MAP (
usb_rst_det => TRUE
)
PORT MAP (
clk => clk, -- i
rst => rst_neg_int, -- i
phy_tx_mode => DriverMode, -- i
usb_rst => usb_rst_phy, -- o
txdp => txdp, -- o
txdn => txdn, -- o
txoe => txoe, -- o
rxd => rxd, -- i
rxdp => d_pos, -- i
rxdn => d_neg, -- i
DataOut_i => Phy_DataOut, -- i (7 downto 0);
TxValid_i => Phy_TxValid, -- i
TxReady_o => Phy_TxReady, -- o
DataIn_o => Phy_DataIn, -- o (7 downto 0);
RxValid_o => Phy_RxValid, -- o
RxActive_o => Phy_RxActive, -- o
RxError_o => Phy_RxError, -- o
LineState_o => Phy_LineState -- o (1 downto 0)
);
 
usb_serial_1 : ENTITY work.usb_serial --Open Cores USB Serial, designed by Joris van Rantwijk
GENERIC MAP (
VENDORID => VENDORID,
PRODUCTID => PRODUCTID,
VERSIONBCD => VERSIONBCD,
HSSUPPORT => FALSE,
SELFPOWERED => SELFPOWERED,
RXBUFSIZE_BITS => BUFSIZE_BITS,
TXBUFSIZE_BITS => BUFSIZE_BITS)
PORT MAP (
clk => clk, -- i 60 MHz UTMI clock.
reset => neg(rst_neg_int), -- i Synchronous reset; clear buffers and re-attach to the bus.
usbrst => usb_rst_slv, -- o High for one clock when a reset signal is detected on the USB bus.
highspeed => OPEN, -- o High when the device is operating (or suspended) in high speed mode.
suspend => OPEN, -- o High if device suspended, drive asynchronously the UTMI SuspendM pin.
online => online, -- o High when the device is in the Configured state.
RXval => RXval, -- o High if a received byte is available on RXDAT.
RXdat => RXdat, -- o (7 downto 0) - Received data byte, valid if RXVAL is high.
RXrdy => RXrdy, -- i High if the application is ready to receive the next byte.
RXlen => RXlen, -- o (RXBUFSIZE_BITS-1 downto 0) - No of bytes available in receive buffer.
TXval => TXval, -- i High if the application has data to send.
TXdat => TXdat, -- i (7 downto 0) - Data byte to send, must be valid if TXVAL is high.
TXrdy => TXrdy, -- o High if the entity is ready to accept the next byte.
TXroom => TXroom, -- o (TXBUFSIZE_BITS-1 downto 0) - No of free bytes in transmit buffer.
TXcork => TXcork, -- i Temporarily suppress transmissions at the outgoing endpoint.
Phy_DataIn => Phy_DataIn, -- i (7 downto 0)
Phy_DataOut => Phy_DataOut, -- o (7 downto 0)
Phy_TxValid => Phy_TxValid, -- o
Phy_TxReady => Phy_TxReady, -- i
Phy_RxActive => Phy_RxActive, -- i
Phy_RxValid => Phy_RxValid, -- i
Phy_RxError => Phy_RxError, -- i
Phy_LineState => Phy_LineState, -- i (1 downto 0)
Phy_OPmode => Phy_OPmode, -- o (1 downto 0) Phy_OPmode "01" -> non-driving
Phy_xcvrselect => OPEN, -- o Phy_OPmode "00" -> normal
Phy_termselect => FPGA_ready, -- o Phy_OPmode "10" -> disable bit stuffing
Phy_reset => OPEN -- o );
);
 
END rtl;
 
/usb_FS_monitor.vhd
0,0 → 1,325
--==========================================================================================================--
-- --
-- Copyright (C) 2011 by Martin Neumann martin@neumanns-mail.de --
-- --
-- This source file may be used and distributed without restriction provided that this copyright statement --
-- is not removed from the file and that any derivative work contains the original copyright notice and --
-- the associated disclaimer. --
-- --
-- This software is provided ''as is'' and without any express or implied warranties, including, but not --
-- limited to, the implied warranties of merchantability and fitness for a particular purpose. in no event --
-- shall the author or contributors be liable for any direct, indirect, incidental, special, exemplary, or --
-- consequential damages (including, but not limited to, procurement of substitute goods or services; loss --
-- of use, data, or profits; or business interruption) however caused and on any theory of liability, --
-- whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way --
-- out of the use of this software, even if advised of the possibility of such damage. --
-- --
--==========================================================================================================--
-- --
-- File name : usb_fs_monitor.vhd --
-- Author : Martin Neumann martin@neumanns-mail.de --
-- Description : USB bus monitor, logs all USB activities in result.out file. --
-- --
--==========================================================================================================--
-- --
-- Change history --
-- --
-- Version / date Description --
-- --
-- 01 05 Mar 2011 MN Initial version --
-- --
-- End change history --
--==========================================================================================================--
 
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_textio.all;
USE std.textio.all;
LIBRARY work;
USE work.usb_commands.all;
 
ENTITY usb_fs_monitor IS PORT(
clk_60MHz : IN STD_LOGIC;
master_oe : IN STD_LOGIC;
usb_Dp : IN STD_LOGIC;
usb_Dn : IN STD_LOGIC);
END usb_fs_monitor;
 
ARCHITECTURE SIM OF usb_fs_monitor IS
TYPE state_mode IS(idle, pid, addr, frame, data, spec, eop);
SIGNAL usb_state : state_mode;
SIGNAL usb_dp_sync : STD_LOGIC;
SIGNAL usb_dn_sync : STD_LOGIC;
SIGNAL clk_en : STD_LOGIC;
SIGNAL usb_byte : STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL byte_valid : STD_LOGIC;
SIGNAL xfer_busy : STD_LOGIC;
SIGNAL bit_cntr : NATURAL;
SIGNAL dll_cntr : NATURAL;
SIGNAL next_state : state_mode;
SIGNAL edge_detect : STD_LOGIC;
SIGNAL usb_dp_s0 : STD_LOGIC;
SIGNAL usb_dp_s1 : STD_LOGIC;
SIGNAL usb_dn_s0 : STD_LOGIC;
SIGNAL usb_dn_s1 : STD_LOGIC;
SIGNAL usb_dp_last : STD_LOGIC;
 
BEGIN
 
--==========================================================================================================--
-- Synchronize Inputs --
--==========================================================================================================--
 
p_usb_dp_sync: process (clk_60MHz)
begin
if rising_edge(clk_60MHz) then
usb_dp_s0 <= usb_dp;
usb_dp_s1 <= usb_dp_s0;
if (usb_dp_s0 and usb_dp_s1) ='1' then
usb_dp_sync <= '1';
elsif (usb_dp_s0 OR usb_dp_s1) ='0' then
usb_dp_sync <= '0';
end if;
end if;
end process;
 
p_usb_dn_sync: process (clk_60MHz)
begin
if rising_edge(clk_60MHz) then
usb_dn_s0 <= usb_Dn;
usb_dn_s1 <= usb_dn_s0;
if (usb_dn_s0 and usb_dn_s1) ='1' then
usb_dn_sync <= '1';
elsif (usb_dn_s0 OR usb_dn_s1) ='0' then
usb_dn_sync <= '0';
end if;
end if;
end process;
 
p_usb_d_last: process (clk_60MHz)
begin
if rising_edge(clk_60MHz) THEN
usb_dp_last <= usb_dp_sync;
end if;
end process;
 
edge_detect <= usb_dp_last XOR usb_dp_sync;
 
p_dll_cntr: process (clk_60MHz)
begin
if rising_edge(clk_60MHz) then
if edge_detect ='1' then
if dll_cntr >= 8 then
dll_cntr <= 2; -- clk_en detected, now centered in following cycle
else
dll_cntr <= 7; -- adjust clk_en to center cycle
end if;
elsif dll_cntr >= 8 then -- normal count sequence is 8->4->5->6->7->8->4...
dll_cntr <= 4;
else
dll_cntr <= dll_cntr +1;
end if;
end if;
end process;
 
clk_en <= '1' WHEN dll_cntr >= 8 ELSE '0';
 
--==========================================================================================================--
-- Analyse USB Inputs --
--==========================================================================================================--
 
 
p_xfer_busy : PROCESS
VARIABLE sync_pattern : STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
WAIT UNTIL rising_edge(clk_60MHz) AND clk_en ='1';
sync_pattern := sync_pattern(6 DOWNTO 0) & usb_Dp_sync;
IF sync_pattern = "01010100" THEN
xfer_busy <= '1';
WAIT UNTIL rising_edge(clk_60MHz) AND usb_Dp_sync ='0' AND usb_Dn_sync ='0' AND clk_en ='1';
END IF;
xfer_busy <= '0';
END PROCESS;
 
p_se0_det : PROCESS
VARIABLE sync_pattern : STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE se0_lev : BOOLEAN;
VARIABLE se0_time : Time := 0 ns;
VARIABLE v_LineWr : line := NULL;
BEGIN
WAIT UNTIL rising_edge(clk_60MHz) AND clk_en ='1';
IF usb_Dp_sync ='0' AND usb_Dn_sync ='0' THEN
IF NOT se0_lev THEN
se0_lev := TRUE;
se0_time := now;
END IF;
ELSE
IF se0_lev THEN
se0_time := now - se0_time;
IF se0_time >= 200 ns THEN
write (v_LineWr, now, right,15);
IF se0_time >= 2500 ns THEN
write (v_LineWr, STRING'(" USB Reset detected for "));
ELSE
write (v_LineWr, STRING'(" USB lines at SE0 for "));
END IF;
write (v_LineWr, se0_time, right,15);
PrintLine(v_LineWr);
END IF;
END IF;
se0_lev := FALSE;
END IF;
END PROCESS;
 
p_usb_byte : PROCESS(xfer_busy, clk_60MHz, clk_en)
VARIABLE hold, usb_last : STD_LOGIC;
VARIABLE ones_cnt : NATURAL;
BEGIN
IF xfer_busy ='0' THEN
usb_last := usb_Dp_sync;
bit_cntr <= 0;
ones_cnt := 0;
byte_valid <= '0';
usb_byte <= (OTHERS => 'H');
ELSIF rising_edge(clk_60MHz) AND clk_en ='1' THEN
IF usb_Dp_sync = usb_last THEN
usb_byte <= '1' & usb_byte(7 DOWNTO 1);
bit_cntr <= (bit_cntr +1) MOD 8;
ones_cnt := (ones_cnt +1);
IF ones_cnt > 6 THEN
ASSERT FALSE REPORT"Stuffing error" SEVERITY ERROR;
END IF;
hold := '0';
ELSE
IF ones_cnt /= 6 THEN
usb_byte <= '0' & usb_byte(7 DOWNTO 1);
bit_cntr <= (bit_cntr +1) MOD 8;
hold := '0';
ELSE
hold := '1';
END IF;
ones_cnt := 0;
END IF;
IF bit_cntr=7 THEN
byte_valid <= NOT hold;
ELSE
byte_valid <= '0';
END IF;
usb_last := usb_Dp_sync;
END IF;
END PROCESS;
 
p_usb_state : PROCESS
BEGIN
WAIT UNTIL rising_edge(clk_60MHz) AND clk_en ='1';
IF xfer_busy ='0' THEN
usb_state <= idle;
ELSIF usb_Dp_sync ='0' AND usb_Dn_sync ='0' THEN
usb_state <= eop;
ELSE
usb_state <= next_state;
END IF;
END PROCESS;
 
p_next_state : PROCESS
VARIABLE address : STD_LOGIC_VECTOR(6 DOWNTO 0);
VARIABLE endpoint : STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE frame_no : STD_LOGIC_VECTOR(10 DOWNTO 0);
VARIABLE byte_cnt : NATURAL;
VARIABLE v_LineWr : line := NULL;
BEGIN
WAIT UNTIL rising_edge(clk_60MHz) AND clk_en ='1';
CASE usb_state IS
WHEN idle => next_state <= pid;
WHEN pid => IF byte_valid ='1' THEN
IF usb_byte(3 DOWNTO 0) /= NOT usb_byte(7 DOWNTO 4) THEN
ASSERT FALSE REPORT"PID error" SEVERITY ERROR;
END IF;
write (v_LineWr, now, right,15);
IF master_oe ='1' THEN
write (v_LineWr, STRING'(" Send "));
ELSE
write (v_LineWr, STRING'(" Recv "));
END IF;
byte_cnt := 0;
CASE usb_byte(3 DOWNTO 0) IS
WHEN x"1" => next_state <= addr;
write (v_LineWr, STRING'("OUT-Token"));
WHEN x"9" => next_state <= addr;
write (v_LineWr, STRING'("IN-Token"));
WHEN x"5" => next_state <= frame;
write (v_LineWr, STRING'("SOF-Token"));
WHEN x"D" => next_state <= addr;
write (v_LineWr, STRING'("Setup"));
WHEN x"3" => next_state <= data;
write (v_LineWr, STRING'("Data0"));
WHEN x"B" => next_state <= data;
write (v_LineWr, STRING'("Data1"));
WHEN x"7" => next_state <= data;
write (v_LineWr, STRING'("Data2"));
WHEN x"F" => next_state <= data;
write (v_LineWr, STRING'("MData"));
WHEN x"2" => next_state <= idle;
write (v_LineWr, STRING'("ACK"));
WHEN x"A" => next_state <= idle;
write (v_LineWr, STRING'("NAK"));
WHEN x"E" => next_state <= idle;
write (v_LineWr, STRING'("STALL"));
WHEN x"6" => next_state <= idle;
write (v_LineWr, STRING'("NYET"));
-- WHEN x"C" => next_state <= spec;
-- write (v_LineWr, STRING'("Preamble"));
WHEN x"C" => next_state <= spec;
write (v_LineWr, STRING'("ERR"));
WHEN x"8" => next_state <= spec;
write (v_LineWr, STRING'("Split"));
WHEN x"4" => next_state <= spec;
write (v_LineWr, STRING'("Ping"));
WHEN OTHERS => next_state <= idle;
ASSERT FALSE REPORT"PID is zero" SEVERITY ERROR;
END CASE;
END IF;
WHEN addr => IF byte_valid ='1' THEN
address := usb_byte(6 DOWNTO 0);
endpoint(0) := usb_byte(7);
WAIT UNTIL rising_edge(clk_60MHz) AND byte_valid ='1' AND clk_en ='1';
endpoint(3 DOWNTO 1) := usb_byte(2 DOWNTO 0);
write (v_LineWr, STRING'(": Address 0x"));
HexWrite (v_LineWr, address);
write (v_LineWr, STRING'(", Endpoint 0x"));
HexWrite (v_LineWr, endpoint);
write (v_LineWr, STRING'(", CRC5 0x"));
HexWrite (v_LineWr, usb_byte(7 DOWNTO 3));
next_state <= idle;
END IF;
WHEN frame =>IF byte_valid ='1' THEN
frame_no(7 DOWNTO 0) := usb_byte;
WAIT UNTIL rising_edge(clk_60MHz) AND byte_valid ='1' AND clk_en ='1';
frame_no(10 DOWNTO 8) := usb_byte(2 DOWNTO 0);
write (v_LineWr, STRING'(": Frame No 0x"));
HexWrite (v_LineWr, frame_no);
write (v_LineWr, STRING'(", CRC5 0x"));
HexWrite (v_LineWr, usb_byte(7 DOWNTO 3));
next_state <= idle;
END IF;
WHEN data => WAIT UNTIL rising_edge(clk_60MHz) AND byte_valid ='1' AND clk_en ='1';
byte_cnt := byte_cnt +1;
IF byte_cnt = 17 THEN
PrintLine(v_LineWr);
write (v_LineWr, now, right,15);
write (v_LineWr, STRING'(" ....."));
byte_cnt := 1;
END IF;
write (v_LineWr, STRING'(" 0x"));
HexWrite (v_LineWr, usb_byte);
WHEN eop => next_state <= idle;
PrintLine(v_LineWr);
WHEN OTHERS => next_state <= idle;
END CASE;
END PROCESS;
 
usb_busy <= usb_state /= idle; -- global signal, used in usb_commands --
 
END SIM;
 
--======================================== END OF usb_fs_monitor.vhd =======================================--
/usb_test.do
0,0 → 1,80
################################################################################################
# This tcl-file is for usage with Model Sim, adopt this information to your simulator needs MN #
################################################################################################
 
echo "===>"
echo "===> Recompiling Sources"
echo "===>"
 
if {[file exists work]} { vdel -lib work -all }
vlib work
vmap work D:/Design/My_USB_Controller/work
 
# Open Cores USB Phy, designed by Rudolf Usselmanns and translated to VHDL by Martin Neumann
vcom -93 -work work D:/Design/My_USB_Controller/Source/usb_phy/usb_rx_phy_60MHz.vhdl
vcom -93 -work work D:/Design/My_USB_Controller/Source/usb_phy/usb_tx_phy.vhdl
vcom -93 -work work D:/Design/My_USB_Controller/Source/usb_phy/usb_phy.vhdl
 
# Open Cores USB Serial, designed by Joris van Rantwijk
vcom -93 -work work D:/Design/My_USB_Controller/Source/usb_serial/usb_pkg.vhdl
vcom -93 -work work D:/Design/My_USB_Controller/Source/usb_serial/usb_init.vhdl
vcom -93 -work work D:/Design/My_USB_Controller/Source/usb_serial/usb_control.vhdl
vcom -93 -work work D:/Design/My_USB_Controller/Source/usb_serial/usb_transact.vhdl
vcom -93 -work work D:/Design/My_USB_Controller/Source/usb_serial/usb_packet.vhdl
vcom -93 -work work D:/Design/My_USB_Controller/Source/usb_serial/usb_serial.vhdl
vcom -93 -work work D:/Design/My_USB_Controller/Source/usb_fs_slave.vhdl
 
# The USB FS test bench files
vcom -93 -work work D:/Design/My_USB_Controller/Testbench/usb_commands.vhd
vcom -93 -work work D:/Design/My_USB_Controller/Testbench/usb_stimuli.vhd
vcom -93 -work work D:/Design/My_usb_Controller/Testbench/usb_fs_monitor.vhd
vcom -93 -work work D:/Design/My_usb_Controller/Testbench/usb_fs_master.vhd
vcom -93 -work work D:/Design/My_USB_Controller/Testbench/usb_tb.vhd
 
echo "===>"
echo "===> Start Simulation"
echo "===>"
vsim -quiet usb_tb
 
#view source
view wave
configure wave -signalnamewidth 1
 
add wave -noupdate -divider {USB_Monitor}
add wave -noupdate -format Literal -radix decimal /usb_tb/usb_fs_master/test_case/t_no
add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_master/usb_fs_monitor/*
add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_master/stimuli_bit
 
add wave -noupdate -divider {USB_MASTER}
add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_master/*
 
add wave -noupdate -divider {USB_STIMULI}
add wave -noupdate -format Literal -radix decimal /usb_tb/usb_fs_master/test_case/t_no
add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_master/test_case/*
 
add wave -noupdate -divider {USB_PHY}
add wave -noupdate -format Literal -radix decimal /usb_tb/usb_fs_master/test_case/t_no
add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_slave_1/usb_phy_1/*
 
# add wave -noupdate -divider {USB_RX_PHY}
# add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_slave_1/usb_phy_1/i_rx_phy/*
#
# add wave -noupdate -divider
# add wave -noupdate -divider {USB_TX_PHY}
# add wave -noupdate -format Literal -radix decimal /usb_tb/usb_fs_master/test_case/t_no
# add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_slave_1/usb_phy_1/i_tx_phy/*
add wave -noupdate -divider {USB_SERIAL}
add wave -noupdate -format Literal -radix decimal /usb_tb/usb_fs_master/test_case/t_no
add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_slave_1/usb_serial_1/*
add wave -noupdate -divider {USB_S-INIT}
add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_slave_1/usb_serial_1/usb_init_inst/*
add wave -noupdate -divider {USB_S-PACKET}
add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_slave_1/usb_serial_1/usb_packet_inst/*
add wave -noupdate -divider {USB_S-TRANSACT}
add wave -noupdate -format Literal -radix decimal /usb_tb/usb_fs_master/test_case/t_no
add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_slave_1/usb_serial_1/usb_transact_inst/*
add wave -noupdate -divider {USB_S-CONTROL}
add wave -noupdate -format Logic -radix hexadecimal /usb_tb/usb_fs_slave_1/usb_serial_1/usb_control_inst/*
 
onbreak {resume}
run -all
/USB FS TestBench.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
USB FS TestBench.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: USB_Commands.vhd =================================================================== --- USB_Commands.vhd (nonexistent) +++ USB_Commands.vhd (revision 2) @@ -0,0 +1,509 @@ +--==========================================================================================================-- +-- -- +-- Copyright (C) 2011 by Martin Neumann martin@neumanns-mail.de -- +-- -- +-- This source file may be used and distributed without restriction provided that this copyright statement -- +-- is not removed from the file and that any derivative work contains the original copyright notice and -- +-- the associated disclaimer. -- +-- -- +-- This software is provided ''as is'' and without any express or implied warranties, including, but not -- +-- limited to, the implied warranties of merchantability and fitness for a particular purpose. in no event -- +-- shall the author or contributors be liable for any direct, indirect, incidental, special, exemplary, or -- +-- consequential damages (including, but not limited to, procurement of substitute goods or services; loss -- +-- of use, data, or profits; or business interruption) however caused and on any theory of liability, -- +-- whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way -- +-- out of the use of this software, even if advised of the possibility of such damage. -- +-- -- +--==========================================================================================================-- +-- -- +-- File name : usb_commands.vhd -- +-- Author : Martin Neumann martin@neumanns-mail.de -- +-- Description : Defines, functions and procedures for the usb_Stimuli.vhd file - the USB data source for -- +-- the test bench file. -- +-- -- +--==========================================================================================================-- +-- -- +-- Change history -- +-- -- +-- Version / date Description -- +-- -- +-- 01 05 Mar 2011 MN Initial version -- +-- -- +-- End change history -- +--==========================================================================================================-- +-- -- +-- USB control concept -- +-- ------------------- -- +-- The usb signal controls the usb command execution and its proper timing : -- +-- -- +-- Each command in the test case file 'usb_stimuli.vhd' is a procedure call with an output signal 'usb'. -- -- +-- Its states (of type usb_action) control the correct timing sequence of the process 'p_stimuli_bit' in -- +-- the file'usb_master'. This procedure sets the signal usb first to any one of the active states, then -- +-- after completion to inactive (idle). -- +-- -- +--==========================================================================================================-- +-- -- +-- Syntax Examples -- +-- -- +-- Procedure Function, Parameters -- +-- -- +-- list (T_No, 30); Test No listed in transcript and report file -- +-- List ("Any Text Message "); Message any text -- +-- Setup (usb, X"00", X"0"); usb setup: device address, endp address (+CRC5) -- +-- send_D0 (usb, (X"10",X"46",X"11",X"47", -- +-- X"12",X"48",X"13",X"49")); usb write data0 : byte string (+CRC16) -- +-- send_D1 (usb, (X"20",X"36",X"21",X"37", -- +-- X"22",X"38",X"23",X"39")); usb write data1 : byte string (+CRC16) -- +-- send_ACK (usb); usb ACK Handshake -- +-- send_NAK (usb); usb NAK Handshake -- +-- send_STALL(usb); usb Stall Handshake -- +-- send_NYET (usb); usb NYET (No Response Yet) Handshake -- +-- wait_slv (usb); wait until transfer of USB-slave completed -- +-- -- +--==========================================================================================================-- + +LIBRARY IEEE; + USE IEEE.std_logic_1164.all; + USE IEEE.std_logic_textio.all; + USE IEEE.std_logic_arith.all; + USE IEEE.std_logic_unsigned.all; + USE std.textio.all; + +PACKAGE usb_commands IS + +--==========================================================================================================-- + + TYPE usb_action IS (idle, sync, pid, addr, rd, wr_odd, wr_even, wr_crc5, wr_crc16, reset, send_eop, recv_eop); + TYPE byte_array IS ARRAY (NATURAL RANGE <>) OF STD_LOGIC_VECTOR(7 DOWNTO 0); + + SIGNAL usb_status : usb_action; + SIGNAL usb_busy : BOOLEAN := FALSE; + SHARED VARIABLE ok : BOOLEAN; + SHARED VARIABLE sv_usb_byte : STD_LOGIC_VECTOR(7 DOWNTO 0); + SHARED VARIABLE sv_usb_addr : STD_LOGIC_VECTOR(10 DOWNTO 0); + SHARED VARIABLE sv_read_loop : BOOLEAN := FALSE; + FILE screen : TEXT OPEN WRITE_MODE IS "STD_OUTPUT"; + FILE outpdata : TEXT OPEN WRITE_MODE IS "Result.out"; + + + PROCEDURE list(message : IN STRING); + PROCEDURE list(SIGNAL no_out : OUT NATURAL; no_in : IN NATURAL); + + PROCEDURE end_of_test(stop : IN BOOLEAN := TRUE); + +--==========================================================================================================-- + + PROCEDURE send_ACK (SIGNAL usb : OUT usb_action); + + PROCEDURE send_NAK (SIGNAL usb : OUT usb_action); + + PROCEDURE send_STALL(SIGNAL usb : OUT usb_action); + + PROCEDURE send_NYET (SIGNAL usb : OUT usb_action); + + PROCEDURE handshake(SIGNAL usb : OUT usb_action; CONSTANT pid_val : IN std_logic_vector(3 DOWNTO 0)); + + PROCEDURE setup( + SIGNAL usb : OUT usb_action; + CONSTANT device_addr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); + CONSTANT endp_addr : IN STD_LOGIC_VECTOR(3 DOWNTO 0) + ); + + PROCEDURE in_token( + SIGNAL usb : OUT usb_action; + CONSTANT device_addr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); + CONSTANT endp_addr : IN STD_LOGIC_VECTOR(3 DOWNTO 0) + ); + + PROCEDURE out_token( + SIGNAL usb : OUT usb_action; + CONSTANT device_addr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); + CONSTANT endp_addr : IN STD_LOGIC_VECTOR(3 DOWNTO 0) + ); + + PROCEDURE sof_token( + SIGNAL usb : OUT usb_action; + CONSTANT frame_no : IN STD_LOGIC_VECTOR(11 DOWNTO 0) + ); + + PROCEDURE token( + SIGNAL usb : OUT usb_action; + CONSTANT pid_val : IN std_logic_vector(3 DOWNTO 0); + CONSTANT token_val : IN STD_LOGIC_VECTOR(10 DOWNTO 0) + ); + + PROCEDURE send_d0(SIGNAL usb : OUT usb_action; CONSTANT wr_data : IN byte_array); + PROCEDURE send_D0(SIGNAL usb : OUT usb_action); + + PROCEDURE send_d1(SIGNAL usb : OUT usb_action; CONSTANT wr_data : IN byte_array); + PROCEDURE send_D1(SIGNAL usb : OUT usb_action); + + PROCEDURE send_d2(SIGNAL usb : OUT usb_action; CONSTANT wr_data : IN byte_array); + PROCEDURE send_D2(SIGNAL usb : OUT usb_action); + + PROCEDURE send_dm(SIGNAL usb : OUT usb_action; CONSTANT wr_data : IN byte_array); + PROCEDURE send_Dm(SIGNAL usb : OUT usb_action); + + PROCEDURE send_dx( + SIGNAL usb : OUT usb_action; + CONSTANT pid_val : IN STD_LOGIC_VECTOR(3 DOWNTO 0); + CONSTANT wr_data : IN byte_array + ); + PROCEDURE send_dx( + SIGNAL usb : OUT usb_action; + CONSTANT pid_val : IN STD_LOGIC_VECTOR(3 DOWNTO 0) + ); + + PROCEDURE send_RES(SIGNAL usb : OUT usb_action); + + PROCEDURE wait_slv(SIGNAL usb : OUT usb_action); + +--==========================================================================================================-- + -- internal functions and procedures -- + + FUNCTION to_01x(d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; + + FUNCTION hex_to_string(D: STD_LOGIC_VECTOR) RETURN STRING; + + PROCEDURE HexWrite( VARIABLE L : INOUT LINE; + CONSTANT VALUE : IN STD_LOGIC_VECTOR; + CONSTANT JUSTIFIED: IN SIDE := right; + CONSTANT FIELD : IN WIDTH := 0); + + PROCEDURE PrintLine (VARIABLE v_Line : INOUT Line); + + END usb_commands; + +--==========================================================================================================-- + + PACKAGE BODY usb_commands IS + + FUNCTION to_01x(d : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS + VARIABLE result : STD_LOGIC_VECTOR (d'RANGE); + BEGIN + FOR i IN d'RANGE LOOP + IF d(i) ='0' OR d(i) ='L' THEN --reduce data to 0, 1 or X + result(i) := '0'; + ELSIF d(i) ='1' OR d(i) ='H' THEN + result(i) := '1'; + ELSE + result(i) := 'X'; + END IF; + END LOOP; + RETURN result; + END to_01x; + +--==========================================================================================================-- + + FUNCTION hex_to_string(d: STD_LOGIC_VECTOR) RETURN STRING is + -- vector is padded with leadin '0's if not modula 4 -- + VARIABLE j, k, p : INTEGER; + VARIABLE d_ext : STD_LOGIC_VECTOR(1 to ((d'LENGTH +3)/4)*4); + VARIABLE nibble : STD_LOGIC_VECTOR(1 to 4); + VARIABLE result : STRING(1 TO (d'HIGH +4 - d'LOW)/4); + VARIABLE hex_val : STRING(1 TO 16) := "0123456789ABCDEF"; + TYPE hex_type IS ARRAY (1 TO 16) OF STD_LOGIC_VECTOR(0 to 3); + CONSTANT hex_tbl : hex_type := + ("0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", + "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"); + BEGIN + j := d_ext'LENGTH - d'LENGTH; + IF j = 0 THEN + d_ext := to_01x(d); + ELSE + d_ext(1 TO j) := (OTHERS =>'0'); + d_ext(j +1 TO d_ext'LENGTH) := to_01x(d); + END IF; + j := 1; + k := 1; + FOR i IN d_ext'RANGE LOOP + nibble(j) := d_ext(i); + IF j = 4 THEN --data nibble is ... + result(k) := 'X'; -- ... default X ... + HEX_CHAR: for h in 1 to 16 LOOP + IF nibble = hex_tbl(h) THEN + result(k) := hex_val(h); -- ... or 1 to F + EXIT HEX_CHAR; + END IF; + END LOOP; + k := k+1; + END IF; + j := (j MOD 4) +1; + END LOOP; + RETURN result; + END; + + PROCEDURE HexWrite( VARIABLE L : INOUT LINE; + CONSTANT VALUE : IN STD_LOGIC_VECTOR; + CONSTANT JUSTIFIED: IN SIDE := right; + CONSTANT FIELD : IN WIDTH := 0) IS + BEGIN + write (L, STRING'(hex_to_string(VALUE)), JUSTIFIED, FIELD); + END; + +--==========================================================================================================-- + + PROCEDURE list(message : IN STRING) IS + VARIABLE v_Line : line := NULL; + BEGIN + WAIT FOR 0 ns; + write(v_Line, " " & Message); + write(Screen, v_Line.all & LF); + writeline(OutpData, v_Line); + END list; + + PROCEDURE list(SIGNAL no_out : OUT NATURAL; no_in : IN NATURAL) IS + VARIABLE v_Line : line := NULL; + BEGIN + IF usb_busy THEN -- set in usb_monitor + WAIT UNTIL NOT usb_busy; + END IF; + write(v_Line, STRING'("Test_No "), right, 25); + write(v_Line, no_in); + PrintLine(v_Line); + no_out <= no_in; + END list; + +--==========================================================================================================-- + + PROCEDURE end_of_test(stop : IN BOOLEAN := TRUE) IS + BEGIN + IF usb_busy THEN -- set in usb_monitor + WAIT UNTIL NOT usb_busy; + END IF; + ASSERT stop = FALSE REPORT"End of Test" SEVERITY FAILURE; + END end_of_test; + +--==========================================================================================================-- + + PROCEDURE PrintLine(VARIABLE v_Line : INOUT Line) IS + BEGIN + IF v_Line /= NULL THEN + write(Screen, v_Line.all & LF); + END IF; + writeline(OutpData, v_Line); + END PrintLine; + +--==========================================================================================================-- + + PROCEDURE send_ACK(SIGNAL usb : OUT usb_action) IS + BEGIN + handshake(usb, X"2"); + END send_ACK; + + PROCEDURE send_NAK(SIGNAL usb : OUT usb_action) IS + BEGIN + handshake(usb, X"A"); + END send_NAK; + + PROCEDURE send_STALL(SIGNAL usb : OUT usb_action) IS + BEGIN + handshake(usb, X"E"); + END send_STALL; + + PROCEDURE send_NYET(SIGNAL usb : OUT usb_action) IS + BEGIN + handshake(usb, X"6"); + END send_NYET; + + PROCEDURE handshake(SIGNAL usb : OUT usb_action; CONSTANT pid_val : IN std_logic_vector(3 DOWNTO 0)) IS + BEGIN + usb <= sync; + WAIT UNTIL usb_status = sync; + WAIT UNTIL usb_status = idle; + sv_usb_byte := NOT pid_val & pid_val; + usb <= pid; + WAIT UNTIL usb_status = pid; + WAIT UNTIL usb_status = idle; + usb <= send_eop; + WAIT UNTIL usb_status = send_eop; + WAIT UNTIL usb_status = idle; + usb <= idle; + END handshake; + +--==========================================================================================================-- + + PROCEDURE setup( + SIGNAL usb : OUT usb_action; + CONSTANT device_addr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); + CONSTANT endp_addr : IN STD_LOGIC_VECTOR(3 DOWNTO 0) + )IS + BEGIN + ASSERT device_addr(7) = '0' REPORT" Token device address out of range 0 to 127" SEVERITY FAILURE; + token(usb, X"D", endp_addr & device_addr(6 DOWNTO 0)); + END setup; + + PROCEDURE in_token( + SIGNAL usb : OUT usb_action; + CONSTANT device_addr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); + CONSTANT endp_addr : IN STD_LOGIC_VECTOR(3 DOWNTO 0) + )IS + BEGIN + ASSERT device_addr(7) = '0' REPORT" Token device address out of range 0 to 127" SEVERITY FAILURE; + token(usb, X"9", endp_addr & device_addr(6 DOWNTO 0)); + END in_token; + + PROCEDURE out_token( + SIGNAL usb : OUT usb_action; + CONSTANT device_addr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); + CONSTANT endp_addr : IN STD_LOGIC_VECTOR(3 DOWNTO 0) + )IS + BEGIN + ASSERT device_addr(7) = '0' REPORT" Token device address out of range 0 to 127" SEVERITY FAILURE; + token(usb, X"1", endp_addr & device_addr(6 DOWNTO 0)); + END out_token; + + PROCEDURE sof_token( + SIGNAL usb : OUT usb_action; + CONSTANT frame_no : IN STD_LOGIC_VECTOR(11 DOWNTO 0) + )IS + BEGIN + token(usb, X"5", frame_no(10 DOWNTO 0)); + END sof_token; + + PROCEDURE token( + SIGNAL usb : OUT usb_action; + CONSTANT pid_val : IN std_logic_vector(3 DOWNTO 0); + CONSTANT token_val : IN STD_LOGIC_VECTOR(10 DOWNTO 0) + )IS + BEGIN + usb <= sync; + WAIT UNTIL usb_status = sync; + WAIT UNTIL usb_status = idle; + sv_usb_byte := NOT pid_val & pid_val; + usb <= pid; + WAIT UNTIL usb_status = pid; + WAIT UNTIL usb_status = idle; + sv_usb_addr := token_val; + usb <= addr; + WAIT UNTIL usb_status = addr; + WAIT UNTIL usb_status = idle; + usb <= wr_crc5; + WAIT UNTIL usb_status = wr_crc5; + WAIT UNTIL usb_status = idle; + usb <= send_eop; + WAIT UNTIL usb_status = send_eop; + WAIT UNTIL usb_status = idle; + usb <= idle; + END token; + +----==========================================================================================================-- + + PROCEDURE send_D0(SIGNAL usb : OUT usb_action; CONSTANT wr_data : IN byte_array) IS + BEGIN + send_dx(usb, X"3", wr_data); + END send_D0; + + PROCEDURE send_D1(SIGNAL usb : OUT usb_action; CONSTANT wr_data : IN byte_array) IS + BEGIN + send_dx(usb, X"B", wr_data); + END send_D1; + + PROCEDURE send_D2(SIGNAL usb : OUT usb_action; CONSTANT wr_data : IN byte_array) IS + BEGIN + send_dx(usb, X"7", wr_data); + END send_D2; + + PROCEDURE send_Dm(SIGNAL usb : OUT usb_action; CONSTANT wr_data : IN byte_array) IS + BEGIN + send_dx(usb, X"F", wr_data); + END send_Dm; + + PROCEDURE send_dx( + SIGNAL usb : OUT usb_action; + CONSTANT pid_val : IN STD_LOGIC_VECTOR(3 DOWNTO 0); + CONSTANT wr_data : IN byte_array + )IS + BEGIN + usb <= sync; + WAIT UNTIL usb_status = sync; + WAIT UNTIL usb_status = idle; + sv_usb_byte := NOT pid_val & pid_val; + usb <= pid; + WAIT UNTIL usb_status = pid; + WAIT UNTIL usb_status = idle; + FOR i in 0 TO wr_data'LENGTH -1 LOOP + sv_usb_byte := wr_data(i); + IF i MOD 2 = 0 THEN + usb <= wr_even; + WAIT UNTIL usb_status = wr_even; + ELSE + usb <= wr_odd; + WAIT UNTIL usb_status = wr_odd; + END IF; + WAIT UNTIL usb_status = idle; + END LOOP; + usb <= wr_crc16; + WAIT UNTIL usb_status = wr_crc16; + WAIT UNTIL usb_status = idle; + usb <= send_eop; + WAIT UNTIL usb_status = send_eop; + WAIT UNTIL usb_status = idle; + usb <= idle; + END send_dx; + +----==========================================================================================================-- + + PROCEDURE send_D0(SIGNAL usb : OUT usb_action) IS + BEGIN + send_dx(usb, X"3"); + END send_D0; + + PROCEDURE send_D1(SIGNAL usb : OUT usb_action) IS + BEGIN + send_dx(usb, X"B"); + END send_D1; + + PROCEDURE send_D2(SIGNAL usb : OUT usb_action) IS + BEGIN + send_dx(usb, X"7"); + END send_D2; + + PROCEDURE send_Dm(SIGNAL usb : OUT usb_action) IS + BEGIN + send_dx(usb, X"F"); + END send_Dm; + + PROCEDURE send_dx( + SIGNAL usb : OUT usb_action; + CONSTANT pid_val : IN STD_LOGIC_VECTOR(3 DOWNTO 0) + )IS + BEGIN + usb <= sync; + WAIT UNTIL usb_status = sync; + WAIT UNTIL usb_status = idle; + sv_usb_byte := NOT pid_val & pid_val; + usb <= pid; + WAIT UNTIL usb_status = pid; + WAIT UNTIL usb_status = idle; + usb <= wr_crc16; + WAIT UNTIL usb_status = wr_crc16; + WAIT UNTIL usb_status = idle; + usb <= send_eop; + WAIT UNTIL usb_status = send_eop; + WAIT UNTIL usb_status = idle; + usb <= idle; + END send_dx; + +----==========================================================================================================-- + + PROCEDURE send_RES(SIGNAL usb : OUT usb_action) IS + BEGIN + usb <= reset; + WAIT UNTIL usb_status = reset; + WAIT UNTIL usb_status = idle; + usb <= idle; + END send_RES; + +----==========================================================================================================-- + + PROCEDURE wait_slv(SIGNAL usb : OUT usb_action) IS + BEGIN + usb <= recv_eop; + WAIT UNTIL usb_status = recv_eop; + WAIT UNTIL usb_status = idle; + usb <= idle; + END wait_slv; + +----==========================================================================================================-- +END usb_commands; Index: usb_tc_01.vhdl =================================================================== --- usb_tc_01.vhdl (nonexistent) +++ usb_tc_01.vhdl (revision 2) @@ -0,0 +1,185 @@ +--==========================================================================================================-- +-- -- +-- Copyright (C) 2011 by Martin Neumann martin@neumanns-mail.de -- +-- -- +-- This source file may be used and distributed without restriction provided that this copyright statement -- +-- is not removed from the file and that any derivative work contains the original copyright notice and -- +-- the associated disclaimer. -- +-- -- +-- This software is provided ''as is'' and without any express or implied warranties, including, but not -- +-- limited to, the implied warranties of merchantability and fitness for a particular purpose. in no event -- +-- shall the author or contributors be liable for any direct, indirect, incidental, special, exemplary, or -- +-- consequential damages (including, but not limited to, procurement of substitute goods or services; loss -- +-- of use, data, or profits; or business interruption) however caused and on any theory of liability, -- +-- whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way -- +-- out of the use of this software, even if advised of the possibility of such damage. -- +-- -- +--==========================================================================================================-- +-- -- +-- File name : USB_tc_01.vhd -- +-- Author : Martin Neumann martin@neumanns-mail.de -- +-- Description : Copy and rename this file to usb_stimuli.vhd before running a new simulation! -- +-- -- +--==========================================================================================================-- +-- -- +-- Change history -- +-- -- +-- Version / date Description -- +-- -- +-- 01 05 Mar 2011 MN Initial version -- +-- -- +-- End change history -- +--==========================================================================================================-- + +LIBRARY work, IEEE; + USE IEEE.std_logic_1164.ALL; + USE work.usb_commands.ALL; + +ENTITY USB_Stimuli IS PORT( + -- Test Control Interface -- + USB : OUT usb_action; + t_no : OUT NATURAL; + -- Application Interface + clk : IN STD_LOGIC; + rst_neg_ext : OUT STD_LOGIC; + RXval : IN STD_LOGIC; -- RX bytes available + RXdat : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Received data bytes + RXrdy : OUT STD_LOGIC := '0'; -- Application ready for data + RXlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Number of bytes available + TXval : OUT STD_LOGIC := '0'; -- Application has valid data + TXdat : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Data byte to send + TXrdy : IN STD_LOGIC; -- Entity is ready for data + TXroom : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- No of free bytes in TX + TXcork : OUT STD_LOGIC := '1'); -- Hold TX transmission +END USB_Stimuli; + +ARCHITECTURE sim OF usb_stimuli IS + +--==========================================================================================================-- + + -- Get discritor (control transfer to endp 0) is a Setup transaction of 8 data0 bytes: + -- ************************************************************************** + -- |Setup Packet |Bytes | Value | Details | CRC5 : Init to "11111" + -- +-----------------+------+-------+---------------------------------------+ Ignor Sync + -- |Setup-PID | 1 | 2Dh | | Ignor PIP + -- +-----------------+------+-------+---------------------------------------+ Process Byte 1 + 2 + -- |Addr EndP CRC-5 | 2 | 1000h | | Send inverted CRC with MSB first + -- | | | | .........00000000 Address (7bit) | CRC-checker expects "01100" + -- | | | | .....0000........ EndP Ar (4bit) | + -- | | | | 00010............ CRC (5bit) | + -- ************************************************************************** + -- ************************************************************************** + -- |Data0 Packet |Bytes | Value | Details | CRC16 : Init to "1111111111111111" + -- +-----------------+------+-------+---------------------------------------+ Ignor Sync + -- |Data0-PID | 1 | C3h | | Process all Bytes + -- +-----------------+------+-------+---------------------------------------+ Send inverted CRC with MSB first + -- |bmRequestType | 1 | 81h | | CRC-checker expects "1000000000001101"; + -- | | | |Recipient ...00001 Interface | + -- | | | |Type .00..... Standard | + -- | | | |Direction 1....... Device to Host | + -- +-----------------+------+-------+---------------------------------------+ + -- |bRequest | 1 | 06h | Get Descriptor | + -- +-----------------+------+-------+---------------------------------------+ + -- |wValue LowByte | 1 | 00h | | + -- +-----------------+------+-------+ Report Descriptor | + -- |wValue HiByte | 1 | 22h | | + -- +-----------------+------+-------+---------------------------------------+ + -- |wIndex | 2 | 0003h | Interface | + -- +-----------------+------+-------+---------------------------------------+ + -- |wLength | 2 | 0072h | Descriptor Length | + -- +-----------------+------+-------+---------------------------------------+ + -- |CRC-16 | 2 | BBCCh | CRC-Check | + -- ************************************************************************** + +BEGIN + + p_stimuli_data : PROCESS + BEGIN + list(T_No, 10); + rst_neg_ext <= '0'; + WAIT FOR 301 ns; + rst_neg_ext <= '1'; + WAIT FOR 40 ns; + list("Reset completed"); + list(T_No, 20); + setup(usb, X"00", X"0"); --Send Setup to addr 0, endp 0 + -- send_D0(usb,(X"01",X"FF",X"FF",X"80",X"FE",X"00",X"02",X"00")); --Stuffing test pattern + -- send_D0(usb,(X"80",X"06",X"00",X"01",X"00",X"00",X"40",X"00")); --Mouse in Example No4 + send_D0(usb,(X"80",X"06",X"00",X"01",X"00",X"00",X"12",X"00")); --Send 'Get Device descriptor' + --=========================================-- + -- Send 'Get Device descriptor' Data Field -- + --=========================================-- + -- Byte 0-1 0x80, 0x06 Get Discriptor -- + -- 2 0x00 Descr.Index=0 -- + -- 3 0x01 Descr.Type=Device -- + -- 4-5 0x00, 0x00 Zero -- + -- 6-7 0x12, 0x00 Byte Cnt (18 byte) -- + --=========================================-- + wait_slv(usb); --Recv ACK + list(T_No, 30); + in_token(usb, X"00", X"0"); --Send IN-Token + wait_slv(usb); --Recv discriptor data + --Recv 12 01 00 02 00 00 00 40 FE 13 00 1E 00 00 00 00 00 01 Mouse in Example No4 + --===========================================================-- + --Recv 12 01 10 01 02 00 00 40 9A FB 9A FB 20 00 00 00 00 01 -- + --======+==============+========+============================-- + -- 0 | bLength | 18 | Valid Length -- + -- 1 | bDiscType | 1 | Device -- + -- 2-3 | bcd USB | 0x0110 | Spec Version -- + -- 4 | bDeviceClass | 0x02 | Communications -- + -- 5 | bDevSubClass | 0x00 | none -- + -- 6 | bDevProtocol | 0x00 | none -- + -- 7 | bMaxPacket | 0x40 | 64 byte -- + -- 8-9 | idVendor | 0xFB9A | ? -- + -- A-B | idProduct | 0xFB9A | ? -- + -- C-D | bcdDevice | 0x0020 | ? -- + -- E | iManufact. | 0x00 | Index to Manufact. (none) -- + -- F | iProduct | 0x00 | Index to ProdString (none) -- + -- 10 | iSerialNo | 0x00 | Index to SerNo (none) -- + -- 11 | bNumConfig | 0x01 | 1 Configuration -- + --===========================================================-- + send_ack(usb); --Send ACK + --Once the device descriptor is sent, a status transaction follows. + list(T_No, 35); + setup(usb, X"00", X"0"); --Send Setup to addr 0, endp 0 + send_D0(usb,(X"80",X"00",X"00",X"00",X"00",X"00",X"02",X"00")); --Send 'Get Status' (Device, 2 byte) + wait_slv(usb); + in_token(usb, X"00", X"0"); + wait_slv(usb); --get 2 bytes + send_ACK(usb); --Send ACK + + --If the transactions were successful, the host will send a zero length packet indicating the overall + --transaction was successful. The function then replies to this zero length packet indicating its status: + list(T_No, 40); + out_token(usb, X"00", X"0"); + send_D0(usb); --Send Zero Data + wait_slv(usb); --Recv ACK + + --Set Address is used during enumeration to assign a unique address to the USB device. The address is + --specified in wValue and can only be a maximum of 127. This request is unique in that the device does + --not set its address until after the completion of the status stage (send an IN Token, expect zero data). + list(T_No, 50); + setup(usb, X"00", X"0"); --Send Setup to addr 0, endp 0 + send_D0(usb,(X"00",X"05",X"03",X"00",X"00",X"00",X"00",X"00")); --Send 'Set Address' to 0x0003 + wait_slv(usb); --Recv ACK + in_token(usb, X"00", X"0"); --Send IN packet + wait_slv(usb); --Recv Data0 zero Length + send_ack(usb); --Send ACK + + --Now we may use the new address : + list(T_No, 60); + setup(usb, X"03", X"0"); --Send Setup to addr 3, endp 0 + send_D0(usb,(X"80",X"06",X"00",X"01",X"00",X"00",X"12",X"00")); --Send 'Get Device descriptor' + wait_slv(usb); --Recv ACK + list(T_No, 70); + in_token(usb, X"03", X"0"); --Send IN-Token + wait_slv(usb); + send_ack(usb); --Send ACK + IF usb_busy THEN -- usb_usy is set in usb_monitor + WAIT UNTIL NOT usb_busy; + END IF; + ASSERT FALSE REPORT"End of Test" SEVERITY FAILURE; + END PROCESS; + +END sim; + Index: USB_FS_master.vhd =================================================================== --- USB_FS_master.vhd (nonexistent) +++ USB_FS_master.vhd (revision 2) @@ -0,0 +1,280 @@ +--==========================================================================================================-- +-- -- +-- Copyright (C) 2011 by Martin Neumann martin@neumanns-mail.de -- +-- -- +-- This source file may be used and distributed without restriction provided that this copyright statement -- +-- is not removed from the file and that any derivative work contains the original copyright notice and -- +-- the associated disclaimer. -- +-- -- +-- This software is provided ''as is'' and without any express or implied warranties, including, but not -- +-- limited to, the implied warranties of merchantability and fitness for a particular purpose. in no event -- +-- shall the author or contributors be liable for any direct, indirect, incidental, special, exemplary, or -- +-- consequential damages (including, but not limited to, procurement of substitute goods or services; loss -- +-- of use, data, or profits; or business interruption) however caused and on any theory of liability, -- +-- whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way -- +-- out of the use of this software, even if advised of the possibility of such damage. -- +-- -- +--==========================================================================================================-- +-- -- +-- File name : usb_fs_master.vhd -- +-- Author : Martin Neumann martin@neumanns-mail.de -- +-- Description : USB FS Master, used with usb_Stimuli.vhd data source and usb_fs_monitor.vhd. -- +-- -- +--==========================================================================================================-- +-- -- +-- Change history -- +-- -- +-- Version / date Description -- +-- -- +-- 01 05 Mar 2011 MN Initial version -- +-- -- +-- End change history -- +--==========================================================================================================-- +-- -- +-- http://en.wikipedia.org/wiki/Universal_Serial_Bus -- +-- USB data is transmitted by toggling the data lines between the J state and the opposite K state. USB -- +-- encodes data using the NRZI convention; a 0 bit is transmitted by toggling the data lines from J to K -- +-- or vice-versa, while a 1 bit is transmitted by leaving the data lines as-is. -- +-- To ensure a minimum density of signal transitions, USB uses bit stuffing - an extra 0 bit is inserted -- +-- into the data stream after any appearance of six consecutive 1 bits. Seven consecutive '1's are always -- +-- an error. -- +-- A USB packet begins with an 8-bit synchronization sequence '00000001'. That is, after the initial idle -- +-- state J, the data lines toggle KJKJKJKK. The final 1 bit (repeated K state) marks the end of the sync -- +-- pattern and the beginning of the USB frame. For high bandwidth USB, the packet begins with a 32-bit -- +-- synchronization sequence. -- +-- A USB packet's end, called EOP (end-of-packet), is indicated by the transmitter driving 2 bit times of -- +-- SE0 (D+ and D- both below max) and 1 bit time of J state. After this, the transmitter ceases to drive -- +-- the D+/D- lines and the aforementioned pull up resistors hold it in the J (idle) state. Sometimes skew -- +-- due to hubs can add as much as one bit time before the SE0 of the end of packet. -- +-- This extra bit can result in a "bit stuff violation" if the six bits before it in the CRC are '1's. -- +-- This bit should be ignored by receiver. -- +-- A USB bus is reset using a prolonged (10 to 20 milliseconds) SE0 signal. -- +-- -- +--==========================================================================================================-- + +LIBRARY IEEE; + USE IEEE.std_logic_1164.all; + USE IEEE.std_logic_textio.all; + USE std.textio.all; + +LIBRARY work; + USE work.usb_commands.all; + +ENTITY usb_fs_master IS PORT( + -- USB Interface -- + usb_clk : IN STD_LOGIC; + int_clk : IN STD_LOGIC; + rst_neg_ext : OUT STD_LOGIC; + usb_Dp : INOUT STD_LOGIC; + usb_Dn : INOUT STD_LOGIC; + -- Application Interface + RXval : IN STD_LOGIC; -- RX bytes available + RXdat : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Received data bytes + RXrdy : OUT STD_LOGIC := '0'; -- Application ready for data + RXlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Number of bytes available + TXval : OUT STD_LOGIC := '0'; -- Application has valid data + TXdat : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Data byte to send + TXrdy : IN STD_LOGIC; -- Entity is ready for data + TXroom : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- No of free bytes in TX + TXcork : OUT STD_LOGIC := '1'); -- Hold TX transmission +END usb_fs_master; + +ARCHITECTURE SIM OF usb_fs_master IS + + SIGNAL T_No : NATURAL; + SIGNAL crc_16 : STD_LOGIC_VECTOR(15 DOWNTO 0); + SIGNAL crc_5 : STD_LOGIC_VECTOR( 4 DOWNTO 0); + SIGNAL master_oe : STD_LOGIC; + SIGNAL stimuli_bit : STD_LOGIC := 'Z'; + SIGNAL stop_sim : BOOLEAN := false; + SIGNAL stuffing_requ : BOOLEAN; + SIGNAL usb_request : usb_action; + + function next_CRC_5 (Data: std_logic; crc: std_logic_vector(4 downto 0)) return std_logic_vector is + -- Copyright (C) 1999-2008 Easics NV. http://www.easics.com/webtools/crctool + variable d: std_logic; + variable c: std_logic_vector(4 downto 0); + variable new_crc: std_logic_vector(4 downto 0); + begin + d := Data; + c := crc; + new_crc(0) := d xor c(4); + new_crc(1) := c(0); + new_crc(2) := d xor c(1) xor c(4); + new_crc(3) := c(2); + new_crc(4) := c(3); + return new_crc; + end next_CRC_5; + + function next_CRC_16 (Data: std_logic; crc: std_logic_vector(15 downto 0)) return std_logic_vector is + -- Copyright (C) 1999-2008 Easics NV. http://www.easics.com/webtools/crctool + variable d: std_logic; + variable c: std_logic_vector(15 downto 0); + variable new_crc: std_logic_vector(15 downto 0); + begin + d := Data; + c := crc; + new_crc(0) := d xor c(15); + new_crc(1) := c(0); + new_crc(2) := d xor c(1) xor c(15); + new_crc(14 DOWNTO 3) := c(13 DOWNTO 2); + new_crc(15) := d xor c(14) xor c(15); + return new_crc; + end next_CRC_16; + + FUNCTION nrzi(data_bit, last_level : std_logic) RETURN STD_LOGIC IS + BEGIN + IF data_bit = '0' THEN + RETURN not last_level; + ELSE + RETURN last_level; + END IF; + END nrzi; + +--==========================================================================================================-- + +begin + + test_case : ENTITY work.usb_stimuli + PORT MAP( + -- Test Control Interface -- + usb => usb_request, + T_No => T_No, + -- Application Interface + clk => int_clk, + rst_neg_ext => rst_neg_ext, + RXval => RXval, + RXdat => RXdat, + RXrdy => RXrdy, + RXlen => RXlen, + TXval => TXval, + TXdat => TXdat, + TXrdy => TXrdy, + TXroom => TXroom, + TXcork => TXcork + ); + + usb_fs_monitor : ENTITY work.usb_fs_monitor + port map ( + clk_60MHz => int_clk, + master_oe => master_oe, + usb_Dp => usb_dp, + usb_Dn => usb_dn + ); + + master_oe <= '0' WHEN usb_request = idle OR usb_request = recv_eop ELSE '1'; + + p_usb_data : PROCESS + VARIABLE d_new : STD_LOGIC; + VARIABLE ones_cnt : NATURAL; + BEGIN + WAIT UNTIL rising_edge(usb_clk); + stuffing_requ <= FALSE; + IF stimuli_bit = 'L' THEN + usb_Dp <= '0'; + usb_Dn <= '0'; + ELSIF stimuli_bit = 'Z' THEN + usb_Dp <= 'Z'; + usb_Dn <= 'L'; + ELSIF stimuli_bit = '1' THEN + ones_cnt := ones_cnt +1; + d_new := nrzi('1', usb_Dp); + usb_Dp <= d_new; + usb_Dn <= not d_new; + IF ones_cnt = 6 THEN -- add stuffing bit + stuffing_requ <= TRUE; + ones_cnt := 0; + WAIT UNTIL rising_edge(usb_clk); + stuffing_requ <= FALSE; + d_new := nrzi('0', usb_Dp); + usb_Dp <= d_new; + usb_Dn <= not d_new; + END IF; + ELSE + ones_cnt := 0; + d_new := nrzi('0', usb_Dp); + usb_Dp <= d_new; + usb_Dn <= not d_new; + END IF; + END PROCESS; + + p_stimuli_bit : PROCESS --always transfer LSB first (exception crc) + CONSTANT sync_data : std_logic_vector(7 DOWNTO 0) := X"80"; --USB FS : sync patter is KJKJKJKK + CONSTANT eop_data : std_logic_vector(3 DOWNTO 0) := "Z0LL"; --'L' forces both usb_up, usb_dn low !! + BEGIN + WAIT ON usb_request; + IF usb_request = reset THEN + usb_status <= usb_request; + stimuli_bit <= 'L'; + WAIT FOR 5 us; + WAIT UNTIL rising_edge(usb_clk); + stimuli_bit <= 'Z'; + usb_status <= idle; + ELSIF usb_request = sync THEN + usb_status <= usb_request; + FOR i IN 0 TO 7 LOOP -- Sync pattern + WAIT UNTIL rising_edge(usb_clk); + stimuli_bit <= sync_data(i); + END LOOP; + usb_status <= idle; + ELSIF usb_request = pid THEN + usb_status <= usb_request; + FOR i IN 0 TO 7 LOOP + WAIT UNTIL rising_edge(usb_clk) AND NOT stuffing_requ; + stimuli_bit <= sv_usb_byte(i); + END LOOP; + crc_5 <= (others =>'1'); + crc_16 <= (others =>'1'); + usb_status <= idle; + ELSIF usb_request = addr THEN + usb_status <= usb_request; + FOR i IN 0 TO 10 LOOP + WAIT UNTIL rising_edge(usb_clk) AND NOT stuffing_requ; + stimuli_bit <= sv_usb_addr(i); + crc_5 <= next_crc_5(sv_usb_addr(i),crc_5); + END LOOP; + usb_status <= idle; + ELSIF usb_request = wr_odd OR usb_request = wr_even THEN + usb_status <= usb_request; + FOR i IN 0 TO 7 LOOP + WAIT UNTIL rising_edge(usb_clk) AND NOT stuffing_requ; + stimuli_bit <= sv_usb_byte(i); + crc_16 <= next_crc_16(sv_usb_byte(i),crc_16); + END LOOP; + usb_status <= idle; + -- WAIT for 1 ns; + ELSIF usb_request = wr_crc5 THEN + usb_status <= usb_request; + FOR i IN 4 DOWNTO 0 LOOP -- Token crc5, LSB last + WAIT UNTIL rising_edge(usb_clk) AND NOT stuffing_requ; + stimuli_bit <= NOT crc_5(i); + END LOOP; + usb_status <= idle; + ELSIF usb_request = wr_crc16 THEN + usb_status <= usb_request; + FOR i IN 15 DOWNTO 0 LOOP -- Data crc16, LSB last + WAIT UNTIL rising_edge(usb_clk) AND NOT stuffing_requ; + stimuli_bit <= NOT crc_16(i); + END LOOP; + usb_status <= idle; + ELSIF usb_request = send_eop THEN + usb_status <= usb_request; + FOR i IN 0 TO 3 LOOP + WAIT UNTIL rising_edge(usb_clk) AND NOT stuffing_requ; + stimuli_bit <= eop_data(i); + END LOOP; + usb_status <= idle; + ELSIF usb_request = Recv_eop THEN + usb_status <= usb_request; + WAIT UNTIL rising_edge(usb_clk) AND usb_Dp ='0' AND usb_Dn ='0'; + WAIT FOR 400 ns; + usb_status <= idle; + ELSE + stimuli_bit <= 'Z'; + usb_status <= idle; + END IF; + END PROCESS; + +END SIM; + +--======================================== END OF usb_fs_master.vhd ========================================-- Index: USB_tb.vhd =================================================================== --- USB_tb.vhd (nonexistent) +++ USB_tb.vhd (revision 2) @@ -0,0 +1,148 @@ + +--==========================================================================================================-- +-- -- +-- Copyright (C) 2011 by Martin Neumann martin@neumanns-mail.de -- +-- -- +-- This source file may be used and distributed without restriction provided that this copyright statement -- +-- is not removed from the file and that any derivative work contains the original copyright notice and -- +-- the associated disclaimer. -- +-- -- +-- This software is provided ''as is'' and without any express or implied warranties, including, but not -- +-- limited to, the implied warranties of merchantability and fitness for a particular purpose. in no event -- +-- shall the author or contributors be liable for any direct, indirect, incidental, special, exemplary, or -- +-- consequential damages (including, but not limited to, procurement of substitute goods or services; loss -- +-- of use, data, or profits; or business interruption) however caused and on any theory of liability, -- +-- whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way -- +-- out of the use of this software, even if advised of the possibility of such damage. -- +-- -- +--==========================================================================================================-- +-- -- +-- File name : USB_tb.vhd -- +-- Author : Martin Neumann martin@neumanns-mail.de -- +-- Description : USB test bench used with usb_mster.vhd, usb_Stimuli.vhd and usb_fs_monitor.vhd. -- +-- -- +--==========================================================================================================-- +-- -- +-- Change history -- +-- -- +-- Version / date Description -- +-- -- +-- 01 05 Mar 2011 MN Initial version -- +-- -- +-- End change history -- +--==========================================================================================================-- + +LIBRARY work, IEEE; + USE IEEE.std_logic_1164.ALL; + USE work.usb_commands.ALL; + +ENTITY usb_tb IS +END usb_tb; + +ARCHITECTURE sim OF usb_tb IS + + CONSTANT BUFSIZE_BITS : POSITIVE := 8; + + SIGNAL FPGA_ready : STD_LOGIC; + SIGNAL RXdat : STD_LOGIC_VECTOR(7 DOWNTO 0); + SIGNAL RXlen : STD_LOGIC_VECTOR(BUFSIZE_BITS-1 DOWNTO 0); + SIGNAL RXrdy : STD_LOGIC; + SIGNAL RXval : STD_LOGIC; + SIGNAL TXcork : STD_LOGIC; + SIGNAL TXdat : STD_LOGIC_VECTOR(7 DOWNTO 0); + SIGNAL TXrdy : STD_LOGIC; + SIGNAL TXroom : STD_LOGIC_VECTOR(BUFSIZE_BITS-1 DOWNTO 0); + SIGNAL TXval : STD_LOGIC; + SIGNAL USB_rst : STD_LOGIC; + SIGNAL online : STD_LOGIC; + SIGNAL clk_12MHz : STD_LOGIC; + SIGNAL clk_60MHz : STD_LOGIC; + SIGNAL rst_neg_ext : STD_LOGIC; + SIGNAL rst_neg_syc : STD_LOGIC; + SIGNAL usb_Dn : STD_LOGIC := 'L'; + SIGNAL usb_Dp : STD_LOGIC := 'Z'; -- allow forcing 'H', avoid 'X' + +BEGIN + + p_clk_60MHz : PROCESS + BEGIN + clk_60MHz <= '0'; + WAIT FOR 2 ns; + While true loop + clk_60MHz <= '0'; + WAIT FOR 8000 ps; + clk_60MHz <= '1'; + -- WAIT FOR 8667 ps; -- 60 MHz + WAIT FOR 8393 ps; -- 61 MHz + -- WAIT FOR 8949 ps; -- 59 MHz + end loop; + END PROCESS; + + p_clk_12MHz : PROCESS + BEGIN + clk_12MHz <= '0'; + WAIT FOR 20866 ps; + clk_12MHz <= '1'; + WAIT FOR 41600 ps; + clk_12MHz <= '0'; + WAIT FOR 20867 ps; + END PROCESS; + + p_rst_neg_ext : PROCESS + BEGIN + rst_neg_ext <= '0'; + WAIT FOR 301 ns; + rst_neg_ext <= '1'; + WAIT; + END PROCESS; + + usb_fs_master : ENTITY work.usb_fs_master + port map ( + usb_clk => clk_12MHz, + int_clk => clk_60MHz, + rst_neg_ext => rst_neg_ext, + usb_Dp => usb_dp, + usb_Dn => usb_dn, + RXval => RXval, + RXdat => RXdat, + RXrdy => RXrdy, + RXlen => RXlen, + TXval => TXval, + TXdat => TXdat, + TXrdy => TXrdy, + TXroom => TXroom, + TXcork => TXcork + ); + + usb_dp <= 'H' WHEN FPGA_ready ='1' ELSE 'L'; -- connect FPGA_ready to the pullup resistor logic, .... + usb_dn <= 'L'; -- ... keeping usb_dp='L' during FPGA initialization. + + usb_fs_slave_1 : ENTITY work.usb_fs_slave + GENERIC MAP( + VENDORID => X"FB9A", + PRODUCTID => X"FB9A", + VERSIONBCD => X"0020", + SELFPOWERED => FALSE, + BUFSIZE_BITS => BUFSIZE_BITS) + PORT MAP( + clk => clk_60MHz, -- i + rst_neg_ext => rst_neg_ext, -- i + rst_neg_syc => rst_neg_syc, -- o RST_NEG_EXT streched to next clock + d_pos => usb_dp, -- io Pos USB data line + d_neg => usb_dn, -- io Neg USB data line + USB_rst => USB_rst, -- o USB reset detected (SE0 > 2.5 us) + online => online, -- o High when the device is in Config state. + RXval => RXval, -- o High if a received byte available on RXDAT. + RXdat => RXdat, -- o Received data byte, valid if RXVAL is high. + RXrdy => RXrdy, -- i High if application is ready to receive. + RXlen => RXlen, -- o No of bytes available in receive buffer. + TXval => TXval, -- i High if the application has data to send. + TXdat => TXdat, -- i Data byte to send, must be valid if TXVAL is high. + TXrdy => TXrdy, -- o High if the entity is ready to accept the next byte. + TXroom => TXroom, -- o No of free bytes in transmit buffer. + TXcork => TXcork, -- i Temp. suppress transmissions at the outgoing endpoint. + FPGA_ready => FPGA_ready -- o Connect FPGA_ready to the pullup resistor logic + ); + +END sim; +

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.