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 :
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 .
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
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
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.
Can you attach your project ?
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
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.
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.
I have it working now. There were a couple of issues that I found.
- First, the pin that I was using for shift_output is being driven internally by some other signal. I originally put it on P2, and that showed the contention as seen in the logic analyzer trace. I ended up moving it to pin P1 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.
- 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.
- 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.
- 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.
Very interesting approach to drive the NeoPixels, looking forward to check your final use of the UDBs.
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.
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.
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.