几天来我一直在调试一段 Verilog 代码,尤其是从 FX2LP(赛普拉斯 CY7C68016A)USB 控制器发送和接收字节。无需赘述,数据在每个周期中按字节发送和传输。对于我的测试,我使用了一个 16 字节的缓冲区,我首先填充它然后再传回(回声测试)。
我的代码的重要部分如下所示:
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
此代码在模拟(iVerilog)中完美运行。但是在 Altera Cyclone 上合成和执行时,我得到了非常奇怪的错误。例如,大多数情况下,每个字节都会读取传输到 FPGA 的第一个字节。例如,发送11 22 33 44 55 66 ...
将接收11 11 11 11 11 11 ...
。
现在,当我改为引入一个新变量时:
reg [127:0] nextDataBuf;
并将顺序always @(posedge FIFO_CLK)
块中的部分替换为:
if(shiftBufRx) begin
dataBuf <= nextDataBuf;
end
if(shiftBufTx) begin
dataBuf <= nextDataBuf;
end
在组合部分:
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
然后它起作用了!
这意味着:我所做的只是将寄存器的移位从顺序块移动到组合块。
我在我的代码和模拟(iVerilog)中没有看到任何竞争条件,两个版本都是相同的。
可能是什么原因?