Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] SPI slave clock problem on fpga

Status
Not open for further replies.

Mahrous

Newbie level 6
Joined
Mar 24, 2011
Messages
13
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,367
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 .
 

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.
 

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

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
 

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.
 

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
 

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.
 

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 .
 

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.
 

getfile.php

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
getfile.php
 

Why don't you simply upload your images to edaboard?

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...
 

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?
 

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.
 

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...
 

CLK.jpgSPI_CLK.jpgCLK2.jpgCLK3.jpg
here are the pics , sorry for troubling you .
i will try to register SCLKr as you said .
 

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

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 worry about all this IBUFG/BUFG business
- 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.
 

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.
 

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.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top