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. :)
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