The protocol interpreter of the FPGA design is responsible for interpreting data sent by the OpenLab GUI. It also generates reply messages to communicate the status of the FPGA or to transfer the requested sample data. Another function of this entity is the controlling of other parts of the FPGA design. The following sub-chapters will describe the functionality of the OpenLab communication protocol and how the interpreter component of the FPGA was implemented.
The interpreter is based on the communication protocol described in . This protocol standardises the way of communication between a OpenLab device and the OpenLab GUI. This ensures that the OpenLab GUI is able to connect to, and communicate with, any OpenLab device. Regardless if it is microcontroller-based, FPGA-based or soundcard-based. The protocol was written from the OpenLab device perspective. This means that every command that is declared by the protocol is sent by the GUI. On the other hand, every reply is sent from the OpenLab device. Two versions of the OpenLab communication protocol are described by .
The first one is human readable and therefore called ASCII protocol. Every command and reply is sent entirely in ASCII format. This enables the user to debug the communication using terminal programs. The ASCII protocol was only used during the first phase of the OpenLab project to get a better understanding for setting up a reliable protocol and debugging sample data.
The second protocol, called the binary protocol, is a much improved version and is currently used at the OpenLab project. By transferring the data in the binary format the overhead of each message is drastically reduced, leading to much faster processing at the GUI and the OpenLab devices. It features, unlike the ASCII protocol, error detection capabilities. With the usage of the CRC16 algorithm, errors during transmission can be detected. This is necessary to detect bad sample data before the sample is displayed on the graph of the GUI.
Table 1 shows the layout of the binary protocol, including the command- and reply structure.
The fixed fields are, regardless of the type of the message, fixed in size. They form the header of a message. This is valid for command and reply messages. The header consists of the command or reply code, the device identifier, the channel number, payload size and the header checksum. The optional fields are directly dependent on the type of the package. The size is variable. Those fields are also called the payload of the message. Some commands or replies only consist of the header field. The payload field of commands is used to transfer configuration data like channel and trigger settings. In case of reply messages, the payload can carry sample data or information necessary for the GUI. The payload is, just like the header of the message, protected by a checksum. In case of defect packets, errors can be detected by either the FPGA or the GUI. CRC16 is not able to reconstruct corrupted data. However, the FPGA and the GUI are able to request the required data again if necessary. Defect sample data packets are currently ignored by the GUI to prevent displaying errors.
The upcoming chapter will explain the integration of the binary-protocol into the FPGA design.
The FPGA design of the communication protocol interpreter consists of several processes. Those processes together form the protocol interpreter of the FPGA design. Every command sent by the GUI is analyzed by the corresponding process. Depending on the type of the command, a reply is than being generated by another process.
Figure 1 shows a diagram of the structure of this entity. Each process is dedicated to a specific function.
The incoming data, which is received by the data communication entity, is first analyzed by the Commander Interpreter - process. If the collected data represents a valid command, the CRC of the command is being verified. If the calculated CRC value is equal to the received value, the packet is considered as valid. Next, the Command Execution State Machine gets informed that a new command was received. Depended on the received command code, the state machine controller will change the active state. The state machine will then prepare the reply message. If the data is ready, the state machine starts the transmission of the message by setting a start flag. This flag is checked by the Reply Transmitter - process. This process accesses the data created by the state machine and transmits the complete message. The following paragraphs will give a more precise description of how each process is implemented.
This process fetches the data received by the data communication entity. It composes every received byte to form the command send by the GUI. The data received is stored in a std_logic_vector array receive buffer. Due to the fact that a standard 8N1 serial connection is used, every received word is exactly 8 bits or 1 byte in size. After a command was successfully received by the Command Interpreter, the process will inform the Command Execution State Machine to set internal parameters and generate a reply message.
Figure 2 illustrates the flow diagram of the Command Interpreter - process.
The process starts first with the header of the command. If any data during the assemble phase is detected as invalid, the Command Interpreter will stop collecting data and restarts. If the structure of the header is valid, the interpreter starts the CRC calculation process by setting a flag. If the result of the CRC calculation is equal to the CRC value of the received header, the interpreter continuous. The interpreter will stop immediately if a CRC error is detected. In that case, the interpreter will inform the Command Execution State Machine to prepare a NOT-ACKNOWLEDGE message.
Depended on the value of the payload size field of the received command, the interpreter will fetch the payload data. Due to the variable nature of the payload field, a value range check cannot be performed. The received data is again stored in a std_logic_vector array. If the complete payload of the sent command is received, the CRC will be calculated.
The procedure is exactly the same as for calculating the header CRC of the received command. Only if the results prove a valid packet, the processing continuous. If both, the header and the payload of the command, is considered as valid, the interpreter will flag the received packet as valid and complete. In order to inform the Command Execution State Machine, the Command Interpreter will set the PACKET_AVAILABLE flag.
This process is responsible for executing the command received from the GUI. The process continuously listens to the Command Interpreter to instantly execute a new available command. If a new packet was received, the state machine will first check the command code. According to the value of the command code, the next state will execute the command and generate the corresponding reply. The structure of the state machine is described by the following diagram seen in figure 3.
As shown in figure 3, the state machine itself can reach the following states:
By powering up the FPGA design the state machine will start execution at this state. This state is used to generate a dummy message. The dummy message is two bytes in size and does not comply to any valid command or reply. It initializes the data path of generating reply messages and prevents corrupted data during the power up phase. The values of the two dummy bytes are considered as don’t care. This state is only reached once during power up and cannot be reached during normal operation.
This state is reached after successfully transferring the dummy message. It is used to initialize internal signals and variables to prepare the process for the next incoming command. During this state no data is send by the transfer entity. The IDLE state listens to the PACKET_AVAILABLE flag. If a valid packet was received by the Command Interpreter process, the IDLE state will change the state to CHECK_DATA. If no command was received the IDLE state will switch to the REPLY_SD state in order to continue any current sample data transfer. Therefore, the IDLE state will be left immediately after execution. The IDLE state can also be reached by the WAIT_PC_REC state after PACKET_AVAILABLE was set. REPLY_SD will switch to the IDLE state if no channel is active and therefore data transmission is undesired. The IDLE state is also reached if any of the following states successfully complete execution: REPLY_HWV, REPLY_SWV and ACK.
After a new command was received, this state will change the next state depended on the value of the command code. It detects if a non-supported command was received. In this case, CHECK_DATA will change the error code to NOT_SUPPORTED and switches to the NACK state in order to generate the error message. Currently the loop back command of the OpenLab project is not supported by the FPGA based oscilloscope. If the command code is not equal to any valid code, this state will set the error code to UNKNOWN_COMMAND and changes the next state to NACK. CHECK_DATA is reached every time a new command was received.
Every time a sample data packet was sent by the FPGA, the actual state switches to the WAIT_PC_REC state. This state is used as a wait state. The state waits a defined number of clock cycles in order to prevent the receiving buffer of the PC from overflowing. After completing execution of the WAIT_PC_REC state, the current state switches back to the REPLY_SD state. This will continue the transmission of sample data. This wait procedure can be interrupted by any incoming command.
This state is reached after a NACK message was sent by the FPGA. It resets some internal signals and variables to prepare the state machine for any new command. The state machine will stay in this state as long as no new valid command was received by the Command Interpreter.
This state gets activated by the CHECK_DATA state only. It will be reached after receiving the SET TRIGGER SETTINGS command from the GUI. The state reads the payload data of the received command and applies any changes to the trigger system. Settings like the current active trigger channel, the trigger type and the trigger level are extracted from the payload data. After completion the next state changes to the ACK state.
After the command SET CHANNEL SETTINGS is received by the Command Interpreter, the CHECK_DATA state of the state machine will switch to the CMD_SCS state. This state extracts the payload data of the command and applies changes to the amplification-stage selection and the sample acquisition system. CMD_SCS decides which channel is turned on or off depended on the payload data. This state is also responsible for correctly setting the amplification-stage. This is done by setting a bit pattern to the input of the de-multiplexer. This bit pattern is directly extracted from the SET CHANNEL SETTINGS message. After execution, the CMD_SCS state will set the next state to ACK.
The state machine will switch to the CMD_STB state if the SET TIME BASE command was received. The switching itself is done by the CHECK_DATA state. This state will extract the sample rate settings from the payload data of the received command. The value of the sample rate received from the GUI is already prepared to be used by the sampling-data-and-triggering entity of the FPGA design. This means that the value already represents the amount of clock cycles the FPGA has to wait before storing a new sample. So complex mathematical operations are not necessary. The sampling procedure will be discussed in chapter Sampling data and triggering. After completion, the next state changes to the ACK state.
This state gets activated by the CHECK_DATA state if the SET SAMPLING MODE command was received by the Command Interpreter process. The CMD_SSM state reads data from the received payload and sets settings for the ETS sampling mode. A general description of ETS can be found in chapter Equivalent Time Sampling - Theory. The implementation of the ETS sampling mode is described in chapter Sequential Equivalent Time Sampling - FPGA Implementation. Again, after completion, the next state will be changed to the ACK state.
This state is responsible for reading the sample data provided by the sampling-data-and-triggering entity of the FPGA design. The REPLY_SD state prepares every sample data packet and starts their transmission. Regardless of the selected sampling mode, the REPLY_SD state will handle the data collection. This state prepares the Extended-Sample-Data packet as described by the binary protocol in .
This state is active if no command was received by the Command Interpreter. If all channels are turned off, the REPLY_SD state will stop the transmission and switch to the IDLE state. If a new command was received during the sample data packet transfer, the current packet will be completed and transmitted. This is necessary to prevent any corrupted data and possible de-synchronization of the GUI. However, the state machine will still be informed about the new arrived command. Immediately after the current packet was transferred, the transmission will stop and the pending command will be executed. If both channels are activated, the REPLY_SD state will alternate between them. This is done to provide a consistent amount of sample data of each channel for the GUI.
The whole sample data packet is stored in a std_logic_vector array. Each std_logic_vector of this array is 1 byte in size. This storage can be used to generate every reply message of the OpenLab protocol. The maximum size of one sample data packet is exactly 532 bytes. The header of the message reserves 7 bytes including the header checksum. The payload of the sample data packet consists of a fixed and a variably field. The fixed payload consists of the current packet number, the sample rate at which the samples were taken, number of bits per sample and the number of samples in this packet. The fixed payload field is 11 bytes in size. The variable field includes the sample data itself and the payload checksum. The size of the variable payload depends on the amount of sample data inside the packet. A maximum of 512 samples can be transferred within one message.
The size of one sample data packet can be calculated by the following formula:
This state creates the answer for the GET HARDWARE VERSION command. The state is activated by the CHECK_DATA state. The generated message will include the actual front-end hardware version of the OpenLab oscilloscope. This message is also used to identify the device as a FPGA-based oscilloscope. This is necessary for calibrating some functions of the GUI.
This state is similar to the REPLY_HWV state. The only difference is that the current version number of the FPGA design is sent instead of the hardware version.
The ACK state is reached every time a command of the OpenLab protocol needs confirmation. For example, if parameters of the trigger settings or channel settings are changed. After complete execution of this state, the next state will be the IDLE state.
This state is reached if a received command cannot be further processed by the FPGA. The NACK state will be activated if a header or payload CRC error occurred. This is also the case if a not supported or unknown command was sent by the GUI. The NACK message also includes an error code which helps to identify the cause of the problem.
Cyclic Redundancy Code (CRC) is a widely used algorithm to detect faulty data during digital communication. However, this technique is not able to correct errors. Therefore, a faulty message has to be re-transmitted. This is not a problem, because the communication between the OpenLab device and the OpenLab GUI is considered as non-critical.
The paper "A Tutorial on CRC Computations"  is concerned to CRC algorithm and how they are structured. The CRC16 calculation consists of two processes. One process is responsible for calculating the CRC of the header of a message. The other process calculates the payload CRC.
This process is responsible for transferring each byte of a reply message to the GUI. The process triggers the data communication entity of the FPGA and controls the data flow. A byte counter is set each time a reply message is ready for transfer. The byte counter represents the length of the transferred message in bytes. This is necessary to indicate how much bytes should be read from the send buffer array. The process gets active if the START_TRANSFER flag is set by the Command Execution State Machine.
Schloffer Harald: Development of a low-cost micro-controller based oscilloscope including equivalent time sampling, University of Applied Sciences FH Technikum Wien, 2016
TEMLASO V. RAMABADRAN, S. S. G.: A Tutorial on CRC Computations. Iowa State University, 1988.