Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
11 years ago

help with register to register timing constraint

Hello,

I'm stuck on what is most likely a simple problem. I'm trying to constrain a signal in my design, but I'm not sure exactly how. I've tried a couple different ways and figured it would be better to just ask. I have a start signal that goes high on the falling edge of a pin. This start signal clocks another register in my design. When I run compilation I get a warning attached below.

https://www.alteraforum.com/forum/attachment.php?attachmentid=9126

Because this signal clocks anther process it determines it to be a clock. How is this normally handled? This is for an I2C module.

Also, is my approach for constraining SDA and SCL correct? I am assuming they will run at 100k so I've constrained them as follows.

create_clock -name SCL_clk -period 10000 [get_ports sm5882_air_data_sensor_0_scl_export]

create_clock -name SDA_clk -period 10000 [get_ports sm5882_air_data_sensor_0_sda_export]

I've also attached my HDL. * Had to zip up my .sdc file because the forum would not let me upload it as is for some reason.

Thanks,

Rob

14 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks again. That is a very clever way, but my clock that would clock the dff isn't necessarily synchronized to the edge i'm trying to detect (SCL) and when I look at the signals on the scope I get some strange blips on the out put of that edge detector circuit that clocks my counters when it shouldn't be. I'm still working on this though so it may be something I'm doing wrong on my end rather than that detection circuit. Thanks so much for the help I've learned a fair amount from talking to you guys :)

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    That's why you first have to 'bring the SCL and SDA into your system clock domain'. In the case of a 1 bit signal (simply signal) it's done by putting it thru two consecutive FF as show in MUXs example.

    process (clk, reset) begin
        if reset = '0' then
            scl_0 <= '0';
            scl_1 <= '0';
            
            sda_0 <= '0';
            sda_1 <= '1';
        elsif (clk'event and clk = '1') then
            scl_1 <= scl_0;
            scl_0 <= scl_in;
            
            sda_1 <= sda_0;
            sda_0 <= sda_1;
        end if;
    end process;

    Now both SCL and SDA signals are brought into your clock domain (synchronized with clk).

    Apparently I can't post links, so google yourself things like 'Synchronous logic', 'clock domains', 'Metastability', 'crossing clock domains (signals vs buses)', etc.

    The basic idea is that every register is clocked by the same clock and the fitter can make sure that setup and hold requirements for each register are met. If you want to pass data between registers clocked by different clocks you have to make extra consideration (like in this example putting SCL and SDA (which are synchronous to your external I2C masters clock) thru two FF to bring them into your FPGAs logics clock domain.

    So, now you will only use 'scl_1' and 'sda_1'. Put them thru edge detect logic etc. (detect the start/stop conditions etc.) but don't use them as clocks!

    Lets say that you have detected a start bit, meaning that now you will have start clock in data on every scl edge, indicating that by some signal 'incoming_data = '1''. Your data shift register would look something like this:

    process(clk, reset, incoming_data, scl_1_edge_detect) begin
        if reset =  '0' then
            data <= (others => '0');
        
        elsif clk'event and clk = '1' then
            if incoming_data = '1' and scl_1_edge_detect '1' then
                data <= data(6 downto 0) & sda_1;
            end if;
        end if;
    end process;

    Note that shift register is clocked by the same clock and the 'little pulse' (in conjunction with incoming_data) from scl edge detect logic is only used as an enable signal (check RTL netlist!)

    Hope this helps,

    Vents
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Vents,

    Thanks so much for the write up. This is making more sense now. I wanted to reply and let you know I really appreciate the info. I'll spend some time this week and next week reading those recommended search topics and going further down this path. The examples also really clarified things. One initial thing I'm wondering right of the bat is why you use to dff to shift sda and scl through to synchronize it to your clock? Why wouldn't one ff work?

    Thanks again for the info. I'm going to re-write some stuff and study this stuff some more.

    Again much appreciated!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    If SDA or SCL happen to change at the exact moment when your system clock changes (to be more precise - setup or hold times aren't met) the output of FF can become unstable. It takes some time for it to settle to a 0 or 1. This reduces the setup time slack for next FF, and if there's some logic in between them it's even worse. So the idea is to simply sample it again (with no additional logic which would cause extra delay - reduce t_su slack) and rely that the possibly unstable output of first FF will settle (giving it more time to settle).

    I attached alteras document on metastability, take a look.

    Vents