Notas del estudio FPGA
1. Protocolo de puerto serie UART y diseño del remitente del puerto serie 1
-
Enviar un solo byte
1.1 Introducción al
diseño del transmisor de protocolo serie UART 1.2
1.1 Introducción a UART
(1) Concepto:
UART: (Receptor / transmisor asíncrono universal) es el término general para la comunicación en serie asíncrona. Dúplex completo, extremo de envío: paralelo a serie; extremo de recepción: serie a paralelo. Incluyendo RS232, RS449, RS423, RS485 (estándares de interfaz y estándares de bus de varios puertos de comunicación serie asíncronos, características eléctricas, velocidad de transmisión, características de conexión, características mecánicas de la interfaz, etc.).
(2) Características:
estructura de circuito simple y bajo costo.
(3). Parámetros clave:
bits de datos : el número de bits de datos enviados durante el inicio y la parada de una única transmisión de datos UART; se pueden seleccionar 5, 6, 7, 8 (predeterminado).
Velocidad en baudios (baudios): desde uno El número de bits de datos que se pueden comunicar por segundo desde un dispositivo a otro dispositivo. Las velocidades en baudios típicas son 300, 1200, 2400, 9600, 19200, 115200 (1s: 115200bits; 1bit: 8.68us), etc. La misma velocidad en baudios debe establecerse en ambos extremos del dispositivo de comunicación.
[Conversión de velocidad en baudios y período de reloj]:
frecuencia (f) = 500MHz, período (T) = 20ns;
velocidad en baudios B (bps) >> 1s para transmitir datos Bbit >> Necesidades de transmisión de datos de 1bit (1 / B (bps) )) s = (1000000000 / B (bps)) ns
valor de recuento de división de velocidad en baudios: (1000000000 / B (bps)) ns / período de
reloj Valor de recuento de reloj del sistema = valor de recuento de división de velocidad en baudios-1;
bit de paridad: verificar la exactitud de los datos. Paridad par (par): el número par de 1 dígito en los dígitos transmitidos; paridad impar (impar): el número impar de 1 dígito en los dígitos transmitidos (incluyendo cada dígito del carácter y el dígito de control).
Bits de parada:Después de que se envía el bit de datos de cada byte, se envía el bit de parada para marcar la finalización de una transmisión de datos. Al mismo tiempo, se puede utilizar para ayudar a la sincronización del hardware del receptor. Bits seleccionables: 1 (predeterminado), 1,5, 2 bits.
RS323: 8N1 (8 bits de datos, 1 bit de parada, sin bit de paridad)
1.2 El diseño del extremo de envío del protocolo de puerto serie
(1). Diagrama de bloques general del transmisor de protocolo de puerto serie
(2). Diagrama de secuencia del transmisor de protocolo del puerto serie
INICIO: nivel bajo
PARADA: nivel alto
DATOS: 8 bits
(3). Código Verilog
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). Modelim simulación
---- El contenido de aprendizaje proviene del video de la FPGA de Xiaomi
[Nota]: Notas de estudio personal, si hay errores, no dude en aclararme, esto es cortés ~~~