0
\$\begingroup\$

I am having some troubles with creating an edge detector in verilog. So far I've come up with this:

module edge_detector (  
        input     ce,               // Clock enable.
        input     data,             // Data signal for edge detection.
        output reg detected,        // Output signal that goes high when edge is detected.
        input     reset,            // Active high reset.
        input     clk,              // Clock.
        input     [1:0] edge_sel,   // Edge selection. Look in description for details.
        output     sim_prev_data    // Simulation variable. Previous data state.
    );

    reg prev_data = 'bx;    // Previous data signal level state.

    always @(posedge clk) begin
        if (reset) begin
            detected <= 0;
            prev_data <= 'bx;
        end else if (ce) begin
            // Upon initialization or after reset prev_data state is unknown.
            // So after first clock tick prev_data is set, but detected output
            // should stay low.
            if (prev_data == 'bx) begin
                prev_data <= data;
                detected <= 0;
            end else begin
                case (edge_sel)
                    'b00: detected = (prev_data == 0 && data == 1);     // Rising edge.
                    'b01: detected = (prev_data == 1 && data == 0);     // Falling edge.                    
                    'b10: detected = ((prev_data == 0 && data == 1) ||  // Any edge.
                                      (prev_data == 1 && data == 0));       
                    'b11: detected = ((prev_data == 0 && data == 0) ||  // No edge change.
                                      (prev_data == 1 && data == 1));           
                endcase

                prev_data = data;
            end
        end
    end

    assign sim_prev_data = prev_data;
endmodule

waves

Picture represents simulation waveform generated by iverilog and gtkwave. As can be seen when reset=1 also detected=0 and prev_data=x. When reset goes low and on first rising edge of a clock tick, marked by red line, detected has a value of x. Even though I have explicitly defined detected<=0; under ...if (prev_data == 'bx) begin...,

Why doesnt detected have a value of 0 after reset?

\$\endgroup\$
1
\$\begingroup\$

I posted this as a comment, but will expand it into an answer.

The logical equality operator is just that, logical. Anything that is not a 1 or a 0 results in an unknown (x) output. The case equality operator (prev_data==='bx) will require matching of x as well as 0 and 1. However the use of x in physical synthesis makes no sense - a bit in hardware will be either 1 or 0.

What your comment describes Upon initialization or after reset prev_data state is unknown. doesn't make sense. After reset, you should specifically initialise the value to something. In physical hardware, how can x be distinguished? A register can't be x, only 1 or 0. So you should ensure that after reset it is set to a known value.

If you wish to achieve what your comment in the code implies, you can simply create a delayed reset signal and use that as a signal that reset has just been deasserted. For example, the following would achieve what you describe:

reg prev_data = 'b0;    // Previous data signal level state.

reg exit_reset;
always @(posedge clk) begin
    if (reset || ce) begin
        exit_reset <= reset; // Exit reset is the reset signal delayed by one cycle, or until the clock is enabled.
    end
end

always @(posedge clk) begin
    if (reset) begin
        detected <= 0;
        prev_data <= 'b0; //Initialise to a known value
    end else if (ce) begin
        // Upon initialization or after reset prev_data state is incorrect.
        if (exit_reset) begin
            //If we just exited reset, then initialise prev_data but keep detected low.
            prev_data <= data;
            detected <= 0;
        end else begin
            ....
            prev_data = data;
        end
    end
end
\$\endgroup\$
  • \$\begingroup\$ Doesnt x in verilog also means "dont care". By setting some variable to x, I am essentialy saying: "I dont care what value this will be, because I will initialize it to appropriate value when I will need it." Wouldnt this enable the synthesis tool to further optimize the solution? P.S I've changed the original code to include another reg, that is 0 upon initialiazation and reset, and goes to 1 after one clock tick. So upon initialiozation and reset prev_data=x but after one clock tick it gets the right value: prev_data=data. The simulation works. Am I missing something? \$\endgroup\$ – Golaž Feb 13 '16 at 14:45
  • \$\begingroup\$ Also detected output only changes after two clock ticks, after first prev_data gets some value (not x) and after second detected output changes to appropriate value. \$\endgroup\$ – Golaž Feb 13 '16 at 14:50
  • \$\begingroup\$ @Golaž that's a common misconception. x doesn't mean "don't care", in means "unknown". There is quite a big difference. If you tell the synthesis tool to initialise something to x it will likely either give you an error, or initialise it to 0. The only time x should really be used is in casex statements to indicate to the synthesis tool that a bit can be ignored when matching it to a case value. \$\endgroup\$ – Tom Carpenter Feb 13 '16 at 15:02
  • \$\begingroup\$ Is there a "dont care" value in verilog? How can I tell the synthesis tool that I dont care what the value is, and just let it choose some value that would produce the most optimized solution? \$\endgroup\$ – Golaž Feb 13 '16 at 15:43
  • 1
    \$\begingroup\$ @Golaž Behavior wise there is no difference. However I find it makes things easier to follow if you break them up - exit_reset is really its own independent signal, so why put it in an always block with lots of other stuff. It comes down to a difference in paradigm between HDL and procedural languages. In procedural you are trying to minimize the number of lines to be executed, whereas in HDL the number of lines is meaningless to the final design size/speed - so use as many as you like, make it as readable as possible. \$\endgroup\$ – Tom Carpenter Feb 13 '16 at 20:56
1
\$\begingroup\$

detected is a function of signal prev_data which is undefined at the clock instance that you indicate.

Upon reset, you have to set prev_data to something. That's what the reset is for.

I don't think that prev_data == 'bx has any practical meaning at all... 'bx is not a value, so it cannot be compared to a value. This cannot be synthesized. If you are trying to do something behavioral only, change the type of your variable and assign something different. Say you make it an integer, then use -1 for "undefined", 0 for 0 and 1 for 1.

\$\endgroup\$
  • \$\begingroup\$ Ahh I see. For some reason I though that synthesis tool can differ between 0,1 and X and implement a solution which would wait one clock tick. Exactly, I though synthesis tool will be able to "know" that by prev_data=='bx I really wanted to check if prev_data was already set or not. \$\endgroup\$ – Golaž Feb 12 '16 at 21:43
  • \$\begingroup\$ @Golaž the logical equality operator is just that, logical. Anything that is not a 1 or a 0 results in an unknown (x) output. The case equality operator (prev_data==='bx) will require matching of x as well as 0 and 1. However the use of x in physical synthesis makes no sense - a bit in hardware will be either 1 or 0. \$\endgroup\$ – Tom Carpenter Feb 13 '16 at 3:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.