cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
matttay
Observer
Observer
3,743 Views
Registered: ‎01-13-2010

Problems with simple SPI

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. 

 

0 Kudos
Reply
3 Replies
woutersj
Explorer
Explorer
3,704 Views
Registered: ‎07-27-2009

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

matttay
Observer
Observer
3,697 Views
Registered: ‎01-13-2010

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. 

0 Kudos
Reply
matttay
Observer
Observer
3,694 Views
Registered: ‎01-13-2010

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? :)

 

 

 

0 Kudos
Reply