uart串口环回(加校验位)

uart串口环回(加校验位)根据传输的数据计算出一个校验位和我们传输的校验位做对比

大家好,欢迎来到IT知识分享网。

一.校验位原理

  • 校验分为无校验位,奇校验位和偶校验位

1.奇校验

  • 数据位中1的个数为奇数,则校验位为0,否则校验位为1

2.偶校验

  • 数据为中1的个数为偶数,则校验位为0,否则校验位为1

二.设计思路

  • 根据传输的数据计算出一个校验位和我们传输的校验位做对比。使能信号需要保证在传输的校验位和计算的校验位相等时才有效
  • 根据无校验位,奇校验位,偶校验位三种情况,需要改变状态转移图
  • uart_tx
    在这里插入图片描述
  • uart_rx
    在这里插入图片描述

三.代码

1.uart_tx

/功能介绍* Date : 2023年8月16日17:07:11 Author : Alegg xy. Version : 2.0 Description: FPGA向上位机发送数据【8bit变1bit(波形)】 */ //---------<模块及端口声名>------------------------------------------------------ module uart_tx( input clk , input rst_n , input [7:0] tx_data , input tx_data_vld, output ready , output reg tx ); //---------<参数定义>--------------------------------------------------------- parameter MAX_BPS = ; parameter CLOCK = 50_000_000; parameter MAX_1bit = CLOCK/MAX_BPS;//1bit要计434次 parameter CHECK_BIT = "None";//None无校验,Odd奇校验,Even偶校验 //状态机参数定义 localparam IDLE = 'b00001,//空闲状态 START = 'b00010,//起始位 DATA = 'b00100,//数据位 CHECK = 'b01000,//校验位 STOP = 'b10000;//停止位 //---------<内部信号定义>----------------------------------------------------- reg [4:0] cstate ;//现态 reg [4:0] nstate ;//次态 wire IDLE_START; wire START_DATA; wire DATA_CHECK; wire CHECK_STOP; wire STOP_IDLE; reg [8:0] cnt_baud ;//波特计数器,波特率 wire add_cnt_baud ; wire end_cnt_baud ; reg [2:0] cnt_bit ;//bit计数器,起始位1bit,数据位8bit,结束位1bit wire add_cnt_bit ; wire end_cnt_bit ; reg [3:0] bit_max;//bit最大值,复用需要考察每个状态的bit值 reg [7:0] tx_data_r; wire check_val; //计434次 always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_baud <= 'd0; end else if(add_cnt_baud)begin if(end_cnt_baud)begin cnt_baud <= 'd0; end else begin cnt_baud <= cnt_baud + 1'd1; end end end assign add_cnt_baud = cstate != IDLE; assign end_cnt_baud = add_cnt_baud && cnt_baud == MAX_1bit - 1'd1; //bit计数器 always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_bit <= 'd0; end else if(add_cnt_bit)begin if(end_cnt_bit)begin cnt_bit <= 'd0; end else begin cnt_bit <= cnt_bit + 1'd1; end end end assign add_cnt_bit = end_cnt_baud; assign end_cnt_bit = add_cnt_bit && cnt_bit == bit_max -1'd1; //计数器复用 always @(*)begin case (cstate) IDLE :bit_max = 'd0; START:bit_max = 'd1;//起始位1bit DATA :bit_max = 'd8;//数据位7bit CHECK:bit_max = 'd1;//校验位1bit STOP :bit_max = 'd1;//结束位1bit default: bit_max = 'd0; endcase end assign IDLE_START = (cstate == IDLE) && tx_data_vld;//考察到开始传输信号 assign START_DATA = (cstate == START) && end_cnt_bit;//计1bit数据 assign DATA_STOP = (cstate == DATA) && end_cnt_bit && CHECK_BIT == "None"; assign DATA_CHECK = (cstate == DATA) && end_cnt_bit;//计8bit数据 assign CHECK_STOP = (cstate ==CHECK) && end_cnt_bit;//计1bit数据 assign STOP_IDLE = (cstate == STOP) && end_cnt_bit;//计1bit数据 //第一段:时序逻辑描述状态转移 always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cstate <= IDLE; end else begin cstate <= nstate; end end //第二段:组合逻辑描述状态转移规律和状态转移条件 always @(*) begin case(cstate) IDLE :begin if (IDLE_START) begin nstate = START; end else begin nstate = cstate; end end START :begin if (START_DATA) begin nstate = DATA; end else begin nstate = cstate; end end DATA :begin if (DATA_CHECK) begin nstate = CHECK; end else if (DATA_STOP) begin nstate = STOP; end else begin nstate = cstate; end end CHECK :begin if (CHECK_STOP) begin nstate = STOP; end else begin nstate = cstate; end end STOP :begin if (STOP_IDLE) begin nstate = IDLE; end else begin nstate = cstate; end end default : nstate = cstate; endcase end //寄存一拍 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin tx_data_r <= 'd0; end else if (tx_data_vld) begin tx_data_r <= tx_data; end else begin tx_data_r <= tx_data_r; end end assign check_val = (CHECK_BIT == "Odd") ? ~^tx_data_r : ^tx_data_r; //第三段:描述输出,时序逻辑或组合逻辑皆可 always @(*)begin case (cstate) IDLE : tx = 1'b1; START: tx = 1'b0;//起始位为0 DATA : tx = tx_data_r[cnt_bit]; CHECK: tx = check_val; STOP : tx = 1'b1;//结束位为1 default: tx = 1'b1; endcase end assign ready = cstate == IDLE;//当状态为IDLE时,表示tx端可以接收数据 endmodule 

2.uart_rx

/功能介绍* Date : 2023年8月16日18:25:03 Author : Alegg xy. Version : 1.0 Description: FPGA收上位机发来的数据【1bit(波形)变8bit】 */ //---------<模块及端口声名>------------------------------------------------------ module uart_rx( input clk , input rst_n , input rx , output rx_data_vld, output [7:0] rx_data ); //---------<参数定义>--------------------------------------------------------- parameter MAX_BPS = ; parameter CLOCK = 50_000_000; parameter MAX_1bit = CLOCK/MAX_BPS;//1bit要计434次 parameter CHECK_BIT = "None";//None无校验,Odd奇校验,Even偶校验 //状态机参数定义 localparam IDLE = 'b0001,//空闲状态 START = 'b0010,//起始位 DATA = 'b0100,//数据位 CHECK = 'b1000; //---------<内部信号定义>----------------------------------------------------- reg [3:0] cstate ;//现态 reg [3:0] nstate ;//次态 wire IDLE_START; wire START_DATA; wire DATA_IDLE; wire DATA_CHECK; wire CHECK_IDLE; reg [8:0] cnt_baud ;//波特计数器,波特率 wire add_cnt_baud ; wire end_cnt_baud ; reg [2:0] cnt_bit ;//bit计数器,起始位1bit,数据位8bit,结束位1bit wire add_cnt_bit ; wire end_cnt_bit ; reg [3:0] bit_max;//bit最大值,复用需要考察每个状态的bit值 reg [7:0] rx_temp; reg rx_check; wire check_val; reg rx_r1; reg rx_r2; wire rx_nege; //打两拍 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin rx_r1 <= 1; rx_r2 <= 1; end else begin rx_r1 <= rx; rx_r2 <= rx_r1; end end assign rx_nege = ~rx_r1 && rx_r2; //计434次 always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_baud <= 'd0; end else if(add_cnt_baud)begin if(end_cnt_baud)begin cnt_baud <= 'd0; end else begin cnt_baud <= cnt_baud + 1'd1; end end end assign add_cnt_baud = cstate != IDLE; assign end_cnt_baud = add_cnt_baud && cnt_baud == MAX_1bit - 1'd1; //bit计数器 always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_bit <= 'd0; end else if(add_cnt_bit)begin if(end_cnt_bit)begin cnt_bit <= 'd0; end else begin cnt_bit <= cnt_bit + 1'd1; end end end assign add_cnt_bit = end_cnt_baud; assign end_cnt_bit = add_cnt_bit && cnt_bit == bit_max -1'd1; //计数器复用 always @(*)begin case (cstate) IDLE :bit_max = 'd0; START:bit_max = 'd1;//起始位1bit DATA :bit_max = 'd8;//数据位8bit CHECK:bit_max = 'd1; default: bit_max = 'd0; endcase end assign IDLE_START = (cstate == IDLE) && rx_nege;//识别到起始位0 assign START_DATA = (cstate == START) && end_cnt_bit;//计1bit数据 assign DATA_IDLE = (cstate == DATA) && end_cnt_bit && CHECK_BIT == "None";//计8bit数据 assign DATA_CHECK = (cstate == DATA) && end_cnt_bit; assign CHECK_IDLE = (cstate == CHECK) && end_cnt_bit; //第一段:时序逻辑描述状态转移 always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cstate <= IDLE; end else begin cstate <= nstate; end end //第二段:组合逻辑描述状态转移规律和状态转移条件 always @(*) begin case(cstate) IDLE :begin if (IDLE_START) begin nstate = START; end else begin nstate = cstate; end end START :begin if (START_DATA) begin nstate = DATA; end else begin nstate = cstate; end end DATA :begin if (DATA_IDLE) begin nstate = IDLE; end else if (DATA_CHECK) begin nstate = CHECK; end else begin nstate = cstate; end end CHECK:begin if (CHECK_IDLE) begin nstate = IDLE; end else begin nstate = cstate; end end default : nstate = IDLE; endcase end //接受校验位 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin rx_check <= 0; end else if (cstate == CHECK && cnt_baud == MAX_1bit >>1) begin rx_check <= rx_r1; end end //计算校验位 assign check_val = (CHECK_BIT == "Odd") ? ~^rx_temp : ^rx_temp; //第三段:描述输出,时序逻辑或组合逻辑皆可 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin rx_temp <= 0; end else if (cstate == DATA && cnt_baud == MAX_1bit >> 1) begin//电平中间值采样,边沿采样容易出错 rx_temp[cnt_bit] <= rx_r1; end else begin rx_temp <= rx_temp; end end assign rx_data = rx_temp; assign rx_data_vld = (CHECK_BIT == "None") ? DATA_IDLE :(CHECK_IDLE && (check_val == rx_check)) ? 1 : 0; endmodule 
  • 其中可以通过top重定义MAX_BPS和CHECK_BIT来修改波特率和校验位
    在这里插入图片描述

四.仿真

  • 仿真有多种情况
    在这里插入图片描述

1.无校验位

1.1无校验位总仿真

在这里插入图片描述

1.2无校验位rx

在这里插入图片描述

1.3无校验位tx

在这里插入图片描述

2.奇校验位

2.1奇校验位正确总仿真

在这里插入图片描述

2.2奇校验位正确rx

在这里插入图片描述

2.3奇校验位正确tx

在这里插入图片描述

2.4奇校验位错误总仿真

在这里插入图片描述

2.5奇校验位错误rx

在这里插入图片描述

2.6奇校验位错误tx

在这里插入图片描述

3.偶校验位

2.1偶校验位正确总仿真

在这里插入图片描述

2.2偶校验位正确rx

在这里插入图片描述

2.3偶校验位正确tx

在这里插入图片描述

2.4偶校验位错误总仿真

在这里插入图片描述

2.5偶校验位错误rx

在这里插入图片描述

2.6偶校验位错误tx

在这里插入图片描述

五.效果

5.1如何在串口助手中设置校验位

  • 选择左下角的更多串口设置后弹窗中调整校验位(None:无校验位、Odd:奇校验位、Even:偶校验位)
    在这里插入图片描述

5.2奇校验

在这里插入图片描述

  • 这里代码中设置奇校验,串口设置无校验位时会有一些问题,大家如果发现了我的错误在哪可以私信或者评论我一下,谢谢大家了

5.3偶校验

在这里插入图片描述

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/121171.html

(0)
上一篇 2025-10-25 10:20
下一篇 2025-10-25 10:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信