当前位置:   article > 正文

FPGA——UART串口通信_fpga uart串口通信

fpga uart串口通信

目   录

一、UART简介

二、收发模块时序图

2.1 接受模块

2.2 发送模块

三、整体逻辑框图

四、代码

4.1 接受模块

4.2 发送模块

4.3 环回模块

4.4 top模块


一、UART简介

        UART(Universal Asynchronous Receiver/Transmitter)是一种通用异步收发器,是计算机与外设之间进行串行通信的一种常见方式。UART能够将数据以比特流的形式从一个设备发送到另一个设备,常用于串行通信接口,如串行通信口(RS-232)。

        UART通过将数据分割成字节并在字节之间插入起始位、数据位、校验位和停止位的方式来进行数据传输。它使用异步通信模式,也就是说发送和接收设备的时钟不是同步的。发送方将数据按照固定的格式发送出去,接收方收到数据后,根据起始位和停止位来确定数据的边界,并通过校验位验证数据的准确性。

        UART可以在不同的波特率下进行通信,波特率定义了数据传输的速度。常见的波特率有9600、19200、38400等,可以根据需求进行设置。

        UART的优点是简单、可靠、灵活,可以适用于各种场景。缺点是通信速度相对较慢,并且需要占用较多的引脚。

二、收发模块时序图

2.1 接受模块

2.2 发送模块

三、整体逻辑框图

加入环回的目的是为了防止在发送的时候同时有接受导致数据的缺失,缺失的主要原因是在发送与接受模块的时序图中最后的结束是半个计数时间。

四、代码

4.1 接受模块

  1. `timescale 1ns / 1ps
  2. module uart_rw(
  3. input sys_clk,
  4. input sys_rst_n,
  5. input uart_rxd,
  6. output reg [7:0] uart_data,
  7. output reg uart_done
  8. );
  9. parameter CLK_FREQ = 50_000_000;
  10. parameter UART_BPS = 115200;
  11. localparam BPS_CNT = CLK_FREQ/UART_BPS;
  12. wire start_flag;
  13. reg uart_rxd_d0;
  14. reg uart_rxd_d1;
  15. reg rx_flag;
  16. reg [ 7:0] uart_data_r;
  17. reg [ 3:0] rx_cnt;
  18. reg [11:0] clk_cnt;
  19. assign start_flag = uart_rxd_d0 & (~uart_rxd_d1);
  20. always@(posedge sys_clk or negedge sys_rst_n)
  21. if(!sys_rst_n) begin
  22. uart_rxd_d0 <= 1'b1;
  23. uart_rxd_d1 <= 1'b1;
  24. end
  25. else begin
  26. uart_rxd_d0 <= uart_rxd;
  27. uart_rxd_d1 <= uart_rxd_d0;
  28. end
  29. always@(posedge sys_clk or negedge sys_rst_n)
  30. if(!sys_rst_n)
  31. rx_flag <= 1'b0;
  32. else if(start_flag)
  33. rx_flag <= 1'b1;
  34. else if((clk_cnt == BPS_CNT/2) && (rx_cnt == 4'd9))
  35. rx_flag <= 1'b0;
  36. always@(posedge sys_clk or negedge sys_rst_n)
  37. if(!sys_rst_n)
  38. clk_cnt <= 12'd0;
  39. else if(rx_flag) begin
  40. if(clk_cnt < BPS_CNT - 1)
  41. clk_cnt <= clk_cnt + 1'b1;
  42. else
  43. clk_cnt <= 12'd0;
  44. end
  45. else
  46. clk_cnt <= 12'd0;
  47. always@(posedge sys_clk or negedge sys_rst_n)
  48. if(!sys_rst_n)
  49. rx_cnt <= 4'd0;
  50. else if(rx_flag) begin
  51. if(clk_cnt == BPS_CNT - 1)
  52. rx_cnt <= rx_cnt + 1'b1;
  53. end
  54. else
  55. rx_cnt <= 4'd0;
  56. always@(posedge sys_clk or negedge sys_rst_n)
  57. if(!sys_rst_n)
  58. uart_data_r <= 8'd0;
  59. else if(rx_flag) begin
  60. if(clk_cnt == BPS_CNT/2) begin
  61. case(rx_cnt)
  62. 4'd1:uart_data_r[0] <= uart_rxd_d1;
  63. 4'd2:uart_data_r[1] <= uart_rxd_d1;
  64. 4'd3:uart_data_r[2] <= uart_rxd_d1;
  65. 4'd4:uart_data_r[3] <= uart_rxd_d1;
  66. 4'd5:uart_data_r[4] <= uart_rxd_d1;
  67. 4'd6:uart_data_r[5] <= uart_rxd_d1;
  68. 4'd7:uart_data_r[6] <= uart_rxd_d1;
  69. 4'd8:uart_data_r[7] <= uart_rxd_d1;
  70. endcase
  71. end
  72. end
  73. always@(posedge sys_clk or negedge sys_rst_n)
  74. if(!sys_rst_n) begin
  75. uart_data <= 8'd0;
  76. uart_done <= 1'b0;
  77. end
  78. else if(rx_cnt == 4'd9) begin
  79. uart_data <= uart_data_r;
  80. uart_done <= 1'b1;
  81. end
  82. else begin
  83. uart_data <= 8'd0;
  84. uart_done <= 1'b0;
  85. end
  86. endmodule

4.2 发送模块

  1. `timescale 1ns / 1ps
  2. module uart_send(
  3. input sys_clk,
  4. input sys_rst_n,
  5. input [7:0] uart_din,
  6. input uart_en,
  7. output reg uart_txd,
  8. output uart_tx_busy
  9. );
  10. parameter CLK_FREQ = 50_000_000;
  11. parameter UART_BPS = 115200;
  12. localparam BPS_CNT = CLK_FREQ/UART_BPS;
  13. wire en_flag;
  14. reg uart_en_d0;
  15. reg uart_en_d1;
  16. reg tx_flag;
  17. reg [ 7:0] uart_data;
  18. reg [ 3:0] tx_cnt;
  19. reg [11:0] clk_cnt;
  20. assign en_flag = uart_en_d1 & (~uart_en_d0);
  21. assign uart_tx_busy = tx_flag;
  22. always@(posedge sys_clk or negedge sys_rst_n)
  23. if(!sys_rst_n) begin
  24. uart_en_d0 <= 1'b0;
  25. uart_en_d1 <= 1'b0;
  26. end
  27. else begin
  28. uart_en_d0 <= uart_en;
  29. uart_en_d1 <= uart_en_d0;
  30. end
  31. always@(posedge sys_clk or negedge sys_rst_n)
  32. if(!sys_rst_n) begin
  33. tx_flag <= 1'b0;
  34. uart_data <= 8'd0;
  35. end
  36. else if(en_flag) begin
  37. tx_flag <= 1'b1;
  38. uart_data <= uart_din;
  39. end
  40. else if((clk_cnt == BPS_CNT - 1) && (tx_cnt == 4'd9)) begin
  41. tx_flag <= 1'b0;
  42. uart_data <= 8'd0;
  43. end
  44. always@(posedge sys_clk or negedge sys_rst_n)
  45. if(!sys_rst_n)
  46. clk_cnt <= 12'd0;
  47. else if(tx_flag) begin
  48. if(clk_cnt < BPS_CNT - 1)
  49. clk_cnt <= clk_cnt + 1'b1;
  50. else
  51. clk_cnt <= 12'd0;
  52. end
  53. else
  54. clk_cnt <= 12'd0;
  55. always@(posedge sys_clk or negedge sys_rst_n)
  56. if(!sys_rst_n)
  57. tx_cnt <= 4'd0;
  58. else if(tx_flag) begin
  59. if(clk_cnt == BPS_CNT - 1)
  60. tx_cnt <= tx_cnt + 1'b1;
  61. end
  62. else
  63. tx_cnt <= 4'd0;
  64. always@(posedge sys_clk or negedge sys_rst_n)
  65. if(!sys_rst_n)
  66. uart_txd <= 1'b1;
  67. else if(tx_flag) begin
  68. case(tx_cnt)
  69. 4'd0:uart_txd <= 1'b0;
  70. 4'd1:uart_txd <= uart_data[0];
  71. 4'd2:uart_txd <= uart_data[1];
  72. 4'd3:uart_txd <= uart_data[2];
  73. 4'd4:uart_txd <= uart_data[3];
  74. 4'd5:uart_txd <= uart_data[4];
  75. 4'd6:uart_txd <= uart_data[5];
  76. 4'd7:uart_txd <= uart_data[6];
  77. 4'd8:uart_txd <= uart_data[7];
  78. 4'd9:uart_txd <= 1'b1;
  79. endcase
  80. end
  81. else
  82. uart_txd <= 1'b1;
  83. endmodule

4.3 环回模块

  1. `timescale 1ns / 1ps
  2. module uart_loop(
  3. input sys_clk,
  4. input sys_rst_n,
  5. input tx_busy,
  6. input [7:0] recv_data,
  7. input recv_done,
  8. output reg [7:0] send_data,
  9. output reg send_en
  10. );
  11. reg uart_rxd_d0;
  12. reg uart_rxd_d1;
  13. reg uart_ready;
  14. wire start_flag;
  15. assign start_flag = uart_rxd_d0 & (~uart_rxd_d1);
  16. always@(posedge sys_clk or negedge sys_rst_n)
  17. if(!sys_rst_n) begin
  18. uart_rxd_d0 <= 1'b1;
  19. uart_rxd_d1 <= 1'b1;
  20. end
  21. else begin
  22. uart_rxd_d0 <= recv_done;
  23. uart_rxd_d1 <= uart_rxd_d0;
  24. end
  25. always@(posedge sys_clk or negedge sys_rst_n)
  26. if(!sys_rst_n) begin
  27. send_data <= 8'd0;
  28. send_en <= 1'b0;
  29. uart_ready <= 1'b0;
  30. end
  31. else begin
  32. if(start_flag) begin
  33. send_data <= recv_data;
  34. send_en <= 1'b0;
  35. uart_ready <= 1'b1;
  36. end
  37. else if((~tx_busy) && uart_ready)begin
  38. send_en <= 1'b1;
  39. uart_ready <= 1'b0;
  40. end
  41. end
  42. endmodule

4.4 top模块

  1. `timescale 1ns / 1ps
  2. module uart(
  3. input sys_clk, //系统时钟
  4. input sys_rst_n, //系统复位,低电平有效
  5. input uart_rxd, //UART接收端口
  6. output uart_txd
  7. );
  8. wire [7:0] uart_data;
  9. wire uart_done;
  10. wire uart_tx_busy;
  11. wire [7:0] send_data;
  12. wire send_en;
  13. uart_rw uart_rw(
  14. .sys_clk (sys_clk ),
  15. .sys_rst_n (sys_rst_n ),
  16. .uart_rxd (uart_rxd ),
  17. .uart_data (uart_data ),
  18. .uart_done (uart_done )
  19. );
  20. uart_send uart_send(
  21. .sys_clk (sys_clk ),
  22. .sys_rst_n (sys_rst_n ),
  23. .uart_din (send_data ),
  24. .uart_en (send_en ),
  25. .uart_txd (uart_txd ),
  26. .uart_tx_busy(uart_tx_busy)
  27. );
  28. uart_loop uart_loop(
  29. .sys_clk (sys_clk ),
  30. .sys_rst_n (sys_rst_n ),
  31. .tx_busy (uart_tx_busy ),
  32. .recv_data (uart_data ),
  33. .recv_done (uart_done ),
  34. .send_data (send_data ),
  35. .send_en (send_en )
  36. );
  37. endmodule
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/952141
推荐阅读
相关标签
  

闽ICP备14008679号