# [SOLVED]SPI slave clock problem on fpga

Status
Not open for further replies.

#### Mahrous

##### Newbie level 6
i have a spartan6 -SP605- fpga board , wrote SPI slave module on it ,
the problem is the clock from the master is not always read correctly , i managed to implement a debugcore using chipscope and viewed the clock , some times it appears to be perfect other times it has some missing edges ~ most of the time i get a very noisy clock ,
i use a 3-bit vector register for synchronizing this clock , the fpga's internal clock is much faster ,
any suggestions ?. some told me to try and remove the input buffer of the clock implemented automatically by the synthesizer . does this solve the problem ? and how?
thanks in advance ,plz help .

#### lucbra

what's the speed of the SPI clock?

How does you code look like?

The fact that your internal clock of the FPGA runs much faster has nothing to do with your SPI clock, as the slave module (as the name implies) takes the clock of the master.

#### alledauser

##### Member level 1
Could it be due to an electrical level mismatch between master and slave IO buffers?

#### lucbra

That might be possible

#### Mahrous

##### Newbie level 6
the speed of the SPI clock is 2 MHz ,
i checked the voltage level of the outputs from the master , a 1 is 3.3V , a 0 is ~ 0 , which is acceptable as the the levels in the fpga for "1" is 2-4.1 volts ,and a 0 is between -0.5,0.8 volts .
i mentioned the internal clock , as it should be faster for sampling the spi clock.

any way this is my code
Code:
module SPIslave(
output wire MISO,	 //Master input , Slave output
output LEDS,
input MOSI, //Master ouput , slave input
input SS, 	 //Slave select
input SCLK,  //Serial clock
input CLK ,
output reg [3:0] ccount,
output reg [7:0] dataBUF
);

reg [7:0] dataBUF2;
reg try;

reg [2:0] SCLKr;

wire SCLK_falling,SCLK_rising;

assign SCLK_rising = (SCLKr[2:1] == 2'b01);
assign SCLK_falling = (SCLKr[2:1] == 2'b10);

always@ (posedge CLK) SCLKr <= {SCLKr[1:0],SCLK};

initial begin
dataBUF   = 8'b11001010;
dataBUF2  = 8'hF0;
ccount = 4'b0000;

end

always @(posedge CLK)
begin

if(!SS) begin

if(SCLK_rising)
begin
dataBUF <= {dataBUF[6:0],MOSI};
ccount = ccount + 4'b1;
end

if(SCLK_falling)
begin
dataBUF2 <= {dataBUF2[6:0],dataBUF2[7]};
end

end
end
assign LEDS = ((dataBUF ==8'h66)||(dataBUF ==8'hAB)||(dataBUF ==8'hBA))? 1'b1:1'b0;
assign MISO = dataBUF2[7];
endmodule

#### lucbra

the speed of the SPI clock is 2 MHz ,
i checked the voltage level of the outputs from the master , a 1 is 3.3V , a 0 is ~ 0 , which is acceptable as the the levels in the fpga for "1" is 2-4.1 volts ,and a 0 is between -0.5,0.8 volts .
i mentioned the internal clock , as it should be faster for sampling the spi clock.

any way this is my code
Code:
module SPIslave(
output wire MISO,	 //Master input , Slave output
output LEDS,
input MOSI, //Master ouput , slave input
input SS, 	 //Slave select
input SCLK,  //Serial clock
input CLK ,
output reg [3:0] ccount,
output reg [7:0] dataBUF
);

reg [7:0] dataBUF2;
reg try;

reg [2:0] SCLKr;

wire SCLK_falling,SCLK_rising;

assign SCLK_rising = (SCLKr[2:1] == 2'b01);
assign SCLK_falling = (SCLKr[2:1] == 2'b10);

always@ (posedge CLK) SCLKr <= {SCLKr[1:0],SCLK};

initial begin
dataBUF   = 8'b11001010;
dataBUF2  = 8'hF0;
ccount = 4'b0000;

end

always @(posedge CLK)
begin

if(!SS) begin

if(SCLK_rising)
begin
dataBUF <= {dataBUF[6:0],MOSI};
ccount = ccount + 4'b1;
end

if(SCLK_falling)
begin
dataBUF2 <= {dataBUF2[6:0],dataBUF2[7]};
end

end
end
assign LEDS = ((dataBUF ==8'h66)||(dataBUF ==8'hAB)||(dataBUF ==8'hBA))? 1'b1:1'b0;
assign MISO = dataBUF2[7];
endmodule

Agree - the voltage levels should be OK.

Why are you sampling with the internal clock?

Wouldn't it be easier to clock the register with SCLK (rising or falling edge)?
The Rx register can the be transfered to the clock domain of the FPGA.

The reason that you don't get a decent output from your Rx process is that you sample several time the same bit of your SPI data.

#### Mahrous

##### Newbie level 6
do you mean that i make the process @posedge SCLK instead ? .
what i know , is that this is not possible in fpga design , it's synthesis-able of course , but when implementing i receive an error .
about receiving an output , thats not the problem , when the clock is read right the data is sampled right and it's sampled once , as you see from the code SCLK_rising , is 1 for just 1 period of CLK .
as i said before someone told me tor remove the input buffer of SCLK "IBUFG" is that possible ? if yes how can i do that

#### FvM

##### Super Moderator
Staff member
Wouldn't it be easier to clock the register with SCLK (rising or falling edge)?
The Rx register can the be transfered to the clock domain of the FPGA.

The reason that you don't get a decent output from your Rx process is that you sample several time the same bit of your SPI data.
I don't agree. The OP is performing state-of-the-art synchronous edge detection for SCLK. It's supposed to work for fCLK > 2*fSCLK. In my opinion, it's the appropriate solution for a slow clock, it's using a single clock domain, as any FPGA text book would suggest for this case. You should visualize SCLK as well as the derived SCLK_xxx signals in Chipscope. If they look "noisy", a hardware problem should be expected.

#### Mahrous

##### Newbie level 6
i did visualize the SCLK_IBUF signal in chipsocope and it's some times noisy or missing some edges , but SCLK_rising, SCLK_falling always follow SCLK and is as expected depending on SCLK.
if it's a hardware problem what could it be?
and would you please mention what fpga text book are you talking about , i could really use it .

#### FvM

##### Super Moderator
Staff member
What do you mean with missing edges? A full high or low period missing? I didn't explicitely mention, that SCLK must have a reasonable duty cycle for the solution to work, strictly spoken, tSCLK_high and tSCLK_low must be > tCLK_period. Otherwise, the slow clock assumption won't be correct.

I'm not particular familar with XILINX, but I can't imagine, that the problem has anything to do with the said IBUFG. I assume, that it's automatically inserted by the synthesis tool and can't be removed anyway.

I can't suggest a specific FPGA design text book, because there are so many, mostly instructive. It also depends on what you're FPGA related main interest is. I would tend to literature focussing on hardware design with FPGA.

#### Mahrous

##### Newbie level 6

that's a missing edge on the right ,the spi clock is "1/16" MHZ , the internal clock is 27Mhz , some other times when i change very little in the design , like adding a counter for the received bits and put the receiving buffer in the sending buffer "dataBUF2 <= dataBUF" , i monitor the clock to be very very noisy , as in this pic

#### FvM

##### Super Moderator
Staff member

I finally managed to decode the link and view the pictures. Looks like missing ground connection or severe interferences created by some other hardware oddity. I presume, that the display isn't caused by buggy Chipscope IP or software...

#### lucbra

I don't agree. The OP is performing state-of-the-art synchronous edge detection for SCLK. It's supposed to work for fCLK > 2*fSCLK. In my opinion, it's the appropriate solution for a slow clock, it's using a single clock domain, as any FPGA text book would suggest for this case. You should visualize SCLK as well as the derived SCLK_xxx signals in Chipscope. If they look "noisy", a hardware problem should be expected.

In an ideal world there is only one clock network ... that's why FPGA's have several clock networks right?

#### FvM

##### Super Moderator
Staff member
In an ideal world there is only one clock network ... that's why FPGA's have several clock networks right?
It's a clear design rule to avoid multiple clock domains where they aren't needed, simply because the data path synchronizing effort will be higher than alternative solutions. A low frequency serial slave interface is a clear example where an additional clock domain for the serial clock won't be appropriate. It would be different of course with a 20 or 50 MHz SPI clock.

#### mrflibble

Code:
	if(SCLK_rising)
begin
dataBUF <= {dataBUF[6:0],MOSI}; // This one...
ccount = ccount + 4'b1; // and this one...
end

Do you intentionally mix blocking and non-blocking assignments?

Also, you could consider registering these combinatorials as well...
Code:
Also, where are those pictures everyone seems to be seeing? @_@

assign SCLK_rising = (SCLKr[2:1] == 2'b01);
assign SCLK_falling = (SCLKr[2:1] == 2'b10);

Although I do admit that for a SPI master clock of 62.5 kHz like you mention the logic delay would not be an issue.

---------- Post added at 13:54 ---------- Previous post was at 13:47 ----------

I'm not particular familar with XILINX, but I can't imagine, that the problem has anything to do with the said IBUFG. I assume, that it's automatically inserted by the synthesis tool and can't be removed anyway.

With the ISE tools on default settings this an IBUFG would be added for a clock input. Although as far as I can tell SCLK input would be a regular (non-clock) input, so that would be an IBUF (also added automatically).

If you want you can influence this by setting BUF_TYPE="whatever" attibute on that SCLK net at the top level module, but I doubt that this is the problem...

#### Mahrous

##### Newbie level 6

here are the pics , sorry for troubling you .
i will try to register SCLKr as you said .

#### Mahrous

##### Newbie level 6
can i use BUF_TYPE to assing BUFG to SCLK ,and dont' use the internal CLK ?

#### mrflibble

can i use BUF_TYPE to assing BUFG to SCLK ,and dont' use the internal CLK ?

Well, for a SPI master clock that low (< 1 MHz) it makes sense to use a regular (non-clock) input pin for ALL the SPI inputs, so SCLK too.

That way you:
- don't have to use a global clock (limited resource)
- don't have to worry about cross clock domain stuff

IMO, the last reason being the main one. Getting the data between 2 clock domains in a clean way takes a bit of work. So if you don't really need the extra clock domain, by all means avoid it.

By treating the SCLK line as a data input just like MOSI, and then registering this at the posedge of your system clock, these inputs will then run synchronous to this system clock. That way you don't have to worry about synchronizers on the input and output.

Like FvM said:
FvM said:
It's a clear design rule to avoid multiple clock domains where they aren't needed, simply because the data path synchronizing effort will be higher than alternative solutions. A low frequency serial slave interface is a clear example where an additional clock domain for the serial clock won't be appropriate.

---------- Post added at 15:12 ---------- Previous post was at 15:08 ----------

If you happen to have the SCLK connected to a pin that is a dedicated clock input ... you can use these dedicated clock inputs as a regular input. I recall that xst handles this properly. As in, if I use it as data, I get an IBUF (regular input) as opposed to an IBUFG (clock input). You can check this in the synthesis report and design summary in ISE. If for whatever reason it still uses a IBUFG where you don't want it to, only then do you have to go to the trouble of explicitely defining the IBUF_TYPE.

Hope that clears things up...

---------- Post added at 15:27 ---------- Previous post was at 15:12 ----------

About that MOSI_IBUF and SCLK_IBUF in this pic:

Have you tried looking at these 2 lines on a oscilloscope? You mention that the DC levels are good, but that doesn't mean that it will be all dandy during actual data activity...

Anyway, what you could do is register these two inputs, and then filter it. So for example something like:

Code:
reg [3:0] mosi_sr;
reg       mosi_filtered;

always (@posedge clk) begin
mosi_sr <= {mosi_sr[2:0], MOSI_IBUF};
if (mosi_filtered == 1'b0) begin
// only change from the current 0 state to a new 1 state if mosi_sr is ALL 1's
mosi_filtered <= (& mosi_sr)
end else begin
// only change from the current 1 state to a new 0 state if mosi_sr is ALL 0's
mosi_filtered <= (| mosi_sr)
end
end

And you would do the exact same thing for that SCLK_IBUF. That way you'd have some basic filtering. The depth of shift register you'd need depends on a lot of things, but I'd just try 4 as a starting point. If it improves somewhat, but still not great, try 8 etc.

#### FvM

##### Super Moderator
Staff member
Some interesting points have been discussed in detail. But I don't hear substantial news regarding the original problem of "noisy" (still an understatement) SCLK. (In the waveform, other signals like SS are screwed up too, by the way). Seriously, you shouldn't think about filtering useless digital signals rather than identifying the problem.

#### mrflibble

Some interesting points have been discussed in detail. But I don't hear substantial news regarding the original problem of "noisy" (still an understatement) SCLK. (In the waveform, other signals like SS are screwed up too, by the way). Seriously, you shouldn't think about filtering useless digital signals rather than identifying the problem.

Good point. Hence the :

Have you tried looking at these 2 lines on a oscilloscope? You mention that the DC levels are good, but that doesn't mean that it will be all dandy during actual data activity..."

If the input really is as noisy as it seems in that screenshot then that is the first order of business. Which means scope it, a DMM is not much use there.

What might help on the fpga side is to set the inputs to as low a slewrate as possible.

@Mahrous:
What IO standard do you have configured for these inputs?

Status
Not open for further replies.