当前位置:   article > 正文

verilog实现UART:RS232串口的收发 FPGA:开发工具ISE,或者QUARTUS_fgpa,uart,quarus

fgpa,uart,quarus

verilog实现UART:RS232串口的收发。
RTL代码及仿真代码100%每行全注释,不用担心看不懂。
FPGA:开发工具ISE,或者QUARTUS。
功能:将电脑上使用串口调试助手发送的数据进行接收,再将接收到的数据发送回去,在串口调试助手界面显示。
RS232协议:1位起始位+8位数据位+1位停止位。
顶层模块和分模块均有modelsim仿真文件及仿真结果波形,便于学习验证及应用。
已下载到板验证通过。

本文将介绍如何使用Verilog语言实现UART协议,实现RS232串口的收发功能。本文提供的RTL代码及仿真代码100%每行全注释,方便读者理解和学习。读者可以使用FPGA开发工具ISE或者QUARTUS进行开发。最终实现的功能是将电脑上使用串口调试助手发送的数据进行接收,再将接收到的数据发送回去,并在串口调试助手界面显示。本文还将介绍RS232协议,并提供了顶层模块和分模块的modelsim仿真文件及仿真结果波形,方便读者进行学习和验证。

一、介绍

UART是一种通讯协议,用于串行数据传输,通常用于将数据发送到计算机或其他设备。UART通常使用RS232协议进行通讯,它是一种标准的串行通信协议,用于连接计算机和串口设备。在这篇文章中,我们将介绍如何使用Verilog语言实现UART协议,以实现串口通讯功能。

二、RS232协议

在实现UART协议之前,我们需要了解一下RS232协议。RS232协议使用一个异步传输的串行通信信道,用于在计算机和串口设备之间传输数据。该协议使用1位起始位、8位数据位和1位停止位,以及可选的奇偶校验位。在本文中,我们将实现基本的RS232协议,即使用1位起始位、8位数据位和1位停止位进行通讯。

三、Verilog实现UART

接下来,我们将介绍如何使用Verilog语言实现UART协议。具体实现过程如下:

1.顶层模块

首先,我们需要创建一个顶层模块,用于接收和发送数据。该模块包括以下子模块:接收模块、发送模块、时钟模块和UART控制模块。其中,接收模块和发送模块分别负责接收和发送数据,时钟模块负责产生时钟信号,并将时钟信号传递给UART控制模块。UART控制模块负责控制接收和发送模块,并将接收到的数据发送给计算机,并将计算机发送的数据发送给接收模块。

以下是一个示例顶层模块的代码:

  1. module uart_top(
  2. input clk,
  3. input rst_n,
  4. input uart_rx,
  5. output uart_tx
  6. );
  7. reg [7:0] rx_data;
  8. reg [7:0] tx_data;
  9. reg rx_flag;
  10. reg tx_flag;
  11. reg [3:0] bit_cnt;
  12. reg [3:0] rx_bit_cnt;
  13. reg [3:0] tx_bit_cnt;
  14. reg stop_bit;
  15. parameter CLK_DIV = 26; // 9600 baud
  16. uart_receiver u_receiver(
  17. .clk(clk),
  18. .rst_n(rst_n),
  19. .data_in(uart_rx),
  20. .data_out(rx_data),
  21. .data_valid(rx_flag),
  22. .bit_cnt(rx_bit_cnt),
  23. .stop_bit(stop_bit)
  24. );
  25. uart_transmitter u_transmitter(
  26. .clk(clk),
  27. .rst_n(rst_n),
  28. .data_out(uart_tx),
  29. .data_in(tx_data),
  30. .data_valid(tx_flag),
  31. .bit_cnt(tx_bit_cnt),
  32. .stop_bit(stop_bit)
  33. );
  34. uart_control u_control(
  35. .clk(clk),
  36. .rst_n(rst_n),
  37. .data_in(rx_data),
  38. .data_valid_in(rx_flag),
  39. .bit_cnt_in(rx_bit_cnt),
  40. .stop_bit_in(stop_bit),
  41. .data_out(tx_data),
  42. .data_valid_out(tx_flag),
  43. .bit_cnt_out(tx_bit_cnt)
  44. );
  45. endmodule

该模块中包含了三个子模块:uart_receiver、uart_transmitter和uart_control模块。顶层模块负责将这些模块连接起来,实现UART通讯功能。

2.接收模块

接下来,我们需要实现接收模块。接收模块负责接收从计算机发送过来的数据,并将数据存储到缓存中。在接收模块中,我们需要使用计数器来计算每个位的时长,并在停止位到达时将数据存储到缓存中。

以下是一个示例接收模块的代码:

  1. module uart_receiver(
  2. input clk,
  3. input rst_n,
  4. input data_in,
  5. output reg [7:0] data_out,
  6. output reg data_valid,
  7. output reg [3:0] bit_cnt,
  8. output reg stop_bit
  9. );
  10. parameter CLK_DIV = 26; // 9600 baud
  11. reg [23:0] bit_timer;
  12. reg [7:0] shift_reg;
  13. reg sync_cnt;
  14. reg sync_flag;
  15. reg [3:0] cnt;
  16. reg data_ready;
  17. always @(posedge clk or negedge rst_n) begin
  18. if (~rst_n) begin
  19. bit_timer <= 0;
  20. shift_reg <= 0;
  21. sync_cnt <= 0;
  22. sync_flag <= 0;
  23. cnt <= 0;
  24. data_ready <= 0;
  25. bit_cnt <= 0;
  26. stop_bit <= 0;
  27. end else begin
  28. if (sync_flag) begin
  29. if (bit_timer == CLK_DIV) begin
  30. bit_timer <= 0;
  31. if (cnt < 8) begin
  32. shift_reg <= {shift_reg[6:0], data_in};
  33. cnt <= cnt + 1;
  34. end else if (cnt == 8) begin
  35. stop_bit <= data_in;
  36. cnt <= cnt + 1;
  37. end else if (cnt == 9) begin
  38. data_valid <= 1;
  39. cnt <= 0;
  40. data_out <= shift_reg;
  41. sync_flag <= 0;
  42. data_ready <= 1;
  43. end
  44. end else begin
  45. bit_timer <= bit_timer + 1;
  46. end
  47. end else if (data_in == 0) begin
  48. sync_cnt <= sync_cnt + 1;
  49. end else if (sync_cnt > 3) begin
  50. sync_flag <= 1;
  51. sync_cnt <= 0;
  52. bit_cnt <= 0;
  53. cnt <= 0;
  54. data_valid <= 0;
  55. data_ready <= 0;
  56. end else begin
  57. sync_cnt <= 0;
  58. end
  59. end
  60. end
  61. endmodule

在该模块中,我们使用了一个计时器来计算每个位的时长,并使用一个移位寄存器来存储数据。当停止位到达时,我们将数据存储到缓存中,并将数据有效标志设为1,表示接收到了有效数据。接收模块还使用了一个同步计数器来检测信号的同步状态。

3.发送模块

接下来,我们需要实现发送模块。发送模块负责将数据从缓存中发送到计算机。在发送模块中,我们需要使用计数器来计算每个位的时长,并在停止位到达时停止发送。

以下是一个示例发送模块的代码:

  1. module uart_transmitter(
  2. input clk,
  3. input rst_n,
  4. output reg data_out,
  5. input [7:0] data_in,
  6. input data_valid,
  7. input [3:0] bit_cnt,
  8. input stop_bit
  9. );
  10. parameter CLK_DIV = 26; // 9600 baud
  11. reg [23:0] bit_timer;
  12. reg [7:0] shift_reg;
  13. reg [3:0] cnt;
  14. reg tx_ready;
  15. reg [3:0] bit_num;
  16. always @(posedge clk or negedge rst_n) begin
  17. if (~rst_n) begin
  18. bit_timer <= 0;
  19. shift_reg <= 0;
  20. cnt <= 0;
  21. tx_ready <= 1;
  22. bit_num <= 0;
  23. end else begin
  24. if (data_valid && tx_ready) begin
  25. shift_reg <= data_in;
  26. tx_ready <= 0;
  27. cnt <= 0;
  28. bit_num <= 0;
  29. end else if (~tx_ready && (bit_timer == CLK_DIV)) begin
  30. bit_timer <= 0;
  31. if (cnt < 8) begin
  32. data_out <= shift_reg[bit_num];
  33. bit_num <= bit_num + 1;
  34. cnt <= cnt + 1;
  35. end else if (cnt == 8) begin

相关代码,程序地址:http://lanzouw.top/692092879411.html
 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号