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.

CLK Generic Routing Warning

Status
Not open for further replies.

KingMoshe

Member level 2
Joined
Aug 10, 2021
Messages
48
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
362
Hi,
I have a "place & route design" warning as following:

66011008 WARNING - The following clock signals will be routed by using generic routing resource and may suffer from excessive delay and/or skew.
Signal=i2c_master/CLK_FSM loads=11 clock_loads=4

How I fix that warning?

Thanks
 
Last edited by a moderator:

This is just a warning. If the the design is working in hardware you may ignore it.

Generally system clocks are routed using dedicated routing resources. The tools are intelligent enough to dedicate resources to such system clocks (that must reach to most parts of the design) from your RTL design.

How I fix that warning?

Is this an IP core or your own design?
I see this is an I2C clock and this clock need not reach to other parts of the design. If this is your design, then try manually inserting a global clock buffer to the I2C clock path.
 

This is just a warning. If the the design is working in hardware you may ignore it.

Generally system clocks are routed using dedicated routing resources. The tools are intelligent enough to dedicate resources to such system clocks (that must reach to most parts of the design) from your RTL design.

How I fix that warning?

Is this an IP core or your own design?
I see this is an I2C clock and this clock need not reach to other parts of the design. If this is your design, then try manually inserting a global clock buffer to the I2C clock path.
Thanks, but my design do not worked well and I see a lot of unexpected events in my logic.
 

Thanks, but my design do not worked well and I see a lot of unexpected events in my logic.

First things first. Did your perform thorough functional verification of your design via simulation?
i.e. do you have a testbench that exercises your design quite well?

If not it must be done asap without even thing about other design steps.
 

Thanks for your reaponse.

Just saw you wrote to me:

Is this an IP core or your own design?
I see this is an I2C clock and this clock need not reach to other parts of the design. If this is your design, then try manually inserting a global clock buffer to the I2C clock path.

How I insert a global clock buffer?

Regarding the testbench, I do not have a testbench yet.
 

Did you run timing analysis? Did you have any timing constraints? If it passed timing analysis, but you say 'it does not work well', then there must be a problem with your hardware.
 

@KingMoshe ,
Regarding the testbench, I do not have a testbench yet.
That means you do not even know if your design does what it is supposed to do.
So it does not make any sense to do PnR of a design which is not functionally verified.

Then I repeat again....
First things first. Did your perform thorough functional verification of your design via simulation?
i.e. do you have a testbench that exercises your design quite well?

If not it must be done asap without even thing about other design steps.
 
Last edited:

@KingMoshe ,
Regarding the testbench, I do not have a testbench yet.
That means you do not even know if your design does what it is supposed to do.
So it does not make any sense to do PnR of a design which is not functionally verified.

Then I repeat again....
First things first. Did your perform thorough functional verification of your design via simulation?
i.e. do you have a testbench that exercises your design quite well?

If not it must be done asap without even thing about other design steps.
I already burn my design code to the fpga and I test it by oscilloscope and I see that everything looked good, I meant to the I2C communication between EEPROM and FPGA, but when I perform little changes in my code all the data line looks terrible and I don't find the reason why.. how testbench can help me in such a case?
 

The FPGA is the I2C master and the EEPROM is the slave. The EEPROM must be having the I2C registers which hold the data send from the FPGA before sending it out to the EEPROM memory.
What you can do is to imitate these EEPROM I2C slave registers in the test bench. Your I2C master can be the DUT. Your testbench can drive the I2C master transactions and monitor if correct data is received at the EEPROM I2C slave registers.
This testbench idea is solely made on the assumption that there is possibly a problem between i2c master and slave communication. At-least I would do it this way, rather than the painful and time-costly of using scopes on the PCB traces.
 

Hi,

just a guess:
You generated the I2C clock by clock dividers / counters, instead of generating clock_enable signals.

I assume the problem lies in your code. Thus I recommend to show your code.

Klaus
 

Hi,

just a guess:
You generated the I2C clock by clock dividers / counters, instead of generating clock_enable signals.

I assume the problem lies in your code. Thus I recommend to show your code.

Klaus
Code:
module I2C_MASTER(
    clk,
    RST,
//    I2C_SDA,
    I2C_SCL,
    data,
    data_addr,
    read_en,
    start,
//    ready,
    WC,
    I2C_SDA_OUT,
    nBytes,
    saved_data_read,
    RAM_WR_CLK_EN,
    RAM_RD_CLK_EN,
    ram_addr
);


//INPUTS-----------------------------------------------------------------------------------------------------
    input wire clk;
    input wire RST;
    input wire [7:0] data;
    input wire [7:0] data_addr;
    input wire read_en;
    input wire start;
    inout wire I2C_SDA_OUT;
    input wire [7:0] nBytes;

//OUTPUTS----------------------------------------------------------------------------------------------------
    reg I2C_SDA = 1;
    output wire I2C_SCL;
//    output wire ready;
    output reg WC;
    output reg [7:0] saved_data_read;
    output reg RAM_WR_CLK_EN = 0;
    output reg RAM_RD_CLK_EN = 0;
//LOCAL------------------------------------------------------------------------------------------------------
    reg [7:0] index;
    reg [7:0] state;
    reg stop;
    reg [7:0] count;
    reg [5:0]     counter         =     0    ;
    reg I2C_CLK = 1;
    reg CLK_FSM;
    reg            SDAin                =    0    ;
    reg SDAin_en = 0;
    reg i2c_scl_enable = 0;
    parameter [6:0] start_init = 7'b1010011;
    parameter [2:0] addr_init = 3'b001;
    reg [7:0] saved_data;                                //saved DATA for write to eeprom
    reg [7:0] saved_data_addr;                            //saved ADDRESS BYTR
    reg [7:0] data_read;                                //data read from eeprom
    reg [7:0] nBytes_count;
    reg [7:0] total_params;
    output reg [7:0] ram_addr;                                //Ram address to write the data from eeprom
    localparam STATE_IDLE = 0;
    localparam STATE_START = 1;
    localparam STATE_INIT_START = 2;
    localparam STATE_INIT_ADDR = 3;
    localparam STATE_ADDR = 4;
    localparam STATE_RW_RD = 5;
    localparam STATE_WACK = 6;
    localparam STATE_DATA_ADDR = 7;
    localparam STATE_WACK2 = 8;
    localparam STATE_DATA_WRITE = 9;
    localparam STATE_DATA_READ = 10;
    localparam STATE_WACK3_WRITE = 11;
    localparam STATE_NO_ACK = 12;
    localparam STATE_STOP_LOW = 13;
    localparam STATE_STOP_HIGH = 14;
    localparam STATE_WACK_READ = 15;
    localparam STATE_RD_EN = 16;
    localparam STATE_START_READ = 17;
    localparam STATE_READ_START_LOW = 18;
    localparam STATE_READ_START_HIGH = 19;
    localparam STATE_INIT_START2 = 20;
    localparam STATE_INIT_ADDR2 = 21;


    assign I2C_SCL = (i2c_scl_enable == 0) ? 1'b1 : I2C_CLK;
//    assign ready = ((RST == 0) &&(state == STATE_IDLE)) ? 1 : 0;
//    assign         I2C_SDA_OUT =         I2C_SDA                    ;        //    SDA is defined as 'HIGH Z' or '0'.
    assign         I2C_SDA_OUT =     (    I2C_SDA        )     ?     1'bZ     : 1'b0            ;        //    SDA is defined as 'HIGH Z' or '0'.

// --------------------------------------
// ------------CLKS GENERATOR------------
// --------------------------------------

//    26.6MHz -> 350kHz
always @(negedge clk)                                                    //    Generating clocks for SCL and FSM.
    begin                                                                    //    The FSM clock should be delayed in order to ensure that
        SDAin <= I2C_SDA_OUT;                                                        //    SDA bits change only when SCL is LOW, and data acquisition
        if ( counter == 0 )     I2C_CLK        <=    ~I2C_CLK;                //    happans only when SCL is high.
        if ( counter == 38 )     counter    <=    0        ;
        else     counter <=     counter + 1'b1;                            //    26.6MHz / (38 * 2) =  350kHz (1.42usec on-time)
         
        if ( counter ==  19)    CLK_FSM    <=    ~CLK_FSM;                    //    19 / 26.6MHz = 0.714usec delay
    end



always @ (negedge CLK_FSM) begin
    if (RST) begin
        i2c_scl_enable <= 0;
        data_read <= 0;
    end else begin
        if (( state == STATE_IDLE) || (state == STATE_START) || (state == STATE_STOP_HIGH) || (state ==STATE_READ_START_LOW)) begin
            i2c_scl_enable <= 0;
        end
        else begin
            i2c_scl_enable <= 1;
        end
        if (SDAin_en == 1)                                                                 //    SDA input is sampled on the negedge of CLK_FSM,
                    begin                                                                        //    when CLK_SCL should be steady HIGH.
                        data_read[index] <= SDAin;
                    end            
    end
end


always @ (posedge CLK_FSM)
    begin
        if (RST || start == 0)
            begin
                state <= 0;                                                    //state = IDLE
                I2C_SDA <= 1;                                            
                count <= 8'd0;                                            
                //start_init <= 4'b1010;
                //addr_init <= 3'b011;
                stop <= 0;
                WC <= 1'b1;
                saved_data_addr <= 0;                                        // ADDRESS BYTE
                saved_data <= 0;                                            // SAVED DATA TO WRITE TO EEPROM
                nBytes_count <= nBytes;                                        // BYTES NUMBER TO READ
                RAM_WR_CLK_EN <= 0;
                RAM_RD_CLK_EN <= 1;            
                total_params <= 0;
                saved_data_read <= 0;                                        //SAVED DATA FROM EEPROM TO RAM
             
            end
            else begin
                case (state)
                    STATE_IDLE: begin                                                //WAITING TO START COMMAND
                        I2C_SDA <= 1;
                        if (start && (stop == 0)) begin
                            state <= STATE_START;
                            saved_data <= data;
                            saved_data_addr <= data_addr;
                            nBytes_count <= nBytes;
                            total_params <= nBytes;
                        end
                        else state <= STATE_IDLE;
                    end
                                 

                    STATE_START: begin                                                 //SDA TO "0" WHEN SCL IS "1"                                            
                        I2C_SDA <= 0;
                        state <= STATE_INIT_START;
                        count <= 6;
                        RAM_RD_CLK_EN <= 0;
                    end
                                     
                 
                    STATE_INIT_START: begin                                            //GENERATING SDA: 1010
                        I2C_SDA <= start_init[count];
                        if (count == 0) begin
                            state <= STATE_RW_RD;
                            //count <= 2;
                            end
                        else count <= count - 1'b1;
                    end    
                 
                    /*
                    STATE_INIT_ADDR: begin                                            //GENERATING SDA TO SALVE EEPROM ADDR: 011
                        I2C_SDA <= addr_init[count];
                        if (count == 0) state <= STATE_RW_RD;
                        else count <= count - 1'b1;
                    end    

*/
                    STATE_RW_RD: begin                                                //"0": WRITE, Selective READ and Sequential READ, "1": Imidiate READ
                        I2C_SDA <= 0;
                        state <= STATE_WACK;
                    end
                 
                 
                    STATE_WACK: begin                                                //WAINTING FOR ACK
                        if(read_en == 0) begin
                            WC <= 1'b0;
                            state <= STATE_DATA_ADDR; end
                        else begin
                            WC <= 1'b1;
                            state <= STATE_DATA_ADDR; end
                        count <= 7;
                    end


                    STATE_DATA_ADDR: begin                                            //EEPROM ADDRESSS POINTER
                        I2C_SDA <= saved_data_addr[count];
                        if (count == 0) state <= STATE_WACK2;
                        else count <= count - 1'b1;
                    end    
                 
                 
                    STATE_WACK2: begin                                                //WAITING FOR ACK
                        if(read_en == 0) state <= STATE_DATA_WRITE;
                        else state <= STATE_READ_START_HIGH;
                        count <= 7;
                    end


//WRITE

                    STATE_DATA_WRITE: begin
                        I2C_SDA <= saved_data[count];                                //DATA WRITE
                        if (count == 0) state <= STATE_WACK3_WRITE;
                        else count <= count - 1'b1;
                    end    
                 
         
                    STATE_WACK3_WRITE: begin                                        //WAITING FOR ACK
                        state <= STATE_STOP_LOW;
                    end    

//READ

                    STATE_READ_START_HIGH:                                            //    Start Condition - SDA to HIGH.
                        begin                                                        //    (SCL also gets HIGH for this state).
                            I2C_SDA    <=    1;
                            state     <=    STATE_READ_START_LOW;
//                            RAM_WR_CLK_EN <= 1;
                        end


                    STATE_READ_START_LOW:                                            //    Start Condition - SDA to LOW when SCL is HIGH.
                        begin                        
                            I2C_SDA <=    0;
                            state     <=    STATE_INIT_START2;
                            count <= 6;
                        end


                    STATE_INIT_START2: begin                                            //GENERATING SDA: 1010 011
                        I2C_SDA <= start_init[count];
                        if (count == 0) begin
                            state <= STATE_RD_EN;
                        //    count <= 2;
                        end
                        else count <= count - 1'b1;
                    end    
                 
            /*    
                    STATE_INIT_ADDR2: begin                                            //GENERATING SDA TO EEPROM ADDR: 011
                        I2C_SDA <= addr_init[count];
                        if (count == 0) state <= STATE_RD_EN;
                        else count <= count - 1'b1;
                    end    
*/

                    STATE_RD_EN: begin                                                //"0" WRITE, "1" READ
                        I2C_SDA <= 1;
                        state <= STATE_WACK_READ;
                    end


                    STATE_WACK_READ: begin                                            //WAITING FOR ACK
                        state <= STATE_DATA_READ;
                        index <= 7;
                    end


                    STATE_DATA_READ: begin                                            //RECIVE READ
                        I2C_SDA <=    1;
                        SDAin_en <= 1;
                        if ( index == 0 )                                      
                            begin
                                index         <= 7;
                                state         <= STATE_NO_ACK;
                                end
                        else  index <= index - 1'b1;
                             
                     
                    end    
                 
         
                    STATE_NO_ACK: begin                                                //WAITING FOR NO ACK                    //    if there are any bytes left to be read - going back                                                                              
                            SDAin_en    <=     0;                                                        //    to previous state.
                            saved_data_read     <= data_read;
                            ram_addr = total_params - nBytes_count;
                            if ( nBytes_count == 0 )
                                begin
                                    I2C_SDA         <=    1;                                    // MASTER NO ACK FOR STOP READING    
                                    state             <=     STATE_STOP_LOW;
                                end
                            else
                                begin
                                    I2C_SDA         <=    0;                                
                                    index        <=    7;
                                    nBytes_count         <=     nBytes_count - 1'b1;                                    
                                    state         <=     STATE_DATA_READ;                                
                                end                          
                        end    


//STOP

                    STATE_STOP_LOW: begin                                            //STOP CONDITION
                        I2C_SDA <=    0;                            
                        state     <=     STATE_STOP_HIGH;
                    end



                    STATE_STOP_HIGH: begin                                            //STOP CONDITION
                        I2C_SDA <= 1;
                        state <= STATE_IDLE;
                        stop <= 1;
                        WC <= 1;
                        RAM_WR_CLK_EN <= 0;
                    end    

                endcase        
            end
    end




endmodule
[moderator action: added code tags]
 
Last edited by a moderator:

Hi,
if ( counter == 19) CLK_FSM <= ~CLK_FSM;
I´m no expert.
But as far as I understand: here you generate a standard signal (not a dedicated clock)

always @ (posedge CLK_FSM)
But here you treat it as a clock.

****
I´d rather set flags: rising_edge_flag and falling_edge_flag within the "always @(negedge clk) "
..and process and clear them in the according sections.

***
In either case (above solution and your solution) it is processed one master_clock delayed

If you don´t want the delay you have to process it within the "always @(negedge clk) " section.

Klaus
 

Hi,

I´m no expert.
But as far as I understand: here you generate a standard signal (not a dedicated clock)


But here you treat it as a clock.

****
I´d rather set flags: rising_edge_flag and falling_edge_flag within the "always @(negedge clk) "
..and process and clear them in the according sections.

***
In either case (above solution and your solution) it is processed one master_clock delayed

If you don´t want the delay you have to process it within the "always @(negedge clk) " section.

Klaus
Can you please detail more? I am not sure I understand what I should do.

Thank you.
Moshe.
 

The correct way to handle the problem is to switch from generated clocks to a common design clock with clock enables. This eleminates clock related warnings and many possible timing issues.
 

The correct way to handle the problem is to switch from generated clocks to a common design clock with clock enables. This eleminates clock related warnings and many possible timing issues.
How I generate clock enable signal?
Do you have an example ?

Thanks
 

Hi,
How I generate clock enable signal?
Do you have an example ?

Thanks
I think it´s the most often discussed topic regarding FPGAs. Thus there already are very many examples around. Just do a search.

Basically what I described in post#12 with the flags is very similar.

Klaus
 

Hi,

I think it´s the most often discussed topic regarding FPGAs. Thus there already are very many examples around. Just do a search.

Basically what I described in post#12 with the flags is very similar.

Klaus
Sorry, but I don't find an example and it will be great if you have a tutorial because I am losing a lot of time.
 

Sorry, but I don't find an example and it will be great if you have a tutorial because I am losing a lot of time.
Phrase for search engine - "I2C Master Verilog"

How I generate clock enable signal?
Do you have an example ?

Phrase for search engine - "generate clock enables Verilog"
 

Seeing your code I noticed that the following line does not match the comments
Code:
        if ( counter == 38 )     counter    <=    0        ;
        else     counter <=     counter + 1'b1;                            //    26.6MHz / (38 * 2) =  350kHz (1.42usec on-time)
This counter has a period of 39 clocks and therefore is a divide by 78 not a divide by 76 as stated in the comment. The problem with the code is that a clock generated by a FF will not be promoted to a global buffer in most cases. Doing so usually requires you instantiate a clock buffer in the design to force the tools to place it on a global.

I recommend as have others just produce a clock enable and run the design using that and the input clock.
https://www.fpga4student.com/2017/08/how-to-generate-clock-enable-signal.html
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top