Forum Discussion

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

Clock signal source should drive only clock input ports

I'm getting this message as a warning:

Warning (308040): (Medium) Rule C104: Clock signal source should drive only clock input ports. Found 2 nodes related to this rule.

My design has a clk input and a wr input. They are asynchronous so I synced the wr using the clk as follows:

always_ff @ (posedge clk)

wr_d1 <= wr;

In another part of the code I want to use the main clock but use the write signal as a qualifier to the operation, like so:


	always_ff @ (posedge clk)
	begin
		if (wr_d1 && (register_addr == ASMI_OPCODE)) wrote_opcode <= 1'b1;
		else wrote_opcode <= 1'b0;
	end

I really need the wrote_opcode signal to be asserted for only one clk cycle, so this process block needs to be triggered by the clk. So how can I set the wrote_opcode for just one clk cycle only when the wr_d1 has been asserted?

3 Replies

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

    --- Quote Start ---

    My design has a clk input and a wr input. They are asynchronous so I synced the wr using the clk as follows:

    always_ff @ (posedge clk)

    wr_d1 <= wr;

    --- Quote End ---

    That is not sufficient to synchronize to clk. The register for wr_d1 has a finite probability of becoming metastable when wr violates the register setup and hold time. You need at least one more register to reduce that probability, eg.

    
    always_ff @ (posedge clk)
       begin
    wr_d1 <= wr;
     wr_d2 <= wr_d1;
     end
    

    Since this code would be used multiple times, you should create a sync() component.

    --- Quote Start ---

    In another part of the code I want to use the main clock but use the write signal as a qualifier to the operation, like so:

    
        always_ff @ (posedge clk)
        begin
            if (wr_d1 && (register_addr == ASMI_OPCODE)) wrote_opcode <= 1'b1;
            else wrote_opcode <= 1'b0;
        end
    
    I really need the wrote_opcode signal to be asserted for only one clk cycle, so this process block needs to be triggered by the clk. So how can I set the wrote_opcode for just one clk cycle only when the wr_d1 has been asserted?

    --- Quote End ---

    You probably don't want to use wr_d1 (or wr_d2) in this code, what you really want is an edge-detect of when wr_d2 goes from low-to-high. You can implement that logic using another delay, eg., wr_d3 <= wr_d2, and then wr_edge <= wr_d2 and !wr_d3; (if that is the right verilog symbol for not). Then use wr_edge in your opcode logic.

    Cheers,

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

    --- Quote Start ---

    That is not sufficient to synchronize to clk. The register for wr_d1 has a finite probability of becoming metastable when wr violates the register setup and hold time. You need at least one more register to reduce that probability, eg.

    
    always_ff @ (posedge clk)
       begin
    wr_d1 <= wr;
     wr_d2 <= wr_d1;
     end
    

    Since this code would be used multiple times, you should create a sync() component.

    Dave

    --- Quote End ---

    Saw that suggestion in another thread. I actually have a double clocked register wr_d2 but I was wondering if its really that critical. I can use the second output.

    Not sure what you mean by a sync component. I have similar syncing for wr, rd, and ale. Its in my main code. What is the advantage of putting it into a sync component?

    --- Quote Start ---

    You probably don't want to use wr_d1 (or wr_d2) in this code, what you really want is an edge-detect of when wr_d2 goes from low-to-high. You can implement that logic using another delay, eg., wr_d3 <= wr_d2, and then wr_edge <= wr_d2 and !wr_d3; (if that is the right verilog symbol for not). Then use wr_edge in your opcode logic.

    Cheers,

    Dave

    --- Quote End ---

    I'm not quite sure how this would shift the edge 1/2 clk. When I code this I basically get the same as wr_d2 on wr_edge. I assume you meant something like:

    assign wr_edge = (wr_d2 && !wr_d3);

    or should I clock it into a register? (it does not seem to matter, other than it delays it one more cycle).
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I actually have a double clocked register wr_d2 but I was wondering if its really that critical.

    --- Quote End ---

    Yes, correct synchronization is very critical.

    --- Quote Start ---

    What is the advantage of putting it into a sync component?

    --- Quote End ---

    Well written code should be easy to read. If you have to synchronize a lot of input signals, then you'll have ale, ale_d1, ale_d2, etc. If you have a synchronizer component, then you'll just have two signals, i.e., ale and ale_sync.

    --- Quote Start ---

    I'm not quite sure how this would shift the edge 1/2 clk.

    --- Quote End ---

    It doesn't. The objective was to create a signal that pulsed for one clock period in the FPGA clock domain for each (asynchronous) ALE pulse.

    --- Quote Start ---

    I assume you meant something like:

    assign wr_edge = (wr_d2 && !wr_d3);

    or should I clock it into a register? (it does not seem to matter, other than it delays it one more cycle).

    --- Quote End ---

    Yeah, something like that. Whether or not it needs to be clocked depends on what that pulse feeds. Since the original signal was asynchronous, there's no harm in adding the output register to reduce the combinatorial path lengths.

    Cheers,

    Dave