# Forum: FPGA, VHDL & Verilog SPI works sometimes

Rate this post
 0 ▲ useful ▼ not useful
Hi everyone,

I'm writing SPI-addressable memory that is synchronous to the SPI sck
clock signal.

So far, some components work as expected, but then cease working
depending on how I add to it.

Currently, I receive data over SPI with a shift register. I send data
over SPI with a shift register with asynchronous loading so that I can
preset the data to send.

The issue is in generating the signal to preset the data to send.

I'd like to preset the shift register with a new byte every time 8 bits
have passed along the spi bus while the CS line is pulled low. (aka, a
multi-byte transfer)

Here's the issue: the code below does just that with the "sendNewData"
signal. The problem is that it's very "sensitive to being changed."

 1 module dataCtrl(input logic cs, sck,  2  output logic setNewData);  3 4  logic [3:0] bitCount;  5   6  assign andOut = bitCount[2] & bitCount[1] & bitCount[0];  7 8   9  always_ff @ (negedge sck, posedge cs)  10  begin  11  if (cs)  12  begin  13  bitCount <= 3'b0000;  14  setNewData <= 1'b1;  15  end  16  else  17  begin  18  bitCount <= bitCount + 3'b0001;  19  setNewData <= andOut;  20  end  21  end  22 endmodule 


If I extend the width of the bitCount signal to 5 or more bits wide,
aka: change from
 1  logic [3:0] bitCount; 
to
 1  logic [4:0] bitCount; 
the code doesn't generate the signal at the right time, and I get data
transferred that is off by one. Does this make sense? I'd like to build
up this module to output other control signals, but I'm hinging my
design on being able to count past 8. Strangely enough, extending this
module in pretty-much any way that builds off of the existing components
reproduces this problem. Do adders need more than one clock cycle to add
if their signals are larger than 4 bits?

I've attached 3 files. The high-level working module. A detailed view of
that same module with the hardware used, and the detailed view of the
module with the larger bitCount signal that doesn't work. (Lastly, the
compiler optimizes away bitCount[3], which isn't used, although the
logic is different.)

Thanks a bunch for your thoughts and input!

Lastly: I'm using a ...
Altera Cyclone IV from a De0 Nano
Quartus II 13.1 Web Edition

Rate this post
 0 ▲ useful ▼ not useful
Joshua Vasquez wrote:
> the code doesn't generate the signal at the right time, and I get data
> transferred that is off by one.
How do you see that? What does the simulation say?

> The problem is that it's very "sensitive to being changed."
Sounds like a "tsu-th-problem" and a race condition.

> Do adders need more than one clock cycle to add if their signals are
> larger than 4 bits?
Look at it the other way: a counter with less than 5 bits is able to get
the result just in time to read the correct word. As far as I see it,
the "setNewData" must be one to late!
But over all: the problem is an interaction with the rest of the code,
because the code you presented is completely synchronous to sck and will
not have a problem on its own.

Joshua Vasquez wrote:
> Do adders need more than one clock cycle to add if their signals are
> larger than 4 bits?
No. An adder is one of the fastest thing in a FPGA, its absolutely
optimized, because each counter is based on an adder and counter are
heavyly used in FPGAs.
And of course: an adder never can be to slow for a clock. Only a clock
can be too fast for an adder! But you don't have to think about such
things at clock frequencies below 100MHz...

Rate this post
 0 ▲ useful ▼ not useful
Thanks for the reply!

I started off by running it on the FPGA directly and sending SPI
messages across via an Arduino. When the bitCount register is 4 bits
wide, the test value sent from the FPGA (8'b00000111) is received as 7
on the Arduino. When bitCount is 5 or more bits wide, the Arduino
receives 3 instead. No other changes are applied to get this output.

My waveform looks all right(from a design where bitCount is 5 bits wide,
though that version doesn't work on the FPGA.)
The setNewData signal triggers the preset value to capture the data to
send through the shift registers on the next clock cycle. My assumption
is that data gets loaded into the shift registers on the rising edge of
this signal.

I've added a picture of the spi shift registers to show how the data
gets loaded.

Rate this post
 1 ▲ useful ▼ not useful
Joshua Vasquez wrote:
> spiShiftRegisters.png
If ALOAD means "asynchronous load" then you can find a race condition in
this module: when the sclk shift out the last data bit with the very
same edge the signal setNewData becomes active and loads the shift
register. so you will have a glitch on the output. Although it may not
be the actual problem, it is not nice.

> is received ... on the Arduino.
I would dig deeper here: maybe there the wrong SPI mode. And a minor
change to the timing on the MISO output of the FPGA leads to a different
value.

Rate this post
 0 ▲ useful ▼ not useful
Lothar Miller wrote:
> If ALOAD means "asynchronous load" then you can find a race condition in
> this module: when the sclk shift out the last data bit with the very
> same edge the signal setNewData becomes active and loads the shift
> register. so you will have a glitch on the output. Although it may not
> be the actual problem, it is not nice.

Thanks; right now I'm conforming to SPI-mode-0, which I'm taking as:
data gets captured by both devices (master and slave) on the rising edge
of SCK and changes on the falling edge of SCK. As long as they both
agree to this standard, neither will try to sample the other while the
other is changing.

One place that I could definitely be going wrong is my understanding of
ALOAD. I'm thinking of it as an edge-triggered, so that data gets
captured onto the shift register only on positive "setNewData" signal
edges. If ALOAD is actually a latch and is transparent whenever the
"setNewData" signal is high, then that could mean that changing data
when the latch becomes opaque could be my problem.

Rate this post
 1 ▲ useful ▼ not useful
Joshua Vasquez wrote:
> LOAD. I'm thinking of it as an edge-triggered,
For sure it isn't, because otherwise you would have a
double-clock-flipflop with two separate data inputs. And such a thing
doesn't exist...

Rate this post
 0 ▲ useful ▼ not useful
Lothar Miller wrote:
> If ALOAD means "asynchronous load" then you can find a race condition in
> this module: when the sclk shift out the last data bit with the very
> same edge the signal setNewData becomes active and loads the shift
> register. so you will have a glitch on the output. Although it may not
> be the actual problem, it is not nice.

This lead me down the right path! I was letting my data change as the
shift register was clocking in new data. It turns out that I wasn't
paying close attention to when data is supposed to be captured onto the
shift register. Rather than stop capturing data at the falling edge of
the first sck pulse, I should stop capturing data on the rising edge of
the first sck pulse, that way the signal isn't being shifted out as it
is being captured.

I posted the revised waveform with the correct setNewData signal. It's
also working on the FPGA now too :)

(Lastly, by "captured," I mean release the aload signal and let the
input data signal go opaque to its input)

Finally, thanks for clearing up that haziness about the asynchronous
loading. It makes sense that it shouldn't be edge triggered...

• $formula (LaTeX syntax)$