module ksa(clk, rst_n, en, rdy, key, addr, rddata, wrdata, wren); input logic clk, rst_n, en; input logic [7:0] rddata; input logic [23:0] key; output logic rdy, wren; output logic [7:0] addr, wrdata; logic started, wren_next; logic [2:0] state, state_next; logic [7:0] i, j, i_next, j_next, wrdata_next, addr_next, si, si_next; always_comb begin: ksa_logic state_next = state + 1; i_next = i; j_next = j; addr_next = i; wrdata_next = 8'b0; wren_next = 1'b0; si_next = si; case (state) /* Fetch s[i]. */ 3'd0: begin end /* s[i] is now in rddata. */ 3'd1: begin end /* Compute j; fetch s[j]; latch s[i] from rddata. */ 3'd2: begin if (i % 3 == 2'd0) j_next = j + rddata + key[23:16]; else if (i % 3 == 2'd1) j_next = j + rddata + key[15:8]; else j_next = j + rddata + key[7:0]; addr_next = j_next; si_next = rddata; end /* s[j] is now in rddata. */ 3'd3: begin end /* Store rddata (s[j]) to address i. */ 3'd4: begin wrdata_next = rddata; wren_next = 1'b1; end /* Store si (s[i]) to address j; increment i; reset. */ 3'd5: begin state_next = 3'd0; i_next = i + 1; addr_next = j; wrdata_next = si; wren_next = 1'b1; end endcase end: ksa_logic always_ff @(posedge clk) begin: ksa_state_machine if (~rst_n) begin rdy <= 1'b1; started <= 1'b0; state <= 3'd0; i <= 8'b0; j <= 8'b0; addr <= 8'b0; end else if (rdy && en) begin rdy <= 1'b0; started <= 1'b1; state <= 3'd0; i <= 8'b0; j <= 8'b0; addr <= 8'b0; wren <= 1'b0; end else if (started) begin state <= state_next; i <= i_next; j <= j_next; addr <= addr_next; wrdata <= wrdata_next; wren <= wren_next; si <= si_next; if ((i == 8'd255) && (state == 3'd5)) begin rdy <= 1'b1; started <= 1'b0; end end end: ksa_state_machine endmodule: ksa