Adharsh
Adharsh

Reputation: 45

Counter changing on both edges of clock

Below code is of up counter. The code has no errors, but the graph has some errors like the count should be at only posedge but the count is counting even at the negedge of clk.

module countergate (clk,rst,current,next);
    input clk,rst;
    input [2:0] current;
    output reg [2:0] next;
    always@(*)
    begin
        if (rst==1)
            {next[2],next[1],next[0]} <= 3'b000;
        else 
        begin   
            next[2] <= ((~current[2])&(current[1])&(current[0]) | (current[2])&(~current[0]) | (current[2])&(~current[1]));
            next[1] <= ((~current[1])&(current[0]) | (current[1])&(~current[0]));
            next[0] <= (~current[0]);
        end
    end
    endmodule

TEST BENCH

`include "countergate.v"
module tb1();
reg clk,rst;
reg [2:0] current;
wire [2:0] next;
countergate DUT (clk,rst,current,next);
initial 
begin
    clk = 1;
    forever #1 clk = ~clk;
end
initial
begin 
rst = 1;
repeat (2) @(posedge clk);
rst = 0;
end
initial
begin
    #4;
    {current[2],current[1],current[0]} = 3'b000;
    #1;
    {current[2],current[1],current[0]} = 3'b001;
    #1;
    {current[2],current[1],current[0]} = 3'b010;
    #1;
    {current[2],current[1],current[0]} = 3'b011;
    #1;
    {current[2],current[1],current[0]} = 3'b100;
    #1;
    {current[2],current[1],current[0]} = 3'b101;
    #1;
    {current[2],current[1],current[0]} = 3'b110;
    #1;
    {current[2],current[1],current[0]} = 3'b111;
    #1;
$finish;    


end
initial
begin
    $monitor("%t :clk = %b , rst = %b , current = %b, next = %b", $time,clk,rst,current,next);
end
endmodule

enter image description here

Upvotes: 1

Views: 746

Answers (2)

m4j0rt0m
m4j0rt0m

Reputation: 354

You have to explicitly indicate that you want the always block to be evaluated at posedge of the clock:

always @ (posedge clk)...

If you also want to include an "asynchronous" reset, this means a reset that doesn't care about the clock cycle, you should also include it in the sensitivity list:

always @ (posedge clk, posedge rst)...

As this, the always block would trigger in both cases, in posedge clk or in posedge rst.

Upvotes: 0

toolic
toolic

Reputation: 62083

As mentioned in a Comment, if you want the count value to only change on the posedge of the clock instead of on both edges of the clock, you should use a sequential always block. Change:

always@(*)

to:

always @(posedge clk or posedge rst)

You also need to change the testbench since it is driving the current input on both edges of the clock as well. You should drive it only on the posedge of the clock. Since you are incrementing the input, you can greatly simplify the code using a for loop. Also, instead of using # delays, you can align it to the clock as you did with the rst signal.

integer i;
initial
begin
    repeat (2) @(posedge clk);
    for (i=0; i<8; i=i+1) begin
        current = i;
        @(posedge clk);
    end
    $finish;    
end

Upvotes: 0

Related Questions