-
Notifications
You must be signed in to change notification settings - Fork 35
Asynchronous serial transmitter unit
Asynchronous serial transmitter unit for the Icestick board
- Baudrates: 300, 600, 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200
- Clock frequency: 12Mhz
- Start bits: 1
- Data bits: 8
- Parity: None
- Stop bits: 1
- Description language: Verilog
- Toolchain: Opensource: Yosys, Arachne-pnr, Icestorm project
Serial packages consist of three parts: the start bit, the 8-bit data and the stop bit
Example of the serial transmission of the K character (ASCII 0x4B: Binary: 01001011)
The serial transmitter is encapsulated in the uart-tx entity
The transmitter unit has 4 inputs and 2 outputs:
-
Inputs:
- clk: System clock (12MHz in the ICEstick board)
- rstn: Active low. When rstn is 0, the serial unit is reset (synchronous reset)
- start: Start the transmission. When it is a 1, the character from the input data is captured and the transmission begins
- data: 8-bit data to transmit
-
Outputs:
- tx: Serial output. The data is sent as a serial package. It is connected to the transmission line
- ready: Transmitter status. When ready is 1, the unit is ready to transmit. A new character can be sent. when it is 0, the unit is busy transmitting the previous character.
The step for transmitting a character are the following:
- Wait until the ready signal is 1
- Place the character in the data input
- Set the start input to 1 (at least for 1 clock cycle)
After that, the unit clears the ready signal and start transmitting the character
The implementation of the transmitter is shown in the given block diagram
It consist of the following parts:
- Data register (8 bits): For storing the data to be sent
- Shift register (10 bits): For storing the serial package and sending its bits one by one. When the load signal is 1, it is loaded with a new character to transmit (8 bits). The two bits less significant are initialized with the binary value 01 (a start bit and a idle bit). When transmitting (load = 0), the less significant line is sent to the transmission line and then the register is shift right. A 1 is introduced in the most significant bit. It is only done when the clk_baud signal is 1. This signals determines the exact time when the next bit should be sent
- Baud generator: It generates a pulse of 1 cycle periodically, according to the baud rate configured
- Bit counter: It counts the bits that have already been transmitted. It only counts when load is 0
- controller: The finite state machine that generates the load and baudgen control signals for controlling the transmitter
- D flip-flops: There are two D flip-flops for registering both signals tx and start
The transmitter controller is a finite state machine with three states:
- IDLE: There is no transmission. The unit is not being used. The ready signal is 1. When the start signal is set to 1, it changes to the START state
- START: The transmission is started. The shift register is loaded with the data to be send (plus the start bit). The baud generator is started. After one clock cycle it automatically moves to the next state
- TRANS: Transmission state. The 10-bits serial packages is sent. When the bit counter is 11, it means that 10 bits have been already transmitted and the state changes to IDLE
This is a generic code for using the UART-tx in your designs in verilog. Of course, some details can change depending on the particular implementation (as for example the definitions of the wires)
//-- Baudrate definitions
`include "baudgen.vh"
//-- Definition of wires to connect to the unit
wire clk;
wire rstn;
wire start;
wire ready;
wire tx;
wire [7:0] data;
//-- UART_TX instantiation
//-- Values for the BAUDRATE:
//-- `B115200, `B57600, `B38400, `B19200, `B9600, `B4800, `B2400, `B1200, `B600, `B300
uart_tx #(.BAUDRATE(`B115200))
TX0 (
.clk(clk),
.rstn(rstn),
.data(data),
.start(start),
.ready(ready),
.tx(tx)
);
Two examples in verilog of how to use the UART-tx unit are shown