01-13-2010 10:47 PM
First, I'm a long time microcontroller guy, and never thought I'd get as far as I have with hdl. My hat is off to Xilinx and the tools. But I'm still learning a lot.
I'm stuck on a problem right now with a simple SPI. In the code below, I can see the value of DataToWrite is not changing on my logic analyzer when I force writes from a computer program. And most of the time the output is correct. But occasionally I'll see a bit that is supposed to be a '1' in the SPIData stream instead be a zero. Behavioral simulation works as expected, and speeds are slow (12 MHz SPI clock)
There are a few clues that I don't understand, but perhaps someone else does
1) I discovered the problem when I was using ISE 11.1. When using that, writing FFFF would show some low order bits flicking to zero unexpectedly. They are correctly aligned time wise. It's just I was expecting to see a '1' there and a zero was seen instead.
3) After I moved to 11.4 tonight (hoping that might fix the problem), the location of the bits flicking to zero moved to a single bit in the higher orders.
4) If I route the DataToWrite[0] signal to the outside world, the problem goes away.
5) Diff'ing the output of the tools with DataToWrite going to the outside and not going to the outside didn't reveal any difference. I was kind of hoping to see something get optimized away when the signal wasn't getting routed to an outside pin, but no luck.
Any thoughts on what to try next? This PCB has 5 bits of easily accessed IO, and no jtag, so 32 channels of debug isn't possible. Next board will have more.
The system clock is 48 MHz. The SPI clock is running at 12 MHz. ClkDiv4 is actually running at 24 MHz. ClkDiv4 is derived by a counter driven by 48 MHz clock.
Status[0] is set/cleared by the 48 MHz clock. This is the indication to start writing.
// State machine to pump out dataalways @(posedge ClkDiv4)begin case (State) IDLE: begin if (Status[0]) begin // If set, we need to begin transmission of the data in DataToWrite TXBuf <= DataToWrite; State <= TX0; end else begin // Nothing to do SPICSReg <= 1; end end TX0: begin State <= TX1; SPICSReg <= 0; SPIClkReg <= 0; BitCounter <= 6'd32; // Each count is half a cycle, so this will transmit 16 bits SPIDataReg <= TXBuf[15]; TXBuf <= {TXBuf[30:0], 1'b0}; end TX1: begin BitCounter <= BitCounter - 1'b1; if (BitCounter > 0) begin SPIClkReg <= ~SPIClkReg; end else State <= IDLE; // Only change data on falling edge if (SPIClkReg) begin SPIDataReg <= TXBuf[15]; TXBuf <= {TXBuf[30:0], 1'b0}; end end default: State <= IDLE; endcaseend// If we don't have this going to the outside world, this doesn't work. Don't know why. What happens is the SPIData signal goes low corrupted at times. // Perhaps there is some optimization going on that isn't clear????assign debug1 = DataToWrite[0];
Thanks for any suggestions.
01-17-2010 12:58 AM
Hi,
I refactored the code a bit for simplicity:
// State machine to pump out data
always @(posedge ClkDiv4)
begin
case (State)
IDLE: begin
SPICSReg <= 1;
BitCounter <= 15;
if (Status[0]) begin
// If set, we need to begin transmission of the data in DataToWrite
SPICSReg <= 0;
TXBuf <= DataToWrite;
State <= TX;
end
end
TX: begin
SPIClkReg <= 1'b0;
if (BitCounter > 0) begin
BitCounter <= BitCounter-1;
State <= TOGGLE_CLOCK;
SPIDataReg <= TXBuf[15];
TXBuf <= {TXBuf[14:0], 1'b0};
end
else begin
State <= IDLE;
end
end
TOGGLE_CLOCK: begin
SPIClkReg <= 1'b1;
State <= TX;
end
default:
State <= IDLE;
endcase
end
The CS gets asserted before the first clock edge and the clock toggle its own state. The data shift register is now only 16 bits wide as that is only what's needed.
I would add a reset state of some kind to make sure CS is not asserted during initialization.
If you have 5 bits of IO, you can put the state on it (2 bits) and CS etc you can probably probe with a scope or logic analyzer. Do some simulations first and read the synthesis reports; they will report any logic optimization, shift register inference etc.
If this still doesn't produce any clues, try to do a gatelevel simulation (can be a bit tedious to set up) of the place and outed netlist. That should provide the exact behavior of the FPGA.
Cheers,
Johan
01-17-2010 06:19 PM
Hi Johan, thanks for taking the time to look at this. I think your BitCounter needed to be set to 16, is that right?
This works most of the time, but another problem has shown up, and like the first problem, I don't understand how this is possible: The clocks will clock out, but sometimes the CS never goes low. In order to get into TX state the CSReg must also get set low. Seems impossible. How can this happen?? Perhaps they logic is all getting routed into a bad block on the xilinx and this is causing problems??
Here's another piece to the puzzle: This board was built in China using parts that were obtained in a rush, and the guy that had them built said he couldn't guarantee that everything was not counterfeit. I was thinking a counterfeit op-amp here or there, but as I look on the web it seems that there are indeed counterfeit xilinx parts floating about. I need to study this more.
http://www.smttech.com/pdf/Engineered-Blacktop-Material-Analysis-SMT-Corporation-PP-08-27-09.pdf
Thanks for the advice on the gate level simulation. In my newness, I wasn't aware of this but I'll definitely study.
I'm going to put this problem on the back burner until I have some more boards and confidence in the hardware. Thanks so much for your help.
01-17-2010 09:32 PM
As I look at the part, the BGA is laser-marked
XC3S400
FT256AFQ0409
D1297924A
4C-ESA
Does the ESA designation mean Easypath? Engineering Sample? It's not mentioned in the 12/9/2009 Spartan 3 data sheet. Perhaps that explains the odd behavior? Or is my newness to FPGAs the bigger culprit? :)