Search code examples
verilogfpgaiverilog

Verilog error handling two posedge signals in "always" block


I have a problem with an "always" block in Verilog. First let me present the code:

module syncRX(clk, signal, detect, output clk_1khz);
    input clk, signal;
    output reg [7:0] detect = 0;

    //wire clk_1khz;
    freq_div div(.clk(clk), .clk_1khz(clk_1khz));
    
    always @(posedge signal, posedge clk_1khz)
     begin
        detect <= detect + 1;
     end

endmodule // top

module freq_div(input clk, output reg clk_1khz);
    reg [12:0] count = 0;
    always @(posedge clk)
     begin
        if(count == 6000)
            begin
                clk_1khz <= ~clk_1khz;
                count <= 0;
            end
        else
            count <= count + 1;
     end
    
endmodule

I got this error message (using Icestorm):

2.3.7. Executing PROC_DFF pass (convert process syncs to FFs). Creating register for signal \freq_div.\clk_1khz' using process \freq_div.$proc$syncRX.v:22$4'. created $dff cell $procdff$15' with positive edge clock. Creating register for signal \freq_div.\count' using process \freq_div.$proc$syncRX.v:22$4'. created $dff cell $procdff$16' with positive edge clock. Creating register for signal \syncRX.\detect' using process \syncRX.$proc$syncRX.v:8$1'. ERROR: Multiple edge sensitive events found for this signal! make: *** [Makefile:44: syncRX.bin] Error 1

I could detect that the "always" block involved is:

always @(posedge signal, posedge clk_1khz)
     begin
        detect <= detect + 1;
     end

becaise if change "always @(posedge signal, posedge clk_1khz)" for "always @(posedge signal)" works.

Also fails in that same way:

always @(posedge signal)
     begin
        detect <= detect + 1;
     end
    
    always @(posedge clk_1khz)
     begin
        detect <= detect + 1;
     end

And the error disappears when comment the line "detect <= detect + 1;" in bought of cases. Then the error is related to the access to the "detect" counter register. I have not idea why I can not trigger this counter from two different signals, but in fact, I have to increase the counter in bought post edge signals (and I can figure out in my mind a very simple digital circuit doing this), and I found many examples in Verilog using a "always" block with two posedges triggers... But mine dont works.

Please, if anyone can explain me why dont work and how I can do it. It will be extremely useful for me.


Solution

  • I guess you can use separate counters for each clk_1khz and signal. Then just add them:

    always @(posedge signal)
         begin
            detect_sig <= detect_sig + 1;
         end
        
    always @(posedge clk_1khz)
         begin
            detect_clk <= detect_clk + 1;
         end
    
    assign detect = detect_sig + detect_clk;
    

    Though, @(posedge signal) looks strange to me. You should not use anything but clocks here. So, check your algorithm.

    And, you should also simulate and verify your model before synthesizing.

    Since you asked this in another question, your second variant with 2 different always blocks is not synthesizable either. It results in the detect signal driven by multiple always blocks and causing a multiply-driven condition in synthesis. In simulation it will cause non-deterministic results. synthesis should break. Check messages.