Máy phát VerART UART gửi byte theo thứ tự


7

Tôi có mã Verilog sau đây sẽ gửi 8 byte tới cổng nối tiếp sau khi nhấn nút.

Vấn đề là, các byte được gửi không theo thứ tự như tôi mong đợi.

Ví dụ: nếu tôi gửi các byte 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF - PC sẽ nhận được 0xEF, 0xAD, 0xEF, 0xAD và đôi khi sẽ không nhận được phần còn lại.

Tôi đã xem mã này nhiều lần và dường như không thể hiểu tại sao điều này có thể xảy ra. Tôi đang sử dụng phần chọn không chính xác? Tôi không nghĩ vậy, nhưng tôi không biết những gì khác có thể là vấn đề.

Tôi đã đính kèm một phiên bản thứ hai của mã này hoạt động (có nghĩa là tất cả các byte được nhận và theo đúng thứ tự), nhưng phải mất thêm một chu kỳ xung nhịp vì nó cập nhật dữ liệu trong thanh ghi thay đổi sau mỗi lần truyền. Nếu bạn có thể thấy bất kỳ lý do nào khiến phiên bản đầu tiên được đăng không hoạt động, nhưng phiên bản thứ hai thì không - vui lòng cho tôi biết!

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

Phiên bản "làm việc" thứ hai:

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

CÁCH MẠNG:

Theo lời khuyên từ @dwikle - thay vì sử dụng một trạng thái "bắt tất cả" xoay quanh việc gửi tất cả 8 byte - tôi đã tạo một trạng thái riêng cho mỗi byte cần gửi.

Đây là mã:

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

Tuy nhiên, kết quả vẫn giống nhau - tôi nhận được mọi byte khác. Đưa cái gì?

Có ý kiến ​​gì không?

Tái bút - Tôi đã đăng mã UART trên tài liệu google của mình - nếu bạn cần xem qua. :)

Mô-đun UART

CẬP NHẬT:

Câu hỏi ban đầu cho chủ đề này xuất phát từ việc cố gắng cô lập một vấn đề giao tiếp trong một mô-đun lớn hơn.

Dự án chỉ đơn giản chấp nhận dữ liệu 64 bit (8 byte) từ PC - mã hóa dữ liệu bằng thuật toán DES - và gửi lại tin nhắn được mã hóa (64 bit, một lần nữa).

Việc chuyển tiền hoạt động, nhưng (dường như là tùy tiện) cúp máy. Khi cố gắng thực hiện 1000 mã hóa, trung bình tôi có thể xử lý khoảng 250 - đôi khi thực hiện tất cả 1000 thành công và đôi khi có thể chỉ thực hiện 20 hoặc 50.

Tôi đã nghĩ rằng việc chuyển đổi là cổ chai ở phía truyền thông của truyền thông - đó là tôi đã viết lại việc truyền tải và do đó là mục đích của chủ đề này. Tuy nhiên, tôi đã nhận ra rằng vấn đề thực sự nằm ở phía tiếp nhận chuyển nhượng. Điều dường như đang xảy ra là sau khi thực hiện một số lần chạy thành công, máy trạng thái thu thập lại 7 byte và sau đó bằng cách nào đó bỏ lỡ hoặc byte cuối cùng của đoạn 64 bit và bị kẹt trong trạng thái tìm kiếm byte cuối cùng.

Tôi đã thử mô phỏng thiết kế - nhưng, tôi cảm thấy như sự kích thích mà tôi cung cấp không hoàn toàn sâu sắc hơn. Testbench sẽ gửi dữ liệu trị giá 8 byte qua uart - và sau đó máy trạng thái sẽ chug cùng, mã hóa và gửi lại tin nhắn.

Tuy nhiên, việc cung cấp các vectơ dữ liệu khác nhau cho dòng rx của uart cho kết quả rất khác nhau. Tùy thuộc vào dữ liệu tôi đang sử dụng, đôi khi uart chỉ nhận được 7 byte (đó là vấn đề tôi đang xem xét với phần cứng thực) hoặc thậm chí trả về lỗi.

Vì vậy, những vấn đề tôi đang cố gắng tìm ra là:

1) Tôi có thể nhận và truyền thành công hàng chục đến hàng trăm mã hóa - nhưng giao tiếp bị treo ở các điểm tùy ý - và dường như khi điều này xảy ra, máy trạng thái đã thu thập được 7 byte và đang tìm kiếm lần cuối.

2) Để chẩn đoán vấn đề này, tôi đã thử xem xét kết quả mô phỏng. Tuy nhiên - ngay cả những điều này dường như đưa ra hành vi bất ngờ - và tôi sợ có lẽ tôi đang kích thích không chính xác.

Bất kỳ ý kiến ​​hoặc đề xuất nào cho việc triển khai testbench - hoặc những gì có thể khiến việc liên lạc chấm dứt sẽ được đánh giá rất cao. Nếu những câu hỏi này có vẻ sơ đẳng, tôi xin lỗi - tôi vẫn đang học.

Tôi đã đính kèm một zip trên tài liệu google của tôi với tất cả các tệp có liên quan, bao gồm cả testbench.

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

Tôi cũng sẽ đăng mô-đun cấp cao nhất ở đây để tham khảo.

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

1
Để xem chính xác những gì xảy ra, tôi nghĩ nên sử dụng 8 mã khác nhau. Nếu bây giờ bạn nhận được 0xBE, bạn không biết đó là lần đầu tiên hay lần thứ hai.
stevenvh

Thành thật mà nói, tôi không chắc một trong hai người họ đang làm việc như thế nào. "Begin_transmit" có phải là xung cho mỗi byte được gửi không? Tôi thấy nơi bạn đang đặt nó, nhưng không phải nơi nó bị xóa.
Dave Tweed

Có, nó giả sử xung cho mỗi byte. Tôi đang cố gắng xóa cờ ở đầu khối luôn.
kbarber

Tôi cũng đã thử sử dụng các vectơ khác nhau làm đầu vào, để chắc chắn. Vấn đề tương tự.
kbarber

Câu trả lời:


4

Vấn đề là mã "Transmission_test" của bạn được viết sao cho nó giả sử rằng "is_transmmit" từ UART trở thành sự thật trước khi cạnh đồng hồ tuân theo khẳng định "Begin_transmit". Nó không - phải mất một chu kỳ đồng hồ trước khi bộ phát UART chuyển khỏi trạng thái "không hoạt động", sau đó "is_transmits" là đúng.

Kết quả là, máy trạng thái "Transmission_test" của bạn đang tiến lên hai trạng thái cho mỗi byte được truyền và bạn chỉ thấy mọi byte khác ở đầu ra của UART.

Có nhiều vấn đề nhỏ với các mẫu mã của bạn, nhưng điều chính bạn cần khắc phục là xác minh rằng "is_transmmit" đã thành sự thật trước khi bạn chuyển sang byte tiếp theo trong thông báo.

Điều này sẽ khá rõ ràng nếu bạn dành thời gian để mô phỏng dự án này. Tôi không thể nhấn mạnh tầm quan trọng của việc mô phỏng trong việc xác minh mã FPGA. Dành thời gian để làm quen với trình giả lập của bạn và tìm hiểu cách viết các bài kiểm tra mô-đun tốt.


Dave - cảm ơn rất nhiều vì đã phản hồi và dành thời gian để xem xét vấn đề. Rõ ràng, tôi nên đã phân tích kết quả mô phỏng chặt chẽ hơn. Tôi vẫn đang học hầu hết các sắc thái của Verilog và đã cho rằng tôi đã quá tìm kiếm thứ gì đó trong chính mã. Bạn đã đề cập rằng có một số vấn đề khác trong mã - tôi rất thích nếu bạn có thể làm sáng tỏ điều đó. Như tôi đã nói, tôi vẫn đang học cách viết HDL tốt và đánh giá cao bất kỳ bình luận hay phê bình nào. Cảm ơn bạn!
kbarber

@KristinBarber: Chà, chỉ cần nhìn vào 'Transmission_test_3.v', không có sự gán cho tín hiệu "đặt lại". Tôi không chắc ý định của bạn là gì với tín hiệu "nút", nhưng theo cách nó được thiết lập, mạch sẽ truyền liên tục miễn là nó hoạt động (ở mức thấp), thay vì gửi một tin nhắn cho mỗi lần nhấn nút. Và tôi cho rằng đó là vấn đề về phong cách hơn là lỗi, nhưng tôi thực sự không thích "gán mặc định" để "bắt đầu truyền" bên ngoài tuyên bố trường hợp. Tôi đã bỏ lỡ điều này lần đầu tiên và điều này làm cho mã của bạn khó đọc nói chung.
Dave Tweed

@KristinBarber: Bản thân mã uart.v có một số vấn đề nghiêm trọng hơn, mặc dù có vẻ như bạn đã nhận được điều này từ người khác. Khối "if (rst) started ..." hoàn toàn không hiệu quả, vì nó bị ghi đè bởi phần còn lại của mã bên trong khối luôn - tất cả các mã khác phải nằm trong "if" khác được liên kết với "if" (đầu tiên) ". Và có rất nhiều trạng thái nội bộ không được đặt thành các giá trị đã biết bằng cách đặt lại. Nó có thể không thực sự quan trọng cuối cùng, nhưng nếu vậy, nó nên được ghi lại rõ ràng như vậy.
Dave Tweed

Dave - Cảm ơn tất cả các đầu vào. Tôi thực sự có thể sử dụng một số trợ giúp để chẩn đoán một vấn đề lớn hơn - mà tôi đã phác thảo trong một bản cập nhật cho bài đăng câu hỏi ban đầu. Nếu bạn có thể nhìn vào nó sẽ giúp tôi rất nhiều.
kbarber

@kbarber: Vấn đề với testbench của bạn là nó chỉ gửi một bit start ở đầu tin nhắn, thay vì một bit start trên mỗi byte. Điều này gây ra hành vi phụ thuộc dữ liệu vì UART đang diễn giải số 0 đầu tiên trong dữ liệu dưới dạng bit start chứ không phải bit dữ liệu. Tôi vẫn đang xem xét các vấn đề có thể xảy ra với phần cứng thực tế.
Dave Tweed

0

Không biết các yêu cầu của UART, tôi đoán là vấn đề nằm ở chỗ begin_transmit. Trong trường hợp "làm việc" của bạn begin_transmitsẽ bị xóa cho mỗi byte vì bạn đang di chuyển qua trạng thái UPDATE_DATA. Tuy nhiên, đối với trường hợp không hoạt động, bạn sẽ ở trạng thái SEND_BYTEScho toàn bộ truyền và begin_transmitsẽ chỉ bị xóa nếu isTransmitting == 1. (Lưu ý begin_transmitđược gán cho 0trước câu lệnh tình huống, tạo một phép gán mặc định.)

Tôi đã mô phỏng trường hợp không hoạt động và begin_transmitchỉ đập từng byte khác, điều này sẽ giải thích những gì bạn đang thấy nếu UART dự kiến ​​sẽ thấy một vị trí trên begin_transmit. Không có mô hình UART, tôi đã mô hình hóa isTransmittingnhư thế này để mô phỏng.

always @(posedge sysclk) begin
  isTransmitting <= begin_transmit;
end

Ồ, đó là sự khai sáng - thực sự. Tôi có ấn tượng rằng mỗi khi khối luôn được nhập vào, mọi câu lệnh sẽ được đánh giá và THÌ trường hợp đó sẽ được đánh giá. Tuy nhiên, bạn đang nói rằng trong một tình huống như thế này - bất cứ điều gì trước khi một tuyên bố trường hợp trong một khối luôn được coi là mặc định của vụ án?
kbarber

Tôi đã cập nhật bài viết gốc của mình để phù hợp với những gợi ý này. Tôi vẫn có vấn đề, mặc dù. Vui lòng xem và cho tôi biết nếu bạn có thêm bất kỳ đề xuất nào - nếu có thể.
kbarber

Về "mặc định", đối với tôi, có vẻ như anh ta nói rằng nếu không có trường hợp nào được thực thi hoặc nếu một phép thử if trong trường hợp được chọn làm cho phần còn lại của mã bị bỏ qua, thì biến sẽ giữ giá trị của nó đã có trước đó - vì vậy, nó giữ lại cái mà nó có ở đầu khối - và do đó, về cơ bản, đó là một giá trị mặc định. Mặc định, như trong, "đây sẽ là giá trị trừ khi có thứ gì khác thay đổi nó".
gbarry
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.