SDRAM working on prototype - not on production.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

SDRAM working on prototype - not on production.

558 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jcarter on Wed May 09 02:00:11 MST 2012
Hello All,

I have a design using an LPC1788 together with a SDRAM module from ISSI (IS42S32800D). This is a 32bit interface.

I have routed this design out and had a prototype made with a PCB manufacturer that does low cost 6 layer prototypes. The prototype PCB works fine. I then thought I would get the PCB manufactured in a small volume batch (100) from my usual PCB supplier. I gave them the stack up information that my prototype used to ensure there would be no issues.

However! I have massive problems with the production board. At first I was unable to raise any response from the SDRAM what-so ever with the same code I used in my prototype board. The previous board was working at 120Mhz so I was sure something was wrong with this new board. I then found a post where people suggested using Repeater Mode on the SDRAM data lines (I had not used this previously) and this raised a response from the SDRAM, however it is not stable. I can write to 16 or so addresses, but then with subsequent reads the data returned (at every address) is the data which I wrote last (probably due to Repeater Mode). When I disable repeater mode, the data returned is 0xFFFFFFF.

I am using the same termination resistors of 22Ohms on both boards, data lines are an average of 3cm long. Clock line is 2.4cm long. Address lines are average of 3.8cm long.

Is this too out of spec, should I delay the clock longer if it substantially shorter? I am really stuck here, as I have changed nothing about the design I was hoping for a seamless manufacture run for these boards.

I would appreciate any help from you guys.
Labels (1)
0 Kudos
11 Replies

509 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by SimonThome on Mon Dec 03 12:25:09 MST 2012
Sounds like you are somewhat "lucky" to get it working at 120MHz, sounds like they will only guarantee a max of 80Mhz, which is a shame really. I would rather not take the risk on my boards when they are in full production, they will be running in an industrial application and I won't be able to get away with the occasional/possible failure.

So am I correct in saying that if the device is running at 120MHz, that will mean that the EMC clock should only be at a max of 60MHz? As according to NXP 80MHz is the max limit, so with the divide by 1 or 2 clock setting that will force me to use 60MHz to be on the safe side
0 Kudos

509 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mc on Mon Dec 03 11:57:55 MST 2012
Hi Dave/Lucas,
Yes, that is Correct. Maximum EMC frequency on LPC1788 is 80MHz.

0 Kudos

509 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Mon Dec 03 10:17:09 MST 2012
That's a loaded question, Simon...  My response above ("...I wonder when they're going to fix that?") was actually sarcasm.  :-)

The official "maximum" clock speed for the EMC, as stated in the manual, is 80Mhz.

Have a look at Table 18; the value for Tcy(clk) is 12.5ns, which is 80Mhz.

However...


...every single LPC1788 I've programmed works just fine at 120Mhz (I've programmed quite a few now).

So, my understanding is that NXP's official position on this is simply: it's 80Mhz.

That's what they will guarantee - anything else is a bonus...

guess I'm just extremely lucky with every processor I've gotten so far...

0 Kudos

509 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by SimonThome on Mon Dec 03 06:35:08 MST 2012
so to clarify, what is the max clock speed for EMC(SDRAM)?
0 Kudos

509 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Fri Sep 21 16:25:38 MST 2012
Yup - it still says 12.5ns, or 80Mhz...  I wonder when they're going to fix that?
0 Kudos

509 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mc on Fri Sep 21 14:42:45 MST 2012
Hi Dave,James and Lucas,
Could you please have a look on LCP177x datasheet below for Maximum SDRAM speed.
http://www.nxp.com/documents/data_sheet/LPC178X_7X.pdf
0 Kudos

509 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mc on Thu Sep 20 16:40:50 MST 2012
Hi Lucas,
Could you post your schematics here?

Thanks
0 Kudos

509 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by lucas.pirolla on Thu Sep 20 14:16:12 MST 2012
Dear James,

I'm also developing a prototype board with the  IS45S32800D and LPC1788, but until now, I couldn't make my LPC talk to the SDRAM!

Could you send me the configuration timings and initialization files you used in order to make this very  IS45S32800D work???  This is my first board with SDRAM, and I'm probably making mistakes regarding the EMC configuration.

Best Regards,
Lucas
0 Kudos

509 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Fri May 11 21:46:52 MST 2012
What type of test software are you using to determine how "perfectly" your SDRAM was working on your prototype?

Can you run a diagnostic on your original prototype and see how it performs?

I too just finished a prototype board, but I used the 208pin QFP.  Also, in my layout, I length matched all of the signals to each other, and have an average length of 3.5" (all within 50 mils of each other), and my prototype functions fine at 120Mhz.

I use a delay constant of 0x00000C04 in LPC_SC->EMCDLYCTL...

Here is copy of the comprehensive memory test I used on my prototype:
<code>
void SDRAM_Test( void )
   {
   uint32_t register *uint32_t_ptr;
   uint16_t register *uint16_t_ptr;
   register uint32_t Mask32;
   register uint16_t Mask16;
   uint32_t i, k, Count, ErrorCount;
   uint32_t RelativeTimer;
  
   Count = 0;
   ErrorCount = 0;                                                   // zero error count for this run...                      
   ANSIsetcolor( BRIGHT, ANSI_WHITE, ANSI_BLUE );                    // set Hyperterm colors                                  
   printf("COUNT BYTES   CLR   MEMSIZE16  WALKBIT16  ALTBIT16  SEQBIT16  MEMSIZE32  WALKBIT32  ALTBIT32  SEQBIT32  ERRORS   EMCcal\r\n");
   printf("----- ------- ----- ---------  ---------  --------  --------  ---------  ---------  --------  --------  ------   ------\r\n");
  
   while( 1 )
      {
      ANSIsetcolor( BRIGHT, ANSI_YELLOW, ANSI_BLUE );                // set Hyperterm colors                                  
      printf("%05u ", Count++);
      printf("%07u %03ums ",(uint32_t)(SDRAM_SIZE), ClearSDRAM());   // Clear content before 16 bit access test               
    
      ANSIsetcolor( BRIGHT, ANSI_WHITE, ANSI_BLUE );                 // set Hyperterm colors                                  
      k = SDRAM_SIZE>>1;                                             // size in bytes divided by 2 (16bit access)             
      printf("%09u  ", k);                                           // show memory size...                                   
     
      ANSIsetcolor( BRIGHT, ANSI_YELLOW, ANSI_BLUE );                // set Hyperterm colors                                  
     
      /* walking bit test 16-bit -------------------------------*/
      RelativeTimer = SystemTimer;
      for( Mask16=0x0001; Mask16; Mask16 <<= 1 )
         {
         uint16_t_ptr = (uint16_t *)(SDRAM_BASE_ADDR);
         for( i=0; i<k; i++ )
            {
            *uint16_t_ptr = Mask16;
            if( *uint16_t_ptr++ != Mask16 )
               ErrorCount++;
            }
         }
      RelativeTimer = SystemTimer - RelativeTimer;
      printf( "%7ums  ", RelativeTimer);
      /* ------------------------------------------------------ */
  

      /* alternate bit test 16-bit -----------------------------*/
      RelativeTimer = SystemTimer;
      for( Mask16=0x5555; Mask16!=0x5554; Mask16 <<= 1 )
         {
         uint16_t_ptr = (uint16_t *)(SDRAM_BASE_ADDR);
         for( i=0; i<k; i++ )
            {
            *uint16_t_ptr = Mask16;
            if( *uint16_t_ptr++ != Mask16 )
               ErrorCount++;
            }
         }
      RelativeTimer = SystemTimer - RelativeTimer;
      printf( "%6ums  ", RelativeTimer);
      /* ------------------------------------------------------ */

  
      /* unique value test 16-bit ----------------------------- */
      uint16_t_ptr = (uint16_t *)(SDRAM_BASE_ADDR);
      RelativeTimer = SystemTimer;
      for( i=0; i<k; i++ )
         *uint16_t_ptr++ = ( i%65536 );
      uint16_t_ptr = (uint16_t *)(SDRAM_BASE_ADDR);
      for( i=0; i<k; i++ )
         {
         if( *uint16_t_ptr++ != ( i%65536 ) )
            ErrorCount++;
         }
      RelativeTimer = SystemTimer - RelativeTimer;
      printf( "%6ums  ", RelativeTimer);
      /* ------------------------------------------------------ */

     
      ANSIsetcolor( BRIGHT, ANSI_WHITE, ANSI_BLUE );                 // set Hyperterm colors                                  
      k = SDRAM_SIZE>>2;                                             // size in bytes divided by 4 (32bit access)             
      printf("%09u  ", k);                                           // show memory size...                                   
      ANSIsetcolor( BRIGHT, ANSI_YELLOW, ANSI_BLUE );                // set Hyperterm colors                                  
     
      /* walking bit test 32-bit -------------------------------*/
      RelativeTimer = SystemTimer;
      for( Mask32=0x00000001; Mask32; Mask32 <<= 1 )
         {
         uint32_t_ptr = (uint32_t *)(SDRAM_BASE_ADDR);
         for( i=0; i<k; i++ )
            {
            *uint32_t_ptr = Mask32;
            if( *uint32_t_ptr++ != Mask32 )
               ErrorCount++;
            }
         }
      RelativeTimer = SystemTimer - RelativeTimer;
      printf( "%7ums  ", RelativeTimer);
     
      /* alternate bit test */
      /* ------------------ */
      RelativeTimer = SystemTimer;
      for( Mask32=0x55555555; Mask32!=0x55555554; Mask32 <<= 1 )
         {
         uint32_t_ptr = (uint32_t *)(SDRAM_BASE_ADDR);
         for( i=0; i<k; i++ )
            {
            *uint32_t_ptr = Mask32;
            if( *uint32_t_ptr++ != Mask32 )
               ErrorCount++;
            }
         }
      RelativeTimer = SystemTimer - RelativeTimer;
      printf( "%6ums  ", RelativeTimer);
  
      /* unique value test */
      /* ----------------- */
      uint32_t_ptr = (uint32_t *)(SDRAM_BASE_ADDR);
      RelativeTimer = SystemTimer;
      for( i=0; i<k; i++ )
         *uint32_t_ptr++ = i;
      uint32_t_ptr = (uint32_t *)(SDRAM_BASE_ADDR);
      for( i=0; i<k; i++ )
         {
         if( *uint32_t_ptr++ != i )
            ErrorCount++;
         }
      RelativeTimer = SystemTimer - RelativeTimer;
      printf( "%6ums  %6u    ", RelativeTimer, ErrorCount);
     
      printf( "%3d\r\n", Check_EMCCAL() );
      }
   }
</code>
0 Kudos

509 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jcarter on Thu May 10 08:05:13 MST 2012
Hi Dave,

  Thanks very much for your reply. Do you think removing the termination resistors(0 ohm jumpers) would affect this in any way?

  I do have one address line stretching 44mm, but again I think this should be fine not to require a termination resistor.

  I thought from my SDRAM datasheet the rise time on these signals is 1ns, but maybe I am incorrect in this. This is the only reference to rise time I could find in the datasheet.

  I have tried various clock delay EMCCLKDLY values. By default the NXP drivers set this to be a Command Delay of 0x8, which is a delay of 1 or 2 ns (not having datasheet here).

  I have tried changing this to CLKOUT0 delay instead, using every value from 0x0 to 0xF but this has the effect stopping the SDRAM completely from about 1ns delay to 1.5ns delay, other values give the same effect.

  There was a post (I belive by yourself) in the forum in the past that suggested the Repeater Mode, the effect of this is to simply retrive the last value outputted to the SDRAM when reading values when the SDRAM has stopped responding (which makes sense).

  I am very confused as I was running this exact same configuration on my prototype 6 layer board at 120Mhz, and the production board should be identical. The dialectric depths are very slightly different (maybe 0.5mm max) across some layers. But surely this cannot have a totally failing effect. I should at least be able to drop the speed to 60Mhz and still have the RAM respond, wouldn't you think?

James
0 Kudos

509 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Wed May 09 08:29:37 MST 2012
A conservative method in calculating transmission line termination is as follows:

Rise time:  0.35/fmax ---> 0.35/120Mhz, or 2.9ns
Max trace length: 2"/ns, or 5.8"

Anything longer will require termination resistors

Since you said your traces are no longer than 3.8cm (1.5"), you probably don't need the termination resistors...

That being said, regarding propagation delay for FR4 material:

- 5.9 mils/ps, or
- 0.1694 ps/mil or
- 169.4ps/inch

If you're traces only vary in length by 0.8cm, you will experience signal latency of up to ~53 ps...


In the LPC1788, you have 3 delays you can control:  the outputs, the feedback clock (for inputs), and the clock.  These are set in the EMCDLYCTL register.

Each bit change in value corresponds to 250 ps of delay...

What value are you storing here during SDRAM initialization?

0 Kudos