首页 > 编程知识 正文

uart串口通信原理,fpga串口收发程序

时间:2023-05-05 10:03:11 阅读:110304 作者:3305

FPGA 18工程模块uart_Rx串行端口接收模块设计

模块名称: uart_byte_rx IP Core

主要功能:串行数据接收模块

实施(设计)处理)在波特率设定端口中使用查找表实施,在波特率时钟计数器的设定和波特率时钟计数器端口中,基于数值生成对应的时钟的同时,输入的Rs232_Rx信号

实验的目的:

1、UART通信协议在工业场景下的实现

2、使用ISSP调试

3、信号采样的概念,已经是数据的分析(判决分析)。

在正常环境或实验室环境下,对其中的每一位进行采样,一般每一位数据的中点最为稳定,一般应用中采集中间时间的数据即可,如下图所示

但在工业应用中,往往存在很强的电磁干扰,只采样一次就作为其数据的电平判断是不安全的,可能会认真采集被干扰的信号并产生错误结果,需要采用【多次采样求概率】的方式进行

以下是改良型的单比特数据接收方式的图像:

采用16倍采样,每个bit采样16次。 图中红色区域(左5次,右5次采样) ) ) )中,被认为是干扰的数据,中央的绿色部分被认为是稳定的信号) )共有6次) )。 比较这6次数据的概率,判断有效的信号就可以了。

设计文件:

moduleuart_byte_rx(clk,Rst_n,baud_set,Rs232_Rx,data_byte,Rx_Done ); 输入时钟; input Rst_n; input [2:0]baud_set; input Rs232_Rx; output reg [7:0]data_byte; output reg Rx_Done; reg s0_Rs232_Rx,s1_Rs232_Rx; //同步寄存器reg tmp0_Rs232_Rx、tmp1_Rs232_Rx; //数据寄存器reg [15:0]bps_DR; //分频计数器计数最大值reg [15:0]div_cnt; //分频计数器reg bps_clk; //reg [7:0]bps_cnt; reg uart_state; reg [ 2:0 ] r _ data _ byte [ 7:0 ]; reg [7:0] tmp_data_byte; reg [2:0] START_BIT,STOP_BIT; wire nedege; //同步寄存器,准稳定状态的always @ (posedgeclkornegedgerst _ n ) if (! Rst_n ) begins0_Rs232_Rx=1'b0; s1_Rs232_Rx=1'b0; endelse begins0_ RS232 _ rx=RS232 _ rx; s1_Rs232_Rx=s0_Rs232_Rx; end//数据寄存器always @ (posedgeclkornegedgerst _ n ) if (! Rst_n ) begintmp0_Rs232_Rx=1'b0; tmp1_Rs232_Rx=1'b0; endelsebegintmp0_ RS232 _ rx=S1 _ RS232 _ rx; tmp1_Rs232_Rx=tmp0_Rs232_Rx; endassign nedege=! tmp0_Rs232_Rx tmp1_Rs232_Rx; //1、波特率设置计数器模块always @ (posedgeclkornegedgerst _ n ) if (! Rst_n ) bps_DR=16'd324; ELSEBegincase(baud_set ) 0:bps_dr=16 ) D324; //9600bps1:bps_DR=16'd162; //19200bps2:bps_DR=16'd80; //38400bps3:bps_DR=16'd53; //57600bps4:bps_DR=16'd26; //115200 bps default : bps _ dr=16 ' d324; endcaseend//2,计数器计数模块always @ (posedgeclkornegedgerst _ n ) if (! Rst_n ) div_cnt=16'd0; ELSEif(UART_State ) Beginif ) div_CNT==bps_dr ) div_cnt=16'd0; elsediv_cnt=div_cnt 1'b1; endelsediv_cnt=16'd0; //3、计数器串口时钟bps_clk生成模块always @ (posedgeclkornegedgerst _ n ) if (! Rst_n ) bps_clk=1'b0; elseif(div_CNT==16'D1 ) bps_clk=1'b1; elsebps_clk=1'b0; //4、采样时钟bps counte

r 统计模块always@(posedge Clk or negedge Rst_n)if(!Rst_n)bps_cnt <= 8'd0;else if(bps_cnt == 8'd159 | (bps_cnt == 8'd12 && (START_BIT > 2)))bps_cnt <= 8'd0;else if(bps_clk)bps_cnt <= bps_cnt + 1'b1;elsebps_cnt <= bps_cnt;//5、采样完成信号Rx_Don处理模块always@(posedge Clk or negedge Rst_n)if(!Rst_n)Rx_Done <= 1'b0; else if(bps_cnt == 8'd159) //接收完成后,让 Rx_Done ==1'b1Rx_Done <= 1'b1;elseRx_Done <= 1'b0;// 会导致信号的延时一拍输出//always@(posedge Clk or negedge Rst_n)//if(!Rst_n)//data_byte <= 8'd0;//else if(bps_cnt == 8'd159)//data_byte <= tmp_data_byte;//else//data_byte <= data_byte;//6、采样数据处理(相加)模块always@(posedge Clk or negedge Rst_n)if(!Rst_n)beginSTART_BIT = 3'd0;r_data_byte[0] <= 3'd0;r_data_byte[1] <= 3'd0;r_data_byte[2] <= 3'd0;r_data_byte[3] <= 3'd0;r_data_byte[4] <= 3'd0;r_data_byte[5] <= 3'd0;r_data_byte[6] <= 3'd0;r_data_byte[7] <= 3'd0;STOP_BIT = 3'd0;endelse if(bps_clk)begincase(bps_cnt)0:beginSTART_BIT = 3'd0;r_data_byte[0] <= 3'd0;r_data_byte[1] <= 3'd0;r_data_byte[2] <= 3'd0;r_data_byte[3] <= 3'd0;r_data_byte[4] <= 3'd0;r_data_byte[5] <= 3'd0;r_data_byte[6] <= 3'd0;r_data_byte[7] <= 3'd0;STOP_BIT = 3'd0;end6,7,8,9,10,11:START_BIT <= START_BIT + s1_Rs232_Rx;22,23,24,25,26,27:r_data_byte[0] <= r_data_byte[0] + s1_Rs232_Rx;38,39,40,41,42,43:r_data_byte[1] <= r_data_byte[1] + s1_Rs232_Rx;54,55,56,57,58,59:r_data_byte[2] <= r_data_byte[2] + s1_Rs232_Rx;70,71,72,73,74,75:r_data_byte[3] <= r_data_byte[3] + s1_Rs232_Rx;86,87,88,89,90,91:r_data_byte[4] <= r_data_byte[4] + s1_Rs232_Rx;102,103,104,105,106,107:r_data_byte[5] <= r_data_byte[5] + s1_Rs232_Rx;118,119,120,121,122,123:r_data_byte[6] <= r_data_byte[6] + s1_Rs232_Rx;134,135,136,137,138,139:r_data_byte[7] <= r_data_byte[7] + s1_Rs232_Rx;150,151,152,153,154,155:STOP_BIT <= STOP_BIT + s1_Rs232_Rx;default:beginSTART_BIT = START_BIT;r_data_byte[0] <= r_data_byte[0];r_data_byte[1] <= r_data_byte[1];r_data_byte[2] <= r_data_byte[2];r_data_byte[3] <= r_data_byte[3];r_data_byte[4] <= r_data_byte[4];r_data_byte[5] <= r_data_byte[5];r_data_byte[6] <= r_data_byte[6];r_data_byte[7] <= r_data_byte[7];STOP_BIT = STOP_BIT;endendcaseend//7、采样数据存储模块always@(posedge Clk or negedge Rst_n)if(!Rst_n)data_byte <= 8'd0;else if(bps_cnt == 8'd159)begindata_byte[0] <= r_data_byte[0][2];data_byte[1] <= r_data_byte[1][2];data_byte[2] <= r_data_byte[2][2];data_byte[3] <= r_data_byte[3][2];data_byte[4] <= r_data_byte[4][2];data_byte[5] <= r_data_byte[5][2];data_byte[6] <= r_data_byte[6][2];data_byte[7] <= r_data_byte[7][2];end//8、采样状态信号处理模块always@(posedge Clk or negedge Rst_n)if(!Rst_n)uart_state <= 1'b0;else if(nedege)uart_state <= 1'b1;else if(Rx_Done || (bps_cnt == 8'd12 && (START_BIT > 2)))uart_state <= 1'b0;elseuart_state <= uart_state;endmodule

模块测试脚本文件

`timescale 1ns/1ns`define clk_period 20module uart_byte_rx_tb;reg Clk;reg Rst_n;reg Rs232_Rx;wire [7:0]data_byte_r;wire Rx_Done;reg [7:0]data_byte_t;reg send_en;reg [2:0]baud_set;wire Rs232_Tx;wire Tx_Done;wire uart_state;uart_byte_rx uart_byte_rx(.Clk(Clk),.Rst_n(Rst_n), .baud_set(baud_set), //baud_set -->reg.Rs232_Rx(Rs232_Tx),.data_byte(data_byte_r),.Rx_Done(Rx_Done));uart_byte_tx uart_byte_tx(.Clk(Clk),.Rst_n(Rst_n),.data_byte(data_byte_t),.send_en(send_en), .baud_set(baud_set),//baud_set --》reg .Rs232_Tx(Rs232_Tx), // Rs232_Tx --》 wire.Tx_Done(Tx_Done),.uart_state(uart_state)); // 模块连接分析 // uart_byte_tx.Rs232_Tx 连接到 uart_byte_rx. Rs232_Rx // 即让 uart_byte_tx发送,uart_byte_rx接收串口信号initial Clk = 1;always#(`clk_period/2)Clk = ~Clk;initial beginRst_n = 1'b0;// 1、设置复位信号data_byte_t = 8'd0;// 设置数据位send_en = 1'd0;// uart_byte_tx.send_en 先暂时关闭baud_set = 3'd4;// 设置串口的发送模块和接收模块的波特率#(`clk_period*20 + 1 );Rst_n = 1'b1;//2、信号复位完成#(`clk_period*50);data_byte_t = 8'haa;//uart_byte_tx.data_byte_t 数据发送send_en = 1'd1; //开启发送信号#`clk_period;send_en = 1'd0; //关闭发送信号 @(posedge Tx_Done) //检测 uart_byte_tx.Tx_Done 信号的上升沿的到来#(`clk_period*5000);data_byte_t = 8'h55;send_en = 1'd1;#`clk_period;send_en = 1'd0;@(posedge Tx_Done)#(`clk_period*5000);$stop;endendmodule

设计uart_rx_top的顶层文件

module uart_rx_top(Clk,Rst_n,Rs232_Rx);input Clk;input Rst_n;input Rs232_Rx;reg [7:0]data_rx_r;wire [7:0]data_rx;wire Rx_Done;uart_byte_rx uart_byte_rx(.Clk(Clk),.Rst_n(Rst_n),.baud_set(3'd0),.Rs232_Rx(Rs232_Rx),.data_byte(data_rx),.Rx_Done(Rx_Done));issp issp(.probe(data_rx_r),.source());//该always块主要是用于issp读取数据的模块always@(posedge Clk or negedge Rst_n)if(!Rst_n)data_rx_r <= 8'd0; else if(Rx_Done) //获取到Rx_Done信号,数据data_rx_r进行更新data_rx_r <= data_rx;elsedata_rx_r <= data_rx_r; //保持不变endmodule

数据接收调试:

In-system Sources and Probes Editor 开启连续数据读取模式

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