Ich debugge ein Stück Verilog-Code für Tage, insbesondere Senden und Empfangen von Bytes von einem FX2LP (Cypress CY7C68016A) USB-Controller. Ohne in viele Details zu gehen, werden Daten in jedem Zyklus byteweise gesendet und übertragen. Für meinen Test verwende ich einen 16-Byte-Puffer, den ich zuerst auffülle und dann zurücksende (Echotest).Bit-Verschiebung im sequentiellen Block schlägt fehl, im Kombinationsmodus nicht. Warum?
Der wesentliche Teil meines Code wie folgt aussieht:
reg [127:0] dataBuf; // 16 byte buffer for USB data
reg [7:0] cntByte; // counter for number of bytes
reg [7:0] nextCntByte;
reg shiftBufRx, shiftBufTx; // flags whether buffer should be shifted
reg [7:0] currentByte; // current read byte
// in transmit cycle, byte is read from USB_DATAOUT
assign USB_DATAOUT = dataBuf[7:0];
always @(posedge FIFO_CLK) begin
// update state variables
CurrentState <= NextState;
cntByte <= nextCntByte;
if(shiftBufRx) begin // cycle was a receive
dataBuf <= { currentByte , dataBuf[127:8] };
end
if(shiftBufTx) begin // cycle was a transmit
dataBuf <= { dataBuf[127-8:0] , 8'h00 };
end
end
always @(*) begin
// avoid race conditions
NextState = CurrentState;
nextCntByte = cntByte;
nextDataBuf = dataBuf;
currentByte = 0;
shiftBufRx = 0;
shiftBufTx = 0;
case(CurrentState)
[...]
STATE_USBRX: begin
if(cntByte < 16) begin
nextCntByte = cntByte + 1;
currentByte = USB_DATAIN; // contains received byte in receive cycle
shiftBufRx = 1; // shift buffer after this cycle
end
[...]
end
STATE_USBTX: begin
if(cntByte < 15) begin
shiftBufTx = 1; // shift buffer after this cycle
nextCntByte = cntByte + 1;
end
[...]
end
[...]
endcase
end
Dieser Code perfekt in Simulation (iVerilog) arbeitet. Aber beim Synthetisieren und Ausführen auf einem Altera Cyclone bekomme ich sehr seltsame Fehler. Zum Beispiel wird das erste Byte, das an das FPGA übertragen wird, meistens für jedes Byte gelesen. Wenn Sie beispielsweise 11 22 33 44 55 66 ...
senden, erhalten Sie 11 11 11 11 11 11 ...
.
Nun, wenn ich stattdessen eine neue Variable vorstellen:
reg [127:0] nextDataBuf;
und das Teil in dem sequentiellen always @(posedge FIFO_CLK)
Block mit ersetzen:
if(shiftBufRx) begin
dataBuf <= nextDataBuf;
end
if(shiftBufTx) begin
dataBuf <= nextDataBuf;
end
und in dem kombinatorischen Teil:
STATE_USBRX: begin
if(cntByte < 16) begin
nextCntByte = cntByte + 1;
//currentByte = FIFO_DATAIN;
nextDataBuf = { dataBuf[127-8:0] , FIFO_DATAIN };
shiftBufRx = 1;
end
[...]
end
STATE_USBTX: begin
if(cntByte < 15) begin
shiftBufTx = 1;
nextCntByte = cntByte + 1;
nextDataBuf = { 8'h00 , dataBuf[127:8] };
end
[...]
end
Dann funktioniert es!
Das bedeutet: Alles, was ich mache, ist die Verschiebung der Verschiebung des Registers vom sequentiellen Block zum kombinatorischen Block.
Ich sehe keine Race-Bedingungen in meinem Code und in der Simulation (iVerilog) beide Versionen sind identisch.
Was könnte der Grund sein?
überprüfen Sie die Beziehung zwischen Tx/Rx Flags. Seltsames Singen kann passieren, wenn beide zur selben Zeit auf sind. – Serge
Ihre Datenstrukturen stimmen nicht überein. '{dataBuf [127-8: 0], 8'h00}'! = '{8'h00, dataBuf [127: 8]}' – Greg