首页 > 编程知识 正文

fpga实现uart串口通信,fpga uart接收

时间:2023-05-05 13:45:53 阅读:241663 作者:717

简介

今天购买了AXLINX AX7020的开发板,从今天开始每一个例程都要做文档记录,为自己加油。
本实验,基于ALINX AX7020开发板,芯片为xc7z020clg400-2。开发板输入时钟为50MHz。

1.UART协议介绍

UART是一种通用串行数据总线,用于异步通信。UART能实现双向通信,在嵌入式设计中,常用于主机与辅助设备通信。UART包括RS232、RS449、RS423等接口标准规范和总线标准规范,即UART是异步串行通信口的总称。而RS232等式对应各种异步串行通信口的接口标准和总线标准,它们规定了通信口的电气特性、传输速率、连接特性和接口的机械特性等内容。实际上是属于通信网络中的物理层(最底层)的概念,与通信协议并没有关系。

UART传输中,相关名词解释如下:
(1)波特率:每秒钟发送的符号数
(2)起始位:先发出一个逻辑0的信号,表示传输数据的开始
(3)数据位:衡量通信中实际数据位的参数。标准的数据位可以是5、7、8位,从最低位开始传输
(4)奇偶校验位:UART发送时,检查发送数据中1的个数,自动在奇偶校验位上添上1或0,用于发送数据的校验
数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。就比如传输“A”(01000001)为例:
当为奇数校验:“A”字符的8个bit位中有两个1,那么奇偶校验位为1才能满足1的个数为奇数(奇校验);
当为偶数校验:“A”字符的8个bit位中有两个1,那么奇偶校验位为0才能满足1的个数为偶数(偶校验);

(5)停止位:数据结束的标志,可以是1位、1.5位、2位的高电平
(6)空闲位:处于逻辑1的状态,表示当前线路上无数据传输

2.UART传输时序


**发送数据过程:**空闲状态,线路处于高电平,当收到发送数据指令后,拉低电平一个数据位的时间,接着数据按低位到高位依次发送,数据位发送完毕,接着发送奇偶校验位和停止位,停止位为高电平,一帧数据发送结束;
**接收数据过程:**空闲状态,线路处于高电平,当检测到线路的下降沿,说明线路有数据传输,按照约定的波特率从低位到高位接收数据,数据接收完毕后接着接收奇偶校验位并比较,看奇偶校验位是否正确,如果正确则通知接收端设备准备接收数据;

2.UART工程设计


UART_TOP模块中共包含三个子模块:
1、Baud_Clock模块用来产生115200的波特率时钟;
2、RX模块为接收(receive)模块,输入信号rx_pin为接收的序列数据,rx_ready为接收端的反压信号,只有当ready信号为高时才会输出rx_data数据,rx_valid用来表明什么时候rx_data有效。rx_erro输出接收的rx_pin序列的奇偶校验是否正确,0表示正确,1表示错误,若检验到错误,会要求发送端重发。
3、TX模块为发送(transmission)模块,输入信号为tx_data并行信号,tx_valid表示tx_data的有效性,tx_ready表示当前发送模块是否空闲;tx_pin为输出的串行数据,tx_erro为检错重发信号,当受到erro=1时就把ready=1拉高,重新发送上一次的数据;

3.RX模块(receive)

`timescale 1ns/1psmodule rx_control( input clk,//50MHz input rst_n, input baud_clk, input rx_pin, output rx_erro, input rx_ready, output rx_valid, output [6:0] rx_data ); parameter IDLE = 4'b0001, RECEIVE = 4'b0010, END = 4'b0100, ERRO = 4'b1000; reg [3:0] state_curt; //current state reg [3:0] state_next; //next state reg [3:0] count; reg [7:0] data; always@(posedge clk or negedge rst_n) begin if(!rst_n) state_curt <= IDLE; end always@(posedge baud_clk) begin state_curt <= state_next; end always@(*) begin case(state_curt) IDLE: if(rx_pin==0) state_next <= RECEIVE; RECEIVE: if(count==7) begin if((^data)==0) state_next <= END; else state_next <= ERRO; end else state_next <= state_next; END: if(rx_ready) state_next <= IDLE; else state_next <= END; ERRO: state_next <= IDLE; default : state_next <= IDLE; endcase end always@(posedge baud_clk) begin if(state_curt==RECEIVE) count <= count +1'b1; else count <= 32'd0; end always@(posedge baud_clk) begin if(state_curt==RECEIVE) begin data[7] <= rx_pin; data[6:0] <= data[7:1]; end else begin if(state_curt==END | state_curt==ERRO) data <= data; else data <= 8'b0; end end assign rx_erro = (state_curt == ERRO)? 1'b1:1'b0; assign rx_data = (state_curt == END )? data[6:0]:7'b0; assign rx_valid= (state_curt == END )? 1'b1:1'b0; endmodule 4.TX模块(transmission)

`timescale 1ns/1psmodule tx_control( input clk, input rst_n, input baud_clk, input tx_erro, output reg tx_pin, input tx_valid, input [6:0] tx_data, output tx_ready ); parameter IDLE = 4'b0001, START = 4'b0010, SEND = 4'b0100, END = 4'b1000; reg [3:0] state_curt; reg [3:0] state_next; reg [7:0] data; reg [7:0] r_data; reg [3:0] count; always@(posedge clk or negedge rst_n) begin if(!rst_n) state_curt <= IDLE; end always@(posedge baud_clk) begin state_curt <= state_next; end always@(*) begin case(state_curt) IDLE: if((tx_valid==1'b1)&(tx_erro==1'b0)) begin state_next <= START; r_data <= tx_data; end else state_next <= IDLE; START: state_next <= SEND; SEND: if(count==3'd7) state_next <= END; else state_next <= SEND; END: if((tx_valid==1'b1)&(tx_erro==1'b0)) begin state_next <= START; r_data <= tx_data; end else state_next <= IDLE; default: state_next <= IDLE; endcase end always@(posedge baud_clk) begin if(state_curt==SEND) count <= count + 1'b1; else count <= 4'b0; end assign tx_ready = ((state_curt==IDLE)|(state_curt==END))? 1'b1:1'b0; always@(posedge baud_clk) begin if(state_next==START) begin tx_pin <= 1'b0; data[6:0] <= r_data; data[7] <= ^r_data; end else begin if(state_next==SEND) begin tx_pin <= data[0]; data[6:0] <= data[7:1]; end else tx_pin <= 1'b1; end endendmodule 5.Baud_Clock模块 `timescale 1ns/1psmodule baud_clock( input clk, input rst_n, output baud_clk ); parameter CLK_FRE = 32'd50; parameter BAUD_RATE = 32'd115200;//波特率:1s传输的二进制码元个数 parameter CNT_NUM = CLK_FRE * 1000_000 / BAUD_RATE; reg [31:0] count; reg b_clk; always@(posedge clk or negedge rst_n) begin if(!rst_n) begin count <= 32'd0; b_clk <= 0; end else begin if(count == CNT_NUM-1) begin count <= 32'd0; b_clk <= 1; end else begin count <= count + 32'd1; b_clk <= 0; end end end assign baud_clk = b_clk;endmodule

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。