Xilinx’ XST synthesizer bug II: Inferred RAM and mux
It looks like inferring RAMs and ROMs is the weak spot of XST. This is the second bug I find using this synthesizer, this time on XST M.63c, coming with ISE Release 12.2. The previous bug was ROM creation from a case statement. But hey, that was two years ago.
This time I the code says (irrelevant parts eliminated):
reg [3:0] writeidx; reg [31:0] buf_w0; reg [31:0] buf_w1; reg buf_wen; reg buf_wen_d; reg [31:0] buf[0:15]; reg [3:0] counter; if (buf_wen) begin buffer[writeidx] <= buf_w0; writeidx <= writeidx + 1; end else if (buf_wen_d) begin buffer[writeidx] <= buf_w1; writeidx <= writeidx + 1; end
The slightly nasty thing about this clause is that “buffer” is an inferred distributed RAM (i.e. implemented in slices) because it’s small, and there’s an “if” statement which controls what is written to it. This messed things up. I’ll forgive the synthesizer for failing to optimize away RAM elements that clearly have a constant value of zero, since their input is always zero. What I can’t leave alone is that it created wrong logic. In particular, it completely ignored the existence of buf_w0, and generated code as if only the buf_w1 assignment existed. As a matter of fact, buf_w0 wasn’t even mentioned in the synthesis report. There was no warning about its disappearance. Like a good-old Soviet elimination. I was lucky enough to read the synthesis warnings to learn that a register, which drives buf_w0, was optimized out, and I couldn’t understand why. Until I checked what happened in FPGA editor, and saw that buf_w0 had gone up in smoke.
And here’s the silly workaround that fixed it. The code is logically equivalent, of course, but feeds XST with what I really want: A mux. Hurray. Not.
if (buf_wen || buf_wen_d) begin buffer[writeidx] <= buf_wen ? buf_w0 : buf_w1; writeidx <= writeidx + 1; end