Notas de estudio de FPGA _ Protocolo de puerto serie UART y diseño de transmisor de puerto serie

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;
Inserte la descripción de la imagen aquí
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
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

(2). Diagrama de secuencia del transmisor de protocolo del puerto serie
Inserte la descripción de la imagen aquí
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

Inserte la descripción de la imagen aquí

---- 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 ~~~

Supongo que te gusta

Origin blog.csdn.net/weixin_50722839/article/details/109554050
Recomendado
Clasificación