FPGA串口通信----uart(一)

 一、Fpga--PLL锁相环的使用

通过PLL锁相环IP的使用,可以输入时钟进行分频,倍频,也可以产生多路时钟输出信号。

外部提供晶振的原因:①Fpga电路大多数需要时序分析

                                 ②晶振在Fpga内部占空间大,所以放置于外部PCB板上

Uart异步传输速率不能很快的原因:考虑到工程实际问题,假如时钟周期大(传输速率慢的话),采取到数据电平变化的边沿时刻的概率会小很多,这样数据也很准确,通常uart适用于2M.

二、Uart 发送

2.1 uart_byte_tx(字节发送)

2.1.1模块设计框图 

2.1.2 Verilog设计及仿真 

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Description:  UART 字节发送 
//////////////////////////////////////////////////////////////////////////////////
module uart_tx_byte(
    Clk			,
	Rst_n		,
  
	data_byte	,
	send_en		,   
	Baud_Set	,  
	
	uart_tx		,  
	Tx_Done		,   
	uart_state 
);

	input 		Clk 		;    //模块全局时钟输入,50M
	input 		Rst_n		;    //复位信号输入,低有效
	input [7:0]	data_byte	;    //待传输8bit数据
	input 		send_en		;    //发送使能
	input [2:0]	Baud_Set	;    //波特率设置
	
	output reg 	uart_tx		;  //串口输出信号
	output reg 	Tx_Done		;  //1byte数据发送完成标志
	output reg 	uart_state	;  //发送数据状态

	localparam START_BIT = 1'b0;
	localparam STOP_BIT  = 1'b1; 
	
	reg 		bps_clk		 ; //波特率时钟	
	reg [15:0]	div_cnt		 ; //分频计数器	
	reg [15:0]	bps_DR		 ; //分频计数最大值	
	reg [3:0]	bps_cnt		 ; //波特率时钟计数器	
	reg [7:0]	data_byte_reg; //data_byte寄存后数据

//******************** UART发送状态标志 ****************** \\
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			uart_state <= 1'b0;
		else if(send_en)
			uart_state <= 1'b1;
		else if(bps_cnt >= 4'd11)
			uart_state <= 1'b0;
		else
			uart_state <= uart_state;
	end
//******************** 输入数据锁存 ****************** \\
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			data_byte_reg <= 8'd0;
		else if(send_en)
			data_byte_reg <= data_byte;
		else
			data_byte_reg <= data_byte_reg;
	end

//******************** 波特率时钟的生成模块 ****************** \\
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			bps_DR <= 16'd5207;
		else begin
			case(Baud_Set)
				0:bps_DR <= 16'd5207;  //波特率为9600      1_000_000_000/9600/20
				1:bps_DR <= 16'd2603;  //波特率为19200		
				2:bps_DR <= 16'd1301;  //波特率为38400
				3:bps_DR <= 16'd867;   //波特率为57600
				4:bps_DR <= 16'd433;   //波特率为115200
				default:bps_DR <= 16'd5207;			
			endcase
		end	
	end
	//counter
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			div_cnt <= 16'd0;
		else if(uart_state)begin
			if(div_cnt >= bps_DR)
				div_cnt <= 16'd0;
			else
				div_cnt <= div_cnt + 1'b1;
		end
		else
			div_cnt <= 16'd0;
	end
	// bps_clk gen
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			bps_clk <= 1'b0;
		else if(div_cnt == 16'd1)     //由于UART发送是从bps_cnt =1 发起始位,而不是从0,因此为了尽快进入发送模块,我们计数器不计满+1,等于一时+1
			bps_clk <= 1'b1;
		else
			bps_clk <= 1'b0;
	end
//******************** Uart的数据发送模块 ****************** \\
	//bps counter
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)	
			bps_cnt <= 4'd0;
		else if(bps_cnt >= 4'd11)
			bps_cnt <= 4'd0;
		else if(bps_clk)
			bps_cnt <= bps_cnt + 1'b1;
		else
			bps_cnt <= bps_cnt;
	end	
	//数据发送
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			uart_tx <= 1'b1;
		else begin
			case(bps_cnt)
				0:uart_tx <= 1'b1;
				1:uart_tx <= START_BIT;        // 从1开始,避免了起始位0与空闲态1冲突
				2:uart_tx <= data_byte_reg[0];
				3:uart_tx <= data_byte_reg[1];
				4:uart_tx <= data_byte_reg[2];
				5:uart_tx <= data_byte_reg[3];
				6:uart_tx <= data_byte_reg[4];
				7:uart_tx <= data_byte_reg[5];
				8:uart_tx <= data_byte_reg[6];
				9:uart_tx <= data_byte_reg[7];
				10:uart_tx <= STOP_BIT;
				default:uart_tx <= 1'b1;
			endcase
		end
	end	
	//数据发送完成标志 
	always@(posedge Clk or negedge Rst_n)begin
		if(!Rst_n)
			Tx_Done <= 1'b0;
		else if(bps_cnt >= 4'd11)
			Tx_Done <= 1'b1;
		else
			Tx_Done <= 1'b0;
	end	
endmodule

 由上图可知,uart发送先发低位再发高位(aa 10101010)

三、Uart接收 

3.1 uart_byte_rx (字节接收)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值