BrunoLevy / learn-fpga

Learning FPGA, yosys, nextpnr, and RISC-V
BSD 3-Clause "New" or "Revised" License
2.58k stars 245 forks source link

Icebreaker FPGA UART communication garbage out #116

Open kir486680 opened 11 months ago

kir486680 commented 11 months ago

I am trying to run step17.v or step18.v and see what kind of output I can get using the ./terminal.sh (picocom -b $BAUDS $DEVICE --imap lfcrlf,crcrlf --omap delbs,crlf --send-cmd "ascii-xfr -s -l 30 -n") after uploading the code into my FPGA with usual BOARDS/run_icebreaker.sh step17.v. However, all I get is continuous flow of garbage ��o�į�����O�������p��o�����O�_x��o�į������O�������p��o�������O_x I have not edited the original code and it seems like the baud rates are matched. What could be causing the problem?

(I have also tried running python3 -m serial.tools.miniterm --dtr=1 $DEVICE $BAUDS or just picocom -b $BAUDS $DEVICE and I still get the same output)

BrunoLevy commented 11 months ago

It really looks like mismatched BAUD rate but can be something else: by default, I have configured it to run at 1000000 (1 million) bauds. Some hw/OS combinations may not support it, so the first thing I'd try is changingit to a more standard 57600 bauds (line 456 of step17.v). Please tell me what it gives, hope that it will work. If it works I will add a "troubleshooting" section.

kir486680 commented 11 months ago

Thanks! I was able to fix that by setting the baud rate to 9600! However, I am running into another issue. I am trying to send two letters consecutively and continuously using this code

    reg [7:0] char_A = 8'h41; // 'A'
    reg [7:0] char_B = 8'h42; // 'B'
    reg [7:0] tx_byte; // Byte to transmit
    reg [4:0] state; // State machine control

    wire uart_valid;
    wire uart_ready;

    // UART module
    corescore_emitter_uart #(
        .clk_freq_hz(`CPU_FREQ*1000000),
        .baud_rate(9600)                
    ) UART (
        .i_clk(clk),
        .i_rst(!resetn),
        .i_data(tx_byte),
        .i_valid(uart_valid),
        .o_ready(uart_ready),
        .o_uart_tx(TXD)                        
    );

// State machine for sending characters
    always @(posedge clk or posedge resetn) begin
        if (resetn) begin
            state <= 0; // Start with state 0 to send 'A'
            uart_valid <= 0;
            tx_byte <= 0;
        end else if (uart_ready && uart_valid) begin
            uart_valid <= 0; // Deassert uart_valid once character is sent
        end else begin
            case (state)
                0: begin
                    tx_byte <= char_A; // Load 'A' to be sent
                    state <= 1;
                    uart_valid <= 1; // Assert uart_valid for 'A'
                end
                1: begin
                    tx_byte <= char_B; // Load 'B' to be sent
                    state <= 0; // Loop back to start
                    uart_valid <= 1; // Assert uart_valid for 'B'
                end
            endcase
        end
    end

Ideally, the output should be ABABAB...but all I get is a non continuous stream of data BAB every time I run the code. Would you happen to know what the issue might be?

BrunoLevy commented 11 months ago

It is because you need to wait for uart_busy to be deasserted before sending the next character (your state machine is much much faster than the UART).

kir486680 commented 11 months ago

Thanks for the suggestion. Do you mean uart_ready be asserted since there is no uart_busy? I changed my code to this, and the output seems to be nothing

always @(posedge clk or posedge resetn) begin
    if (resetn) begin
        state <= 0; // Start with state 0 to send 'A'
        tx_byte <= 0;
        uart_valid <= 0;
    end else if (uart_valid) begin
        uart_valid <= 0; // Deassert uart_valid once character is sent
    end else if (uart_ready) begin
        case (state)
            0: begin
                tx_byte <= char_A; // Load 'A' to be sent
                state <= 1;
                uart_valid <= 1; // Assert uart_valid for 'A'
            end
            1: begin
                tx_byte <= char_B; // Load 'B' to be sent
                state <= 0; // Loop back to start
                uart_valid <= 1; // Assert uart_valid for 'B'
            end
        endcase
    end
end