Search code examples
verilogquartustest-bench

Reset a simple counter


I'm trying to write a simple counter using Verilog on Quartus Prime and a testbench in Verilog being tested with Questa FPGA modelSim.

The goal of my counter is to count up to 7 at positive edge of a clock cycle and wrap back to 0 after 7 or if the low assert reset signal is asserted.

I am getting the counting and the wrapping after 7 correct; however, the counter does not wrap back when the reset is asserted.

Module

// TFT_LCD_Driver Second Version
module TFT_LCD_Driver(  
    input clk,
    input rst_n,
    output reg [3:0] cnt    
);

initial cnt = 0;


always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            cnt <= 0;
        if (cnt == 4'd7)
            cnt <= 0;
        else
            cnt <= cnt + 4'd1;
end
endmodule

TestBench

// TFT_LCD_Driver_tb
// spi driver test bench
`define clk_period 20

module TFT_LCD_Driver_tb();

    reg clk;
    reg rst_n;
    wire [3:0] cnt;
    
    TFT_LCD_Driver tft(
        .clk(clk),
        .rst_n(rst_n),
        .cnt(cnt)
    );
    
    
    initial begin
        clk = 1'b1;
        rst_n = 1'b1;
        
        #30 rst_n = 1'b0;
        #30 rst_n = 1'b1;
    end
    
    always #(`clk_period/2) clk = ~clk;
    
endmodule

Here is waveform of the incorrect counter

reset signal is not wrapping the counter

I expect to see that the counter goes to 0 when the low assert reset signal is pulled low. However, the waveform shows that it continues to count until 7 and then wraps back to 0. I have highlighted and marked the incorrect spot where I expect the restart.


Solution

  • You have 2 separate if statements in your always block. The 2nd one takes precedence over the 1st. Just before reset is asserted, cnt is 2. The 1st assignment does not take effect, but the increment assignment does take effect, setting cnt to 3.

    You should change:

        if (cnt == 4'd7)
    

    to:

        else if (cnt == 4'd7)
    

    always @(posedge clk or negedge rst_n) begin
            if (!rst_n) 
                cnt <= 0;
            else if (cnt == 4'd7)
                cnt <= 0;
            else
                cnt <= cnt + 4'd1;
    end