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

  // state bits
  parameter 
  IDLE = 0, 
  DLY  = 2, 
  DONE = 1, 
  READ = 3; 
  
  reg [3:0] state;
  reg [3:0] nextstate;
  
  // comb always block
  always @* begin
    nextstate = 4'b0000;
    case (1'b1) // synopsys parallel_case full_case
      state[IDLE]: begin
        if (go) begin
          nextstate[READ] = 1'b1;
        end
        else begin
          nextstate[IDLE] = 1'b1;
        end
      end
      state[DLY] : begin
        if (ws) begin
          nextstate[READ] = 1'b1;
        end
        else begin
          nextstate[DONE] = 1'b1;
        end
      end
      state[DONE]: begin
        begin
          nextstate[IDLE] = 1'b1;
        end
      end
      state[READ]: begin
        begin
          nextstate[DLY] = 1'b1;
        end
      end
    endcase
  end
  
  // sequential always block
  always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
      state <= 4'b0001 << IDLE;
    else
      state <= nextstate;
  end
  
  // datapath sequential always block
  always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      ds <= 0;
      rd <= 0;
    end
    else begin
      ds <= 0; // default
      rd <= 0; // default
      case (1'b1) // synopsys parallel_case full_case
        nextstate[DLY] : begin
          rd <= 1;
        end
        nextstate[DONE]: begin
          ds <= 1;
        end
        nextstate[READ]: begin
          rd <= 1;
        end
      endcase
    end
  end
  
  // This code allows you to see state names in simulation
  `ifndef SYNTHESIS
  reg [31:0] statename;
  always @* begin
    case (1)
      state[IDLE]:
        statename = "IDLE";
      state[DLY] :
        statename = "DLY";
      state[DONE]:
        statename = "DONE";
      state[READ]:
        statename = "READ";
      default:
        statename = "XXXX";
    endcase
  end
  `endif

  
endmodule