当前位置:   article > 正文

FPGA串口发送学习_如何通过串口发送命令fpga

如何通过串口发送命令fpga

波特率技术举例:

 

1.串口发送原理:

 设计框图

时序图:bps_clk为波特率时钟

串口发送模块代码:

  1. //时钟频率是50Mhz,也就是周期是20ns
  2. module uart_byte_tx(
  3. input [7:0] Data, //将要发送的数据
  4. input En, //发送数据的使能信号
  5. input clk, //系统时钟
  6. input rst, //复位信号
  7. input [2:0] Baud_set, //8种波特率模式
  8. output reg uart_tx, //发送后接受到的串行数据 起始位+数据+停止位
  9. output reg Tx_Done //数据发送完成的标志
  10. );
  11. reg [17:0] cnt; // 用来分频得到波特率时钟
  12. reg [17:0] Baud; //Baud由Bund_set决定,用来控制波特率
  13. reg [3:0] counter_1; //对发送的第几位数据进行计数
  14. wire [9:0] data_last;//加上起始位和停止位的数据
  15. assign data_last = {1'd1,Data,1'd0};
  16. //Baud
  17. always@(Baud_set)
  18. case(Baud_set)
  19. 3'd0:Baud=18'd166666;//波特率为300
  20. 3'd1:Baud=18'd41666;//波特率为1200
  21. 3'd2:Baud=18'd20833;//波特率为2400
  22. 3'd3:Baud=18'd5208;//波特率为9600
  23. 3'd4:Baud=18'd2604;//波特率为19200
  24. 3'd5:Baud=18'd1302;//波特率为38400
  25. 3'd6:Baud=18'd868;//波特率为57600
  26. 3'd7:Baud=18'd434;//波特率为115200
  27. endcase
  28. //波特率分频
  29. always@(posedge clk or negedge rst)
  30. if(!rst) cnt <=0;
  31. else if(En==1)
  32. begin
  33. if (cnt==Baud-1) cnt<=0;
  34. else cnt<=cnt +1;
  35. end
  36. else cnt <=0;
  37. //always@(posedge clk or negedge rst)
  38. // if(!rst) Baud_clk <=0;
  39. // else if (cnt==Baud/2-1) Baud_clk<=!Baud_clk;
  40. // else if (cnt==Baud-1) Baud_clk<=!Baud_clk;
  41. // else Baud_clk<=Baud_clk ;
  42. //对发送的数据进行计数
  43. always@(posedge clk or negedge rst)
  44. if(!rst) counter_1<=0;
  45. else if(En==1)
  46. begin
  47. if(cnt==Baud-1&&cnt==Baud-1)
  48. begin
  49. if(counter_1==9) counter_1<=0;
  50. else counter_1<=counter_1+1;
  51. end
  52. else counter_1<=counter_1;
  53. end
  54. else counter_1<=0;
  55. //控制Tx_Done
  56. always@(posedge clk or negedge rst)
  57. if(!rst) Tx_Done<=0;
  58. else if(counter_1==9&&cnt==Baud-1) Tx_Done<=1;
  59. else Tx_Done<=0;
  60. //发送数据
  61. always@(posedge clk or negedge rst)
  62. if(!rst) begin uart_tx<=1;end
  63. else if(En==1&&Tx_Done==0)
  64. begin
  65. if(counter_1==9) uart_tx<=1;
  66. else
  67. uart_tx<=data_last[counter_1];
  68. end
  69. else
  70. uart_tx<=1;
  71. endmodule

2.完成5个字节的数据发送

因为串口通信协议只能完成8位比特的发送(8bit=1byte),因此发送5个字节的数据需要将5个字节的数据拆分成一个字节一个字节来依次发送。即最先发送[7:0]位,然后发送[15:8]位,直至发送至[39:32]位。

多个 字节发送的模块图:

       

采用状态机的思想来设计多个字节的发送:

     状态0:此时没有接收到发送数据请求信号,该模块处于空闲状态

     状态1:该模块接收到发送数据请求信号(Trans_Go),开始发送数据的第一个字节,第一个字节发送完成后,转移到状态2

     状态2:发送数据[15:8]

     状态3:发送数据[23:16]

    状态4:发送数据[31:24]

    状态5:发送数据[39:32],发送完数据的最后一个字节后,回到零状态,等待数据请求信号(Trans_Go)的来临。

源文件

  1. //采用状态机的思想发送5个字节的数据
  2. //
  3. module top_2(
  4. input clk,
  5. input Trans_Go, //请求发送
  6. input [39:0] Send_Data,
  7. input rst,
  8. output reg Done, //5个字节发送完成
  9. output uart_tx
  10. );
  11. reg [7:0] Data;
  12. reg En;
  13. wire Tx_Done;
  14. reg [2:0] state;
  15. //例化串口模块
  16. uart_byte_tx uart_nux_byte_Inst (
  17. .Data(Data),
  18. .En(En),
  19. .clk(clk),
  20. .rst(rst),
  21. .Baud_set(3'd7),
  22. .uart_tx(uart_tx),
  23. .Tx_Done(Tx_Done)
  24. );
  25. //开始状态转移
  26. always@(posedge clk or negedge rst)
  27. if(!rst)
  28. begin
  29. Done<=0;
  30. state<=0;
  31. Data<=0;
  32. En<=0;
  33. end
  34. else if(state==0)
  35. begin
  36. if(Trans_Go) begin
  37. if(Tx_Done) state<=3'd1;
  38. else begin En<=1;Data<=Send_Data[7:0]; end
  39. end
  40. else begin state<=state;Data<=0;En<=0; Done<=0;end
  41. end
  42. else if(state==3'd1)
  43. begin
  44. if(Tx_Done) state<=3'd2;
  45. else begin
  46. En<=1;
  47. Data<=Send_Data[15:8];
  48. end
  49. end
  50. else if(state==3'd2)
  51. begin
  52. if(Tx_Done) state<=3'd3;
  53. else begin
  54. En<=1;
  55. Data<=Send_Data[23:16];
  56. end
  57. end
  58. else if(state==3'd3)
  59. begin
  60. if(Tx_Done) state<=3'd4;
  61. else begin
  62. En<=1;
  63. Data<=Send_Data[31:24];
  64. end
  65. end
  66. else if(state==3'd4)
  67. begin
  68. if(Tx_Done) begin state<=3'd0;Done<=1;En=0;end
  69. else begin
  70. En<=1;
  71. Data<=Send_Data[39:32];
  72. end
  73. end
  74. endmodule

   激励文件

  1. module top_2_test();
  2. reg clk;
  3. reg Trans_Go; //请求发送
  4. reg rst;
  5. reg [39:0] Send_Data;
  6. wire Done; //5个字节发送完成
  7. wire uart_tx;
  8. top_2 top_2_test(
  9. .clk(clk),
  10. .Trans_Go(Trans_Go),
  11. .Send_Data(Send_Data),
  12. .rst(rst),
  13. . Done(Done),
  14. .uart_tx(uart_tx)
  15. );
  16. initial
  17. begin
  18. Send_Data = 40'h0;
  19. Trans_Go=0;
  20. clk=1;
  21. rst=0;
  22. #10000 rst=1;
  23. Send_Data = 40'h1234567899;
  24. #5000 Trans_Go=1;
  25. @(posedge Done)
  26. Trans_Go=0;
  27. #10000
  28. Send_Data= 40'h1187654321;
  29. Trans_Go=1;
  30. @(posedge Done)
  31. Trans_Go=0;
  32. end
  33. always #10 clk=~clk;
  34. endmodule

代码优化:采用2个或者3个状态机发送数据,并且容易修改成发送任意字节的数据。

 状态1:空闲状态,没有发送数据,当数据请求信号Trans_Go来临时,转为状态1 

 状态2:正在发送数据

源文件

  1. //采用2个或者3个状态机实现任意字节数据的发送
  2. //
  3. module top_3(
  4. clk,
  5. Trans_Go, //请求发送
  6. Send_Data, //最多能发送20个字节的数据
  7. rst,
  8. Done, //5个字节发送完成
  9. uart_tx
  10. );
  11. parameter Num_Byte = 7; //发送数据的字节数
  12. parameter Num_bit = Num_Byte*8; //发送数据的位数
  13. input [Num_bit-1:0] Send_Data;
  14. input clk;
  15. input Trans_Go; //请求发送
  16. input rst;
  17. output reg Done; //数据发送完成
  18. output uart_tx;
  19. reg [0:1] state; //状态
  20. reg [Num_bit-1:0] Data_1;
  21. reg [2:0] counter_byte; //对发送的字节数进行计数
  22. reg [7:0] Data;
  23. reg En;
  24. wire Tx_Done;
  25. uart_byte_tx uart_nux_byte_Inst (
  26. .Data(Data),
  27. .En(En),
  28. .clk(clk),
  29. .rst(rst),
  30. .Baud_set(3'd7),
  31. .uart_tx(uart_tx),
  32. .Tx_Done(Tx_Done)
  33. );
  34. always@(posedge clk or negedge rst)
  35. if(!rst) begin state<=0;Done<=0;Data<=0;En<=0;Data_1<=0;counter_byte <= 0;end
  36. else if(state==0)
  37. begin
  38. if(Trans_Go==1&&Done==0) begin state<=1;Data_1<=Send_Data;end
  39. else begin
  40. Data_1<=0;
  41. state<=0;
  42. Done<=0;
  43. Data<=0;
  44. En<=0;
  45. counter_byte <= 0;
  46. end
  47. end
  48. else if(state==1)
  49. begin
  50. if(Tx_Done)
  51. begin
  52. if(counter_byte==Num_Byte-1) begin state<=0; Done<=1;En<=0;counter_byte<=0;end
  53. else
  54. begin
  55. counter_byte <= counter_byte+1;
  56. Data_1 <={Data_1[7:0],Data_1[Num_bit-1:8]};
  57. Data <=Data_1[7:0];
  58. Done<=0;
  59. end
  60. end
  61. else if(!Tx_Done)
  62. begin
  63. Data <=Data_1[7:0];
  64. En<=1;
  65. Done<=0;
  66. end
  67. end
  68. endmodule

激励文件

  1. module top_3_test();
  2. parameter Num_Byte = 7;
  3. parameter Num_bit = Num_Byte*8;
  4. reg clk;
  5. reg Trans_Go; //请求发送
  6. reg rst;
  7. reg [Num_bit-1:0] Send_Data;
  8. wire Done; //5个字节发送完成
  9. wire uart_tx;
  10. top_3 top_3_test(
  11. .clk(clk),
  12. .Trans_Go(Trans_Go),
  13. .Send_Data(Send_Data),
  14. .rst(rst),
  15. . Done(Done),
  16. .uart_tx(uart_tx)
  17. );
  18. initial
  19. begin
  20. Send_Data = 56'h0;
  21. Trans_Go=0;
  22. clk=1;
  23. rst=0;
  24. #10000 rst=1;
  25. Send_Data = 56'h12345678991234;
  26. #5000 Trans_Go=1;
  27. @(posedge Done)
  28. Trans_Go=0;
  29. #10000
  30. Send_Data= 56'h11876543214321;
  31. Trans_Go=1;
  32. @(posedge Done)
  33. Trans_Go=0;
  34. end
  35. always #10 clk=~clk;
  36. endmodule

板级测试文件,实现1分钟发送一个数据

  1. //多个字节发送板级测试文件
  2. //
  3. module top4(
  4. input clk,
  5. input rst,
  6. output uart_tx
  7. );
  8. //例化
  9. wire Done;
  10. reg Trans_Go;
  11. parameter Num_Byte = 7;
  12. parameter Num_bit =Num_Byte*8;
  13. reg [Num_bit-1:0] Send_Data;
  14. reg [Num_bit-1:0] Data_chuzhi=56'h1234567891234;
  15. top_3 top_3_Inst(
  16. .clk(clk),
  17. .rst(rst),
  18. .Send_Data(Send_Data),
  19. .Trans_Go(Trans_Go),
  20. .Done(Done),
  21. .uart_tx(uart_tx)
  22. );
  23. //10ms计数
  24. parameter MCNT = 33'd3000000000;// 2s计数值
  25. reg [32:0] counter_10ms;
  26. always@(posedge clk or negedge rst)
  27. if(!rst) counter_10ms<=0;
  28. else if(counter_10ms==MCNT-1) counter_10ms<=0;
  29. else counter_10ms<=counter_10ms+1;
  30. //每隔10ms发送一个数据
  31. always@(posedge clk or negedge rst)
  32. if(!rst) Trans_Go<=0;
  33. else if(counter_10ms==1) Trans_Go<=1;
  34. else if(Done) Trans_Go<=0;
  35. else Trans_Go<=Trans_Go;
  36. //对发送的数据加1
  37. always@(posedge clk or negedge rst)
  38. if(!rst) Send_Data<=Data_chuzhi;
  39. else if(Done) Send_Data<=Send_Data+1;
  40. else Send_Data<=Send_Data;
  41. endmodule

测试成功

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

闽ICP备14008679号