基于FPGA Uart串口通信实验
2017-09-04 19:16
651 查看
基于FPGA Uart串口通信实验
首先需要了解uart串口通信协议,根据个人专业需求不同,了解的层面可以不同。UART简介
通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART。UART通信在工作中相当常见,项目中需要生成uart信号,在博客中记录下。uart是异步通信,因为它只有一根线就可以数据的通信。不像SPI,I2C等同步传输信号。所以串口的传输速度和其它协议的速度相比是比较慢的。下面具体讲解一些uart协议以及是如何通信的。
一些概念意义
波特率:此参数容易和比特率混淆,其实他们是由区别的。具体可以百度更清楚。但是我认为uart中的波特率就可以认为是比特率,即每秒传输的位数(bit)。一般选波特率都会有9600,19200,115200等选项。其实意思就是每秒传输这么多个比特位数(bit)。
起始位:先发出一个逻辑”0”信号,表示传输字符的开始。
数据位:可以是5~8位逻辑”0”或”1”。如ASCII码(7位),扩展BCD码(8位)。一般情况下都选择8位而不选择7,因为这样能尽可能避免数据的丢失或者混乱。小端传输(即从LSB_D0端开始发送数据,而且是串行发送)。
校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验)
停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。
空闲位:处于逻辑“1”状态,表示当前线路上没有资料传送。
注意:异步通信是按字符传输的,接收设备在收到起始信号之后只要在一个字符的传输时间内能和发送设备保持同步就能正确接收。下一个字符起始位的到来又使同步重新校准(依靠检测起始位来实现发送与接收方的时钟自同步的)
时钟程序
`timescale 1ns/1ps module clkdiv(clk50,rst_n,clkout); input clk50; //系统时钟 input rst_n; output clkout; reg clkout; reg [15:0] cnt; /////分频进程, 50Mhz 的时钟 27 分频///////// /*计算过程 波特率115200bps 每个bit接收的数据有16个时钟采样 则分频数为:50_000_000/115200/16=27.13 约为27分频 */ always @(posedge clk50 or negedge rst_n) begin if (!rst_n) begin clkout <=1'b0; cnt<=0; end else if(cnt == 16'd13) begin clkout <= 1'b1; cnt <= cnt + 16'd1; end else if(cnt == 16'd27) begin clkout <= 1'b0; cnt <= 16'd0; end else begin cnt <= cnt + 16'd1; end end endmodule
串口发送程序
`timescale 1ns/1ps module uarttx(clk, rst_n, datain, wrsig, idle, tx); input clk; //UART 时钟 input rst_n; //系统复位 input [7:0] datain; //需要发送的数据 input wrsig; //发送命令,上升沿有效 output idle; //线路状态指示,高为线路忙,低为线路空闲 output tx; //发送数据信号 reg idle, tx; reg send; reg wrsigbuf, wrsigrise; reg presult; reg[7:0] cnt; //计数器 parameter paritymode = 1'b0; //////////////////////////////////////////////////////////////// //检测发送命令 wrsig 的上升沿 //////////////////////////////////////////////////////////////// always @(posedge clk) begin wrsigbuf <= wrsig; wrsigrise <= (~wrsigbuf) & wrsig; end //////////////////////////////////////////////////////////////// //启动串口发送程序 //////////////////////////////////////////////////////////////// always @(posedge clk) begin if (wrsigrise && (~idle)) //当发送命令有效且线路为空闲时,启动新的数据发送进程 begin send <= 1'b1; end else if(cnt == 8'd168) //一帧数据发送结束 begin send <= 1'b0; end end //////////////////////////////////////////////////////////////// //串口发送程序, 16 个时钟发送一个 bit //////////////////////////////////////////////////////////////// always @(posedge clk or negedge rst_n) begin if (!rst_n) begin tx <= 1'b0; idle <= 1'b0; cnt<=8'd0; presult<=1'b0; end else if(send == 1'b1) begin case(cnt) //产生起始位 8'd0: begin tx <= 1'b0; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd16: begin tx <= datain[0]; //发送数据 0 位 presult <= datain[0]^paritymode; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd32: begin tx <= datain[1]; //发送数据 1 位 presult <= datain[1]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd48: begin tx <= datain[2]; //发送数据 2 位 presult <= datain[2]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd64: begin tx <= datain[3]; //发送数据 3 位 presult <= datain[3]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd80: begin tx <= datain[4]; //发送数据 4 位 presult <= datain[4]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd96: begin tx <= datain[5]; //发送数据 5 位 presult <= datain[5]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd112: begin tx <= datain[6]; //发送数据 6 位 presult <= datain[6]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd128: begin tx <= datain[7]; //发送数据 7 位 presult <= datain[7]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd144: begin tx <= presult; //发送奇偶校验位 presult <= datain[0]^paritymode; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd160: begin tx <= 1'b1; //发送停止位 idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd168: begin tx <= 1'b1; idle <= 1'b0; //一帧数据发送结束 cnt <= cnt + 8'd1; end default: begin cnt <= cnt + 8'd1; end endcase end else begin tx <= 1'b1; cnt <= 8'd0; idle <= 1'b0; end end endmodule
测试模块程序
`timescale 1ns / 1ps module testuart(clk, rst_n, dataout, wrsig); input clk; input rst_n; output[7:0] dataout; output wrsig; reg [7:0] dataout; reg wrsig; reg [7:0] cnt; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin cnt<=8'd0; wrsig<=1'b0; end else begin if(cnt == 254) begin dataout <= dataout + 8'd1; //每次数据加“1” wrsig <= 1'b1; //产生发送命令 cnt <= 8'd0; end else begin wrsig <= 1'b0; cnt <= cnt + 8'd1; end end end endmodule
创建并编译顶层文件
实验结果
相关文章推荐
- 【iCore4 双核心板_FPGA】例程十二:基于UART的ARM与FPGA通信实验
- [置顶] ARM开发(5)基于STM32的UART串口通信实验
- 【iCore3 双核心板_FPGA】实验二十五:NIOS II之UART串口通信实验
- 【iCore3 双核心板_FPGA】实验十六:基于SPI总线的ARM与FPGA通信实验
- 【iCore3 双核心板_FPGA】实验十七:基于I2C总线的ARM与FPGA通信实验
- 基于AVR的串口与PC机通信代码(uart8位数据)
- 【iCore1S 双核心板_FPGA】例程十五:基于I2C的ARM与FPGA通信实验
- UART通信实验-------深入浅出玩转FPGA(转)
- FPGA基础设计(三):UART串口通信
- 【iCore4 双核心板_FPGA】例程十三:基于SPI的ARM与FPGA通信实验
- 基于C8051F410的串口通信实验
- 基于FPGA的通信系统实验
- 基于fpga的串口通信实现
- 【iCore4 双核心板_FPGA】例程十四:基于I2C的ARM与FPGA通信实验
- UART通信实验-------深入浅出玩转FPGA(转)
- 基于FPGA的串口通信调试问题总结
- 【iCore1S 双核心板_FPGA】例程十六:基于SPI的ARM与FPGA通信实验
- 【iCore3 双核心板_FPGA】实验十五:基于USART的ARM与FPGA通信实验
- 基于FPGA的串口通信
- S3C2410 实验五—— 串口通信实验