D
Darol Klawetter
Guest
I recently fixed a problem with one of my state machines, and I think
that the cause could be a bug in Xilinx XST. Below is the code that
produced the failure. The state-machine worked most of the time,
though occasionally the 'phaseRamWE' signal would be stuck low, even
though I could see 'phaseRamReadAdr' and 'phaseRamWriteAdr'
incrementing. I fixed it by explicitly declaring the desired value of
'phaseRamWE' in every state. Notice that all states are defined so it
should recover from any conditions introduced by asynchronous inputs.
Have any of you seen similar behavior? Appears to be an XST bug to me.
parameter [3:0]
S1 = 4'b0000,
S2 = 4'b0001,
S3 = 4'b0010,
S4 = 4'b0011,
S5 = 4'b0100,
S6 = 4'b0101,
S7 = 4'b0110,
S8 = 4'b0111,
S9 = 4'b1000,
S10 = 4'b1001,
S11 = 4'b1010,
S12 = 4'b1011,
S13 = 4'b1100,
S14 = 4'b1101,
S15 = 4'b1110,
S16 = 4'b1111;
always @(posedge rst or posedge clk)
begin
if (rst) // 'rst' is asserted
and deasserted synchronously to 'clk'
begin
rfd <= 1'b0;
phaseRamWE <= 1'b0;
phaseRamWriteAdr <= 0;
phaseRamReadAdr <= 0;
phaseAccum <= 0;
state <= S1;
end
else
begin
case (state)
S1:
begin
if (pipeFill == 1'b1) // 'pipeFill' is
asynchronous to 'clk'
begin
phaseRamWE <= 1'b1;
state <= S2;
end
end
S2:
begin
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S3;
end
S3:
begin
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S4;
end
S4:
begin
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S5;
end
S5:
begin
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S6;
end
S6:
begin
rfd <= 1'b1;
phaseRamReadAdr <= phaseRamReadAdr + 1;
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
if (start == 1'b0) // 'start' is
synchronous
begin
state <= S7;
end
else
begin
state <= S8;
end
end
S7:
begin
if (start == 1'b0) // 'start' is
synchronous
begin
state <= S7;
end
else
begin
state <= S8;
phaseRamReadAdr <= phaseRamReadAdr + 1;
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
end
end
S8:
begin
if (start == 1'b0) // 'start' is
synchronous
begin
state <= S9;
phaseRamWE <= 1'b0;
phaseAccum <= 0;
rfd <= 1'b0;
phaseRamReadAdr <= 0;
phaseRamWriteAdr <= 0;
end
else
begin
state <= S8;
phaseRamReadAdr <= phaseRamReadAdr + 1;
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
end
end
S9: state <= S10;
S10: state <= S11;
S11: state <= S12;
S12: state <= S13;
S13: state <= S14;
S14: state <= S15;
S15: state <= S16;
S16: state <= S1;
endcase
end
end
that the cause could be a bug in Xilinx XST. Below is the code that
produced the failure. The state-machine worked most of the time,
though occasionally the 'phaseRamWE' signal would be stuck low, even
though I could see 'phaseRamReadAdr' and 'phaseRamWriteAdr'
incrementing. I fixed it by explicitly declaring the desired value of
'phaseRamWE' in every state. Notice that all states are defined so it
should recover from any conditions introduced by asynchronous inputs.
Have any of you seen similar behavior? Appears to be an XST bug to me.
parameter [3:0]
S1 = 4'b0000,
S2 = 4'b0001,
S3 = 4'b0010,
S4 = 4'b0011,
S5 = 4'b0100,
S6 = 4'b0101,
S7 = 4'b0110,
S8 = 4'b0111,
S9 = 4'b1000,
S10 = 4'b1001,
S11 = 4'b1010,
S12 = 4'b1011,
S13 = 4'b1100,
S14 = 4'b1101,
S15 = 4'b1110,
S16 = 4'b1111;
always @(posedge rst or posedge clk)
begin
if (rst) // 'rst' is asserted
and deasserted synchronously to 'clk'
begin
rfd <= 1'b0;
phaseRamWE <= 1'b0;
phaseRamWriteAdr <= 0;
phaseRamReadAdr <= 0;
phaseAccum <= 0;
state <= S1;
end
else
begin
case (state)
S1:
begin
if (pipeFill == 1'b1) // 'pipeFill' is
asynchronous to 'clk'
begin
phaseRamWE <= 1'b1;
state <= S2;
end
end
S2:
begin
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S3;
end
S3:
begin
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S4;
end
S4:
begin
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S5;
end
S5:
begin
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
phaseRamReadAdr <= phaseRamReadAdr + 1;
state <= S6;
end
S6:
begin
rfd <= 1'b1;
phaseRamReadAdr <= phaseRamReadAdr + 1;
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
if (start == 1'b0) // 'start' is
synchronous
begin
state <= S7;
end
else
begin
state <= S8;
end
end
S7:
begin
if (start == 1'b0) // 'start' is
synchronous
begin
state <= S7;
end
else
begin
state <= S8;
phaseRamReadAdr <= phaseRamReadAdr + 1;
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
end
end
S8:
begin
if (start == 1'b0) // 'start' is
synchronous
begin
state <= S9;
phaseRamWE <= 1'b0;
phaseAccum <= 0;
rfd <= 1'b0;
phaseRamReadAdr <= 0;
phaseRamWriteAdr <= 0;
end
else
begin
state <= S8;
phaseRamReadAdr <= phaseRamReadAdr + 1;
phaseRamWriteAdr <= phaseRamWriteAdr + 1;
end
end
S9: state <= S10;
S10: state <= S11;
S11: state <= S12;
S12: state <= S13;
S13: state <= S14;
S14: state <= S15;
S15: state <= S16;
S16: state <= S1;
endcase
end
end