library ieee; use ieee.std_logic_1164.all; package basicblocks_definitions is constant period: time := 10 ns; constant half_period: time := period / 2; constant reset_time: time := 11 ns; end; library ieee; use ieee.std_logic_1164.all; library work; use work.basicblocks_definitions.all; -- FOR SIMULATION ONLY. NOT FOR PRODUCTION. entity clkgen is port( clk_out: out std_logic; resetn: out std_logic := '0' ); end; -- Tested 2016/01/19 with ghdl. works. architecture struct_clkgen of clkgen is begin process begin resetn <= '1' after reset_time; clk_out <= '1'; wait for half_period; clk_out <= '0'; wait for half_period; end process; end; library ieee; use ieee.std_logic_1164.all; entity incrementer is port( input: in std_logic; carry_in: in std_logic; sum: out std_logic; carry_out: out std_logic ); end; -- tested with ghdl for N = 16 starting 2016/01/22, finished ?, works. architecture struct_incrementer of incrementer is begin sum <= input xor carry_in; carry_out <= input and carry_in; end; library ieee; use ieee.std_logic_1164.all; entity andNbit is generic( N: positive ); port( input: in std_logic_vector((N-1) downto 0); y: out std_logic ); end; -- Tested as part of counter testing. Works. architecture struct_andNbit of andNbit is signal and_vector: std_logic_vector(N downto 0); begin and_vector(0) <= '1'; and_generator: for i in 1 to N generate and_vector(i) <= and_vector(i-1) and input(i-1); end generate and_generator; y <= and_vector(N); end; library ieee; use ieee.std_logic_1164.all; entity orNbit is generic( N: positive ); port( input: in std_logic_vector((N-1) downto 0); y: out std_logic ); end; architecture struct_orNbit of orNbit is signal or_vector: std_logic_vector(N downto 0); begin or_vector(0) <= '0'; or_generator: for i in 1 to N generate or_vector(i) <= or_vector(i-1) or input(i-1); end generate or_generator; y <= or_vector(N); end; library ieee; use ieee.std_logic_1164.all; entity incrementerN is generic( N: positive ); port( input: in std_logic_vector((N-1) downto 0); carry_in: in std_logic; sum: out std_logic_vector((N-1) downto 0); carry_out: out std_logic ); end; -- tested with ghdl at N = 16 starting 2016/01/22, finished ?, works. architecture struct_incrementerN of incrementerN is component incrementer is port( input: in std_logic; carry_in: in std_logic; sum: out std_logic; carry_out: out std_logic ); end component; signal carry: std_logic_vector(N downto 0); signal result: std_logic_vector((N-1) downto 0); begin carry(0) <= carry_in; u1: for i in (N-1) downto 0 generate u: incrementer port map( input => input(i), carry_in => carry(i), sum => result(i), carry_out => carry(i + 1) ); end generate; carry_out <= carry(N); sum <= result; end; library ieee; use ieee.std_logic_1164.all; entity decoder1x16 is port( data: in std_logic; y0: out std_logic; y1: out std_logic; y2: out std_logic; y3: out std_logic; y4: out std_logic; y5: out std_logic; y6: out std_logic; y7: out std_logic; y8: out std_logic; y9: out std_logic; y10: out std_logic; y11: out std_logic; y12: out std_logic; y13: out std_logic; y14: out std_logic; y15: out std_logic; address: in std_logic_vector(3 downto 0) ); end; architecture struct_decoder1x16 of decoder1x16 is begin with address select y0 <= data when x"0", '0' when others; with address select y1 <= data when x"1", '0' when others; with address select y2 <= data when x"2", '0' when others; with address select y3 <= data when x"3", '0' when others; with address select y4 <= data when x"4", '0' when others; with address select y5 <= data when x"5", '0' when others; with address select y6 <= data when x"6", '0' when others; with address select y7 <= data when x"7", '0' when others; with address select y8 <= data when x"8", '0' when others; with address select y9 <= data when x"9", '0' when others; with address select y10 <= data when x"a", '0' when others; with address select y11 <= data when x"b", '0' when others; with address select y12 <= data when x"c", '0' when others; with address select y13 <= data when x"d", '0' when others; with address select y14 <= data when x"e", '0' when others; with address select y15 <= data when x"f", '0' when others; end; -- For reasons unknown, ghdl appears to ignore the generic definition of N in this and only -- this architecture. Error messages are generated at line 129 onwards. No unusual characters -- found in the file where the first error message is generated. library ieee; use ieee.std_logic_1164.all; entity decoderNx16 is generic( N: positive ); port( data: in std_logic_vector((N-1) downto 0); y0: out std_logic_vector((N-1) downto 0); y1: out std_logic_vector((N-1) downto 0); y2: out std_logic_vector((N-1) downto 0); y3: out std_logic_vector((N-1) downto 0); y4: out std_logic_vector((N-1) downto 0); y5: out std_logic_vector((N-1) downto 0); y6: out std_logic_vector((N-1) downto 0); y7: out std_logic_vector((N-1) downto 0); y8: out std_logic_vector((N-1) downto 0); y9: out std_logic_vector((N-1) downto 0); y10: out std_logic_vector((N-1) downto 0); y11: out std_logic_vector((N-1) downto 0); y12: out std_logic_vector((N-1) downto 0); y13: out std_logic_vector((N-1) downto 0); y14: out std_logic_vector((N-1) downto 0); y15: out std_logic_vector((N-1) downto 0); address: in std_logic_vector(3 downto 0) ); end; architecture struct_decoderNx16 of decoderNx16 is component decoder1x16 is port( data: in std_logic; y0: out std_logic; y1: out std_logic; y2: out std_logic; y3: out std_logic; y4: out std_logic; y5: out std_logic; y6: out std_logic; y7: out std_logic; y8: out std_logic; y9: out std_logic; y10: out std_logic; y11: out std_logic; y12: out std_logic; y13: out std_logic; y14: out std_logic; y15: out std_logic; address: in std_logic_vector(3 downto 0) ); end component; begin u1: for i in (N-1) downto 0 generate u: decoder1x16 port map( data => data(i), y0 => y0(i), y1 => y1(i), y2 => y2(i), y3 => y3(i), y4 => y4(i), y5 => y5(i), y6 => y6(i), y7 => y7(i), y8 => y8(i), y9 => y9(i), y10 => y10(i), y11 => y11(i), y12 => y12(i), y13 => y13(i), y14 => y14(i), y15 => y15(i), address => address ); end generate u1; end; library ieee; use ieee.std_logic_1164.all; entity decoder1x2 is port( data: in std_logic; selector: in std_logic; y0: out std_logic; y1: out std_logic ); end; -- Tested 2015/12/04 with Modelsim. Works. architecture struct_decoder1x2 of decoder1x2 is begin with selector select y0 <= data when '0', '0' when others; with selector select y1 <= data when '1', '0' when others; end; library ieee; use ieee.std_logic_1164.all; entity decoderNx2 is generic( N: positive ); port( data: in std_logic_vector((N-1) downto 0); selector: in std_logic; y0: out std_logic_vector((N-1) downto 0); y1: out std_logic_vector((N-1) downto 0) ); end; -- tested 2015/12/27 at N = 8 with modelsim. works. -- tested 2016/01/23 at N = 8 with ghdl. works. architecture struct_decoderNx2 of decoderNx2 is component decoder1x2 is port( data: in std_logic; selector: in std_logic; y0: out std_logic; y1: out std_logic ); end component; begin u1: for i in (N-1) downto 0 generate u: decoder1x2 port map( data => data(i), selector => selector, y0 => y0(i), y1 => y1(i) ); end generate u1; end; library ieee; use ieee.std_logic_1164.all; entity encoder2x1oe is port( data0, data1: in std_logic; selector: in std_logic; enable: in std_logic; output: out std_logic ); end; -- tested during testing of encoder2xNoe, works. architecture struct_encoder2x1oe of encoder2x1oe is begin with selector select output <= (data0 and enable) when '0', (data1 and enable) when '1', '0' when others; end; library ieee; use ieee.std_logic_1164.all; entity encoder2xN_oe is generic( N: positive ); port( data0: in std_logic_vector((N-1) downto 0); data1: in std_logic_vector((N-1) downto 0); selector: in std_logic; enable: in std_logic; output: out std_logic_vector((N-1) downto 0) ); end; architecture struct_encoder2xN_oe of encoder2xN_oe is component encoder2x1oe is port( data0: in std_logic; data1: in std_logic; selector: in std_logic; enable: in std_logic; output: out std_logic ); end component; begin u1: for i in (N-1) downto 0 generate u: encoder2x1oe port map( data0 => data0(i), data1 => data1(i), selector => selector, enable => enable, output => output(i) ); end generate u1; end; library ieee; use ieee.std_logic_1164.all; entity encoder2x1 is port( data0: in std_logic; data1: in std_logic; selector: in std_logic; output: out std_logic ); end; -- tested during double register pair testing 2015/12/03. Works. architecture struct_encoder2x1 of encoder2x1 is begin with selector select output <= data0 when '0', data1 when '1', '0' when others; end; library ieee; use ieee.std_logic_1164.all; entity encoder2xN is generic( N: positive ); port( data0: in std_logic_vector((N-1) downto 0); data1: in std_logic_vector((N-1) downto 0); selector: in std_logic; output: out std_logic_vector((N-1) downto 0) ); end; -- tested during double register pair testing 2015/12/03. Works for N = 8. -- also tested during alu testing. works there too. architecture struct_encoder2xN of encoder2xN is component encoder2x1 is port( data0: in std_logic; data1: in std_logic; selector: in std_logic; output: out std_logic ); end component; begin u1: for i in (N-1) downto 0 generate u: encoder2x1 port map( data0 => data0(i), data1 => data1(i), selector => selector, output => output(i) ); end generate u1; end; library ieee; use ieee.std_logic_1164.all; entity synchronous_latch is port( rstn: in std_logic; clock: in std_logic; clock_enable: in std_logic; d: in std_logic; q: out std_logic ); end; -- Tested 2016/11/21, works on Modelsim simulator. architecture struct_synchronous_latch of synchronous_latch is begin process(rstn, clock, clock_enable) variable datum: std_logic; begin if rstn = '0' then datum := '0'; elsif rising_edge(clock) then if clock_enable = '1' then datum := d; end if; end if; q <= datum; end process; end; library ieee; use ieee.std_logic_1164.all; -- library altera; -- use altera.altera_primitives_components.all; entity synchronous_latchN is generic( N: positive ); port( rstn: in std_logic; clock: in std_logic; clock_enable: in std_logic; d: in std_logic_vector((N-1) downto 0); q: out std_logic_vector((N-1) downto 0) ); end; -- Tested 2016/11/21, works on Modelsim simulator. architecture struct_synchronous_latchN of synchronous_latchN is component synchronous_latch is port( rstn: in std_logic; clock: in std_logic; clock_enable: in std_logic; d: in std_logic; q: out std_logic ); end component; begin u1: for i in 0 to (N-1) generate u: synchronous_latch port map( rstn => rstn, clock => clock, clock_enable => clock_enable, d => d(i), q => q(i) ); end generate u1; end; library ieee; use ieee.std_logic_1164.all; entity synchronous_latch_oe is port( rstn: in std_logic; clock: in std_logic; clock_enable: in std_logic; oe: in std_logic; d: in std_logic; q: out std_logic ); end; -- tested 2015/12/27 as part of testing synchronous_latchN_oe. works. architecture struct_synchronous_latch_oe of synchronous_latch_oe is begin process(rstn, clock, clock_enable, oe) variable datum: std_logic; begin if rstn = '0' then datum := '0'; elsif rising_edge(clock) then if clock_enable = '1' then datum := d; end if; end if; if oe = '1' then q <= datum; else q <= 'Z'; end if; end process; end; library ieee; use ieee.std_logic_1164.all; entity synchronous_latchN_oe is generic( N: positive ); port( rstn: in std_logic; clock: in std_logic; clock_enable: in std_logic; oe: in std_logic; d: in std_logic_vector((N-1) downto 0); q: out std_logic_vector((N-1) downto 0) ); end; -- tested 2015/12/27, N = 8 with modelsim. works. architecture struct_synchronous_latchN_oe of synchronous_latchN_oe is component synchronous_latch_oe is port( rstn: in std_logic; clock: in std_logic; clock_enable: in std_logic; oe: in std_logic; d: in std_logic; q: out std_logic ); end component; begin u1: for i in (N-1) downto 0 generate u: synchronous_latch_oe port map( rstn => rstn, clock => clock, clock_enable => clock_enable, oe => oe, d => d(i), q => q(i) ); end generate u1; end; library ieee; use ieee.std_logic_1164.all; entity synchronous_latch_autoclear is port( rstn: in std_logic; clock: in std_logic; clock_enable: in std_logic; d: in std_logic; q: out std_logic ); end; -- Tested 2016/11/21, works on Modelsim simulator. architecture struct_synchronous_latch_autoclear of synchronous_latch_autoclear is begin process(rstn, clock) variable datum: std_logic; begin if rstn = '0' then datum := '0'; elsif rising_edge(clock) then if clock_enable = '1' then if datum = '1' then datum := '0'; else datum := d; end if; else datum := '0'; end if; end if; q <= datum; end process; end; library ieee; use ieee.std_logic_1164.all; ent
/*
LUFA Library
Copyright (C) Dean Camera, 2017.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* uIP Management functions. This file contains the functions and globals needed to maintain the uIP
* stack once an RNDIS device has been attached to the system.
*/
#define INCLUDE_FROM_UIPMANAGEMENT_C
#include "uIPManagement.h"
/** Connection timer, to retain the time elapsed since the last time the uIP connections were managed. */
static struct timer ConnectionTimer;
/** ARP timer, to retain the time elapsed since the ARP cache was last updated. */
static struct timer ARPTimer;
/** MAC address of the RNDIS device, when enumerated. */
struct uip_eth_addr MACAddress;
/** Configures the uIP stack ready for network traffic processing. */
void uIPManagement_Init(void)
{
/* uIP Timing Initialization */
clock_init();
timer_set(&ConnectionTimer, CLOCK_SECOND / 2);
timer_set(&ARPTimer, CLOCK_SECOND * 10);
/* uIP Stack Initialization */
uip_init();
uip_arp_init();
/* DHCP/Server IP Settings Initialization */
if (USB_CurrentMode == USB_MODE_Device)
{
MACAddress.addr[0] = SERVER_MAC_ADDRESS[0];
MACAddress.addr[1] = SERVER_MAC_ADDRESS[1];
MACAddress.addr[2] = SERVER_MAC_ADDRESS[2];
MACAddress.addr[3] = SERVER_MAC_ADDRESS[3];
MACAddress.addr[4] = SERVER_MAC_ADDRESS[4];
MACAddress.addr[5] = SERVER_MAC_ADDRESS[5];
#if defined(ENABLE_DHCP_SERVER)
DHCPServerApp_Init();
#endif
uip_ipaddr_t IPAddress, Netmask, GatewayIPAddress;
uip_ipaddr(&IPAddress, DEVICE_IP_ADDRESS[0], DEVICE_IP_ADDRESS[1], DEVICE_IP_ADDRESS[2], DEVICE_IP_ADDRESS[3]);
uip_ipaddr(&Netmask, DEVICE_NETMASK[0], DEVICE_NETMASK[1], DEVICE_NETMASK[2], DEVICE_NETMASK[3]);
uip_ipaddr(&GatewayIPAddress, DEVICE_GATEWAY[0], DEVICE_GATEWAY[1], DEVICE_GATEWAY[2], DEVICE_GATEWAY[3]);
uip_sethostaddr(&IPAddress);
uip_setnetmask(&Netmask);
uip_setdraddr(&GatewayIPAddress);
}
else
{
#if defined(ENABLE_DHCP_CLIENT)
DHCPClientApp_Init();
#else
uip_ipaddr_t IPAddress, Netmask, GatewayIPAddress;
uip_ipaddr(&IPAddress, DEVICE_IP_ADDRESS[0], DEVICE_IP_ADDRESS[1], DEVICE_IP_ADDRESS[2], DEVICE_IP_ADDRESS[3]);
uip_ipaddr(&Netmask, DEVICE_NETMASK[0], DEVICE_NETMASK[1], DEVICE_NETMASK[2], DEVICE_NETMASK[3]);
uip_ipaddr(&GatewayIPAddress, DEVICE_GATEWAY[0], DEVICE_GATEWAY[1], DEVICE_GATEWAY[2], DEVICE_GATEWAY[3]);
uip_sethostaddr(&IPAddress);
uip_setnetmask(&Netmask);
uip_setdraddr(&GatewayIPAddress);
#endif
}
/* Virtual Webserver Ethernet Address Configuration */
uip_setethaddr(MACAddress);
/* HTTP Webserver Initialization */
HTTPServerApp_Init();
/* TELNET Server Initialization */
#if defined(ENABLE_TELNET_SERVER)
TELNETServerApp_Init();
#endif
}
/** uIP Management function. This function manages the uIP stack when called while an RNDIS device has been
* attached to the system.
*/
void uIPManagement_ManageNetwork(void)
{
if (((USB_CurrentMode == USB_MODE_Host) && (USB_HostState == HOST_STATE_Configured)) ||
((USB_CurrentMode == USB_MODE_Device) && (USB_DeviceState == DEVICE_STATE_Configured)))
{
uIPManagement_ProcessIncomingPacket();
uIPManagement_ManageConnections();
}
}
/** uIP TCP/IP network stack callback function for the processing of a given TCP connection. This routine dispatches
* to the appropriate TCP protocol application based on the connection's listen port number.
*/
void uIPManagement_TCPCallback(void)
{
/* Call the correct TCP application based on the port number the connection is listening on */
switch (uip_conn->lport)
{
case HTONS(HTTP_SERVER_PORT):
HTTPServerApp_Callback();
break;
#if defined(ENABLE_TELNET_SERVER)
case HTONS(TELNET_SERVER_PORT):
TELNETServerApp_Callback();
break;
#endif
}
}
/** uIP TCP/IP network stack callback function for the processing of a given UDP connection. This routine dispatches
* to the appropriate UDP protocol application based on the connection's listen port number.
*/
void uIPManagement_UDPCallback(void)
{
/* Call the correct UDP application based on the port number the connection is listening on */
switch (uip_udp_conn->lport)
{
#if defined(ENABLE_DHCP_CLIENT)
case HTONS(DHCP_CLIENT_PORT):
DHCPClientApp_Callback();
break;
#endif
#if defined(ENABLE_DHCP_SERVER)
case HTONS(DHCP_SERVER_PORT):
DHCPServerApp_Callback();
break;
#endif
}
}
/** Processes Incoming packets to the server from the connected RNDIS device, creating responses as needed. */
static void uIPManagement_ProcessIncomingPacket(void)
{
/* Determine which USB mode the system is currently initialized in */
if (USB_CurrentMode == USB_MODE_Device)
{
/* If no packet received, exit processing routine */
if (!(RNDIS_Device_IsPacketReceived(&Ethernet_RNDIS_Interface_Device)))
return;
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
/* Read the Incoming packet straight into the UIP packet buffer */
RNDIS_Device_ReadPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, &uip_len);
}
else
{
/* If no packet received, exit processing routine */
if (!(RNDIS_Host_IsPacketReceived(&Ethernet_RNDIS_Interface_Host)))
return;
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
/* Read the Incoming packet straight into the UIP packet buffer */
RNDIS_Host_ReadPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, &uip_len);
}
/* If the packet contains an Ethernet frame, process it */
if (uip_len > 0)
{
switch (((struct uip_eth_hdr*)uip_buf)->type)
{
case HTONS(UIP_ETHTYPE_IP):
/* Filter packet by MAC destination */
uip_arp_ipin();
/* Process Incoming packet */
uip_input();
/* If a response was generated, send it */
if (uip_len > 0)
{
/* Add destination MAC to outgoing packet */
uip_arp_out();
uip_split_output();
}
break;
case HTONS(UIP_ETHTYPE_ARP):
/* Process ARP packet */
uip_arp_arpin();
/* If a response was generated, send it */
if (uip_len > 0)
uip_split_output();
break;
}
}
LEDs_SetAllLEDs(LEDMASK_USB_READY);
}
/** Manages the currently open network connections, including TCP and (if enabled) UDP. */
static void uIPManagement_ManageConnections(void)
{
/* Poll TCP connections for more data to send back to the host */
for (uint8_t i = 0; i < UIP_CONNS; i++)
{
uip_poll_conn(&uip_conns[i]);
/* If a response was generated, send it */
if (uip_len > 0)
{
/* Add destination MAC to outgoing packet */
uip_arp_out();
/* Split and send the outgoing packet */
uip_split_output();
}
}
/* Manage open connections for timeouts */
if (timer_expired(&ConnectionTimer))
{
timer_reset(&ConnectionTimer);
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
for (uint8_t i = 0; i < UIP_CONNS; i++)
{
/* Run periodic connection management for each TCP connection */
uip_periodic(i);
/* If a response was generated, send it */
if (uip_len > 0)
{
/* Add destination MAC to outgoing packet */
uip_arp_out();
/* Split and send the outgoing packet */
uip_split_output();
}
}
#if defined(ENABLE_DHCP_CLIENT)
for (uint8_t i = 0; i < UIP_UDP_CONNS; i++)
{
/* Run periodic connection management for each UDP connection */
uip_udp_periodic(i);
/* If a response was generated, send it */
if (uip_len > 0)
{
/* Add destination MAC to outgoing packet */
uip_arp_out();
/* Split and send the outgoing packet */
uip_split_output();
}
}
#endif
LEDs_SetAllLEDs(LEDMASK_USB_READY);
}
/* Manage ARP cache refreshing */
if (timer_expired(&ARPTimer))
{
timer_reset(&ARPTimer);
uip_arp_timer();
}
}