FPGA学习笔记02——串口通信

串行通信

串行通信是将数据分成一位一位的形式在一条传输线上逐个传输。根据发送方和接受方是否由同一时钟控制分为同步通信和异步通信。
常见的串行通信接口有:
在这里插入图片描述

串口通信

UART(universal asynchronous receiver-transmitter)是一种采用异步串行通信方式的传输器。在发送数据时将并行数据转换成串行数据来传输,在接收数据时将串行数据转换为并行数据接收,主要功能就是实现数据的串并转换。
在这里插入图片描述
当检测到电平拉低时标记为起始位,接着是8个(5、6、7个也行)数据位和校验位(奇校验保证1的个数为奇数,偶校验反之),到停止位时电平又被拉高,进入空闲状态。
串口通信的传输速率用波特率表示,即每秒传输的二进制数据的位数,单位bps,常用的波特率有9600、19200、38400、57600及115200。
串口通信的接口标准如下:
在这里插入图片描述

串口接收

输入信号有系统时钟、复位、uart_rxd,输出有uart_done、uart_data,其余为中间变量。
start_flag:检测uart_rxd的下降沿,标志起始位的到来
rx_flag:接收使能,为高电平时执行接收任务
clk_cnt:时钟计数,计到波特率周期CLK_SYS/BPS
rx_cnt:接收计数器,每个数据比特对应一个计数值
在这里插入图片描述

//串口发送模块
//设时钟频率为50MHz,波特率为115200,8位数据,无校验位
module uart_rx(
	input 				clk,
	input 				rst_n,
	input 				uart_rxd,
	
	output reg			uart_done,
	output reg [7:0] 	uart_data
);

parameter BPS      = 115200;
parameter CLK_SYS  = 50_000_000;
parameter BPS_CNT  = CLK_SYS/BPS;

wire start_flag;

reg uart_rxd_d0;
reg uart_rxd_d1;

reg 		rx_flag;
reg [3:0]	rx_cnt;
reg [15:0]	clk_cnt;

reg [7:0]	uart_data_reg;

//检测输入数据uart_rxd的下降沿,标志起始位的到来
assign start_flag = uart_rxd_d1 & (~uart_rxd_d0);

//打两拍,防亚稳态,同步时钟
always @(posedge clk or negedge rst_n) begin   
	if(!rst_n) begin
		uart_rxd_d0 <= 1;
		uart_rxd_d1 <= 1;
	end
	else begin
		uart_rxd_d0 <= uart_rxd;
		uart_rxd_d1 <= uart_rxd_d0;
	end
end

//数据发送旗帜,高电平时进行数据发送
always @(posedge clk or negedge rst_n) begin   
	if(!rst_n) 
		rx_flag <= 0;
	else if(start_flag) 
		rx_flag <= 1;
	else if((rx_cnt == 4'd9) && (clk_cnt == BPS_CNT/2 - 1'b1))
		rx_flag <= 0;
	else
		rx_flag <= rx_flag;
end

//计数器,将时钟周期计数为波特率周期
always @(posedge clk or negedge rst_n) begin   
	if(!rst_n)
		clk_cnt <= 0;
	else if(rx_flag) begin
		if(clk_cnt < BPS_CNT - 1'b1)
			clk_cnt <= clk_cnt + 1;
		else
			clk_cnt <= 0;
	end
	else
		clk_cnt <= 0;
end

//波特率计数
always @(posedge clk or negedge rst_n) begin   
	if(!rst_n)
		rx_cnt <= 0;
	else if((clk_cnt == BPS_CNT - 1'b1) && (rx_flag))
		rx_cnt <= rx_cnt + 1;
	else if((rx_cnt == 9) && (clk_cnt == BPS/2))
		rx_cnt <= 0;
	else
		rx_cnt <= rx_cnt;
end

//对输入数据uart_rxd寄存,并实现串转并
always @(posedge clk or negedge rst_n) begin   
	if(!rst_n) 
		uart_data_reg <= 0;
	else if((rx_flag) && (clk_cnt == BPS/2)) begin
	/*
		uart_data_reg <= {uart_data_reg[6:0],uart_rxd_d1}
	*/
		case(rx_cnt)
			1:uart_data_reg[0] <= uart_rxd_d1;
			2:uart_data_reg[1] <= uart_rxd_d1;
			3:uart_data_reg[2] <= uart_rxd_d1;
			4:uart_data_reg[3] <= uart_rxd_d1;
			5:uart_data_reg[4] <= uart_rxd_d1;
			6:uart_data_reg[5] <= uart_rxd_d1;
			7:uart_data_reg[6] <= uart_rxd_d1;
			8:uart_data_reg[7] <= uart_rxd_d1;
			default:uart_data_reg <= uart_data_reg;
		endcase
	end
end

//输出模块,将寄存器中的数据输出
always @(posedge clk or negedge rst_n) begin   
	if(!rst_n) begin
		uart_done <= 0;
		uart_data <= 0;
	end
	else if(rx_cnt == 9) begin
		uart_done <= 1;
		uart_data <= uart_data_reg;
	end
	else begin
		uart_done <= 0;
		uart_data <= 0;
	end
end
endmodule

串口发送

在这里插入图片描述

//串口接收模块
module uart_tx(
	input 		clk,
	input 		rst_n,
	input 		uart_en,
	input 		uart_din,
	
	output reg 	uart_txd
);

parameter BPS      = 115200;
parameter CLK_SYS  = 50_000_000;
parameter BPS_CNT  = CLK_SYS/BPS;

wire 		en_flag;

reg 		uart_en_d0;
reg 		uart_en_d1; 

reg 		tx_flag;
reg [3:0] 	tx_cnt;
reg [15:0]	clk_cnt;

reg [7:0] 	uart_din_reg;

assign en_flag = (~uart_en_d1) && uart_en_d0;

always @(posedge clk or negedge rst_n) begin   
	if(!rst_n) begin
		uart_en_d0 <= 0;
		uart_en_d1 <= 0;
	end
	else begin
		uart_en_d0 <= uart_en;
		uart_en_d1 <= uart_en_d0;
	end
end

always @(posedge clk or negedge rst_n) begin   
	if(!rst_n) 
		uart_din_reg <= 0;
	else if(en_flag)
		uart_din_reg <= uart_din;
	else
		uart_din_reg <= uart_din_reg;
end

always @(posedge clk or negedge rst_n) begin   
	if(!rst_n) 
		tx_flag <= 0;
	else if(en_flag) 
		tx_flag <= 1;
	else if((tx_cnt == 4'd9) && (clk_cnt == BPS_CNT - BPS_CNT/10))
		tx_flag <= 0;
	else
		tx_flag <= tx_flag;
end

always @(posedge clk or negedge rst_n) begin   
	if(!rst_n)
		clk_cnt <= 0;
	else if(tx_flag) begin
		if(clk_cnt < BPS_CNT - 1'b1)
			clk_cnt <= clk_cnt + 1;
		else
			clk_cnt <= 0;
	end
	else
		clk_cnt <= 0;
end

always @(posedge clk or negedge rst_n) begin   
	if(!rst_n)
		tx_cnt <= 0;
	else if((clk_cnt == BPS_CNT - 1'b1) && (tx_flag))
		tx_cnt <= tx_cnt + 1;
	else if((tx_cnt == 9) && (clk_cnt == BPS_CNT - BPS_CNT/10))
		tx_cnt <= 0;
	else
		tx_cnt <= tx_cnt;
end

always @(posedge clk or negedge rst_n) begin   
	if(!rst_n)
		uart_txd <= 1;
	else if(tx_flag) begin
		case(tx_cnt)
			0:uart_txd <= 0;
			1:uart_txd <= uart_din_reg[0];
			2:uart_txd <= uart_din_reg[1];
			3:uart_txd <= uart_din_reg[2];
			4:uart_txd <= uart_din_reg[3];
			5:uart_txd <= uart_din_reg[4];
			6:uart_txd <= uart_din_reg[5];
			7:uart_txd <= uart_din_reg[6];
			8:uart_txd <= uart_din_reg[7];
			9:uart_txd <= 1;
		endcase
	end
end
endmodule
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 《FPGA自学笔记——设计与验证》是一本关于FPGA设计和验证的入门教材。本书以VHDL和Verilog两种HDL语言为主要工具,通过实例讲解FPGA的基本概念、设计流程和验证方法。同时,本书还通过实例演示了如何使用Xilinx ISE和ModelSim这两个主流软件工具进行FPGA设计和验证。 本书的内容分为五个部分,分别是FPGA基础知识、FPGA设计流程、FPGA验证方法、FPGA性能优化以及FPGA应用实例。其中,FPGA基础知识部分介绍了FPGA的基本构成、组成部件以及通用数字电路设计知识;FPGA设计流程部分从设计输入、RTL设计、布局布线、实现生成等方面详细介绍了FPGA设计流程;FPGA验证方法部分主要介绍了功能验证和时序验证这两个方面的知识;FPGA性能优化部分介绍了FPGA的几种性能指标以及如何通过一定的优化方法提高FPGA性能;FPGA应用实例部分通过几个实例演示了如何应用FPGA进行数字电路设计。 本书的难度适中,适合初学者学习和参考,同时也可以作为FPGA初学者的参考书籍。本书涉及的知识点较为全面,可以为初学者提供一个全面的FPGA设计和验证入门指南。其内容易于理解,实例讲解深入浅出,对于想要学习FPGA设计和验证的人群来说是一本很好的参考书。 ### 回答2: 《FPGA自学笔记——设计与验证》PDF是一本很好的自学FPGA的书籍。这本书包含了FPGA基本概念、设计流程、Verilog HDL语言、开发工具、测试方法等多个主题,非常详尽地介绍了FPGA的基本知识和开发技巧。读这本书可以帮助我们更好地理解FPGA的原理和功能,从而更加熟练地掌握FPGA的设计和验证。 此外,这本书还提供了很多实例来帮助我们更好地理解FPGA的设计和验证。这些实例包含多种应用场景,例如数字逻辑、时序控制、通信等,能够帮助我们从不同角度学习FPGA的相关知识。而且,这本书还提供了实验指导,通过做实验来让我们更深入地理解FPGA的各种知识和技能。 总之,这本书《FPGA自学笔记——设计与验证》PDF是一本非常好的FPGA自学指南,通过阅读这本书,我们可以掌握FPGA基本知识和开发技能,更好地应用FPGA进行各种应用开发。我相信,读完这本书,你一定能够对FPGA有更深刻的认识,并且能够灵活运用FPGA进行各种应用开发。 ### 回答3: 《FPGA自学笔记——设计与验证》是一本以FPGA为研究对象的书籍。它详细介绍了FPGA的诸多特性和应用。该书主要分为两部分,第一部分介绍了FPGA的基本概念,并讲解了Verilog的语法和使用方法。第二部分是实践性较强的部分,通过编写案例代码进行实际操作。 该书着重强调了FPGA设计流程,通过案例演示了FPGA设计的全过程。该书还提供了大量的练习题和案例代码,读者可以通过反复练习和实际操作,逐渐掌握FPGA的设计和验证技能。 总体来说,《FPGA自学笔记——设计与验证》是一本非常实用的FPGA入门教材。它从基础知识入手,循序渐进地讲解了FPGA的各个方面。并且,该书重点讲解了如何运用Verilog语言进行FPGA设计,这对FPGA初学者来说是一个非常实用的指南。 如果你对FPGA领域感兴趣,且希望通过自学来掌握FPGA的基本操作和设计方法,那么《FPGA自学笔记——设计与验证》是一本非常值得推荐的书籍。  

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值