0
votes

So I'm trying to implement a counter that takes a one-clock-cycle enable and starts counting from there. It sends a one-clock-cycle expired once the counter finishes counting. The enable will never be sent again until the counter is done counting, and the value input is continuous.

I was thinking of just using a reg variable that is changed to high when enable = 1, and changed to low once the counter finishes counting. I fear this may imply latches that I don't want... is there a better way to do this?

current code:

module Timer(
input [3:0] value,
input start_timer,
input clk,
input rst,
output reg expired
);

//counter var
reg [3:0] count;

//hold variable
reg hold;

//setting hold
always @*
begin
    if (start_timer == 1'b1)
         hold <= 1'b1;
end


//counter
if (hold == 1'b1)
begin
always @ (posedge(clk))
begin
    if(count == value - 1)
    begin
        expired <= 1'b1;
        count <= 4'b0;
        hold <= 1'b0;
    end
    else
        count <= count + 1'b1;
end
end

endmodule
1

1 Answers

0
votes

Well, you seem to be on the right track, but you are correct that your current design will imply latches. You can fix this by making hold its own flipflop and only counting when its set as you have done, clearing it once your counting is complete. Note this will impact the timing of your system, so you have to make sure everything happens on the correct cycle. Its hard to say from your description whether you want expired to be set on the "value"th cycle or "value + 1"th cycle. In order to show you a few of what youll need to do to your code to get it to compile and have the proper timing, Im going to assume a few things:

  1. value is held at a constant number and doesnt not change while counting
  2. expired will pulse on the valueth clock after start_timer is set
  3. value will not be 4'h0 (though this is easy to deal with, as no counting is required based on assumption 1)

So, your module would look like this:

module Timer(
             input [3:0] value,
             input start_timer,
             input clk,
             input rst,
             output expired
            );

//counter var
reg [3:0] count;

//hold variable
reg hold;

// Note you cannot assign hold from multiple blocks, so the other one has been removed

// In order to meet the timing from assumption 2, we need to combinationally determine expired (be sure we only set it while we are counting; thus the dependence on hold)
assign expired = (count == value - 4'd1) && (hold == 1'b1);

//counter
// Note, you cannot have logic outside of a procedural block!
always @(posedge clk) begin
  if ((hold == 1'b0) && (start_timer == 1'b1)) begin
    hold <= 1'b1; // Hold is part of the register, making it its own flipflop
    count <= 4'd0;
  end
  else if (hold == 1'b1) begin
    if (count == value - 4'd1) begin
        hold <= 1'b0; // Clear hold, we are done counting
        // No need to clear count, it will be cleared at the start of the timer
    end
    else begin
      count <= count + 4'd1;
    end
  end
end

endmodule