FPGA Synthesize - Xilinx ISE - Removing most all FF from FSM

I have a verilog module that contains an FSM.

I have extracted parts of it for this post below.

ISE XST issues warning that all the FF associated with the reg variables shown are removed and I don't understand why.

One of the warnings: Xst:1710 - FF/Latch (without init value) has a constant value of 0 in block . This FF/Latch will be trimmed during the optimization process.

If you look below - bit 3 of RedRam_Data3 is clearly set.


reg [7:0] RedRam_Data1, RedRam_Data1_next, RedRam_Data2, RedRam_Data2_next,
RedRam_Data3, RedRam_Data3_next, RedRam_Data4, RedRam_Data4_next;
reg [5:0] Stream1_Counter, Stream2_Counter, Stream3_Counter, Stream4_Counter;
reg [6:0] Stream1_Counter_next, Stream2_Counter_next, Stream3_Counter_next,
Stream4_Counter_next;

localparam Bit_1_Compare_Value = 6'd14;

always @(posedge clk)
begin

RedRam_Data1 <= RedRam_Data1_next;
RedRam_Data2 <= RedRam_Data2_next;
RedRam_Data3 <= RedRam_Data3_next;
RedRam_Data4 <= RedRam_Data4_next;

Stream1_Counter <= Stream1_Counter_next[5:0];
Stream2_Counter <= Stream2_Counter_next[5:0];
Stream3_Counter <= Stream3_Counter_next[5:0];
Stream4_Counter <= Stream4_Counter_next[5:0];

end

always @*
begin
Stream1_Counter_next = Stream1_Counter;
Stream2_Counter_next = Stream2_Counter;
Stream3_Counter_next = Stream3_Counter;
Stream4_Counter_next = Stream4_Counter;

if(Diff1_Q)
Stream1_Counter_next = Stream1_Counter + 1;

if(Diff2_Q)
Stream1_Counter_next = Stream2_Counter + 1;

if(Diff3_Q)
Stream1_Counter_next = Stream3_Counter + 1;

if(Diff4_Q)
Stream1_Counter_next = Stream4_Counter + 1;

RedRam_Data1_next = RedRam_Data1;
RedRam_Data2_next = RedRam_Data2;
RedRam_Data3_next = RedRam_Data3;
RedRam_Data4_next = RedRam_Data4;

case(FSM_State)

SomeState:
begin
if(Stream1_Counter > Bit_1_Compare_Value)
begin
case(Which_Bit)
0: RedRam_Data1_next[7] = 1'b1;
1: RedRam_Data1_next[6] = 1'b1;
2: RedRam_Data1_next[5] = 1'b1;
3: RedRam_Data1_next[4] = 1'b1;
4: RedRam_Data1_next[3] = 1'b1;
endcase
end // #7

if(Stream2_Counter > Bit_1_Compare_Value)
begin
case(Which_Bit)
0: RedRam_Data2_next[7] = 1'b1;
1: RedRam_Data2_next[6] = 1'b1;
2: RedRam_Data2_next[5] = 1'b1;
3: RedRam_Data2_next[4] = 1'b1;
4: RedRam_Data2_next[3] = 1'b1;
endcase
end // #7

if(Stream3_Counter > Bit_1_Compare_Value)
begin
case(Which_Bit)
0: RedRam_Data3_next[7] = 1'b1;
1: RedRam_Data3_next[6] = 1'b1;
2: RedRam_Data3_next[5] = 1'b1;
3: RedRam_Data3_next[4] = 1'b1;
4: RedRam_Data3_next[3] = 1'b1;
endcase
end // #7

if(Stream4_Counter > Bit_1_Compare_Value)
begin // #7
case(Which_Bit)
0: RedRam_Data4_next[7] = 1'b1;
1: RedRam_Data4_next[6] = 1'b1;
2: RedRam_Data4_next[5] = 1'b1;
3: RedRam_Data4_next[4] = 1'b1;
4: RedRam_Data4_next[3] = 1'b1;
endcase
end // #7


• Did it work perfectly in all respects, in simulation? If not, synthesis may have identified opportunities for "optimisation" that you did not intend. – Brian Drummond Feb 19 at 19:00
• Simulates as expected. The warning says that the optimizer will remove the FF which suggests to me that execution on the actual FPGA will not match simulation -- or am I wrong in that belief? – JHinkle Feb 19 at 19:51
• Maybe, maybe not. I don't do Verilog, so I can't tell if Stream3_Counter ever gets incremented; I can't see anything that would increment it. So this : " bit 3 of RedRam_Data3 is clearly set" si not at all clear to me. However if you say it simulates as you would expect, normally synth results will do exactly the same. – Brian Drummond Feb 19 at 20:18
• A Thought: RedRam_Data1 is a FF that holds a bit from a Ram Data Byte. I am sending each bit out an output port. The Ram Data Byte does not change during that whole process so could the optimizer just be routing the bit directly from the Data Byte and NOT perform the extra pipline stage I have in place by discreetly pulling the data bit on it's own? – JHinkle Feb 19 at 20:29
• A Thought. Pay attention when using the paste key. – Brian Drummond Feb 19 at 21:15

Test reasonably fully in simulation. Preferably with a self checking testbench which reports whether or not what ought to happen, actually is happening.

Almost always - as here - if synthesis is trimming away your code, it is because your code isn't actually doing anything, so it can safely be removed without affecting the result.

Proceeding to synthesis without testing reasonably well in simulation is doing things the hard way.

On quick projects I don't always test everything ... at first.

But if I see something suspicious in synth, as you did here, I revisit the testbench and add tests for it, so that

If you look below - bit 3 of RedRam_Data3 is clearly set.

... is actually demonstrated ... and then if it isn't, further tests to reveal why not (e.g. is that counter counting?)