2

I'm working on a Verilog project where I have implemented a countdown timer using preset counters. However, I'm encountering a strange issue when I set a time and start the countdown. On the initial start, the timer begins counting down from the wrong value, but after that, it functions correctly. Here's what happens:

If I set the timer to 1 minute, the countdown starts from 1 minute 59 seconds instead of 1 minute. If I set the timer to 10 minutes, it starts from 19 minutes 59 seconds instead of 10 minutes. If I set the timer to 1 hour, it starts from 1 hour 59 minutes instead of 1 hour.

After this initial incorrect behavior, the timer works as expected for subsequent countdowns. I suspect the issue has something to do with the preset values or how the timer initializes, but I'm not sure how to fix it.

//Timer Module
module timer(KEY,SW,oCNT0,oCNT1,oCNT2,oCNT3,oCNT4,oCNT5,CLOCK_50,Done);

input [1:0] KEY; 
input [9:0] SW;
input      CLOCK_50;


output [3:0] oCNT0,oCNT1,oCNT2,oCNT3,oCNT4,oCNT5;
output wire Done;

wire EN0,EN1,EN2,EN3,EN4,EN5;
wire [3:0] oCNT0, oCNT1,oCNT2,oCNT3,oCNT4,oCNT5;
wire [18:0] oCNT;

assign Done = ({oCNT5,oCNT4,oCNT3,oCNT2,oCNT1,oCNT0}==(24'b000000000000000000000000)) ? 1'b0 : 1'b1;   

assign iRSTn=(SW[7]&~SW[6]&~KEY[0]) ? 1'b0 : 1'b1;  

reg start;

reg [26:0] press_counter;
reg long_press;

reg button_pressed;

//This part of the code implements logic to perform two different functions using a single key.
always @(posedge CLOCK_50 or negedge iRSTn) begin
    if (!iRSTn) begin
        press_counter <= 0;
        button_pressed <= 0;
        long_press <= 0;
        start <= 0;
    end else begin
        if (KEY[1]) begin
            press_counter <= press_counter + 1;
            button_pressed <= 1;

            // 2sec over
            if (press_counter >27'd100000000) begin
                long_press <= 1;
            end
        end else if (button_pressed) begin
            if (long_press) begin
                start <= start; // Preset
            end else begin
                start <= ~start; //Toggle
            end
            // reset
            press_counter <= 0;
            button_pressed <= 0;
            long_press <= 0;
        end
    end
end


COUNTER_LAB
#(.n(23),.k(5000000))
U_Counter_ms_gen(
        .iRSTn(iRSTn),
        .iCLK(CLOCK_50),
        .iEN(start&Done),
        .oEN(EN0),
        .oCNT(oCNT)
); // 5M Count

COUNTER_PRESET_DOWN
#(.n(4),.k(10))
COUNTER_timer_ms(.iCLK(CLOCK_50), .iRSTn(iRSTn), .iPRSTn(1'b0), .iEN(EN0), .iDATA_Preset(4'b0000), .oEN(EN1), .oCNT(oCNT0));  // ms

COUNTER_PRESET_DOWN
#(.n(4),.k(10))
COUNTER_timer_s0(.iCLK(CLOCK_50), .iRSTn(iRSTn), .iPRSTn(1'b0), .iEN(EN1), .iDATA_Preset(4'b0000), .oEN(EN2), .oCNT(oCNT1));  // seconds (units)

COUNTER_PRESET_DOWN
#(.n(3),.k(6))
COUNTER_timer_s1(.iCLK(CLOCK_50), .iRSTn(iRSTn), .iPRSTn((~KEY[1] & ~long_press) & (SW[5:4] == 2'b00) & (SW[7:6] == 2'b10)), .iEN(EN2), .iDATA_Preset(SW[3:0]), .oEN(EN3), .oCNT(oCNT2));  // seconds (tens)

COUNTER_PRESET_DOWN
#(.n(4),.k(10))
COUNTER_timer_m0(.iCLK(CLOCK_50), .iRSTn(iRSTn), .iPRSTn((~KEY[1] & ~long_press) & (SW[5:4] == 2'b01) & (SW[7:6] == 2'b10)), .iEN(EN3), .iDATA_Preset(SW[3:0]), .oEN(EN4), .oCNT(oCNT3));  // minutes (units)

COUNTER_PRESET_DOWN
#(.n(3),.k(6))
COUNTER_timer_m1(.iCLK(CLOCK_50), .iRSTn(iRSTn), .iPRSTn((~KEY[1] & ~long_press) & (SW[5:4] == 2'b10) & (SW[7:6] == 2'b10)), .iEN(EN4), .iDATA_Preset(SW[2:0]), .oEN(EN5), .oCNT(oCNT4));  // minutes (tens)

COUNTER_PRESET_DOWN
#(.n(4),.k(13))
COUNTER_timer_h(.iCLK(CLOCK_50), .iRSTn(iRSTn), .iPRSTn((~KEY[1] & ~long_press) & (SW[5:4] == 2'b11) & (SW[7:6] == 2'b10)), .iEN(EN5), .iDATA_Preset(SW[3:0]), .oEN(), .oCNT(oCNT5));  // hours

endmodule
//Timer Counter
module COUNTER_PRESET_DOWN(
    iCLK,
    iRSTn,
    iPRSTn,
    iEN,
    iDATA_Preset,
    oEN, //roll-over signal
    oCNT
);

parameter n=4;
parameter k=10;

input iCLK,iRSTn,iPRSTn,iEN;
input [n-1:0] iDATA_Preset;
output [n-1:0] oCNT;
output oEN;

reg [n-1:0] oCNT;

assign oEN =((oCNT == 0) && (iEN == 1'b1)) ? 1'b1 : 1'b0;

always@(posedge iCLK or negedge iRSTn)
begin
    if(~iRSTn)
    begin
        oCNT <= 0;
    end
    else if(iPRSTn)
    begin 
        oCNT <= iDATA_Preset;
    end
    else if(iEN)
    begin
        if(oCNT==0)
        begin
            oCNT<=k-1;
        end
        else
        begin
            oCNT<=oCNT-1;
        end
    end
    else
    begin 
        oCNT<=oCNT;
    end
end

endmodule
1
  • How do you set the timer to 1 minute, for example? Commented Oct 13, 2024 at 10:15

1 Answer 1

0

One potential problem is how you drive your asynchronous reset iRSTn:

assign iRSTn=(SW[7]&~SW[6]&~KEY[0]) ? 1'b0 : 1'b1;  

Since it is combinational logic of 3 signals, the reset is subject to glitches.

Consider changing your code to use a synchronous reset:

always @(posedge CLOCK_50) begin
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.