0
\$\begingroup\$

I want to use a counter to count how many clock cycles an input signal is high. The issue I am running into is that once the input signal returns back to zero, my counter resets which causes my output to also reset since my counter and output are set equal to one another.

In other words, you can see in my simulation that my output is set to 5 for only one clock cycle before it is reset back to zero. What I would like to happen is my output signal to remain equal to my last clock cycle until a new count is finished.

I've posted my code and simulation below.

///////////// HDL Code //////////////
module counter    (
out     ,  // Output of the counter
in_1  ,  // input signal
clk     ,  // clock Input
reset   ,     // reset Input
);

  output [7:0] out;
  input in_1, clk, reset;
     
  reg [7:0] out;
  reg [7:0] counter;
    
always @(posedge clk)
if (reset) 
  counter <= 8'b0;
else if (in_1) 
  counter <= counter + 1;
else if (in_1 == 8'b0) 
begin 
  out = counter; 
  counter = 8'b0;
end
endmodule 

///////////// Test bench Code //////////////

`timescale 1ns/100ps

module counter_tb;

//parameter SYSCLK_PERIOD = 20;// 50MHZ

reg clk_1;
reg in_11;
reg reset_1;

wire [7:0] out_1; 

initial
begin
    clk_1 = 1'b0;
    in_11 = 1'b0;
    reset_1 = 1'b1;
    
    #20;
    
    in_11 = 1'b1;
    reset_1 = 1'b0;
    
    #50;
    
    in_11 = 1'b0;
    
    #100;
    
    in_11 = 1'b1;
    
    #100;
    
    in_11 = 1'b0;
    
    #50;
    
    $stop;
end

//////////////////////////////////////////////////////////////////////
// Clock Driver
//////////////////////////////////////////////////////////////////////
always
    #5 clk_1 = ~clk_1;


//////////////////////////////////////////////////////////////////////
// Instantiate Unit Under Test:  counter
//////////////////////////////////////////////////////////////////////
counter counter_0 (
    // Inputs
    .in_1(in_11),
    .clk(clk_1),
    .reset(reset_1),

    // Outputs
    .out( out_1 ),

enter image description here

\$\endgroup\$
0
\$\begingroup\$

Don't mix <= and = in a single always block. Though I have never done this way yet, I can think of that on the 2nd active clock edge after in_1's deassertion, out is updated to the new counter which has been reset to zero one clock cycle before.

What you need is to latch the counter to out only when clk sees a deassertion on in_1. Design and figure out what circuit match your requirements, and then code.

Circuit first. This is not software program.

\$\endgroup\$
0
\$\begingroup\$

maybe its of some help for you, here is a counter example I have written some time ago

https://sourceforge.net/p/verilog-code-collection/code/ci/default/tree/counter/

my toolchain is iverilog + gtkwave

\$\endgroup\$
0
\$\begingroup\$

You need a falling-edge detector, created by delaying the input and then acting only when the original signal is low but the delayed signal is still high.

module counter (
  output reg      [7:0] out,    // Output of the counter
  input                 in_1,   // input signal
  input                 clk,    // clock Input
  input                 reset   // reset Input
);
  reg     [7:0] counter;
  reg           in_delay;
    
  always @(posedge clk) begin
    in_delay <= in_1;
    if (reset) begin
      counter <= 8'b0;
    end else if (in_1) begin
      counter <= counter + 1;
    end else if (in_delay) begin 
      out <= counter; 
      counter <= 8'b0;
    end
  end
endmodule 
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.