UDB shift output not getting correct values

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

I'm working on a simple Neopixel driver on a PSoC 4200 using UDBs.  The state machine accepts 24 bits into the F0 FIFO, moves the F0 into A0, then shifts the 24 bits one at a time using the shifter.  The state machine portion, accepting data into the FIFO, transferring it into A0, sending bits out one bit at a time, adding the proper bits for the Neopixel protocol, works properly.  The output from the UDB shifter seems give random values.

To observe the shift out signal, I created a data path out signal for the shift out, and routed it to an external pin.  The shifting only happens at a single point in the state machine.  Is the shift out from the shifter persistent (i.e. does it retain its last value until another shift operation occurs)?  The value of shift out seems to change faster than the clock input to the state machine.

I have tried to base my model off the example found in Designing PSoC Creator™ Components with UDB Datapata document Project #3 (Simple UART).  That example only uses a 8-bit wide data path, while I'm using a 24 bit wide data path.  I have tried changing the data path width to 8 bits, but still see random values as the shift output.  I am using version 4.1 of PSoC Creator.

Any pointers towards where the problem could be would be greatly appreciated.

1 Solution
Anonymous
Not applicable

I have it working now.  There were a couple of issues that I found.

  1. First, the pin that I was using for shift_output is being driven internally by some other signal.  I originally put it on P2[4], and that showed the contention as seen in the logic analyzer trace.  I ended up moving it to pin P1[0] and the signal started making a lot more sense.  This could simply be that the pioneer board that I'm using has something else hanging off that signal, but I've been too lazy to look at the schematics.
  2. Using the UDB editor, it seems that when F0 FIFO is moved to A0, it always shifts and fills out the shift output bit regardless of whether the shift is set in that instruction.    This is probably a bug in the UDB editor but works well if the UDB datapath is being used to create a serial protocol.  If the UDB datapath is used as a FIFO to change the width of a PWM, this would cause problems.  It would take more investigation to really understand this, but it works good enough for me.
  3. Shift output is overwritten by a carry output ALU operation.  I incorrectly believed that the shift output from the shifter and carry output from the ALU were separate bits and updated at separate times.  It seems like they share the same register somewhere in the hardware or running an ALU operation overwrites the last value of the shift output regardless of if a shift is configured.  If the shift output value is needed later, it must be saved in a separate variable.
  4. UDB editor gets into endless unexpected exception when trying to configure instructions.  Don't know how I get Creator v4.1 into this state, but it couldn't find its way out.  Every change to an instruction after pressing OK resulted in an unexpected exception and the new configuration not being saved.  The kludgy fix that I came up with was to delete the whole datapath and recreate it from scratch.

After I wrap everything up, I will post the completed NeoPixel library.

!!! Warning:  Technical Jargon and timings coming up.  !!!

Basically a 24 bit value is handed in for each Neopixel to set the color value, and an interrupt/status bit is used to say when the FIFO is at the midpoint.  When the FIFO becomes empty, it assumes the chain is completed, and properly ends the cycle by keeping the line low.  It is up to higher level firmware to guarantee the 50 us dead time at the end of the cycle.  (I tend to use a longer timer to start processing every 20 ms).  The base frequency of the timer is 2.4MHz so each bit is transferred every 1.25 us, so 24 * 1.25 us = 30 us per Neopixel.  If updating every 1 ms, (1000 us - 50 us)/30 us = 31 Neopixels.  If updating every 10 ms, (10000 us - 50 us)/30 us = 331 Neopixels, etc.  Since using the mid point of the FIFO, an interrupt should come in approximately every 60 us to request that the FIFO be refilled.  If RGBW LEDs are used, the timings per Neopixel will be 40 us.

I will mark this post as the correct answer when I take the time to finish it up and post the code.

View solution in original post

0 Likes
13 Replies
bharadhwajas_91
Employee
Employee
First like received First like given

Hi

I'm not sure what your datapath configuration is but the shifter configuration should be simple.

Please start with a 8 bit shifter , an example configuration is as shown below :

pastedImage_0.png

If you are looking for 24 bit , I would suggest you to refer to the already existing Shift reg component.

Please import the B_ShiftReg_V2_30 component , which is the base verilog file for the shift register component, you can find the example reference for 32, 24,16 and 8 bit shift registers .

When using three datpaths ,please use chain config for middle datapath and the last datapath (based on your direction) for Shift SELA ,B configurations in datapath .

The datapath output is the output of the last/first flipflop in the register configuration based on the direction ,so it will retain its value if there is no more shifts ,also So_reg is a delayed version of the output .

Anonymous
Not applicable

I'm trying to configure it using the UDB Editor found in Creator v4.1. A

shift output is configured for the 24 bit register, and I am definitely

seeing that value change at times other than the rising clock edge of the

UDB clock. The state machine itself which was done through the Editor

works perfectly, and I see it walking through the steps appropriately. (I

outputted the state bits to pins, so I can monitor that the state machine

works properly).

I have also changed the 24 bit register to an 8 bit register to see if that

would work better. (Note: all of these are left shifting the register,

not right shifting the register). Even with a width of 8 bits or a single

UDB FIFO, I see a noisy signal as the shift output. It almost looks as if

the shift output is not being driven at all, so it is just floating within

the part.

On Tuesday I'm planning to try and change to a right shift from a left

shift to see if that gives a better output. When using the UDB Editor, I

fill out the output section of the datapath with Shift_Output as the output

of the shift. I then use Shift_Output and send that signal to a pin so

that it can be observed. Are any other steps necessary to "enable" the

shift output signal than adding it to the output section? I also have

probes on the UDB clock signal, so I know that the signal is changing at

times other than the rising edge of the clock.

0 Likes

Can you attach your project ?

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

I tried to remove all the extra stuff so only the NeoPixel library/state

machine is included in this project. I've included the archive file which

should have everything.

I've also included a trace that I get on the logic analyzer. The last

signal (labeled as Shift) is the shift output from the shifter in the UDB.

When I zoom in, I can see that it doesn't look like a latched signal, but

appears to change randomly. The trace is from sending 2 bytes (0xa5, 0xff)

into the FIFO. Looking at the output of SerOut (output going to neopixel

data line) the it is sending 0x4a 0xfe. (Last bit is cut off in image

below)

The only state that shifts the data from the FIFO is state 010. If the

shift output is a registered signal, it should not be changing nearly as

frequently as I'm seeing.

0 Likes
Anonymous
Not applicable

Forgot to mention that the above project is simply using an 8 bit FIFO and not trying to chain 3 UDB together to form a 24 bit FIFO.  If I can't get a single UDB to shift out data properly, there is little reason to try and chain multiple UDBs together.  Once the 8 bit works, I will move back to the 24 bit FIFO which will reduce the amount of interrupts the processor will need to handle.

0 Likes
Anonymous
Not applicable

I have it working now.  There were a couple of issues that I found.

  1. First, the pin that I was using for shift_output is being driven internally by some other signal.  I originally put it on P2[4], and that showed the contention as seen in the logic analyzer trace.  I ended up moving it to pin P1[0] and the signal started making a lot more sense.  This could simply be that the pioneer board that I'm using has something else hanging off that signal, but I've been too lazy to look at the schematics.
  2. Using the UDB editor, it seems that when F0 FIFO is moved to A0, it always shifts and fills out the shift output bit regardless of whether the shift is set in that instruction.    This is probably a bug in the UDB editor but works well if the UDB datapath is being used to create a serial protocol.  If the UDB datapath is used as a FIFO to change the width of a PWM, this would cause problems.  It would take more investigation to really understand this, but it works good enough for me.
  3. Shift output is overwritten by a carry output ALU operation.  I incorrectly believed that the shift output from the shifter and carry output from the ALU were separate bits and updated at separate times.  It seems like they share the same register somewhere in the hardware or running an ALU operation overwrites the last value of the shift output regardless of if a shift is configured.  If the shift output value is needed later, it must be saved in a separate variable.
  4. UDB editor gets into endless unexpected exception when trying to configure instructions.  Don't know how I get Creator v4.1 into this state, but it couldn't find its way out.  Every change to an instruction after pressing OK resulted in an unexpected exception and the new configuration not being saved.  The kludgy fix that I came up with was to delete the whole datapath and recreate it from scratch.

After I wrap everything up, I will post the completed NeoPixel library.

!!! Warning:  Technical Jargon and timings coming up.  !!!

Basically a 24 bit value is handed in for each Neopixel to set the color value, and an interrupt/status bit is used to say when the FIFO is at the midpoint.  When the FIFO becomes empty, it assumes the chain is completed, and properly ends the cycle by keeping the line low.  It is up to higher level firmware to guarantee the 50 us dead time at the end of the cycle.  (I tend to use a longer timer to start processing every 20 ms).  The base frequency of the timer is 2.4MHz so each bit is transferred every 1.25 us, so 24 * 1.25 us = 30 us per Neopixel.  If updating every 1 ms, (1000 us - 50 us)/30 us = 31 Neopixels.  If updating every 10 ms, (10000 us - 50 us)/30 us = 331 Neopixels, etc.  Since using the mid point of the FIFO, an interrupt should come in approximately every 60 us to request that the FIFO be refilled.  If RGBW LEDs are used, the timings per Neopixel will be 40 us.

I will mark this post as the correct answer when I take the time to finish it up and post the code.

0 Likes

Very interesting approach to drive the NeoPixels, looking forward to check your final use of the UDBs.

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Updated/cleaned up the library with an example project.  This is the minimal CPU utilization on the PSoC4 that I can imagine.  The example uses either polling to fill the FIFO or interrupts depending on a single define in the code.  Using interrupts is more efficient since no polling when processing isn't occurring.  A DMA into the FIFO would make this even better, but alas, the PSoC4 doesn't haven any DMAs.  (Almost makes me want to purchase a PSoC5 just to add the DMA.

The example project drives 8 NeoPixels with a rotating color scheme with an update every 500 ms.  In real life, the pixel update function would simply statically allocate the RAM for a pixel buffer, and just continuously use that list to update the NeoPixels.  The main program would then update the individual pixels in the RAM pixel buffer as it wanted their colors to change.  Doesn't get much simpler than that.

There's PSoC 4M and 4L families with DMA, but the DMA configuration is different from the 5LP DMA.

0 Likes
Anonymous
Not applicable

I'm using the Cy8ckit‑049‑42xx which does not have any DMAs available.  I've been telling people to buy those boards for the last 3 or 4 years for the open source project I run.  While they don't have a DMA, they are more than sufficient for how they are used in the project.

0 Likes

Having the opportunity to debug your project (setting breakpoins, inspecting or setting variables) and getting DMA resources is worth the money a CY8CKIT-043 PSoC M prototyping kit costs.

Bob

0 Likes
Anonymous
Not applicable

I actually use the Pioneer CYCKIT-042 kit to debug.  (Was the only available debugging kit back four years ago).  The new "stick" kits are cheaper and even nicer in my opinion.  I would certainly go that way today for debug purposes.  The Cy8ckit‑049‑42xx is used for the final build because of price and size.  I use approximately four of those per pinball machine to drive the electronics, and having them so small allows them to live under the playfield and be distributed to minimize wiring.  They work well for me.  Thanks for the suggestions.

0 Likes

Hi thanks for posting this. I wondered if you can help? I have a CY8C4125AZI-S423 and I am trying to run your code on it. I have two problems. Number 1 is that the component TFF does not work on the 4100 series, secondly my max clock is 24Mhz not 48MHz, is there anything I can do?

thanks

0 Likes