当前位置:   article > 正文

uart串口通信传输协议_串口通信协议 uart_bdii20

串口通信协议 uart_bdii20

一、Uart串口通信

        uart串口通信是一种异步串行全双工通信方式,tx端用于数据发送;rx端用于数据接收。信号线在空闲时为高电平。

        异步通信是按字符传输的。每传输一个字符就用起始位来收、发双方的同步。不会因收发双方的时钟频率的小的偏差导致错误。这种传输方式利用每一帧的起、止信号来建立发送与接收之间的同步。特点是:每帧内部各位均采用固定的时间间隔,而帧与帧之间的间隔时随即的。接收机完全靠每一帧的起始位和停止位来识别字符时正在进行传输还是传输结束。uart也是异步通信方式,数据发送会包装成数据帧的形式发送,数据帧的格式为:

        空闲时间为高电平,故rx端接收到低电平时,表示有数据开始发送,再根据波特率对数据进行接收。波特率:每秒传输二进制数据的位数,单位bps。

                若波特率为115200bps,即代表一秒钟需要传输115200个bit数据。

                1s=10e9ns,50MHz时钟周期为20ns,则传输一个bit所需的时间为

                                10e9/115200=8681ns

                则传输一个bit需要的时钟周期为8681/20=434个时钟周期。

        数据位的传输是串行从低位到高位传输,接收到的数据暂时存储在寄存器中,待接收完1字节的数据,通过串并转换保存接收到的数据。发送时通过tx信号线按照设置好的比特率将数据发送出去,数据发送仍要按照数据帧发送,先发送起始位,再从低位到高位发送数据。

        奇偶校验位:数据位加上校验位后,使得“1”的位数为偶数(偶校验)或者奇数(奇校验)。(一般都是无奇偶校验位的。)

        停止位:数据位传输完成后都会发送停止位,标志一个传输已经完成。(默认1位,可选择1.5位、2位。)

二、Verilog 代码

1.发送模块

  1. module uart_tx(
  2. input clk, //系统时钟
  3. input rst_n, //系统复位信号
  4. input [2:0]baud_set, //波特率选择信号
  5. input [7:0]data_byte, //并行数据
  6. input send_en, //发送使能信号
  7. output reg rs_Tx, //发送串行数据
  8. output reg tx_state, //uart正在发送信号
  9. output reg tx_done //发送完成信号
  10. );
  11. reg [15:0]baud_temp; //波特率
  12. reg [15:0]baud_cnt; //波特率分频器
  13. reg baud_clk; //波特率时钟
  14. reg [3:0]baud_clk_cnt; //波特率时钟计数器
  15. //波特率选择
  16. always @(posedge clk or negedge rst_n)begin
  17. if(!rst_n)
  18. baud_temp <= 3'd0;
  19. else begin
  20. case(baud_set)
  21. 3'd0:baud_temp <= 16'd5207; //波特率9600bps
  22. 3'd1:baud_temp <= 16'd2603; //波特率19200bps
  23. 3'd2:baud_temp <= 16'd1301; //波特率38400bps
  24. 3'd3:baud_temp <= 16'd867; //波特率57600bps
  25. 3'd4:baud_temp <= 16'd433; //波特率115200bps
  26. default: baud_temp <= 16'd5207;
  27. endcase
  28. end
  29. end
  30. //波特率分频计数器
  31. always @(posedge clk or negedge rst_n)begin
  32. if(!rst_n)
  33. baud_cnt <= 16'd0;
  34. else if(tx_state)begin //开始发送后波特率分频计数器开始工作
  35. if(baud_cnt == baud_temp)
  36. baud_cnt <= 16'd0;
  37. else
  38. baud_cnt <= baud_cnt + 1'b1;
  39. end
  40. else
  41. baud_cnt <= 16'd0;
  42. end
  43. //生成波特率时钟
  44. always @(posedge clk or negedge rst_n)begin
  45. if(!rst_n)
  46. baud_clk <= 1'b0;
  47. else if(baud_cnt == 1'b1)
  48. baud_clk <= 1'b1;
  49. else
  50. baud_clk <= 1'b0;
  51. end
  52. //对波特率时钟进行计数
  53. always @(posedge clk or negedge rst_n)begin
  54. if(!rst_n)
  55. baud_clk_cnt <= 4'd0;
  56. else if(baud_clk_cnt == 4'd11)
  57. baud_clk_cnt <= 4'd0;
  58. else if(baud_clk)
  59. baud_clk_cnt <= baud_clk_cnt + 1'b1;
  60. else
  61. baud_clk_cnt <= baud_clk_cnt;
  62. end
  63. //发送完成标志
  64. always @(posedge clk or negedge rst_n)begin
  65. if(!rst_n)
  66. tx_done <= 1'b0;
  67. else if(baud_clk_cnt == 4'd11) //波特率计数器记到4'd11时,发送完成
  68. tx_done <= 1'd1;
  69. else
  70. tx_done <= 1'd0;
  71. end
  72. //正在发送标志
  73. always @(posedge clk or negedge rst_n)begin
  74. if(!rst_n)
  75. tx_state <= 1'b0;
  76. else if(send_en) //发送使能拉高时,发送开始
  77. tx_state <= 1'b1;
  78. else if(baud_clk_cnt == 4'd11)
  79. tx_state <= 1'd0;
  80. else
  81. tx_state <= tx_state;
  82. end
  83. //数据寄存
  84. reg [7:0]data_byte_r;
  85. always @(posedge clk or negedge rst_n)begin
  86. if(!rst_n)
  87. data_byte_r <= 8'd0;
  88. else if(send_en)
  89. data_byte_r <= data_byte;
  90. else
  91. data_byte_r <= data_byte_r;
  92. end
  93. //并行数据转变成串行发送
  94. always @(posedge clk or negedge rst_n)begin
  95. if(!rst_n)
  96. rs_Tx <= 1'b0;
  97. else begin
  98. case(baud_clk_cnt)
  99. 0:rs_Tx <= 1'b1;
  100. 1:rs_Tx <= 1'b0;
  101. 2:rs_Tx <= data_byte_r[0];
  102. 3:rs_Tx <= data_byte_r[1];
  103. 4:rs_Tx <= data_byte_r[2];
  104. 5:rs_Tx <= data_byte_r[3];
  105. 6:rs_Tx <= data_byte_r[4];
  106. 7:rs_Tx <= data_byte_r[5];
  107. 8:rs_Tx <= data_byte_r[6];
  108. 9:rs_Tx <= data_byte_r[7];
  109. 10:rs_Tx <= 1'b1;
  110. endcase
  111. end
  112. end
  113. endmodule
  1. `timescale 1ns/1ps
  2. `define clk_period 20
  3. module uart_tx_tb();
  4. reg clk;
  5. reg rst_n;
  6. reg [2:0]baud_set;
  7. reg [7:0]data_byte;
  8. reg send_en;
  9. wire rs_Tx;
  10. wire tx_state;
  11. wire tx_done;
  12. uart_tx u1(
  13. .clk(clk),
  14. .rst_n(rst_n),
  15. .baud_set(baud_set),
  16. .data_byte(data_byte),
  17. .send_en(send_en),
  18. .rs_Tx(rs_Tx),
  19. .tx_state(tx_state),
  20. .tx_done(tx_done)
  21. );
  22. initial clk = 0;
  23. always #(`clk_period/2)clk = ~clk;
  24. initial begin
  25. rst_n = 1'b0;
  26. data_byte = 8'd0;
  27. send_en = 1'b0;
  28. baud_set = 3'd4;
  29. #(`clk_period*20+1)
  30. rst_n = 1'b1;
  31. #(`clk_period*50);
  32. data_byte = 8'hae;
  33. send_en = 1'b1;
  34. #`clk_period;
  35. send_en = 0;
  36. @(posedge tx_done)
  37. #(`clk_period*5000);
  38. data_byte = 8'hbc;
  39. send_en = 1'b1;
  40. #`clk_period;
  41. send_en = 1'b0;
  42. @(posedge tx_done)
  43. #(`clk_period*5000);
  44. $stop;
  45. end
  46. endmodule

仿真图

 2.接收模块

  1. module uart_rx(
  2. input clk, //系统时钟
  3. input rst_n, //系统复位信号
  4. input rs_rx, //输入接收到的串行数据
  5. input reg[2:0]baud_set, //波特率选择信号
  6. output reg[7:0]r_data_byte, //输出并行数据
  7. output reg rx_done //接收完成信号
  8. );
  9. reg rs_rx_r1,rs_rx_r2; //同步寄存器
  10. reg rs_rx_temp1,rs_rx_temp2; //数据寄存器
  11. wire nedege; //判断起始信号
  12. //此时输入信号相对与系统时钟是异步信号,需要对其进行同步处理
  13. //同步寄存器,消除亚稳态
  14. always @(posedge clk or negedge rst_n)begin
  15. if(!rst_n)begin
  16. rs_rx_r1 <= 1'b0;
  17. rs_rx_r2 <= 1'b0;
  18. end
  19. else begin
  20. rs_rx_r1 <= rs_rx;
  21. rs_rx_r2 <= rs_rx_r1;
  22. end
  23. end
  24. //数据寄存
  25. always @(posedge clk or negedge rst_n)begin
  26. if(!rst_n)begin
  27. rs_rx_temp1 <= 1'b0;
  28. rs_rx_temp2 <= 1'b0;
  29. end
  30. else begin
  31. rs_rx_temp1 <= rs_rx_r2;
  32. rs_rx_temp2 <= rs_rx_temp1;
  33. end
  34. end
  35. assign nedege = (!rs_rx_temp1) && rs_rx_temp2; //若为1,则输入了起始位
  36. /*
  37. 实际传输中,会有许多干扰,只采样一次的数据是很不可靠的。这里将每个数据平均分为16段,采样中间6段较为平稳的数据,进行累加,
  38. 1-3'b001,2-3'b010,3-3'b011,4-3'b100,5-3'b101,6-3'b110.
  39. 可见当采样数据有一半的状态为1时,最高位都为1,故以最高位来判断此时传输的数据
  40. */
  41. reg [15:0]baud_temp; //波特率
  42. reg [15:0]baud_cnt; //波特率分频计数器
  43. reg baud_clk; //波特率时钟
  44. reg [7:0]baud_clk_cnt; //波特率时钟计数器
  45. //波特率选择
  46. //相比较发送模式的采样频率,接收模式的采样频率是其的16
  47. always @(posedge clk or negedge rst_n)begin
  48. if(!rst_n)
  49. baud_temp <= 16'd324;
  50. else begin
  51. case(baud_set)
  52. 0:baud_temp <= 16'd324;
  53. 1:baud_temp <= 16'd162;
  54. 2:baud_temp <= 16'd80;
  55. 3:baud_temp <= 16'd53;
  56. 4:baud_temp <= 16'd26;
  57. default : baud_temp <= 16'd324;
  58. endcase
  59. end
  60. end
  61. reg rx_state; //正在传输信号
  62. //正在传输数据时baud_cnt开始计数
  63. always @(posedge clk or negedge rst_n)begin
  64. if(!rst_n)
  65. baud_cnt <= 16'd0;
  66. else if(rx_state)begin
  67. if(baud_cnt == baud_temp)
  68. baud_cnt <= 16'd0;
  69. else
  70. baud_cnt <= baud_cnt + 1'b1;
  71. end
  72. else
  73. baud_cnt <= 16'd0;
  74. end
  75. //
  76. always @(posedge clk or negedge rst_n)begin
  77. if(!rst_n)
  78. baud_clk <= 1'b0;
  79. else if(baud_cnt == 16'd1)
  80. baud_clk <= 1'b1;
  81. else
  82. baud_clk <= 1'b0;
  83. end
  84. reg [2:0]data_byte_r [7:0];
  85. reg [2:0]START_BIT,STOP_BIT;
  86. always @(posedge clk or negedge rst_n)begin
  87. if(!rst_n)
  88. baud_clk_cnt <= 8'd0;
  89. else if(baud_clk_cnt == 8'd159 || ((baud_clk_cnt == 8'd12) && (START_BIT > 2)))//baud_clk_cnt计满时、或者是起始信号不为1时清零;
  90. baud_clk_cnt <= 8'd0;
  91. else if(baud_clk)
  92. baud_clk_cnt <= baud_clk_cnt + 1'b1;
  93. else
  94. baud_clk_cnt <= baud_clk_cnt;
  95. end
  96. //传输完成信号
  97. always @(posedge clk or negedge rst_n)begin
  98. if(!rst_n)
  99. rx_done <= 1'b0;
  100. else if(baud_clk_cnt == 8'd159)
  101. rx_done <= 1'b1;
  102. else
  103. rx_done <= 1'b0;
  104. end
  105. //正在传输信号
  106. always @(posedge clk or negedge rst_n)begin
  107. if(!rst_n)
  108. rx_state <= 1'b0;
  109. else if(nedege)
  110. rx_state <= 1'b1;
  111. else if(rx_done || (baud_clk_cnt == 8'd12 &&(START_BIT>2)))
  112. rx_state <= 1'b0;
  113. else
  114. rx_state <= rx_state;
  115. end
  116. //计数完成时,串行数据转成并行数据
  117. always @(posedge clk or negedge rst_n)begin
  118. if(!rst_n)
  119. r_data_byte <= 8'b0;
  120. else if(baud_clk_cnt == 8'd159)begin
  121. r_data_byte[0] <= data_byte_r[0][2];
  122. r_data_byte[1] <= data_byte_r[1][2];
  123. r_data_byte[2] <= data_byte_r[2][2];
  124. r_data_byte[3] <= data_byte_r[3][2];
  125. r_data_byte[4] <= data_byte_r[4][2];
  126. r_data_byte[5] <= data_byte_r[5][2];
  127. r_data_byte[6] <= data_byte_r[6][2];
  128. r_data_byte[7] <= data_byte_r[7][2];
  129. end
  130. else begin
  131. r_data_byte[0] <= data_byte_r[0];
  132. r_data_byte[1] <= data_byte_r[1];
  133. r_data_byte[2] <= data_byte_r[2];
  134. r_data_byte[3] <= data_byte_r[3];
  135. r_data_byte[4] <= data_byte_r[4];
  136. r_data_byte[5] <= data_byte_r[5];
  137. r_data_byte[6] <= data_byte_r[6];
  138. r_data_byte[7] <= data_byte_r[7];
  139. end
  140. end
  141. always @(posedge clk or negedge rst_n)begin
  142. if(!rst_n)begin
  143. START_BIT <= 3'd0;
  144. data_byte_r[0] <= 3'd0;
  145. data_byte_r[1] <= 3'd0;
  146. data_byte_r[2] <= 3'd0;
  147. data_byte_r[3] <= 3'd0;
  148. data_byte_r[4] <= 3'd0;
  149. data_byte_r[5] <= 3'd0;
  150. data_byte_r[6] <= 3'd0;
  151. data_byte_r[7] <= 3'd0;
  152. end
  153. else if(baud_clk)begin
  154. case(baud_clk_cnt)
  155. 0:begin
  156. START_BIT <= 3'd0;
  157. data_byte_r[0] <= 3'd0;
  158. data_byte_r[1] <= 3'd0;
  159. data_byte_r[2] <= 3'd0;
  160. data_byte_r[3] <= 3'd0;
  161. data_byte_r[4] <= 3'd0;
  162. data_byte_r[5] <= 3'd0;
  163. data_byte_r[6] <= 3'd0;
  164. data_byte_r[7] <= 3'd0;
  165. STOP_BIT <= 3'd0;
  166. end
  167. 6,7,8,9,10,11:START_BIT <= START_BIT + rs_rx_r2;
  168. 22,23,24,25,26,27:data_byte_r[0] <= data_byte_r[0] + rs_rx_r2;
  169. 38,39,40,41,42,43:data_byte_r[1] <= data_byte_r[1] + rs_rx_r2;
  170. 54,55,56,57,58,59:data_byte_r[2] <= data_byte_r[2] + rs_rx_r2;
  171. 70,71,72,73,74,75:data_byte_r[3] <= data_byte_r[3] + rs_rx_r2;
  172. 86,87,88,89,90,91:data_byte_r[4] <= data_byte_r[4] + rs_rx_r2;
  173. 102,103,104,105,106,107:data_byte_r[5] <= data_byte_r[5] + rs_rx_r2;
  174. 118,119,120,121,122,123:data_byte_r[6] <= data_byte_r[6] + rs_rx_r2;
  175. 134,135,136,137,138,139:data_byte_r[7] <= data_byte_r[7] + rs_rx_r2;
  176. 150,151,152,153,154,155:STOP_BIT <= STOP_BIT + rs_rx_r2;
  177. default : begin
  178. START_BIT <= START_BIT;
  179. data_byte_r[0] <= data_byte_r[0];
  180. data_byte_r[1] <= data_byte_r[1];
  181. data_byte_r[2] <= data_byte_r[2];
  182. data_byte_r[3] <= data_byte_r[3];
  183. data_byte_r[4] <= data_byte_r[4];
  184. data_byte_r[5] <= data_byte_r[5];
  185. data_byte_r[6] <= data_byte_r[6];
  186. data_byte_r[7] <= data_byte_r[7];
  187. STOP_BIT <= STOP_BIT;
  188. end
  189. endcase
  190. end
  191. end
  192. endmodule
  1. `timescale 1ns/1ps
  2. `define clk_period 20
  3. module uart_rx_tb();
  4. reg clk;
  5. reg rst_n;
  6. reg send_en;
  7. reg [2:0]baud_set;
  8. reg rs_rx;
  9. wire rs_Tx;
  10. wire tx_state;
  11. wire tx_done;
  12. wire rx_done;
  13. reg [7:0]data_byte;
  14. wire [7:0]r_data_byte;
  15. uart_tx u1(
  16. .clk(clk),
  17. .rst_n(rst_n),
  18. .baud_set(baud_set),
  19. .data_byte(data_byte),
  20. .send_en(send_en),
  21. .rs_Tx(rs_Tx),
  22. .tx_state(tx_state),
  23. .tx_done(tx_done)
  24. );
  25. uart_rx u2(
  26. .clk(clk),
  27. .rst_n(rst_n),
  28. .rs_rx(rs_Tx),
  29. .baud_set(baud_set),
  30. .r_data_byte(r_data_byte),
  31. .rx_done(rx_done)
  32. );
  33. initial clk = 1;
  34. always #(`clk_period/2)clk = ~clk;
  35. initial begin
  36. rst_n = 1'b0;
  37. data_byte <= 8'd0;
  38. send_en = 1'b0;
  39. baud_set = 4'd4;
  40. #(`clk_period*20+1);
  41. rst_n = 1'b1;
  42. #(`clk_period*500);
  43. data_byte = 8'haa;
  44. send_en = 1;
  45. #(`clk_period);
  46. send_en = 0;
  47. @(posedge tx_done)
  48. #(`clk_period*500);
  49. data_byte = 8'h55;
  50. send_en = 1;
  51. #(`clk_period);
  52. send_en = 0;
  53. @(posedge tx_done)
  54. #(`clk_period*5000);
  55. $stop;
  56. end
  57. endmodule

仿真图

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/467882
推荐阅读
相关标签
  

闽ICP备14008679号