英文:
Why am I receiving the wrong bits when sending data through UART on Basys3 FPGA?
问题
以下是您要翻译的 Verilog 代码的部分:
module TopUART#(parameter cycle_BRG = 5208, idle = 2'b00, loading = 2'b01, sending = 2'b11, done = 2'b10)(
input clk, input [7:0] data_send, input transmit, output Txd
);
// 这里是 Verilog 代码的一部分,用于实现 UART 通信。
// 代码包括时钟生成,状态机,数据路径等部分。
// 请注意代码的逻辑和信号处理。
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.
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:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 05/24/2023 04:33:54 PM
// Design Name:
// Module Name: TopUART
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module TopUART#(parameter cycle_BRG = 5208, idle = 2'b00, loading = 2'b01, sending = 2'b11, done = 2'b10)(
input clk, input [7:0] data_send, input transmit, output Txd
);
reg [13:0] BRG_counter = 0;
reg [9:0] bit_counter = 0;
reg BRG_SET; //set to 1 every (1/9600) seconds
reg BRG_SET_tracker; //used so that I can set BRG_SET in two always blocks
reg [1:0] state = 0;
reg load = 0;
reg shift = 0;
reg clear = 0;
reg Txd = 1;
reg [9:0] shiftright_register = 0;
//BRG for UART
always @(posedge clk)
begin
if(BRG_counter == cycle_BRG)
begin
BRG_SET <= 1;
BRG_counter <= 0;
end
else
begin
BRG_counter <= BRG_counter + 1;
BRG_SET <= 0;
end
end
//controller for UART
always@(posedge clk)
begin
case(state)
idle: //waiting for transmit button to be pressed
begin
if(transmit)
begin
state <= loading;
load <= 1;
shift <= 0;
clear <= 0;
Txd <= 1;
end
else
begin
state <= idle;
load <= 0;
shift <= 0;
clear <= 0;
Txd <= 1;
end
end
loading: //button was pressed, keeping load signal high until BRG has been set so that data path can update the shift register
begin
if(BRG_SET)
begin
state <= sending;
load <= 0;
shift <= 1;
clear <= 0;
Txd <= 1;
end
else
begin
state <= loading;
load <= 1;
shift <= 0;
clear <= 0;
Txd <= 1;
end
end
sending: //send data until 10 bits have been sent on TX line
begin
if(bit_counter == 10)
begin
state <= done;
load <= 0;
shift <= 0;
clear <= 1;
Txd <= 1;
end
else
begin
state <= sending;
load <= 0;
shift <= 1;
clear <= 0;
Txd <= shiftright_register[0];
end
end
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
begin
if(BRG_SET)
begin
state <= idle;
load <= 0;
shift <= 0;
clear <= 0;
Txd <= 1;
end
else
begin
state <= done;
load <= 0;
shift <= 0;
clear <= 1;
Txd <= 1;
end
end
endcase
end
//data path for UART
always @(posedge BRG_SET)
begin
if(load)
begin
shiftright_register <= {1'b1, data_send, 1'b0};
bit_counter <= 0;
end
else if(shift)
begin
shiftright_register <= shiftright_register >> 1;
bit_counter <= bit_counter +1;
end
else if(clear)
begin
bit_counter <= 0;
end
end
endmodule
Constraints:
set_property IOSTANDARD LVCMOS33 [get_ports {data_send[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data_send[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data_send[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data_send[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data_send[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data_send[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data_send[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {data_send[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {transmit}]
set_property IOSTANDARD LVCMOS33 [get_ports {Txd}]
set_property PACKAGE_PIN W13 [get_ports {data_send[7]}]
set_property PACKAGE_PIN W14 [get_ports {data_send[6]}]
set_property PACKAGE_PIN V15 [get_ports {data_send[5]}]
set_property PACKAGE_PIN W15 [get_ports {data_send[4]}]
set_property PACKAGE_PIN W17 [get_ports {data_send[3]}]
set_property PACKAGE_PIN W16 [get_ports {data_send[2]}]
set_property PACKAGE_PIN V16 [get_ports {data_send[1]}]
set_property PACKAGE_PIN V17 [get_ports {data_send[0]}]
set_property PACKAGE_PIN T17 [get_ports {transmit}]
set_property PACKAGE_PIN A18 [get_ports {Txd} ]
set_property PACKAGE_PIN W5 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
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:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 05/25/2023 09:53:23 AM
// Design Name:
// Module Name: TopUARTTestbench
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module TopUARTTestbench(
);
reg clk = 0;
always #10 clk = ~clk;
reg [7:0] data_send;
reg transmit;
wire Txd;
TopUART x (clk, data_send, transmit, Txd);
initial
begin
#20
transmit = 1; #30;
transmit = 0;
data_send = 8'b01010101;
end
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论