为什么我通过Basys3 FPGA的UART发送数据时收到错误的位?

huangapple go评论86阅读模式
英文:

Why am I receiving the wrong bits when sending data through UART on Basys3 FPGA?

问题

以下是您要翻译的 Verilog 代码的部分:

  1. module TopUART#(parameter cycle_BRG = 5208, idle = 2'b00, loading = 2'b01, sending = 2'b11, done = 2'b10)(
  2. input clk, input [7:0] data_send, input transmit, output Txd
  3. );
  4. // 这里是 Verilog 代码的一部分,用于实现 UART 通信。
  5. // 代码包括时钟生成,状态机,数据路径等部分。
  6. // 请注意代码的逻辑和信号处理。
  7. endmodule

这是您提供的 Verilog 代码的部分翻译。如果您需要更多的翻译或有其他问题,请随时提问。

英文:

My goal is to send data from my Basys3 board to my laptop, and I am using UART to do so. The Verilog code I wrote successfully sends data to my computer, but I am receiving the wrong bits.

Below you can see the results of my simulation when sending 01010101, which corresponds to the letter U's ASCII encoding. As the markers show, I am sending a bit around every (1/9600)s, so after 10 bits are sent, time will be at 1041.66us. My timing is a bit off, but the maximum acceptable baud rate error is 2.5%, and my rate is well within this range.

As you can see, I start with pulling TX LOW to start the transmission, then I send my data, starting with the LSB. I end the transmission by pulling TX HIGH, and the line remains HIGH in its IDLE state.

When sending the same data 01010101 and viewing the results in Pyserial, I see the following:
This is not the desired result

The same data is being sent consistently (the letter A, along with some additional bits), but I am not sure why they are not the correct results. Below shows the symbols that are printed on the PuTTy terminal corresponding to this data:
Symbols being A and something else I am not sure of

Below is my code and constraints file. I am not sure what changes I should make because the simulation looks good to me. On the computer's end, I set the baud rate to 9600, 8 bits, 1 stop bit, and no parity bit for both PuTTy and Pyserial, so I do not think I made a mistake there either:

Design Source:

  1. `timescale 1ns / 1ps
  2. //////////////////////////////////////////////////////////////////////////////////
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 05/24/2023 04:33:54 PM
  7. // Design Name:
  8. // Module Name: TopUART
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //////////////////////////////////////////////////////////////////////////////////
  21. module TopUART#(parameter cycle_BRG = 5208, idle = 2'b00, loading = 2'b01, sending = 2'b11, done = 2'b10)(
  22. input clk, input [7:0] data_send, input transmit, output Txd
  23. );
  24. reg [13:0] BRG_counter = 0;
  25. reg [9:0] bit_counter = 0;
  26. reg BRG_SET; //set to 1 every (1/9600) seconds
  27. reg BRG_SET_tracker; //used so that I can set BRG_SET in two always blocks
  28. reg [1:0] state = 0;
  29. reg load = 0;
  30. reg shift = 0;
  31. reg clear = 0;
  32. reg Txd = 1;
  33. reg [9:0] shiftright_register = 0;
  34. //BRG for UART
  35. always @(posedge clk)
  36. begin
  37. if(BRG_counter == cycle_BRG)
  38. begin
  39. BRG_SET <= 1;
  40. BRG_counter <= 0;
  41. end
  42. else
  43. begin
  44. BRG_counter <= BRG_counter + 1;
  45. BRG_SET <= 0;
  46. end
  47. end
  48. //controller for UART
  49. always@(posedge clk)
  50. begin
  51. case(state)
  52. idle: //waiting for transmit button to be pressed
  53. begin
  54. if(transmit)
  55. begin
  56. state <= loading;
  57. load <= 1;
  58. shift <= 0;
  59. clear <= 0;
  60. Txd <= 1;
  61. end
  62. else
  63. begin
  64. state <= idle;
  65. load <= 0;
  66. shift <= 0;
  67. clear <= 0;
  68. Txd <= 1;
  69. end
  70. end
  71. loading: //button was pressed, keeping load signal high until BRG has been set so that data path can update the shift register
  72. begin
  73. if(BRG_SET)
  74. begin
  75. state <= sending;
  76. load <= 0;
  77. shift <= 1;
  78. clear <= 0;
  79. Txd <= 1;
  80. end
  81. else
  82. begin
  83. state <= loading;
  84. load <= 1;
  85. shift <= 0;
  86. clear <= 0;
  87. Txd <= 1;
  88. end
  89. end
  90. sending: //send data until 10 bits have been sent on TX line
  91. begin
  92. if(bit_counter == 10)
  93. begin
  94. state <= done;
  95. load <= 0;
  96. shift <= 0;
  97. clear <= 1;
  98. Txd <= 1;
  99. end
  100. else
  101. begin
  102. state <= sending;
  103. load <= 0;
  104. shift <= 1;
  105. clear <= 0;
  106. Txd <= shiftright_register[0];
  107. end
  108. end
  109. done: //once 10 bits set, keep clear high and wait for BRG_SET to become 1 so that data path can reset the bit counter and BRG counter
  110. begin
  111. if(BRG_SET)
  112. begin
  113. state <= idle;
  114. load <= 0;
  115. shift <= 0;
  116. clear <= 0;
  117. Txd <= 1;
  118. end
  119. else
  120. begin
  121. state <= done;
  122. load <= 0;
  123. shift <= 0;
  124. clear <= 1;
  125. Txd <= 1;
  126. end
  127. end
  128. endcase
  129. end
  130. //data path for UART
  131. always @(posedge BRG_SET)
  132. begin
  133. if(load)
  134. begin
  135. shiftright_register <= {1'b1, data_send, 1'b0};
  136. bit_counter <= 0;
  137. end
  138. else if(shift)
  139. begin
  140. shiftright_register <= shiftright_register >> 1;
  141. bit_counter <= bit_counter +1;
  142. end
  143. else if(clear)
  144. begin
  145. bit_counter <= 0;
  146. end
  147. end
  148. endmodule

Constraints:

  1. set_property IOSTANDARD LVCMOS33 [get_ports {data_send[7]}]
  2. set_property IOSTANDARD LVCMOS33 [get_ports {data_send[6]}]
  3. set_property IOSTANDARD LVCMOS33 [get_ports {data_send[5]}]
  4. set_property IOSTANDARD LVCMOS33 [get_ports {data_send[4]}]
  5. set_property IOSTANDARD LVCMOS33 [get_ports {data_send[3]}]
  6. set_property IOSTANDARD LVCMOS33 [get_ports {data_send[2]}]
  7. set_property IOSTANDARD LVCMOS33 [get_ports {data_send[1]}]
  8. set_property IOSTANDARD LVCMOS33 [get_ports {data_send[0]}]
  9. set_property IOSTANDARD LVCMOS33 [get_ports {transmit}]
  10. set_property IOSTANDARD LVCMOS33 [get_ports {Txd}]
  11. set_property PACKAGE_PIN W13 [get_ports {data_send[7]}]
  12. set_property PACKAGE_PIN W14 [get_ports {data_send[6]}]
  13. set_property PACKAGE_PIN V15 [get_ports {data_send[5]}]
  14. set_property PACKAGE_PIN W15 [get_ports {data_send[4]}]
  15. set_property PACKAGE_PIN W17 [get_ports {data_send[3]}]
  16. set_property PACKAGE_PIN W16 [get_ports {data_send[2]}]
  17. set_property PACKAGE_PIN V16 [get_ports {data_send[1]}]
  18. set_property PACKAGE_PIN V17 [get_ports {data_send[0]}]
  19. set_property PACKAGE_PIN T17 [get_ports {transmit}]
  20. set_property PACKAGE_PIN A18 [get_ports {Txd} ]
  21. set_property PACKAGE_PIN W5 [get_ports clk]
  22. set_property IOSTANDARD LVCMOS33 [get_ports clk]
  23. create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]

Edit: This is the testbench I used to simulate this design:

  1. `timescale 1ns / 1ps
  2. //////////////////////////////////////////////////////////////////////////////////
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 05/25/2023 09:53:23 AM
  7. // Design Name:
  8. // Module Name: TopUARTTestbench
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //////////////////////////////////////////////////////////////////////////////////
  21. module TopUARTTestbench(
  22. );
  23. reg clk = 0;
  24. always #10 clk = ~clk;
  25. reg [7:0] data_send;
  26. reg transmit;
  27. wire Txd;
  28. TopUART x (clk, data_send, transmit, Txd);
  29. initial
  30. begin
  31. #20
  32. transmit = 1; #30;
  33. transmit = 0;
  34. data_send = 8'b01010101;
  35. end
  36. endmodule

Edit: I want to note that I changed the code to count to exactly 10416 cycles per bit by setting cycle_BRG = 10416. When using 10417, I noticed that my MSB was always being read as a 1 by my laptop. This may be due to the computer missing the final data bit when sampling and reading the stop bit as my final bit.

答案1

得分: 0

  • 根据这篇帖子 basys-3,basys-3 开发板使用 100 MHz 时钟。测试台代码将时钟编码为 always #10 clk = ~clk1,这将创建一个 50MHz 的时钟。如果测试台的结果看起来正确,也许设计中某处存在2倍的错误。

  • 我没有在设计中看到 bufg 实例。如果这是你的所有代码,那么时钟是分布在局部路由上的。局部路由会导致从触发器到触发器的时序偏差足够大,足以导致普通的数字设计结构(如计数器和移位寄存器)表现不如预期。在时钟输入部分插入一个 bufg 是解决方案。在每次构建后,在时钟上添加时钟约束(约束 bufg 输出),并查看工具生成的时序报告,以验证设计是否符合时序要求。随着设计规模的增大和利用率的增加,这将变得更加重要和必要。

英文:

A couple of things to consider for debug:

  • According to this post basys-3 the basys-3 board uses a 100 MHz clock. The testbench codes the clock as always #10 clk = ~clk1 which will create a 50MHz clock. If the testbench results look correct, perhaps there is a factor of 2 error somewhere in the design.

  • I don't see a bufg instance in the design. If this is all the code you have then the clock is being distributed on local routing. Local routing will have timing skew from flop to flop that is significant enough to cause ordinary digital design structures like counters & shift-registers to not behave as expected. Inserting a bufg where the clock enters the part is the solution. Internet search 'Xilxnx bufg' for more.

  • Recommend using a clock constraint on the clock (constrain the bufg output), and reviewing the timing report generated by the tools after each build to verify that the design meets timing. This becomes more of an issue and is essential as the design gets larger and the %utilization increases.

huangapple
  • 本文由 发表于 2023年5月30日 03:48:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76359989.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定