当前位置:   article > 正文

FPGA(Verilog)实现uart传输协议传输数据(含仿真)_uart verilog

uart verilog

目录

实现功能:

1.接收uart串行数据,输出并行数据(1byte)。

2.输入并行数据(1byte),输出uart串行数据。

3.完成uart传输的1次环回。

uart协议的1帧数据传输

模块封装-port设置

Verilog代码实现

1.uart接收模块:接收串行数据,输出并行数据和其有效标志。

仿真结果:

2.uart发送模块:接收并行数据,发送串行数据。

仿真结果:

3.uart环回测试。

仿真验证:

仿真结果:

FPGA系统集成-RTL框图


实现功能:

1.接收uart串行数据,输出并行数据(1byte)。

2.输入并行数据(1byte),输出uart串行数据。

3.完成uart传输的1次环回。

uart协议的1帧数据传输

模块封装-port设置

Verilog代码实现
1.uart接收模块:接收串行数据,输出并行数据和其有效标志。
  1. module uart_rx#(
  2. parameter UART_BPS='d9600 , //波特率:1s传输9600个bit
  3. parameter CLK_FREQ='d50_000_000 //时钟频率:50MHz
  4. )(
  5. input wire clk ,
  6. input wire rst_n ,
  7. input wire rx , //接收的串行数据
  8. output reg [7:0] po_data , //输出并行数据
  9. output reg po_flag //输出有效并行数据的标志信号
  10. );

首先对rx进行时钟同步,消除亚稳态,以及打拍处理提取下降沿;

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) begin
  3. rx_d1<=1'b1;
  4. rx_d2<=1'b1;
  5. rx_d3<=1'b1;
  6. end
  7. else begin
  8. rx_d1<=rx; //时钟同步,消除亚稳态
  9. rx_d2<=rx_d1; //时钟同步,消除亚稳态
  10. rx_d3<=rx_d2; //打拍处理
  11. end
  12. assign rx_fall = ~rx_d2 & rx_d3 ; //提取rx下降沿

然后需要数据帧的有效信号,以便知道什么时候计数;

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) frame_val<=1'b0;
  3. else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag) //接收完1帧数据
  4. frame_val<=1'b0;
  5. else if(rx_fall)
  6. frame_val<=1'b1;
  7. else
  8. frame_val<=frame_val;

1码元符号(1bit)所需的计数器;

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) baud_cnt<=16'd0;
  3. else if(frame_val==1'b0) //数据帧无效
  4. baud_cnt<=16'd0;
  5. else if(baud_cnt==BAUD_CNT_MAX-1'b1)
  6. baud_cnt<=16'd0;
  7. else
  8. baud_cnt<=baud_cnt+1'b1;

1bit稳定数据的采样标志信号;

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) bit_flag<=1'b0;
  3. else if(baud_cnt==BAUD_CNT_MAX_HALF-1'b1) //采样需要在中间数据才稳定
  4. bit_flag<=1'b1;
  5. else
  6. bit_flag<=1'b0;

对采样到的bit数据进行计数;

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) bit_cnt<=4'd0;
  3. else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag) //10bit数据采样完毕
  4. bit_cnt<=4'd0;
  5. else if(bit_flag) //采样到1bit数据
  6. bit_cnt<=bit_cnt+1'b1;
  7. else
  8. bit_cnt<=bit_cnt;

将接收到的串行数据rx转化为并行数据po_data_t;

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) po_data_t<=8'b0;
  3. else if((bit_cnt>=4'd1) && (bit_cnt<BIT_CNT_MAX-1'b1) && bit_flag) //8bit数据
  4. po_data_t<={rx_d3,po_data_t[7:1]}; //起始位后接的是低位
  5. else
  6. po_data_t<=po_data_t;

并行数据全部拼接完成的标志信号;

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) po_flag_t<=1'b0;
  3. else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag)
  4. po_flag_t<=1'b1;
  5. else
  6. po_flag_t<=1'b0;

输出并行数据和输出有效并行数据的标志信号。

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) po_data<=8'b0;
  3. else if(po_flag_t)
  4. po_data<=po_data_t;
  5. else
  6. po_data<=po_data;
  7. //po_flag_t延迟1拍与po_data同步
  8. always@(posedge clk or negedge rst_n)
  9. if(!rst_n) po_flag<=1'b0;
  10. else
  11. po_flag<=po_flag_t;
仿真结果:

2.uart发送模块:接收并行数据,发送串行数据。
  1. module uart_tx#(
  2. parameter UART_BPS='d9600 , //波特率:1s传输9600个bit
  3. parameter CLK_FREQ='d50_000_000 //时钟频率:50MHz
  4. )(
  5. input wire clk ,
  6. input wire rst_n ,
  7. input wire pi_flag , //输入并行数据
  8. input wire [7:0] pi_data , //输入有效并行数据的标志信号
  9. output reg tx //输出串行数据
  10. );

首先同样是uart 1帧数据的有效信号;

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) frame_val<=1'b0;
  3. else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag) //发送完1帧数据
  4. frame_val<=1'b0;
  5. else if(pi_flag) //接收到有效的并行数据
  6. frame_val<=1'b1;
  7. else
  8. frame_val<=frame_val;

1码元符号(1bit)所需的计数器;

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) baud_cnt<=16'd0;
  3. else if(frame_val==1'b0) //数据帧无效
  4. baud_cnt<=16'd0;
  5. else if(baud_cnt==BAUD_CNT_MAX-1'b1)
  6. baud_cnt<=16'd0;
  7. else
  8. baud_cnt<=baud_cnt+1'b1;

1bit数据的发送标志信号;

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) bit_flag<=1'b0;
  3. else if(frame_val && !baud_cnt)
  4. bit_flag<=1'b1;
  5. else
  6. bit_flag<=1'b0;

对bit数据的发送进行计数;

  1. always@(posedge clk or negedge rst_n)
  2. if(!rst_n) bit_cnt<=4'd0;
  3. else if((bit_cnt==BIT_CNT_MAX-1'b1) && bit_flag) //10bit数据计数完毕
  4. bit_cnt<=4'd0;
  5. else if(bit_flag) //发送完1bit数据
  6. bit_cnt<=bit_cnt+1'b1;
  7. else
  8. bit_cnt<=bit_cnt;

输出串行数据。

  1. always@(posedge clk or negedge rst_n)
  2. if(rst_n==1'b0) tx<=1'b1; //空闲
  3. else if(bit_flag)
  4. case(bit_cnt)
  5. 4'd0: tx<=1'b0; //起始位
  6. 4'd1: tx<=pi_data[0]; //最低位数据
  7. 4'd2: tx<=pi_data[1];
  8. 4'd3: tx<=pi_data[2];
  9. 4'd4: tx<=pi_data[3];
  10. 4'd5: tx<=pi_data[4];
  11. 4'd6: tx<=pi_data[5];
  12. 4'd7: tx<=pi_data[6];
  13. 4'd8: tx<=pi_data[7]; //最高位数据
  14. 4'd9: tx<=1'b1; //结束位
  15. default:tx<=1'b1;
  16. endcase
仿真结果:

3.uart环回测试。
  1. module uart_test#(
  2. parameter UART_BPS='d9600 , //波特率:1s传输9600个bit
  3. parameter CLK_FREQ='d50_000_000 //时钟频率:50MHz
  4. )(
  5. input wire clk ,
  6. input wire rst_n ,
  7. input wire rx , //接收的串行数据
  8. output wire tx //发送的串行数据
  9. );
  10. wire [7:0] data ;
  11. wire data_flag ;
  12. uart_rx#(
  13. .UART_BPS(UART_BPS),
  14. .CLK_FREQ(CLK_FREQ)
  15. )u_uart_rx(
  16. .clk (clk ),
  17. .rst_n (rst_n ),
  18. .rx (rx ),
  19. .po_data(data),
  20. .po_flag(data_flag)
  21. );
  22. uart_tx#(
  23. .UART_BPS(UART_BPS),
  24. .CLK_FREQ(CLK_FREQ)
  25. )u_uart_tx(
  26. .clk (clk ),
  27. .rst_n (rst_n ),
  28. .pi_data(data),
  29. .pi_flag(data_flag),
  30. .tx(tx)
  31. );
  32. endmodule
仿真验证:
  1. `timescale 1ns/1ns
  2. module tb_uart_test();
  3. parameter UART_BPS='d9600 ; //波特率:1s传输9600个bit
  4. parameter CLK_FREQ='d50_000_000 ; //时钟频率:50MHz
  5. reg clk;
  6. reg rst_n;
  7. reg rx;
  8. wire tx;
  9. initial
  10. begin
  11. clk=1'b0;
  12. rst_n<=1'b0;
  13. rx<=1'b1;
  14. #20
  15. rst_n<=1'b1;
  16. end
  17. always #10 clk=~clk;
  18. initial
  19. begin
  20. #200 //空闲状态
  21. rx_test();
  22. #(5208*10*20*3)
  23. #200
  24. $stop;
  25. end
  26. //输出uart数据帧(10-13)
  27. task rx_test(); //任务函数,类似C语言
  28. integer j;
  29. for(j=10;j<13;j=j+1)
  30. rx_8bit(j);
  31. endtask
  32. //输入8bit并行数据,输出uart数据帧
  33. task rx_8bit(
  34. input [7:0] data
  35. );
  36. integer i;
  37. for(i=0;i<10;i=i+1)
  38. begin
  39. case(i)
  40. 0:rx<=1'b0; //1帧数据
  41. 1:rx<=data[0];
  42. 2:rx<=data[1];
  43. 3:rx<=data[2];
  44. 4:rx<=data[3];
  45. 5:rx<=data[4];
  46. 6:rx<=data[5];
  47. 7:rx<=data[6];
  48. 8:rx<=data[7];
  49. 9:rx<=1'b1;
  50. endcase
  51. #(5208*20); //9600波特率
  52. end
  53. endtask
  54. uart_test#(
  55. .UART_BPS(UART_BPS),
  56. .CLK_FREQ(CLK_FREQ)
  57. )u_uart_test(
  58. .clk (clk ),
  59. .rst_n (rst_n ),
  60. .rx (rx ),
  61. .tx(tx)
  62. );
  63. endmodule
仿真结果:

FPGA系统集成-RTL框图

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

闽ICP备14008679号