Forum Discussion

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

This short verilog code is not working

The following code is supposed to be easy and straight forward, but its not giving the correct results!

I want the output to follow input whenever the counter = 5. But whenever there is an edge in the input, i want the counter to load the value of 3. The counter is initialied to 3.

assign invdata = ~data;

always @ (posedge clk or posedge data or posedge invdata) begin

if (clk) begin

if (counter==5) begin output<=input; counter<=1; end

else counter<=counter+1;

end

else if (data) counter<=3;

else counter<=3;

end

the results shows that the counter will always be stuck on 3. but, on every clock edge the counter will change randomly to around 5 values then go back to 3 after a while.why?

isnt that code 100% correct? if not, whats the correct code to do the same job?

im simulating on quartus II.

Another thought, what if data has a positive edge, and the it enters the above always loop at the same time clk is high. this way it will act exactly the same as if a posedge clk occured. no? and thats wrong! what should i do in such a case?

PS: the input is a clock with period = 200ns.

clk is a clk with period = 20ns.

Thanx.

6 Replies

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

    A few things to mention:

    1 - It looks like you're getting confused in your signal names. You're using a signal called data but you're also using a signal called input. Are they supposed to be the same thing?

    2 - You should never use the names "input" or "output" to name signals. Those are keywords in Verilog and should only be used when declaring inputs and outputs to a module, task, or function.

    3 - You're event triggerred always block. You need to keep in mind that what you are writing is going to be turned into hardware. Flip-flops in hardware have a single clock input. You cannot use a rising and falling edge of a signal as a clock input to a flip-flop. Your code is actually not synthesizable. You have a clock input, data input, and a asynchronous set and/or reset signal at your disposal.

    4 - It's good practice to provide a reset signal to initialize your registers to a pre-determined state.

    Does this meet your needs? I haven't compiled it so there might be a syntax error or two:

    module ocd(
        input       clk,            // clock
        input       reset_n,        // active low reset
        input       data_in,
        output      data_out
    );
    reg         last_data;
    reg    counter;
    wire        edge;
    assign      edge = last_data ^ data_in;
    always @(posedge clk or negedge reset_n) begin
        if(!reset_n) begin
                            data_out    <= 1'b0;
                            last_data   <= 1'b0;
                            counter     <= 3'd0;
        end else begin
                            last_data   <= data_in;
                            counter     <= counter + 3'd1;
            if(edge)        counter     <= 3'd3;
            else if(counter == 5) begin
                            counter     <= 3'd1;
                            data_out    <= data_in;
            end
        end
    end
    endmodule
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The original code is edge sensitive only for posedge(invdata) and level sensitive for clk and data. The code isn't generally unsynthesizable but most likely neither intended this way nor creating any meaningful logic behaviour. Additionally latching on data == 1 and sampling on posedge(invdata) respectively negedge(data) creates a timing violation for the edge triggered flip-flop.

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

    --- Quote Start ---

    A few things to mention:

    1 - It looks like you're getting confused in your signal names. You're using a signal called data but you're also using a signal called input. Are they supposed to be the same thing?

    2 - You should never use the names "input" or "output" to name signals. Those are keywords in Verilog and should only be used when declaring inputs and outputs to a module, task, or function.

    3 - You're event triggerred always block. You need to keep in mind that what you are writing is going to be turned into hardware. Flip-flops in hardware have a single clock input. You cannot use a rising and falling edge of a signal as a clock input to a flip-flop. Your code is actually not synthesizable. You have a clock input, data input, and a asynchronous set and/or reset signal at your disposal.

    4 - It's good practice to provide a reset signal to initialize your registers to a pre-determined state.

    Does this meet your needs? I haven't compiled it so there might be a syntax error or two:

    module ocd(
        input       clk,            // clock
        input       reset_n,        // active low reset
        input       data_in,
        output      data_out
    );
    reg         last_data;
    reg    counter;
    wire        edge;
    assign      edge = last_data ^ data_in;
    always @(posedge clk or negedge reset_n) begin
        if(!reset_n) begin
                            data_out    <= 1'b0;
                            last_data   <= 1'b0;
                            counter     <= 3'd0;
        end else begin
                            last_data   <= data_in;
                            counter     <= counter + 3'd1;
            if(edge)        counter     <= 3'd3;
            else if(counter == 5) begin
                            counter     <= 3'd1;
                            data_out    <= data_in;
            end
        end
    end
    endmodule
    

    --- Quote End ---

    Sorry for the typo. Yes input means the data, as the keywords wont even compile successfully.

    According to ur code, edge is high only for a short amount of time. so if edge is high only between two clock pulses and goes back to low before the next clock pulse, the edge wont be detected in such case. right?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    The original code is edge sensitive only for posedge(invdata) and level sensitive for clk and data. The code isn't generally unsynthesizable but most likely neither intended this way nor creating any meaningful logic behaviour. Additionally latching on data == 1 and sampling on posedge(invdata) respectively negedge(data) creates a timing violation for the edge triggered flip-flop.

    --- Quote End ---

    I want the flip flop to be triggered on both posedge and negedge of my data input signal.

    I imagined the clk port of the FF is connected to an output of an OR gate, and triggered on posedge. This OR gate has (clk, data, invdata) as its inputs. whats wrong with such setup?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    It's not possible to trigger a single FF on both edges, neither a discrete device, e. g. a 74HC74 nor a FPGA FF. It doesn't work directly or by any trick (as defining an inverted signal).

    To design logic, that is sensitive for both edges, you can use two FFs and combine the results, but you have to be careful not to generate glitches in the output.

    Another option is synchronous edge detection by a sufficient fast clock.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I want the flip flop to be triggered on both posedge and negedge of my data input signal.

    I imagined the clk port of the FF is connected to an output of an OR gate, and triggered on posedge. This OR gate has (clk, data, invdata) as its inputs. whats wrong with such setup?

    --- Quote End ---

    I modified the code you got from jacobjones, because "edge" is a reserved keyword in Verilog. The code could not compiled by Quartus.

    I inserted two edge detectors, which looks for the rising and the falling edge of your input signal. I check at least the basic function.

    module ocd(

    input clk, // clock

    input reset_n, // active low reset

    input data_in,

    output reg data_out

    );

    reg last_data;

    reg [2:0] counter;

    wire edge_pos /* synthesis keep */;

    wire edge_neg /* synthesis keep */;

    // wire edge;

    // assign edge = last_data ^ data_in;

    assign edge_pos = !last_data & data_in; // detects posedge in data_in

    assign edge_neg = last_data & !data_in; // detects negedge in data_in

    always @(posedge clk or negedge reset_n) begin

    if(!reset_n) begin

    data_out <= 1'b0;

    last_data <= 1'b0;

    counter <= 3'd0;

    end else begin

    last_data <= data_in;

    counter <= counter + 3'd1;

    if(edge_pos ^ edge_neg ) counter <= 3'd3;

    // if(edge) counter <= 3'd3;

    else if(counter == 5) begin

    counter <= 3'd1;

    data_out <= data_in;

    end

    end

    end

    endmodule