Verilog Implementation of the Transmit UART | Cypress Semiconductor
Verilog Implementation of the Transmit UART
In the next few posts I'll go through the implementation of the Transmit UART.
The first step is to create a state machine that controls the operation of the UART. Most all components will include a state machine and a datapath. The state machine will be written in synthesizable Verilog and gets placed into the PLD logic of the UDBs. The datapath portion will get instantiated into the Verilog description and is implemented with a datapath instance in the UDBs. Below is the state diagram for the UART:
The state machine waits for the CPU or DMA to place an entry in the transmit FIFO. Once there is data present it transmits one Start bit, 8 data bits and finishes with one Stop bit. The bits are sent starting with bit 0. A design requirement is that two bytes can be sent back to back, so the STOP state must go directly to the START state if more data is available. The implementation in Verilog is a direct mapping of this diagram to a Verilog case statement:
Now that the state diagram is in place, what happens in each of those states needs to be defined. For a UART implementation the Start bit is a 0, the Stop bit is a 1, and the data bits are shifted out from bit 0 to bit 7. In addition when nothing is being transmitted (Idle state) the output is held high (same as the Stop state). To avoid any glitches on the output the tx signal is implemented with a register. If it was implementated directly as combinatorial logic the value output can quickly oscillate between low and high as all the state bits are decoded to determine the next output value. The code below implements this functionality. The signal "so" is the Shift Out value from the datapath.
The state machine is used to control the datapath. Based on these 11 states there are just 2 operations that need to be performed. Either a new value needs to be LOADed from FIFO or a bit of the data needs to be SHIFTed out. There are some other states such as STOP and IDLE where what operation happens doesn't matter as long as there aren't any negative side effects. In these cases SHIFTing can be done and the shift out bit is just ignored. The code to map the states to the datapath operations is as follows:
So there are two operations that need to be implemented in the datapath: LOAD and SHIFT. The datapath allows up to 8 operations to be configured. Each operation will do an ALU operation and update some registers. Only a limited number of combinations are possible, so based on capabilities of the datapath, the registers and ALU operations need to be carefully laidout. Below are the two operations that this component needs:
During the LOAD operation the FIFO (F0) is read from and the value is stored in the accumulator (A0). During the SHIFT operation A0 is read, passed through the ALU (no operation), shifted right and then written back to A0. The bit that is shifted out is sent out of the datapath on the "so" signal which was shown in the Verilog code earlier.
With the next post I'll show how these operations are mapped onto the datapath with the Datapath Configuration Tool.