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

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

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.

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:

`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.

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:

确定