Fast and slow clocks

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
I'm wondering what the correct way to handle the following situation
is. Sorry this is a bit long winded. BTW, it's not homework, all that
was 40+ years ago.


I have two clocks, clk which is the FPGA clock rate, and sclk which I
create using a simple divide by n counter. Typically, sclk is 1024
times slower than clk.  

An event occurs that sets a reg, DR, for one clk cycle.  

There is a register, calcreg [7:0] which is to be incremented slowly,
but reset to zero on DR.

There are two sections, one triggered by clk and one by sclk, ie:

//    Fast section
always @ (posedge clk)
    begin
    ....
    end

// Slow section
always @ (posedge sclk)
    begin
    if (DR)  calcreg <= 8'h0  ;         // Reset calcreg on DR  
    else calcreg <= calcreg + 1   ;  // Else increment
    end

The problem of course is that the on state of DR will almost always be
missed, it will only appear if it happens to coincide with a sclk edge
(1 / 1024). So the above doesn't work.

So I tried modifying the clk section as follows:
  
always @ (posedge clk)
    begin
    ....
    if (DR) calcreg <= 8'h0  ;  
    end

This threw up build errors,  

Error (10028): Can't resolve multiple constant drivers for net
"FlashCtr[3]" at tick.v(43)

I think I see the reason, it's like trying to wire two gate outputs to
the same point, something that's obviously verboten with active drive
hardware.  


If someone could help with the following specific questions it would
help a lot.....

Is using the two clocks simply bad practice, ie. should everything be
done in a single always block at clk rate?

Is there a standard way to latch the DR signal when it occurs on the
fast clock, so that it will be there on the next transition of sclk,
which must then clear the DR latch? I've tried this, and come up with
the same build error with the latch.





Re: Fast and slow clocks
Hi,

I would put it all into a single clk block. I.e.

reg [9:0] count = 0;
always @(posedge clk) begin
  count <= count + 1;
  // fast "clock" here
  if (count == 0) begin

  end
end

Depending on what you want to achieve, you could also re-synchronize the     
  

                    
---------------------------------------        
Posted through http://www.FPGARelated.com

Re: Fast and slow clocks
.. you could also resynchronize the slow "clock" on the event.  
Maybe the difficulty is to define how exactly the circuit is going to
behave, not so much coding it in RTL.


Multiple clocks might be used on an ASIC where it allows use of smaller
cells for the slow part.  

For a simple FPGA project, my main goal would be to keep the code as
readable as possible.

        
                    
---------------------------------------        
Posted through http://www.FPGARelated.com

Re: Fast and slow clocks
On 10/18/2014 3:53 AM, "Bruce Varley" wrote:
Quoted text here. Click to load it

If you're really just dividing one clock to make another, then you're
probably better off using a single clock and generating a count enable
for your slow process.  On the other hand your problem of using a fast
signal to reset a slow process is also applicable to situations where
the two clocks are not related and are both necessary for the design.
In that case I would normally have an intermediate variable in the fast
clock domain that gets set by DR and cleared by a signal returned from
the slow process.  Something like:

reg  DR_hold = 0;
reg  DR_seen = 0;
always @ (posedge clk)
   begin
     if (DR) DR_hold <= 1;
     else if (DR_resync) DR_hold <= 0;
   end

always @ (posedge sclk)
   begin
     DR_resync <= DR_hold;
   end

Note that if you use DR_resync as the reset term, it will
cause additional latency from DR to the reset of the counter.
You could use DR_hold instead, but then the problem is if
the two clocks are really unrelated you could miss a reset
if DR_hold asserts very near the rising edge of sclk and
DR_resync catches the event but the counter (or some of its
bits) does not.

--  
Gabor

Re: Fast and slow clocks
On 10/18/2014 10:53 AM, Gabor wrote:
Quoted text here. Click to load it

Oops, in the previous post I started with "DR_seen" but then
went to "DR_resync" for the same signal.  But you get the idea...

--  
Gabor

Re: Fast and slow clocks
On Sat, 18 Oct 2014 10:53:42 -0400, Gabor wrote:

Quoted text here. Click to load it
else

+1.  Using the DR_resync (who looks at 'reg' declarations, anyway) should  
work even if sclk isn't generated from clk.

--  

Tim Wescott
Wescott Design Services
We've slightly trimmed the long signature. Click to see the full one.
Re: Fast and slow clocks
Okay, you ain't going to like VHDL, but here is a solution based on a Johns
on ring divider:

---------------------------------------------------------------------------
---------------------------------------------------------------------------
----------
-- File        : wrapper_SPI_Master.vhd
-- Author      : David Greig (email : snipped-for-privacy@ieee.org)
-- Revision    :
-- Description :
---------------------------------------------------------------------------
---------------------------------------------
-- Notes :
--========================
=========================
=========================
=========================
=========================
=========================
=======--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

--========================
=========================
=========================
=========================
=========================
=========================
=======--
entity wrapper_SPI_Master is
        port(
            arstn            : in    std_logic;
            clk            : in    std_logic;
            spi_rst_i        : in    std_logic;
            clken            : in    std_logic;

            cpol_i            : in    std_logic;
            cpha_i            : in    std_logic;

            spi_wr_i        : in    std_logic;-----------------------------------------------
---------------------------------------------------------------------------
--------------------------------------
-- File        : wrapper_SPI_Master.vhd
-- Author      : David Greig (email : snipped-for-privacy@ieee.org)
-- Revision    :
-- Description :
---------------------------------------------------------------------------
---------------------------------------------
-- Notes :
--========================
=========================
=========================
=========================
=========================
=========================
=======--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

--========================
=========================
=========================
=========================
=========================
=========================
=======--
entity wrapper_SPI_Master is
        port(
            arstn            : in    std_logic;
            clk            : in    std_logic;
            spi_rst_i        : in    std_logic;
            clken            : in    std_logic;

            cpol_i            : in    std_logic;
            cpha_i            : in    std_logic;

            spi_wr_i        : in    std_logic;
            spi_tx_data_i    : in    std_logic_vector(16-1 downto 0);
            spi_tx_empty_o    : out    std_logic;
            spi_tx_full_o    : out    std_logic;
            spi_tx_ovf_o    : out    std_logic;
            spi_tx_unf_o    : out    std_logic;
            spi_tx_done_o    : out    std_logic;

            spi_rd_i        : in    std_logic;
            spi_rx_data_o    : out    std_logic_vector(16-1 downto 0);
            spi_rx_empty_o    : out    std_logic;
            spi_rx_full_o    : out    std_logic;
            spi_rx_ovf_o    : out    std_logic;
            spi_rx_unf_o    : out    std_logic;

            sck_o            : out    std_logic;
            ssn_o            : out    std_logic;
            mosi_o            : out    std_logic;
            miso_i            : in    std_logic
        );
end entity wrapper_SPI_Master;
--========================
=========================
=========================
=========================
=========================
=========================
=======--

--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~--
architecture rtl of wrapper_SPI_Master is
---------------------------------------------------------------------------
---------------------------------------------
    component SPI_Master
        generic(
            Gram_pref        : string;
            Gfifo_depth        : natural;
            Gdwidth            : natural;
            Gspi_clk_div    : natural
        );
        port(
            arstn            : in    std_logic;
            clk            : in    std_logic;
            spi_rst_i        : in    std_logic;
            clken            : in    std_logic;

            cpol_i            : in    std_logic;
            cpha_i            : in    std_logic;

            spi_wr_i        : in    std_logic;
            spi_tx_data_i    : in    std_logic_vector(Gdwidth-1 downto 0);
            spi_tx_empty_o    : out    std_logic;
            spi_tx_full_o    : out    std_logic;
            spi_tx_ovf_o    : out    std_logic;
            spi_tx_unf_o    : out    std_logic;
            spi_tx_done_o    : out    std_logic;

            spi_rd_i        : in    std_logic;
            spi_rx_data_o    : out    std_logic_vector(Gdwidth-1 downto 0);
            spi_rx_empty_o    : out    std_logic;
            spi_rx_full_o    : out    std_logic;
            spi_rx_ovf_o    : out    std_logic;
            spi_rx_unf_o    : out    std_logic;

            sck_o            : out    std_logic;
            ssn_o            : out    std_logic;
            mosi_o            : out    std_logic;
            miso_i            : in    std_logic
        );
    end component SPI_Master;
---------------------------------------------------------------------------
---------------------------------------------
begin
---------------------------------------------------------------------------
---------------------------------------------
    inst_SPI_Master : SPI_Master
        generic map(
            Gram_pref        => "logic",
            Gfifo_depth        => 2,
            Gdwidth            => 16,
            Gspi_clk_div    => 4
        )
        port map(
            arstn            => arstn            ,
            clk            => clk            ,
            spi_rst_i        => spi_rst_i        ,
            clken            => clken            ,

            cpol_i            => cpol_i            ,
            cpha_i            => cpha_i            ,

            spi_wr_i        => spi_wr_i        ,
            spi_tx_data_i    => spi_tx_data_i    ,
            spi_tx_empty_o    => spi_tx_empty_o    ,
            spi_tx_full_o    => spi_tx_full_o    ,
            spi_tx_ovf_o    => spi_tx_ovf_o    ,
            spi_tx_unf_o    => spi_tx_unf_o    ,
            spi_tx_done_o    => spi_tx_done_o    ,

            spi_rd_i        => spi_rd_i        ,
            spi_rx_data_o    => spi_rx_data_o    ,
            spi_rx_empty_o    => spi_rx_empty_o    ,
            spi_rx_full_o    => spi_rx_full_o    ,
            spi_rx_ovf_o    => spi_rx_ovf_o    ,
            spi_rx_unf_o    => spi_rx_unf_o    ,

            sck_o            => sck_o            ,
            ssn_o            => ssn_o            ,
            mosi_o            => mosi_o            ,
            miso_i            => miso_i
        );
---------------------------------------------------------------------------
---------------------------------------------
end architecture rtl;
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~--


            spi_tx_data_i    : in    std_logic_vector(16-1 downto 0);
            spi_tx_empty_o    : out    std_logic;
            spi_tx_full_o    : out    std_logic;
            spi_tx_ovf_o    : out    std_logic;
            spi_tx_unf_o    : out    std_logic;
            spi_tx_done_o    : out    std_logic;

            spi_rd_i        : in    std_logic;
            spi_rx_data_o    : out    std_logic_vector(16-1 downto 0);
            spi_rx_empty_o    : out    std_logic;
            spi_rx_full_o    : out    std_logic;
            spi_rx_ovf_o    : out    std_logic;
            spi_rx_unf_o    : out    std_logic;

            sck_o            : out    std_logic;
            ssn_o            : out    std_logic;
            mosi_o            : out    std_logic;
            miso_i            : in    std_logic
        );
end entity wrapper_SPI_Master;
--========================
=========================
=========================
=========================
=========================
=========================
=======--

--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~--
architecture rtl of wrapper_SPI_Master is
---------------------------------------------------------------------------
---------------------------------------------
    component SPI_Master
        generic(
            Gram_pref        : string;
            Gfifo_depth        : natural;
            Gdwidth            : natural;
            Gspi_clk_div    : natural
        );
        port(
            arstn            : in    std_logic;
            clk            : in    std_logic;
            spi_rst_i        : in    std_logic;
            clken            : in    std_logic;

            cpol_i            : in    std_logic;
            cpha_i            : in    std_logic;

            spi_wr_i        : in    std_logic;
            spi_tx_data_i    : in    std_logic_vector(Gdwidth-1 downto 0);
            spi_tx_empty_o    : out    std_logic;
            spi_tx_full_o    : out    std_logic;
            spi_tx_ovf_o    : out    std_logic;
            spi_tx_unf_o    : out    std_logic;
            spi_tx_done_o    : out    std_logic;

            spi_rd_i        : in    std_logic;
            spi_rx_data_o    : out    std_logic_vector(Gdwidth-1 downto 0);
            spi_rx_empty_o    : out    std_logic;
            spi_rx_full_o    : out    std_logic;
            spi_rx_ovf_o    : out    std_logic;
            spi_rx_unf_o    : out    std_logic;

            sck_o            : out    std_logic;
            ssn_o            : out    std_logic;
            mosi_o            : out    std_logic;
            miso_i            : in    std_logic
        );
    end component SPI_Master;
---------------------------------------------------------------------------
---------------------------------------------
begin
---------------------------------------------------------------------------
---------------------------------------------
    inst_SPI_Master : SPI_Master
        generic map(
            Gram_pref        => "logic",
            Gfifo_depth        => 2,
            Gdwidth            => 16,
            Gspi_clk_div    => 4
        )
        port map(
            arstn            => arstn            ,
            clk            => clk            ,
            spi_rst_i        => spi_rst_i        ,
            clken            => clken            ,

            cpol_i            => cpol_i            ,
            cpha_i            => cpha_i            ,

            spi_wr_i        => spi_wr_i        ,
            spi_tx_data_i    => spi_tx_data_i    ,
            spi_tx_empty_o    => spi_tx_empty_o    ,
            spi_tx_full_o    => spi_tx_full_o    ,
            spi_tx_ovf_o    => spi_tx_ovf_o    ,
            spi_tx_unf_o    => spi_tx_unf_o    ,
            spi_tx_done_o    => spi_tx_done_o    ,

            spi_rd_i        => spi_rd_i        ,
            spi_rx_data_o    => spi_rx_data_o    ,
            spi_rx_empty_o    => spi_rx_empty_o    ,
            spi_rx_full_o    => spi_rx_full_o    ,
            spi_rx_ovf_o    => spi_rx_ovf_o    ,
            spi_rx_unf_o    => spi_rx_unf_o    ,

            sck_o            => sck_o            ,
            ssn_o            => ssn_o            ,
            mosi_o            => mosi_o            ,
            miso_i            => miso_i
        );
---------------------------------------------------------------------------
---------------------------------------------
end architecture rtl;
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~--

---------------------------------------------------------------------------
---------------------------------------------------------------------------
----------
-- File        : SPI_Master.vhd
-- Author      : David Greig (email : snipped-for-privacy@ieee.org)
-- Revision    :
-- Description : SPI master with individual fifo buffers on RX and TX
---------------------------------------------------------------------------
---------------------------------------------
-- Notes :
-- Verified conforming with "Freescale Semiconductor, Inc." SPI Block Guide
 V4 S12SPIV4.pdf
-- cpha 0 means "sample on 1st edge", cpha = 1 means "sample on 2nd edge"
.
-- cpol simply changes the effective polarity of the clock
-- Tranfer latency - ssn goes low 2 clk cycles after first spi_wr
-- One complete sck period is inserted between ssn falling edge to data sta
rt, and again from data end to ssn rising edge, and again at the end to giv
e minimum
-- ssn high of one sck period
-- Illustration for 8 bit data :- overall time = (nbits + 3) * sck period
s


____________~


-- cpha=0  sdo  ~-------------------X=======X====
===X=======X=======X=======
X=======X=======X=======X--------
-----~







-- cpha=0  sdo  ~-------------------X=======X====
===X=======X=======X=======
X=======X=======X=======X--------
-----~
--


____________~


-- cpha=1  sdo  ~-------------------X=======X====
We've slightly trimmed the long signature. Click to see the full one.
Re: Fast and slow clocks
You have a CDC (clock-domain-crossing) situation going from a fast clock domain to a slow clock domain. Some others have already mentioned solutions:


On Saturday, October 18, 2014 3:53:31 AM UTC-4, snipped-for-privacy@googlegroups.com wrote:
Quoted text here. Click to load it


Re: Fast and slow clocks
You have a CDC (clock-domain-crossing) situation going from a fast to slow  
domain. Are you sure those clocks are synchronous?Some solutions have alrea
dy been mentioned:

1) Use a single clock domain for everything and just capture the event in t
he fast clock domain and clear it when you enable the slow domain (count=
10%24). This will consume more power as you are using the same clock for  
all logic but you have a fully synchronous design (easier for timing).  

2) Use handshake to pass the signal across the CDC boundary but be sure to  
double-register signals to avoid metastability (asynchronous clock crossing
). i.e. Gabor's code with synchronizing flops.

It really depends on the relationship between the clocks in your design. St
aying synchronous keeps things a lot simpler.

-Ganesh


On Saturday, October 18, 2014 3:53:31 AM UTC-4, snipped-for-privacy@googlegroups.com wro
te:
Quoted text here. Click to load it

Re: Fast and slow clocks

Bruce Varley:

Quoted text here. Click to load it

A good question, and it sounds like you're already analysing  
the problems correctly.

In terms of electronic circuit complexity (however), the problem
you describe scales down to what single design primitives of the  
hardware deliver.

So it'll be best to start with taking a look at what kind of
design primitives are supported by the hardware platform
(so in case of an FPGA, the interesting information would be
about which "slice"-FlipFlop-Types are available).

To me it seems like at least all Xilinx FPGA support both,  
synchroneous and asychroneous (re)set for clocked data paths.  

If I got your pronlem description correcty, a simple solution
would be to use async reset FlipFlops for calcreg:

always @(posedge sclk or posedge DR)
begin
  if (DR) calcreg <= n'b0
  else calcreg <= calcreg + n'd1;
end


Gruss

Jan Bruns



Re: Fast and slow clocks
On Sat, 18 Oct 2014 15:53:31 +0800
Bruce Varley wrote:

Quoted text here. Click to load it

Your problem is a hair underdefined here.  Is it imperative that
calcreg be reset to zero at the exact time of DR, or is it good enough
that the DR ensure that calcreg go to zero on the next sclk edge?

Quoted text here. Click to load it

"Bad practice" is a bit of a blanket statement, but in this instance
yes.  The two clock domains are causing you unnecessary grief and
probably can't be justified.  mnentwig already provided example code
for how to do it synchronously; the /1024 counter becomes a "count up"
enable input, and DE becomes a synchronous reset.

In an FPGA, any time you find yourself with multiple clock domains you
should always ask "What is the technical reason that _requires_ it be
this way?"  Sometimes that question will have a good answer, but when
it doesn't keep it all on the same clock.

Quoted text here. Click to load it

Various forms of asynchronous horribleness.  Gabor gave you one, Jan's
use of the async clear is another, and I'll present you a third by
saying to Google "flancter" (a clever little arrangement with two
cross-coupled flops and an XOR gate).

All these will work.  All of them will require you to get creative
with your design's timing constraints if you want the tools to really
analyze the path and make _sure_ that it works over
process/temp/voltage variations.  Timing analysis and async logic go
hand in hand, and both have the exciting feature that, unlike
synchronous logic, you'll never have a simulation that can tell you
that you've got it right.  You just design it very hard, then sit there
digging through the report outputs of your timing analysis to make sure
that it actually got constrained, and that the constraint actually does
what you want, and then you hope that on subsequent recompiles key
signals don't get renamed and break it.  Then you too can know the joy
of wasting an hour or two trying to get the tools to work properly on a
chunk of code that's only 20 lines long.

Or you can do it synchronously.

--  
Rob Gaddi, Highland Technology -- www.highlandtechnology.com
Email address domain is currently out of order.  See above to fix.

Site Timeline