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.

Base design on SCK or CLK?

Status
Not open for further replies.

phased

Newbie level 2
Joined
Jun 1, 2012
Messages
2
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,306
I'm having some confusion regarding a design: I have a 20 MHz clock on my system that connects a CPLD. The CPLD's only purpose is to act as an 'intelligent' shift register with an SPI interface - it also has a parallel input. I designed the system in such a way that it sampled SCK on every rising edge of the clock and synchronized SCK with the clock as, from what I've learned, asynchronous design in CPLDs/FPGAs is a no-no.

The trouble with my design is that it works fine at 1 MHz but at 2 MHz it transfers bad data occasionally. I believe the issue is that my MISO waveform is nearing the tolerance of the setup time for the SPI interface in my MCU (which is the master). You can see that here:

EQWzz.png


The obvious solution is to utilize a faster clock (40 MHz as opposed to 20 Mhz) but I was hoping there was a better way. One approach that I thought of was instead of using the clock, I should directly use SCK to output data. Here's another that shows more clearly how close I get to the setup time:

jUpqx.png


I only have a 50 Mhz o-scope, but I also looked at the 20 Mhz clock and SCK. The 20 Mhz produced, as expected, about 10 cycles during one cycle of SCK. Because of the synchronization and edge detection of SCK, I'm writing data to MISO about three clock cycles later than the actual falling edge of SCK. So, my question is, is there a better way to design this?
 

It sounds like there is some issue with the synchronizer. So how many flipflops do you use for the synchronizer? I could guess some stuff, because 3 cycles delay sounds about right, but I thought I'd better ask instead of randomly guess...

Another way you could do it is to handle the SCK etc synchronously in the SCK clock domain, and then use a FIFO or some handshaking. But with a 20 MHz clock you should have no trouble handling a 2 MHz SCK I'd say, so there must be some other fun issue...

Also, assuming you have 2 synchronizer FFs ... make sure the place & route places these closely together. That way you get good setup & hold for the 2nd FF, and minimize the metastability fun.
 
  • Like
Reactions: phased

    phased

    Points: 2
    Helpful Answer Positive Rating
Thanks for taking the time to respond.

Yes, I have two FFs that sync the waveform and then another one for detecting the rising or falling edge of the synced waveform. So about 3 clock-cycle delay does sound right and the logic simulation also shows that.

But if think about it, the 20 Mhz clock has a period of 50 ns. So 3 clock cycles means 150 ns. The typical setup time (max isn't given in the datasheet!) of the MCU is 10 ns. So that means I have a total of 250 - 10 ns = 240 ns.to setup my waveform. 240 - 150 = 90 ns. The waveform should arrive around this time but it doesn't. It's arriving about 50 ns later and I feel that's a little too close in violating the setup time. I also have constraints setup, of course.

The code for my synchronizer is:

Code:
entity sync is
	generic (
		RESET_STATE : std_logic := '0' -- '0' for active low sync
	);
    port (
        clk   : in  std_logic;
        rstN  : in  std_logic;
        d     : in  std_logic;
        q     : out std_logic
    );
end entity;

-- ----------------------------------------------------------------

architecture behavioral of sync is
    signal d_meta : std_logic;
begin
	process(clk, rstN)
	begin
		if (rstN = '0') then
			d_meta <= RESET_STATE;
			q      <= RESET_STATE;
		elsif (clk'event and clk = '1') then
			d_meta <= d;
			q      <= d_meta;
		end if;
	end process;
end architecture;

And here is my edge detection:

Code:
process(clk, nRESET)
	begin
		if (nRESET = '0') then
			sck_rising  <= '0';
			sck_falling <= '0';
			sck_delay   <= '0';
		elsif rising_edge(clk) then
			if cs_sync = '1' then
				sck_delay   <= '0';
				sck_rising  <= '0';
				sck_falling <= '0';
			else
				sck_delay   <= sck_sync;
				sck_rising  <= sck_sync and (not sck_delay);
				sck_falling <= (not sck_sync) and sck_delay;
			end if;
		end if;
	end process;

And this is the main application:

Code:
process(CLK, nRESET)
	begin
		if (nRESET = '0') then
			tmp <= (others => '0');
		elsif rising_edge(CLK) then
			if CS_sync = '0' then
				if SCK_falling = '1' then
					tmp <= tmp(PI'high -1 downto PI'low) & '0';
				end if;
			elsif CS_sync = '1' then
				tmp <= PI;
			end if;
		end if;
	end process;
		
	SO <= tmp(PI'high) when nCS = '0' else 'Z';
 
Last edited:

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top