Programming the Ethernet controller
The modules involved in communication with the Ethernet Controller chip serve as the core of the FPGA. The different tasks that need to be performed by these modules include
- executing the complex board reset and address lookup sequence
- polling for new packets and switching execution accordingly
- collecting sensor information upon a status report request
- programming the DAC upon a program packet receipt
- building return packets
In our design, the modules involved with packet handling and interfacing with sensor chip controllers are organized by state. A state register specifies the current stage of the process and only the corresponding module is allowed to act during that stage. Aside from defining a process sequence, the state serves as a complex "enable" signal for the modules, ensuring that only one module is driving the communication bus used to query the Ethernet Controller chip.
Interface
- See also: Ethernet packets
The compact approach to wire and poll the Ethernet Controller chop is via the Multiplexed Intel bus format. Aside from some use of the interrupt and reset pins, all communication is done via this bus. (The control architecture of the chip uses 8-bit registers selected with 8-bit addresses.) A communication over this bus begins with an pulse on the "ALE" pin, by the fall of which a valid address is expected on the 8-bit inout "AD" bus. After this /RD (/WR) signal falls, executing the read (write) process, and then rises accompanied with valid input from (to) the chip. The adjacent figure illustrates this process along with the approach to timing the conversation taken in this design. Please refer to Section 16.2 in the manual for details on the timing tolerances on this bus.
As shown in the figure, the 20 MHz clock is very convenient for metering this conversation. The communication delay for the FPGA (most of which runs essentially on 5 MHz) turns out to be only two clock cycles.
The eight states
There are eight major states to the module.
State list
- (000) Reset Cycle
- The reset cycle resets the selected chips. There are flags for resetting all 4 chips: DAC, ADC, temperature sensor, Ethernet controller. This is the entry state from a power-on. From this state, proceed unconditionally to 001.
(001) Transmit "I"This state transmits an "I" packet to acknowledge that a reset occurred but the board is now prepared to accept new packets and function normally. From this state, proceed unconditionally to 010."S"-Packet (from state 101) would do just as well, returning zeroed registers, location address etc for computer's address LUT.- (010) Idle
- This is the idle state where the state machine awaits a new packet's arrival. If the Receive FIFO is empty, it loops back on itself and continues checking the FIFO. If the FIFO is not empty, proceed to 011.
- (011) Read Packet
- This state accesses the first packet. If packets need to be filtered by the FPGA, this state will filter and return to 010 on a bad packet. The MAC data is discarded, as it is unimportant to the FPGA, and the first data byte is read. This byte is used as a switch: an ASCII "R" loops to 000. A "Q" proceeds to 100. A "P" proceeds to 110. Any other value is a bad packet and the state machine returns to 010.
- (100) Poll Status
- This state polls the status chips (the ADC and the temperature sensor) so that recent data is ready for transmission.
- (101) Transmit "S"
- This state packages and transmits an "S" packet over the Ethernet to report back the status of the board in response to a "Q" packet.
- (110) Program DAC
- This state programs the DAC with new values according to the mask and data in the "P" packet.
- (111) Transmit "D"
- This state packages and transmits a "D" packet over the Ethernet to report back the DAC voltages in response to a "P" packet.
State interconnect
These states will form the outline of the functional block diagram. Within each state will be a smaller process or set of processes, possibly broken into substates. This implementation calls for a central state register. Each block reads the state value in the register and enables itself upon seeing its own value. After completion of its function, a block will write a new value to the state register to enable the next block. With several modules writing to the register, usual precautions must be taken to avoid more than one drivers forcing a line simultaneously. All modules must be designed to go to high impedance on their output lines when they are not active.
State variable
Based on the assignments of state values to the various states, certain interpretations of the state's bits arise. They may or may not prove useful in coding the system. They are given here in the case that they do become useful.
- S2:1:
- S2 = 0: "Core cycle" that executes regularly and forms the spine of the state diagram.
- S2:1 = 00: "Initialization cycle" that prepares the state diagram for normal functioning.
- S2:1 = 01: "Standard cycle" that the state machine returns to most frequently to process appropriate switching to branches.
- S2 = 1: "Branch cycles" that execute selectively based on received packets.
- S2:1 = 10: "Query cycle" as described in the page on Ethernet packets.
- S2:1 = 11: "Programming cycle" as described in the page on Ethernet packets.
- S2 = 0: "Core cycle" that executes regularly and forms the spine of the state diagram.
- S0:
- S0 = 0: "Setup state" to prepare internal workings for a communication.
- S0 = 1: "Transfer state" to communicate with the external PC.
Controller
Foreword on Timing
With a controller this complex, the timing of signals must be inspected even more scrupulously than usual. In particular, simultaneous transitions of data and "Done" lines must be avoided. When possible, a one-cycle-delayed "Done" signal is used to ensure that the data lines have been stabilized. (All delays are implemented via the c_delay module which postpones the signal by one cycle via two sequential flip-flops, each shifting by half-cycle). When this is inconvenient (e.g. when writing to registers) the target component must not be enabled on rising edges on "Go" or the clock. The registers, for instance, have been designed to read values on the falling edge of the clock - middle of the "Go" pulse, safely after the data line transitions.
Packet Reader (Packet type inspection)
Miscellaneous Reusable Components
(101) Transmit "S"
This block compiles the status values into a single packet by loading them into the CP2200/1 in a defined order and format, including padding/converting any values that need it. Once the packet has been sent, the block transitions to state 010.
inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- State: 3-bit state value
internal signals
- S_En: state enable, S_En <= not (St(2) or St(1) or St(0))
- Go: when S_En goes high Go pulses for one cycle
blocks
- Temp Loader
- This block reads the temperature value from the internal registers and loads it to the transmit buffer.
- inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- Go: pulse to begin; feeds from Go internal signal of block 101
- D_in: 16-bit data bus from internal registers
- TxRx_Done: Done signal from transceiver
- ouputs
- TxRx_Go: Go signal on transceiver
- TxRx_R/W: R/W signal on transceiver
- TxRx_A: A_in bus on transceiver
- TxRx_D: D_in bus on transceiver
- Done: pulse to signal completion
- ADC Loader
- This block reads the ADC values from the internal registers and loads them to the transmit buffer in order: channel zero to channel seven.
- inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- Go: pulse to begin; feeds from Done signal of Temp Loader
- D_in: 16-bit data bus from internal registers
- TxRx_Done: Done signal from transceiver
- ouputs
- Sel: 3-bit select bus for internal registers
- TxRx_Go: Go signal on transceiver
- TxRx_R/W: R/W signal on transceiver
- TxRx_A: A_in bus on transceiver
- TxRx_D: D_in bus on transceiver
- Done: pulse to signal completion
- Padder
- This block pads the packet to the minimum 46 bytes. Only 19 bytes have been loaded by this point (1 byte "S", 2 byte temperature, 8 x 2 byte ADC), so 27 bytes of padding (zero) must be loaded.
- inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- Go: pulse to begin; feeds from Done signal of ADC Loader
- TxRx_Done: Done signal from transceiver
- outputs
- TxRx_Go: Go signal on transceiver
- TxRx_R/W: R/W signal on transceiver
- TxRx_A: A_in bus on transceiver
- TxRx_D: D_in bus on transceiver
- Done: pulse to signal completion
- Sender
- This block tells the CP2200/1 to send the completed packet.
- inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- Go: pulse to begin; feeds from Done signal of Padder
- TxRx_Done: Done signal from transceiver
- outputs
- TxRx_Go: Go signal on transceiver
- TxRx_R/W: R/W signal on transceiver
- TxRx_A: A_in bus on transceiver
- TxRx_D: D_in bus on transceiver
- Done: pulse to signal completion
(110) Program DAC
This block will have a substate to obtain the programming mask. It then loops 32 (or 24 or 16) times on a second substate that obtains the next programming value and, if the corresponding mask bit is high, programs that channel of the DAC. A mux may be needed to select the appropriate bit from the programming mask. It also updates the locally stored DAC channel values (which may be stored on the FPGA, the CP2200/1 Flash, or other) in preparation for a "D" response packet. Then it transitions to state 111.
inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- State: 3-bit state value
internal signals
- S_En: state enable, S_En <= not (St(2) or St(1) or St(0))
- Go: when S_En goes high Go pulses for one cycle
blocks
- Mask Fetcher
- This block reads the programming mask, contained in the second data byte (first remaining byte) through the 5th/4th/3rd byte (4th/3rd/2nd remaining byte), and saves it into a 32/24/16-bit register.
- inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- Go: pulse to begin, comes from Go internal signal of block 110
- TxRx_D: 8-bit data bus from transceiver
- TxRx_Done: Done signal from transceiver
- outputs
- TxRx_Go: Go input on transceiver
- TxRx_R/W: R/W input on transceiver; tied to read (one)
- TxRx_A: A_in bus on transceiver
- Mask: 32/24/16-bit readout of programming mask
- Done: pulse to signal that mask has been obtained
- Programmer
- Programs the DAC. Loops 32/24/16 times, obtaining the next byte from the CP2200/1 buffer, checking the mask, programming the DAC if the mask is 1 or skipping if the mask is 0. Also writes the value to the internal DAC value storage registers (or Flash memory or other).
- inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- Go: pulse to begin; feeds from Done signal of Mask Fetcher
- TxRx_D: D_out bus on transceiver
- TxRx_Done: Done signal on transceiver
- outputs
- - DAC control lines -
- TxRx_Go: Go signal on transceiver
- TxRx_R/W: R/W signal on transceiver
- TxRx_A: A_in bus on transceiver
- Sel: 5/5/4-bit select bus to internal registers
- Data: 32/24/16-bit data bus to internal registers
- Done: pulse to signal completion
- Discarder
- This block orders the CP2200/1 to discard the packet, now that the FPGA is done with all the data contained within the packet.
- inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- Go: pulse to begin; feeds from Done signal of Programmer
- TxRx_Done: Done signal on transceiver
- outputs
- TxRx_Go: Go signal on transceiver
- TxRx_R/W: R/W signal on transceiver
- TxRx_A: A_in bus on transceiver
- Done: pulse to signal completion
- New_St: next state to load into the state register; goes to 111 when Done is high
(111) Transmit "D"
This block loads a "D" to the transmit buffer then loops 32 (or 24 or 16) times to load the locally stored DAC channel values to the transmit buffer. Once the full packet has been loaded, it sends the packet, then transitions to state 010.
inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- State: 3-bit state value
internal signals
- S_En: state enable, S_En <= not (St(2) or St(1) or St(0))
- Go: when S_En goes high Go pulses for one cycle
blocks
- Loader
- Loads the DAC values into a packet in the transmission buffer of the CP2200/1. Loops through all values and loads them in order (channel zero to channel thirty-one).
- inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- Go: pulse to begin loading a packet
- TxRx_Done: Done signal on transceiver
- Data: 14-bit data bus from internal registers
- outputs
- TxRx_Go: Go signal on transceiver
- TxRx_RW: R/W signal on transceiver
- TxRx_A: A_in bus on transceiver
- TxRx_D: D_in bus on transceiver
- Done: pulse to signal completion
- Sender
- Tells CP2200/1 to send the packet
- inputs
- Clk: clock
- /Rst: asynchronous, active-low reset
- Go: pulse to begin, connected to Done signal from Loader
- TxRx_Done: Done signal from transceiver
- outputs
- TxRx_Go: Go signal on transceiver
- TxRx_RW: R/W signal on transceiver
- TxRx_A: A_in bus on transceiver
- TxRx_D: D_in bus on transceiver
- Done: pulse to signal completion
- New_St: 3-bit bus of new state to write to state register; goes to 010 when Done is high
Emulator
Since the modules described here represent the core of the FPGA, their combined simulation calls for inclusion of all other fringe modules. Essentially the whole FPGA will have to be tested to ensure this scheme for the core is acting properly. The challenge is in the complexity of the stimulus for such simulation: whole packets will need to be sent in and possibly inter-packet Ethernet Controller Chip states tested.
A stripped down emulator for the Ethernet Controller has been written. It is a essentially a set of registers with a Multiplexed Intel bus communication layer and packet file read/write layers. These registers, however, are not passive memory banks but include "events" that are triggered by particular register states. For instance writing to registers designated to make up a receive buffer pointer actually delivers the requested byte from the buffer to the appropriate control register to be available for a subsequent request. A simple interrupt system (stimulated externally by the simulation layer) has also been included.