module cliff_classic (
  output logic ds,
  output logic rd,
  input logic clk,
  input logic go,
  input logic rst_n,
  input logic ws
);

  // state bits
  enum {
    IDLE_BIT,
    DLY_BIT,
    DONE_BIT,
    READ_BIT
  } index;

  enum logic [3:0] {
    IDLE = 4'b1<<IDLE_BIT,
    DLY  = 4'b1<<DLY_BIT,
    DONE = 4'b1<<DONE_BIT,
    READ = 4'b1<<READ_BIT,
    XXX = 'x
  } state, nextstate;


  // comb always block
  always_comb begin
    nextstate = XXX; // default to x because default_state_is_x is set
    unique case (1'b1)
      state[IDLE_BIT]: begin
        if (go) begin
          nextstate = READ;
        end
        else begin
          nextstate = IDLE;
        end
      end
      state[DLY_BIT]: begin
        if (ws) begin
          nextstate = READ;
        end
        else begin
          nextstate = DONE;
        end
      end
      state[DONE_BIT]: begin
        begin
          nextstate = IDLE;
        end
      end
      state[READ_BIT]: begin
        begin
          nextstate = DLY;
        end
      end
    endcase
  end

  // sequential always block
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n)
      state <= IDLE;
    else
      state <= nextstate;
  end

  // datapath sequential always block
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      ds <= 0;
      rd <= 0;
    end
    else begin
      ds <= 0; // default
      rd <= 0; // default
      unique case (1'b1)
        nextstate[IDLE_BIT]: begin
          ; // case must be complete for onehot
        end
        nextstate[DLY_BIT]: begin
          rd <= 1;
        end
        nextstate[DONE_BIT]: begin
          ds <= 1;
        end
        nextstate[READ_BIT]: begin
          rd <= 1;
        end
      endcase
    end
  end
endmodule