380|1

441

帖子

2

资源

纯净的硅(初级)

07、安路SparkRoad国产FPGA测评【学习篇】串口回环实验 [复制链接]

本帖最后由 1nnocent 于 2022-7-30 09:10 编辑

    该例程实现串口回环实验,FPGA 实时监测 uart_rx 信号是否有数据, 若接收到 PC 端发送的数据, 则把接收到的数据通过 uart_tx 返回给 PC 端。先下载程序试下效果,发现PC端发送数据时,没有现象,检查了原理图和管脚约束文件发现是管脚约束时例程使用的不是USB对应的引脚,通过原理图可知TX_RX对应的引脚分别为F16_E16。

image.png   image.png   image.png

  修改引脚后功能正常。

    先看下一步串口通讯的数据格式:首先是起始位,空闲时为高电平,起始位时拉低电平,之后是数据位,校验位和停止位,停止位时拉高电平。 image.png  

    例程顶层模块的输入接口为25MHz时钟,外部复位(对应中间的按键)、输入引脚(rx_引脚)、输出引脚(tx_引脚)。

    波特率设置模块(波特率为9600,时钟周期40ns_):其中bps_start是uart_tx引脚捕获的起始位信号,clk_bps位波特率采样中点。

module speed_setting
#(
    parameter BPS_SET      =   96,  // 波特率
    parameter CLK_PERIORD  =   40   // 系统时钟周期 40ns(25MHz)
)
(
	input	clk,		// 25MHz 系统时钟
	input	rst_n,		// 系统复位
	input	bps_start,	// 捕获起始信号的脉冲信号
	output	clk_bps		// 波特率采样中点脉冲信号
);

`define BPS_PARA	(10_000_000/CLK_PERIORD/BPS_SET)	// 10_000_000/`CLK_PERIORD/96;
`define BPS_PARA_2	(`BPS_PARA/2)						// BPS_PARA/2;	

reg	[12:0] cnt;		    // 为得到指定的波特率,需要对系统时钟进行计数
reg clk_bps_r;	        // 接收过程标志信号 寄存器

always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        cnt <= 13'd0;
	else if((cnt == `BPS_PARA) || !bps_start)	// 捕获起始信号后开始波特率计数
        cnt <= 13'd0;	    // 计时到指定波特率次数后清零
	else
        cnt <= cnt + 1'b1;  // 否则计数器自加
end

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
        clk_bps_r <= 1'b0;
	else if(cnt == `BPS_PARA_2)
        clk_bps_r <= 1'b1;			// 波特率采样中点标志
	else
        clk_bps_r <= 1'b0;
end

assign clk_bps = clk_bps_r;

endmodule

    rx_接收模块:该模块捕获下降沿时使用的四个寄存器uart_rx0、uart_rx1、uart_rx2、uart_rx3,捕获的下降沿用于产生波特率模块。该模块主要功能是接收数据,把rx_引脚上的数据进行串转并的功能。

module my_uart_rx
(
	input			clk,		// 25MHz 系统时钟
	input			rst_n,		// 系统复位
	input			uart_rx,	// uart_rx 输入引脚
	output	[7:0]	rx_data,	// uart_rx 接收数据
	output			rx_int,		// 接收过程标志信号
	input			clk_bps,	// 波特率采样中点
	output			bps_start	// 捕获的起始位脉冲信号
);

//----------------------------------------------------------------
reg		uart_rx0,uart_rx1,uart_rx2,uart_rx3;	// 起始位下降沿信号寄存器
wire	neg_uart_rx;							

always @ (posedge clk or negedge rst_n)	// 起始位下降沿信号寄存
begin 
	if(!rst_n) 
    begin
		uart_rx0 <= 1'b0;
		uart_rx1 <= 1'b0;
		uart_rx2 <= 1'b0;
		uart_rx3 <= 1'b0;
	end
	else 
    begin
		uart_rx0 <= uart_rx;
		uart_rx1 <= uart_rx0;
		uart_rx2 <= uart_rx1;
		uart_rx3 <= uart_rx2;
	end
end

assign neg_uart_rx = uart_rx3 & uart_rx2 & ~uart_rx1 & ~uart_rx0;	// 捕获起始位下降沿信号

//----------------------------------------------------------------
reg 		bps_start_r;	// 起始位脉冲信号寄存器
reg	[3:0] 	num;	
reg 		rx_int;		// 接收过程标志信号

always @ (posedge clk or negedge rst_n)
begin
	if(!rst_n)  
    begin
		bps_start_r <= 1'bz;
		rx_int 		<= 1'b0;
	end
	else if(neg_uart_rx) 
    begin	                    // 捕获起始位下降沿  
		bps_start_r <= 1'b1;	// 起始位脉冲信号置一   
		rx_int 		<= 1'b1;	// 接收过程标志信号置一
	end
	else if(num == 4'd9) 
    begin	                    // 接收到停止位
		bps_start_r <= 1'b0;	// 起始位脉冲信号置零
		rx_int 		<= 1'b0;	// 接收过程标志信号置零
	end
end

assign bps_start = bps_start_r;

//----------------------------------------------------------------
reg	[7:0]	rx_data_r;		// 接收数据寄存器
reg	[7:0]	rx_temp_data;	// 临时接收数据寄存器

always @ (posedge clk or negedge rst_n)
begin
	if(!rst_n) 
    begin
		rx_temp_data 	<= 8'd0;
		num 			<= 4'd0;
		rx_data_r 		<= 8'd0;
	end
	else if(rx_int) 
    begin	                // 接收过程标志信号为一时
		if(clk_bps) 		// 波特率采样中点时,寄存接收数据
        begin	            	
			num <= num+1'b1;
			case (num)
				4'd1: rx_temp_data[0] <= uart_rx;	//寄存接收数据0bit
				4'd2: rx_temp_data[1] <= uart_rx;	//寄存接收数据1bit
				4'd3: rx_temp_data[2] <= uart_rx;	//寄存接收数据2bit
				4'd4: rx_temp_data[3] <= uart_rx;	//寄存接收数据3bit
				4'd5: rx_temp_data[4] <= uart_rx;	//寄存接收数据4bit
				4'd6: rx_temp_data[5] <= uart_rx;	//寄存接收数据5bit
				4'd7: rx_temp_data[6] <= uart_rx;	//寄存接收数据6bit
				4'd8: rx_temp_data[7] <= uart_rx;	//寄存接收数据7bit
				default: ;
			endcase
		end
		else if(num == 4'd9) 
        begin		
			num			<= 4'd0;			// 停止位时,清零接收数据计数器
			rx_data_r	<= rx_temp_data;	// 寄存临时接收数据寄存器的数据
		end
	end
end

assign rx_data = rx_data_r;	

endmodule

 

    发送模块,该模块的功能主要是将接收的数据进行并转串,并发送给PC端。发送模块与接受模块不同的地方是需要发送起始位和停止位。

module my_uart_tx
(
	input			clk,		// 系统时钟
	input			rst_n,		// 复位信号
	input	[7:0]	rx_data,	// 接收到的数据
	input			rx_int,		// 接收过程标志信号
	output			uart_tx,	// uart_tx 输出引脚
	input			clk_bps,	// 波特率采样中点
	output			bps_start	// 捕获的结束位脉冲信号
);

//---------------------------------------------------------
reg 	rx_int0,rx_int1,rx_int2;	// 接收过程标志信号寄存器
wire 	neg_rx_int;					// 接收过程标志信号下降沿

always @ (posedge clk or negedge rst_n)	// 寄存接收过程标志信号
begin 
	if(!rst_n) 
    begin
		rx_int0 <= 1'b0;
		rx_int1 <= 1'b0;
		rx_int2 <= 1'b0;
	end
	else 
    begin
		rx_int0 <= rx_int;
		rx_int1 <= rx_int0;
		rx_int2 <= rx_int1;
	end
end

assign neg_rx_int =  ~rx_int1 & rx_int2;	// 捕获接收过程标志信号

//---------------------------------------------------------
reg	[7:0] 	tx_data;		// 发送的数据
reg 		bps_start_r;
reg 		tx_en;			// 发送数据使能
reg	[3:0] 	num;

always @ (posedge clk or negedge rst_n)
begin 
	if(!rst_n) 
    begin
		bps_start_r <= 1'bz;
		tx_en 		<= 1'b0;
		tx_data 	<= 8'd0;
	end
	else if(neg_rx_int) 
    begin		                    // 捕获到接收过程标志信号
		bps_start_r <= 1'b1;
		tx_data 	<= rx_data;		// 将接收到的数据送到发送模块
		tx_en 		<= 1'b1;		// 发送数据使能置一
	end
	else if(num == 4'd10) 
    begin		                    // 结束
		bps_start_r <= 1'b0;
		tx_en		<= 1'b0;
	end
end

assign bps_start = bps_start_r;

//---------------------------------------------------------
reg uart_tx_r;

always @ (posedge clk or negedge rst_n)	// 将接收到的数据进行并转串
begin
	if(!rst_n) 
    begin
		num 		<= 4'd0;
		uart_tx_r 	<= 1'b1;
	end
	else if(tx_en) 
    begin
		if(clk_bps)	
        begin
			num <= num+1'b1;
			case (num)
				4'd0: uart_tx_r <= 1'b0; 		// 起始位
				4'd1: uart_tx_r <= tx_data[0];	// 寄存发送数据bit0
				4'd2: uart_tx_r <= tx_data[1];	// 寄存发送数据bit1
				4'd3: uart_tx_r <= tx_data[2];	// 寄存发送数据bit2
				4'd4: uart_tx_r <= tx_data[3];	// 寄存发送数据bit3
				4'd5: uart_tx_r <= tx_data[4];	// 寄存发送数据bit4
				4'd6: uart_tx_r <= tx_data[5];	// 寄存发送数据bit5
				4'd7: uart_tx_r <= tx_data[6];	// 寄存发送数据bit6
				4'd8: uart_tx_r <= tx_data[7];	// 寄存发送数据bit7
				4'd9: uart_tx_r <= 1'b1;		// 停止位
			 	default: uart_tx_r <= 1'b1;
			endcase
		end
		else if(num == 4'd10)
                num <= 4'd0;		
	end
end

assign uart_tx = uart_tx_r;

endmodule


 

    历程运行效果:

image.png  


回复

1784

帖子

3

资源

版主

uart是最常用的通信方式,感谢分享!

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

最新文章 更多>>
    关闭
    站长推荐上一条 1/10 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表