FPGA study notes
1. UART serial port protocol and serial port sender design 1
-
Send a single byte
1.1 Introduction to UART
1.2 Serial protocol transmitter design
1.1 Introduction to UART
(1). Concept:
UART: (Universal Asynchronous Receiver/Transmitter) is the general term for asynchronous serial communication. Full duplex, sending end: parallel to serial; receiving end: serial to parallel. Including RS232, RS449, RS423, RS485 (interface standards and bus standards of various asynchronous serial communication ports, electrical characteristics, transmission rate, connection characteristics, mechanical characteristics of the interface, etc.).
(2). Features:
simple circuit structure and low cost.
(3). Key parameters:
data bits : the number of data bits sent during the start and stop of a single UART data transmission; 5, 6, 7, 8 (default) can be selected.
Baud rate (baud): from one The number of data bits that can be communicated per second from a device to another device. Typical baud rates are 300, 1200, 2400, 9600, 19200, 115200 (1s: 115200bits; 1bit: 8.68us), etc. The same baud rate should be set at both ends of the communication device.
[Conversion of baud rate and clock period]:
frequency (f)=500MHz, period (T)=20ns;
baud rate B(bps) >> 1s to transmit Bbit data >> 1bit data transmission needs (1/B(bps) )) s=(1000000000/ B(bps)) ns
baud rate division count value: (1000000000/ B(bps)) ns/clock period
System clock count value = baud rate division count value-1;
Parity bit: verify the correctness of the data. Even parity (even): the even number of 1 digits in the transmitted digits; odd parity (odd): the odd number of 1 digits in the transmitted digits (including each digit of the character and the check digit).
Stop bits:After the data bit of each byte is sent, the stop bit is sent to mark the completion of a data transmission. At the same time, it can be used to help the receiver's hardware synchronization. Selectable bits: 1 (default), 1.5, 2 bits.
RS323: 8N1 (8 data bits, 1 stop bit, no parity bit)
1.2 The design of the sending end of the serial port protocol
(1). Overall block diagram of the serial port protocol transmitter
(2). Sequence diagram of the serial port protocol transmitter
START: low level
STOP: high level
DATA: 8bits
(3). Verilog code
module uart_tx_r0#(
parameter START = 1'b0,
parameter STOP = 1'b1
)
(
input clk, //50MHz
input rst_n,
input send_en,
input [2:0] baud_set,
input [7:0] data_byte,
output reg rs232_tx,
output reg tx_done,
output reg uart_state
);
//----define--------------------------------------
reg [7:0] reg_data_byte;
reg [15:0] cnt;//divide frequence counter
reg baud_clk;
reg [15:0] cnt_max;//baud value
reg [3:0] cnt_bit;//
//----baud_set--------------------------------------
always@(*)begin
case(baud_set)
// 0: cnt_max <= 16'd20832;
// 1: cnt_max <= 16'd10415;
0: cnt_max <= 16'd5207;
1: cnt_max <= 16'd2603;
2: cnt_max <= 16'd1301;
3: cnt_max <= 16'd867;
4: cnt_max <= 16'd433;
// 7: cnt_max <= 16'd194;
default: cnt_max <= 5207;
endcase
end
//----divide frequence counter-->baud clock------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt <= 0;
end
else if(uart_state)begin
if(cnt == cnt_max)
cnt <= 0;
else
cnt <= cnt +16'd1;
end else
cnt <= 0;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
baud_clk <= 1'b0;
else if(cnt == 16'd1)
baud_clk <= 1'b1;
else
baud_clk <= 1'b0;
end
//----cnt_bit----------------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt_bit <= 0;
else if(cnt_bit == 4'd11)
cnt_bit <= 0;
else if(baud_clk)
cnt_bit <= cnt_bit + 4'd1;
else
cnt_bit <= cnt_bit;
end
//----rs232_tx --------------------------------------
always@(posedge clk or negedge rst_n)begin // asynchronos transimiter, reg_data_byte is used to keep input data stable
if(!rst_n)
reg_data_byte <= 8'd0;
else if(send_en)
reg_data_byte <= data_byte;
else
reg_data_byte <= reg_data_byte;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rs232_tx <= 0;
end begin
case(cnt_bit) //0:initial cnt_bit=0 --> after sending data, rs232_tx always be 0;
0: rs232_tx <= 1'b1;
1: rs232_tx <= START; //0
2: rs232_tx <= reg_data_byte[0];
3: rs232_tx <= reg_data_byte[1];
4: rs232_tx <= reg_data_byte[2];
5: rs232_tx <= reg_data_byte[3];
6: rs232_tx <= reg_data_byte[4];
7: rs232_tx <= reg_data_byte[5];
8: rs232_tx <= reg_data_byte[6];
9: rs232_tx <= reg_data_byte[7];
10: rs232_tx <= STOP; //1
default: rs232_tx <= 1;
endcase
end
end
//----tx_done-----------------------------------------
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
tx_done <= 1'b0;
else if(cnt_bit == 4'd11)
tx_done <= 1'b1;
else
tx_done <= 1'b0;
end
//----uart_state--------------------------------------
always@(posedge clk or negedge rst_n)
if(!rst_n)
uart_state <= 1'b0;
else if(send_en)
uart_state <= 1'b1;
else if(cnt_bit == 4'd11)
uart_state <= 0;
else
uart_state <= uart_state;
endmodule
//------------------------------------------------
//----testbench-----------------------------------
`timescale 1ns/1ns
`define clk_period 20
module tb_uart_tx_r0;
reg clk;
reg rst_n;
reg send_en;
reg [2:0] baud_set;
reg [7:0] data_byte;
wire rs232_tx;
wire tx_done;
wire uart_state;
uart_tx_r0 uut(
.clk(clk),
.rst_n(rst_n),
.send_en(send_en),
.baud_set(baud_set),
.tx_done(tx_done),
.data_byte(data_byte),
.uart_state(uart_state),
.rs232_tx(rs232_tx)
);
initial begin
clk = 1;
rst_n = 0;
send_en = 0;
baud_set = 3'd4;
#(`clk_period*20+1);
rst_n = 1;
#(`clk_period*50);
data_byte = 8'haa;//8'b1010_1010
send_en = 1;
#`clk_period;
send_en = 0;
@(posedge tx_done)
#(`clk_period*5000);
data_byte = 8'h55;//0101_0101
send_en = 1;
#`clk_period;
send_en = 0;
@(posedge tx_done)
#(`clk_period*5000);
$stop;
end
always begin #(`clk_period/2) clk = ~clk;end
endmodule
(3). Modelsim simulation
----The learning content comes from the video of Xiaomei's FPGA [Note]: Personal study notes, if there are mistakes, please
feel free to enlighten me, this is polite~~~