Electronic – Verilog UART Transmitter Sends Bytes Out of Order

fpgauartverilog

I have the following Verilog code which sends 8 bytes to the serial port successively after a button is pressed.

The problem is, the bytes are sent out of order as to what I would expect.

For example, if I send out the bytes 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF – the PC gets 0xEF, 0xAD, 0xEF, 0xAD and sometimes does not receive the rest and will hang-up.

I've looked at this code many times, and can't seem to figure out why this might be. Am I using the part-select incorrectly? I don't think so, but I don't know what else could be the issue.

I've attached a second version of this code that does work(meaning all the bytes are received and in the correct order), but it takes an extra clock cycle because it updates the data in the shift register after each transmission. If you can see any reason why the first version posted does not work, but the second does – please let me know!

module transmission_test_2(sysclk, rxd, txd, LED, button);

input sysclk, rxd, button;
output txd;
output reg LED;

wire receiving_complete, isReceiving, isTransmitting, isError;
reg begin_transmit;
reg [7:0] tbyte;

wire [7:0] rbyte;

reg [2:0] state;

reg [63:0] plain_text;

integer byteN;


parameter IDLE = 0, BEGIN_TRANSMISSION = 1, UPDATE_DATA = 2, SEND_BYTES = 3;


uart uart1(
.clk(sysclk),
.rx(rxd),
.tx(txd),
.transmit(begin_transmit),
.tx_byte(tbyte),
.received(receiving_complete),
.rx_byte(rbyte),
.is_receiving(isReceiving), 
.is_transmitting(isTransmitting),
.recv_error(isError)
);


always @(posedge sysclk)
begin
    begin_transmit = 1'b0;
    case(state)
    IDLE: begin
        if(button==1'b0) begin
            LED = 1'b1;
            plain_text = 64'hDEADBEEFDEADBEEF;
            state = BEGIN_TRANSMISSION;
        end else begin
            LED <= 1'b0;
        end
    end
    BEGIN_TRANSMISSION: begin
        tbyte = plain_text[7:0];
        begin_transmit = 1'b1;
        byteN = 1;
        state = SEND_BYTES;
    end
    SEND_BYTES: begin
        if(!isTransmitting) begin
            tbyte = plain_text[byteN*8 +: 8];
            begin_transmit = 1'b1;
            byteN = byteN + 1;
            if(byteN == 8) begin
                state = IDLE;
            end
        end
    end
    endcase
end

endmodule

Second "working" version:

module transmission_test(sysclk, rxd, txd, LED, button);


input sysclk, rxd, button;

output txd;

output reg LED;


wire receiving_complete, isReceiving, isTransmitting, isError;

reg begin_transmit;

reg [7:0] tbyte;


wire [7:0] rbyte;


reg [2:0] state;

reg [63:0] plain_text;

integer bytes_remaining;


parameter IDLE = 0, BEGIN_TRANSMISSION = 1, UPDATE_DATA = 2, SEND_BYTES = 3, DONE = 4;


uart uart1(
.clk(sysclk),
.rx(rxd),
.tx(txd),
.transmit(begin_transmit),
.tx_byte(tbyte),
.received(receiving_complete),
.rx_byte(rbyte),
.is_receiving(isReceiving), 
.is_transmitting(isTransmitting),
.recv_error(isError)
);


always @(posedge sysclk)
begin
    begin_transmit = 1'b0;
    case(state)
    IDLE: begin
        if(button==1'b0) begin
            LED = 1'b1;
            plain_text = 64'hDEADBEEFDEADBEEF;
            state = BEGIN_TRANSMISSION;
        end else begin
            LED <= 1'b0;
        end
    end
    BEGIN_TRANSMISSION: begin
        tbyte = plain_text[7:0];
        begin_transmit = 1'b1;
        bytes_remaining = 7;
        state = UPDATE_DATA;
    end
    UPDATE_DATA: begin
        plain_text = plain_text >> 8;
        state = SEND_BYTES;
    end
    SEND_BYTES: begin
        if(!isTransmitting) begin
            tbyte = plain_text[7:0];
            begin_transmit = 1'b1;
            bytes_remaining = bytes_remaining - 1;
            if(bytes_remaining == 0) begin
                state = IDLE;
            end else begin
                state = UPDATE_DATA;
            end
        end
    end
    endcase
end

endmodule

REVISION:

Following advice from @dwikle – instead of using one "catch-all" state that cycles through sending all 8 bytes – I created a seperate state for each byte that needed to be sent.

Here is the code:

module transmission_test_3(sysclk, rxd, txd, LED, button);

input sysclk, rxd, button;
output txd;
output reg LED;

wire receiving_complete, isReceiving, isTransmitting, isError, reset;
reg begin_transmit;
reg [7:0] tbyte;

wire [7:0] rbyte;

reg [2:0] state = 4'b0;
reg [63:0] plain_text = 64'h0;

uart uart1(
.clk(sysclk),
.rst(reset),
.rx(rxd),
.tx(txd),
.transmit(begin_transmit),
.tx_byte(tbyte),
.received(receiving_complete),
.rx_byte(rbyte),
.is_receiving(isReceiving), 
.is_transmitting(isTransmitting),
.recv_error(isError)
);

always @(posedge sysclk)
begin
    begin_transmit = 1'b0;
    case(state)
    4'b0000: begin
        if(button==1'b0) begin
            LED = 1'b1;
            plain_text = 64'hDEADBEEFAAABACAD;
            state = 4'b0001;
        end else begin
            LED = 1'b0;
        end
    end
    4'b0001: begin
        tbyte = plain_text[7:0];
        begin_transmit = 1'b1;
        state = 4'b0010;
    end
    4'b0010: begin
        if(!isTransmitting) begin
            tbyte = plain_text[15:8];
            begin_transmit = 1'b1;
            state = 4'b0011;
        end
    end
    4'b0011: begin
            if(!isTransmitting) begin
                tbyte = plain_text[23:16];
                begin_transmit = 1'b1;
                state = 4'b0100;
            end
        end
    4'b0100: begin
        if(!isTransmitting) begin
            tbyte = plain_text[31:24];
            begin_transmit = 1'b1;
            state = 4'b0101;
        end
    end
    4'b0101: begin
        if(!isTransmitting) begin
            tbyte = plain_text[39:32];
            begin_transmit = 1'b1;
            state = 4'b0110;
        end
    end
    4'b0110: begin
        if(!isTransmitting) begin
            tbyte = plain_text[47:40];
            begin_transmit = 1'b1;
            state = 4'b0111;
        end
    end
    4'b0111: begin
        if(!isTransmitting) begin
            tbyte = plain_text[55:48];
            begin_transmit = 1'b1;
            state = 4'b1000;
        end
    end
    4'b1000: begin
        if(!isTransmitting) begin
            tbyte = plain_text[63:56];
            begin_transmit = 1'b1;
            state = 4'b0000;
        end
    end
    endcase
end
endmodule

However, the results are still the same – I receive every other byte. What gives?

Any ideas?

P.S. – I've posted the UART code on my google docs – if you need to take a look. 🙂

UART module

UPDATE:

The original question for this thread came from attempting to isolate a communication issue in a larger module.

The project simply accepts 64-bit (8 bytes) of data from the PC – encrypts the data with the DES algorithm – and sends the encrypted message (64-bit, again) back.

The transfer works, but (what seems to be arbitrarily) hangs up. When attempting to do 1000 encryptions, I can on average handle around 250 – sometimes doing all 1000 successfully, and sometimes maybe only doing 20 or 50.

I had thought that the transfer was bottle-necking on the transmission side of the communication – which is was I was rewriting the transmission and hence the purpose of this thread. I've come to realize, however, that the problem actually lies in the reception side of the transfer. What seems to be happening is that after doing several successful runs, the state machine collects 7 bytes again and then somehow misses or the last byte of the 64-bit chunk and gets stuck in the state looking for the last byte.

I've tried simulating the design – but, I feel like the stimulus I'm providing isn't quite kosher. The testbench should send 8 bytes worth of data over the uart – and then the state machine should chug along, encrypting and sending back the message.

However, providing different vectors of data to the rx line of the uart gives drastically different results. Depending on the data I'm using, the uart sometimes recieves only 7 bytes (which is the problem I'm looking at with real hardware) or even returns errors.

So, the problems I'm trying to figure out are:

1) I can successfully receive and transmit several tens to hundreds of encryptions – but the communication hangs up at arbitrary points – and it seems to be that when this happens, the state machine has collected 7 bytes and is looking for the last.

2) To diagnose this problem, I tried looking into the simulation results. However – even these seem to give unexpected behavior – and I'm afraid perhaps I'm giving stimuli incorrectly.

Any comments or suggestions for the implementation of the testbench – or what may be causing the communication to cease would be greatly appreciated. If these questions seem elementary I apologize – I'm still learning.

I've attached a zip on my google docs with all the relevant files, including the testbench.

https://docs.google.com/open?id=0B4WyEjzmIhtNN0V6a0x5U19SMUU

I'll also post the top-level module here for reference.

module rs232_neek(sysclk, rxd, txd, reset, LED);

input sysclk, rxd, reset;
output txd;
wire receiving_complete, isTransmitting, isReceiving, isError;

output reg [3:0] LED;   //The LEDs are used simply as debug - to determine which state the machine gets held-up in.

reg begin_transmit;
reg [7:0] tbyte;

wire [7:0] rbyte;

parameter FIRST_BYTE = 0, GET_BYTES = 1, BEGIN_ENC = 2, CHECK_ENC_STATUS = 3,     BEGIN_TRANSMISSION = 4, SEND_BYTES = 5;

reg [2:0] state = 3'b0;
integer byteN = 0;

reg [3:0] sel = 4'b0;
reg [63:0] plain_text;
reg [63:0] cipher_text;
wire [63:0] cipher_net;

uart uart1(
.clk(sysclk),
 .rst(~reset),
.rx(rxd),
.tx(txd),
.transmit(begin_transmit),
.tx_byte(tbyte),
.received(receiving_complete),
.rx_byte(rbyte),
.is_transmitting(isTransmitting),
.is_receiving(isReceiving),
.recv_error(isError)
);

des des1(
 .clk(sysclk),
 .key(56'h0),
 .roundSel(sel),
 .decrypt(1'b0),
 .desIn(plain_text),
 .desOut(cipher_net)
 );

always @(posedge sysclk)
begin

    if(~reset) begin
        state = FIRST_BYTE;
    end

    LED = 4'b1111;

    case(state)
        FIRST_BYTE: begin
            LED[0] = 1'b0;
            begin_transmit = 1'b0;
            if(receiving_complete) begin
               plain_text[7:0] = rbyte;
                byteN = 1;
                state = GET_BYTES;
            end
        end
        GET_BYTES: begin
            LED[1] = 1'b0;
            if(receiving_complete) begin
                plain_text[byteN*8 +: 8] = rbyte;
                byteN = byteN + 1;
                if(byteN == 8) begin
                    state = BEGIN_ENC;
                end
            end
        end
        BEGIN_ENC: begin
            sel = 4'b0;
            state = CHECK_ENC_STATUS;
        end
        CHECK_ENC_STATUS: begin
            LED[2] = 1'b0;
            sel = sel + 1;
            if(sel == 15) begin
                state = BEGIN_TRANSMISSION;
            end
        end
        BEGIN_TRANSMISSION: begin
            cipher_text = cipher_net;
            tbyte = cipher_text[7:0];
            begin_transmit = 1'b1;
            byteN = 1;
            state = SEND_BYTES;
        end
        SEND_BYTES: begin
            LED[3] = 1'b0;
            if(!isTransmitting && !begin_transmit) begin
                tbyte = cipher_text[byteN*8 +: 8];
                begin_transmit = 1'b1;
                byteN = byteN + 1;
                if(byteN == 8) begin
                    state = FIRST_BYTE;
                end
            end else begin
                begin_transmit = 1'b0;
            end
        end
    endcase
end

endmodule

Best Answer

The problem is that your "transmission_test" code is written such that it assumes that "is_transmitting" from the UART goes true before the clock edge that follows the assertion of "begin_transmit". It doesn't -- it takes a clock cycle before the UART transmitter moves out of its "idle" state, after which "is_transmitting" is true.

As a result, your "transmission_test" state machine is advancing two states for each byte transmitted, and you see only every other byte at the output of the UART.

There are many minor problems with your code samples, but the main thing you need to fix is to verify that "is_transmitting" has gone true before you advance to the next byte in the message.

This would have been pretty obvious if you had taken the time to simulate this project. I can't overemphasize the importance of simulation in verifying FPGA code. Take the time to get familiar with your simulator and learn how to write good module testbenches.