`default_nettype none module tdc #(parameter COUNTER_WIDTH=16)( input wire i_clk, input wire i_start, input wire i_stop, input wire i_reset, output wire o_ready, output wire [COUNTER_WIDTH-1:0] o_data ); reg [COUNTER_WIDTH-1:0] counter; assign o_data = counter; // states localparam state_idle = 2'b00; localparam state_started = 2'b01; localparam state_running = 2'b10; localparam state_stopped = 2'b11; reg [1:0] current_state, next_state; // ensure that state changes each clock always @(posedge i_clk) begin if (i_reset) begin current_state <= state_idle; end else begin current_state <= next_state; end end // state logic /* verilator lint_off COMBDLY */ always @(*) begin case (current_state) state_idle: begin if (i_start && (~i_stop)) next_state <= state_started; else next_state <= state_idle; end state_started: begin if (~i_start && (~i_stop)) next_state <= state_running; else next_state <= state_started; end state_running: begin if (~i_start && (i_stop)) next_state <= state_stopped; else next_state <= state_running; end state_stopped: begin if (i_reset) next_state <= state_idle; else next_state <= state_stopped; end default : next_state <= current_state; endcase end /* verilator lint_on COMBDLY */ // counter runs during running state only always @(posedge i_clk) begin case (current_state) state_idle: counter <= 0; state_started: counter <= 0; state_running: counter <= counter + 1; state_stopped: counter <= counter; default : counter <= 0; endcase end assign o_ready = (current_state == state_stopped); endmodule // Local Variables: // verilog-library-directories:(".." "./rtl" ".") // End: