Shop OBEX P1 Docs P2 Docs Learn Events
Need Help! Weird counter behavior at PLL16X only! — Parallax Forums

Need Help! Weird counter behavior at PLL16X only!

lonesocklonesock Posts: 917
edited 2009-06-28 01:11 in Propeller 1
Hi, All.

I've been working on some fast SPI routines for SD card access, and I have code that works fine at RCFAST, and PLL1X through PLL8X, but bombs on PLL16X. I thought maybe I was violating the SD timing spec at the fast rates, but all the data-sheets I could get my hands looked like I was well within my timing "rights". So I boiled it down to the simplest test case I could think of...

TEST CASE:

* Set Counter A to "LOGIC A" mode, with pinCLK as my input
* Set Counter B to "NCO single ended" mode, with pinCLK as my output
* set the dira register to allow pinCLK as an output
* Have Counter B clock out 8 pulses (2 clocks high, 2 clocks low)
* Start FRQA at 1<<14
* After each clock pulse, shr frqa by 2
* This should give me 2 accumulations per clock pulse, then shift my frqa down by 2 bits
* NOTE: because "LOGIC A" mode in fact reads A1, or the pin delayed by one clock, I had to have the clock line look like 0110, instead of 0011, otherwise the clock pulse would straddle each "shr frqa".

RESULTS:
PLL1X - PLL8X: "Counter Feedback = 01010101010101010" (as expected)
PLL16X only:    "Counter Feedback = 00110101010101011" (the weirdness)



Can anyone help me understand why PLL16X would yield different results? (Note: nothing is connected to the pin)

{{
  Testing a PLL16X weirdness

  Jonathan Dummer
}}

CON
  _clkmode      = xtal1 + pll16x
  _xinfreq      = 5_000_000
  pinCLK        = 27

OBJ
  term : "FullDuplexSerial"

VAR
  long feedback

PUB StartTest
  ' set up my serial link to use the same pins as the programmer
  term.start( 31, 30, 0, 19200 )
  ' I will use 2 counters to drive and monitor pinCLK
  ' set the clock mode to "Numerically Controlled Oscilator, Single Ended", driving pinCLK
  clockMode := (%00100 << 26) | (pinCLK << 0)
  ' set the reader mode to "LOCIG A", where A is pinCLK
  readerMode := (%11010 << 26) | (pinCLK << 0)
  ' and the mask for output?
  feedback := |<pinCLK
  ' start my test assembly cog
  cognew( @test_asm_entry, @feedback )
  ' now do infinite status updates
  repeat
    term.str( string( "Counter Feedback = " ) )
    term.bin( feedback, 17 )
    term.tx( 13 )
    waitcnt( (clkfreq << 1) + cnt )  

DAT
ORG 0

test_asm_entry
        ' read in the bitmask for the clock line
        rdlong dira,par
        ' set up my counters
        mov ctra,readerMode
        mov ctrb,clockMode
        ' clear my mask
        mov value,#0

test_loop
        ' update our main feedback variable
        wrlong value,par
        mov value,#0         
        ' set up my input timer, done outside
        mov frqa,#1
        shl frqa,#14
        mov phsa,#0
        ' set up my clock, and start it
        movi phsb,#%01_0000000 ' works for 5MHz PLL1x to PLL8x
        movi frqb,#%01_0000000
        ' keep reading in my value
        shr frqa,#2
        shr frqa,#2 
        shr frqa,#2 
        shr frqa,#2 
        shr frqa,#2 
        shr frqa,#2 
        shr frqa,#2 
        mov frqb,#0 ' stop the clock
        mov value,phsa
        mov frqa,#0
        
        ' start over
        
        jmp #test_loop

{=== PASM Variables ===}
clockMode     long 0
readerMode    long 0

{=== PASM scratch variables ===}
value         res 1

FIT 476


▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
lonesock
Piranha are people too.

Comments

  • whickerwhicker Posts: 749
    edited 2009-06-25 16:48
    jitter for the ratio between high and low time on the clock?

    after all we're multiplying by 16 here. with 8x and lower, there's going to be a divider that makes the high and low time 50-50.

    just a thought.
  • lonesocklonesock Posts: 917
    edited 2009-06-25 23:34
    whicker said...
    jitter for the ratio between high and low time on the clock?

    after all we're multiplying by 16 here. with 8x and lower, there's going to be a divider that makes the high and low time 50-50.

    just a thought.
    Makes sense. I was just hoping that since both counters are operating on the same internal clock that they could match up better. I'm going ahead with using 2 instructions per bit for the read, unless a guru knows how to sidestep this issue? (Or maybe we could tease Chip away from II long enough to look at this [noparse][[/noparse]8^)

    pressing on...

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    lonesock
    Piranha are people too.
  • kuronekokuroneko Posts: 3,623
    edited 2009-06-26 01:20
    FWIW, it works for me. The only change I made (demo board LED debugging) is that I stop the cog (instead of looping) after I copied value to feedback. In the SPIN part I just wait 2 sec after cognew and display either high or low byte of the 16bit value. And I always get $AAAA.
  • lonesocklonesock Posts: 917
    edited 2009-06-26 02:11
    kuroneko said...
    FWIW, it works for me. The only change I made (demo board LED debugging) is that I stop the cog (instead of looping) after I copied value to feedback. In the SPIN part I just wait 2 sec after cognew and display either high or low byte of the 16bit value. And I always get $AAAA.
    Hmmm. It fails for me on 2 boards, 1 is a default protoboard (not USB), and the other is custom. I have a few more I could test, I guess, but if the code will fail on any percentage of otherwise working props, I'll have to scrap it. (I do need it to work repeatedly back to back, as this is for transferring blocks of data from SD cards).

    Thanks very much for trying it out for me,
    Jonathan

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    lonesock
    Piranha are people too.
  • kuronekokuroneko Posts: 3,623
    edited 2009-06-26 02:23
    Just curious, why do you sample twice? If you're just after 8 bits then isn't once enough?
  • lonesocklonesock Posts: 917
    edited 2009-06-26 03:18
    kuroneko said...
    Just curious, why do you sample twice? If you're just after 8 bits then isn't once enough?
    Sorry, the test case is misleading. I wish I could figure out a way to just sample once, and shift it into a result register, all in one instruction. What I was actually doing to read in a single byte was this:

            mov value,#0         
            ' set up my input timer, done outside
            mov frqa,#1<<7
            mov phsa,#0
            ' set up my clock, and start it
            movi phsb,#%01_0000000 ' works for 5MHz PLL1x to PLL8x
            movi frqb,#%01_0000000
            ' keep reading in my value
            shr frqa,#1
            shr frqa,#1 
            shr frqa,#1 
            shr frqa,#1 
            shr frqa,#1 
            shr frqa,#1 
            shr frqa,#1 
            mov frqb,#0 ' stop the clock
            mov value,phsa
            mov frqa,#0
            shr value,#1
    


    The LOGIC A&B counter would end up sampling twice because the clock line is high for 2 counts out of every 4, but that is easily fixed by dividing by 2 at the end. This limits me to reading 31 bits, but I was just reading 2 16-bit words and combining for the final long. However in the 16X PLL, it seemed that the timing shifts for one of the counters (it was as if it was doing LOGIC A2&B2, instead of A1&B1).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    lonesock
    Piranha are people too.
  • kuronekokuroneko Posts: 3,623
    edited 2009-06-26 03:34
    lonesock said...
    The LOGIC A&B counter would end up sampling twice because the clock line is high for 2 counts out of every 4, but that is easily fixed by dividing by 2 at the end. This limits me to reading 31 bits, but I was just reading 2 16-bit words and combining for the final long. However in the 16X PLL, it seemed that the timing shifts for one of the counters (it was as if it was doing LOGIC A2&B2, instead of A1&B1).
    So what you want is 1 high-pulse in 4? Then use DUTY cycle or am I missing something?

    Re: 16X PLL that certainly looks odd, I had the impression that the first bit was only added once (%01) and the last bit 3 times (%11). But even with the 20MHz clock that shouldn't be an issue.
  • lonesocklonesock Posts: 917
    edited 2009-06-26 03:44
    kuroneko said...
    So what you want is 1 high-pulse in 4? Then use DUTY cycle or am I missing something?
    I was just trying to play nice with the SD card and give it a 50% duty cycle, but that is definitely an assumption on my part, thanks for catching that. I will review the specs and see if there are any problems driving it at 25%. (I am using this on a 100MHz prop system, so I am at the maximum specified SD clock rate of 25MHz if I use 1 instruction per bit.)

    thanks,
    Jonathan

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    lonesock
    Piranha are people too.
  • kuronekokuroneko Posts: 3,623
    edited 2009-06-26 05:42
    Does it work at 80MHz (that's what I tested it with)?
  • lonesocklonesock Posts: 917
    edited 2009-06-26 13:06
    kuroneko said...
    Does it work at 80MHz (that's what I tested it with)?
    Nope. The first system it failed on was a standard protoboard, 80MHz. The 100MHz system is the target for a project I'm working on right now, and I have one prototype built up with a uSD slot on board, and that system fails as well at PLL16X. The good news, though, is I checked the MMC spec timing, and they say the minimum clock high time is 10ns, so I think a 25% duty cycle may work for reading in data, thanks for the suggestion! I will let you know how it goes.

    thanks,
    Jonathan

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    lonesock
    Piranha are people too.
  • SapiehaSapieha Posts: 2,964
    edited 2009-06-26 14:55
    Hi lonesock

    Add at last 2 Tantalum Caps with voltage regs in holes betwen GND and 5V, GND and 3.3V. (22-47uF)
    For correctness one more betwen GND and IN Voltage (it may be Electrolitic 100uF) but be sure it havs dual voltage spec that Yours IN Voltage to protoboard.
    and test if it helps.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nothing is impossible, there are only different degrees of difficulty.
    For every stupid question there is at least one intelligent answer.
    Don't guess - ask instead.
    If you don't ask you won't know.
    If your gonna construct something, make it·as simple as·possible yet as versatile as posible.


    Sapieha
  • lonesocklonesock Posts: 917
    edited 2009-06-26 22:52
    Sapieha said...
    Hi lonesock

    Add at least 2 Tantalum Caps with voltage regs in holes betwen GND and 5V, GND and 3.3V. (22-47uF)
    For correctness one more betwen GND and IN Voltage (it may be Electrolitic 100uF) but be sure it havs dual voltage spec that Yours IN Voltage to protoboard.
    and test if it helps.
    I will definitely try this, Sapieha, thanks! (It will probably be a few days, things are busy, but I will let you know how it goes.)

    Does anyone have docs on on when counters sample a pin? (beginning of a clock, middle, end, variable, throughout?) I know about accumulation happening one clock after the sampling.

    thanks,
    Jonathan

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    lonesock
    Piranha are people too.
  • lonesocklonesock Posts: 917
    edited 2009-06-27 06:41
    Hi, All.

    Thanks so much for your help and suggestions...I got it working using kuroneko's elegant suggestion (checking the MMC spec, 25% duty cycle is still within spec at 100MHz operation...10ns high time minimum). I'm still going to try the tantalum caps, per Sapieha's recommendation, because I really want to find out why the counters' behavior changed at PLL16x, but that will probably be next week some time.

    thanks again,
    Jonathan

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    lonesock
    Piranha are people too.
  • kuronekokuroneko Posts: 3,623
    edited 2009-06-28 01:11
    I just made a disturbing observation. When I use a clean pin (no pull-up/down, demo board 0..7) for the clock (i.e. what links the counters in your test case) I get expected behaviour. However, when running with pin 27 (which uses 10K+100 against Vdd, keyboard clock) I can see the %01/%11 weirdness.
    • If I keep the clock running (20MHz ctrb) rather than switching it on/off around the byte it gets rid of the top bit error (%01)
    • The lower bit is still %11 but that is I believe due to the way the clock is placed in relation to when phsa is sampled. I.e. if I simply remove the stop the clock bit then it accumulates once, placing a nop gives you 2 more accumulations.
    • An 8th shr frqa, #2 will resolve that problem (this won't accumulate anything but keeps the relevant bits in sync).
    I did some more tests and what it boils down to is that unclean pins can delay your signal by as much as one clock cycle (in terms of getting sampled or not). I also confirmed A1 being used to trigger accumulation (not that I doubted it). Well, that leaves quite a bit of thinking on your part as to how you want to handle this issue. Keep us informed!

    Also, the counter application note has some basic schematics which suggests sampling with L/H clock edge (around page 15).

    Post Edited (kuroneko) : 6/28/2009 4:10:25 AM GMT
Sign In or Register to comment.