// keccak_core.v - Synchronous Keccak-f[1600] core with valid/ready // // Runs 24 rounds of keccak_round on the input state. // valid_i high with ready_o high → load state_i, start 24-round sequence. // Each round takes 1 cycle. After round 23, valid_o asserted with state_o. // // Parameter: // ROUNDS = 24 (default) // // Interface: // clk, rst_n - clock, active-low reset // state_i - 1600-bit input state // valid_i - start permutation // ready_o - core can accept new input // state_o - 1600-bit output state (after permutation) // valid_o - output is valid // ready_i - consumer accepts output module keccak_core #(parameter ROUNDS = 24) ( input clk, input rst_n, input [1599:0] state_i, input valid_i, output ready_o, output [1599:0] state_o, output valid_o, input ready_i ); // ================================================================ // Internal registers // ================================================================ reg busy_r; // 1 while running permutation reg [4:0] cnt_r; // round counter (0 to ROUNDS-1) reg [1599:0] state_r; // current state // ================================================================ // Next-state logic // ================================================================ wire cnt_is_last; // cnt_r == ROUNDS-1 ? wire [1599:0] state_next; // combinational round output assign cnt_is_last = (cnt_r == (ROUNDS - 1)); // keccak_round: apply one round to current state keccak_round u_round ( .state_i(state_r), .round_i(cnt_r), .state_o(state_next) ); // ================================================================ // Valid/ready handshake // ================================================================ // ready_o: accept new input when not busy (or just finishing) assign ready_o = !busy_r; // valid_o: output valid when we just finished the last round // (the final state is already in state_r at the output cycle) assign valid_o = busy_r && cnt_is_last; // state_o: output the final state assign state_o = state_next; // final state from the last round // ================================================================ // Sequential logic // ================================================================ always @(posedge clk or negedge rst_n) begin if (!rst_n) begin busy_r <= 1'b0; cnt_r <= 5'd0; state_r <= 1600'd0; end else begin if (!busy_r) begin // IDLE: wait for valid_i if (valid_i) begin state_r <= state_i; cnt_r <= 5'd0; busy_r <= 1'b1; end end else begin // BUSY: running permutations if (cnt_is_last) begin // Final round: check if output can be accepted if (ready_i) begin busy_r <= 1'b0; cnt_r <= 5'd0; end // else: hold until ready_i end else begin // Intermediate round: advance state state_r <= state_next; cnt_r <= cnt_r + 5'd1; end end end end endmodule