sampling rate

M

Marco

Hi,

I'm implementing a small entity capable of receiving serial spi-like
data at speeds up to 20MHz. The spi clock will be an input (being a
slave) at the same rate. I was thinking about reading each bit on each
rising edge of that clock. My concern is now that this way I'll not be
able to be sure about the stability of the bit value.
Is this approach (one clock -> one bit read) to completely avoid or is,
sometimes, used?
In UART-like snippet I saw the FPGA clock runs faster than the serial
one and each bit value is then acquired in the mid-point of the
serial-clock-period, even if the data shuold be presented on its line
with some advance on the clock rising front in order to be yet stable.
Sometimes, then, you may need to see that the reading bit keeps the
same value for at least n FPGA-clock cycles and this is like inserting
a filter.
Comments are welcome.

Thanks,
Marco
 
T

Thomas Fischer

Marco said:
Hi,

I'm implementing a small entity capable of receiving serial spi-like
data at speeds up to 20MHz. The spi clock will be an input (being a
slave) at the same rate. I was thinking about reading each bit on each
rising edge of that clock. My concern is now that this way I'll not be
able to be sure about the stability of the bit value.
Is this approach (one clock -> one bit read) to completely avoid or is,
sometimes, used?
In UART-like snippet I saw the FPGA clock runs faster than the serial
one and each bit value is then acquired in the mid-point of the
serial-clock-period, even if the data shuold be presented on its line
with some advance on the clock rising front in order to be yet stable.
Sometimes, then, you may need to see that the reading bit keeps the
same value for at least n FPGA-clock cycles and this is like inserting
a filter.
Comments are welcome.

Thanks,
Marco
some comments,

a spi interface is an synchronous interface mostly used between chips.
it' origin is from motorola. Therefore noise is not so much expected
for datatransfers between chips, as it is, if you connect two computers
with a uart over several meters
normally data is clocked out at the falling edge of SCLK and sampled
at the rising edge of sclk. ( this depends on CPOL and CPHA see link)
the dataline has half the clock time to setup correctly.

a uart is a asynchronous interface, so you have to oversample the data line
to find the bit transitions (mostly 16x oversampling is used).

see e.g.
http://www.maxim-ic.com/appnotes.cfm?appnote_number=802

so normally i would use the rxclk to shift in the data in a shift
register bit by bit.
remember that you will get two clock domains with this approch, and you
should use two stage sysnchronizers to transfer signals from one clock
domain
to the other.

hope this is correct and this helps a little
 
M

Marco

Thomas,

your comments are a great help, thanks.
Let me check with you if this way to synchronize is correct.
I have 2 different processes, one moved by the serial clock that only
acquires 1 bit each rising edge, counts for bits received and stores
them into a vector, when done it activates the data_ready flag. The
other process, powered by the faster system clock, makes its work when
it find the data_ready flag activated, then it builds up another vector
with the answer (communication between an FPGA and a DSP) and sets the
answer_ready flag on. Finally, a serial-clock-process will send the
answer back to the DSP on reading the answer_ready flag.

Should I do in a different way, unsing a temp flag that gives its value
to another one on the rising edge of the system clock or something?

Thanks,
Marco




Thomas Fischer ha scritto:
 
T

Thomas Fischer

Marco said:
Thomas,

your comments are a great help, thanks.
Let me check with you if this way to synchronize is correct.
I have 2 different processes, one moved by the serial clock that only
acquires 1 bit each rising edge, counts for bits received and stores
them into a vector, when done it activates the data_ready flag. The
other process, powered by the faster system clock, makes its work when
it find the data_ready flag activated, then it builds up another vector
with the answer (communication between an FPGA and a DSP) and sets the
answer_ready flag on. Finally, a serial-clock-process will send the
answer back to the DSP on reading the answer_ready flag.

Should I do in a different way, unsing a temp flag that gives its value
to another one on the rising edge of the system clock or something?

Thanks,
Marco




Thomas Fischer ha scritto:

you will need two data_ready flags. one that is generated from
your rx process and a second that is the data_ready_flag synchronized
to your system clock domain.

google for two stage synchronizer, or fpga metastability
e.g.

http://www.asic-world.com/tidbits/clock_domain.html
http://www.chipdesignmag.com/print.php?articleId=32?issueId=5
http://www.embedded.com/showArticle.jhtml?articleID=9901007

you can make a simple synchronizer component like the following

--###################################

-- two stage synchronizer

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity sync is
port (
rst : in std_logic;
clk : in std_logic;
d0 : in std_logic;
q0 : out std_logic);
end sync;


architecture a of sync is
signal q_temp : std_logic;
begin
process (clk,rst)
begin
if(rst = '1') then
q0 <= '0';
q_temp <= '0';
elsif rising_edge(clk) then
q_temp <= d0;
q0 <= q_temp;
end if;
end process;
end a;

--###################################

then use in your main vhdl

signal sys_clk : std_logic; -- system clock
signal rx_clk : std_logic; -- receive clock
signal data_rdy_d0_s : std_logic; -- signal data ready in rxclk
domain (d0)
signal data_rdy_d1_s : std_logic; -- signal data ready in sys clk
domain (d1)
signal rx_data_d0 : std_logic_vector(7 downto 0); -- rxdata in
domain rxclk (shiftregister)
signal rx_data_d1 : std_logic_vector(7 downto 0); -- rxdata in
domain sys_clk

begin

-- synchronize rx_data_rdy from rx_clk domain to sys_clk domain
sync_rx_data_rdy : sync
port map (rst => rst, clk => sys_clk, d0 => data_rdy_d0_s, q0 =>
data_rdy_d1_s);

-- synchronize rx_enable from sys_clk domain to rx_clk domain
sync_rx_enable : sync
port map (rst => rst, clk => rx_clk, d0 => rx_enable_d1_s, q0 =>
rx_enable_d0_s);

process (sys_clk, rst)
begin
if(rst = '1') then
rx_data_d1 <= (others => '0');
elsif rising_edge(sys_clk) then
if (data_rdy_d1_s = '1') then
rx_data_d1 <= rx_data_d0; -- rx_data_d0 will not change in
this monment
end if;
end if;
end process;
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top