2540|2

866

帖子

3

TA的资源

版主

楼主
 

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

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

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

   

  修改引脚后功能正常。

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

 

    例程顶层模块的输入接口为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

 

    历程运行效果:

 

最新回复

感谢分享   详情 回复 发表于 2023-1-26 08:48
点赞 关注
 
 

回复
举报

7192

帖子

11

TA的资源

版主

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

回复

2655

帖子

6

TA的资源

五彩晶圆(初级)

板凳
 

感谢分享

个人签名

希望做一些大家觉得好用的东西!

 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条
有奖直播报名| TI 面向楼宇和工厂自动化行业的毫米波雷达解决方案
【内容简介】TI 60GHz IWRL6432和 IWRL1432毫米波雷达传感器如何帮助解决楼宇和工厂自动化应用中的感应难题
【直播时间】5月28日(周三)上午10:00
【直播礼品】小米双肩包、contigo水杯、胶囊伞、安克充电器

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

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

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

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

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