Serpent in ICE40, Part 2.
This article is a continuation of "Can the Serpent Cipher fit in the ICE40 FPGA?".
Below is a revision of the forward S-box of Serpent from the previous article, with all of the S-Box equations rewritten in the same form, i.e. using strictly AND, OR, and NOT operations, with none having more than six subclauses, and reformatted for clarity:
module sbox_forward(clk, fire, box_n, a, b, c, d, w, x, y, z); // clock input wire clk; // trigger input wire fire; // number of sbox input [3:0] box_n; // inputs input [31:0] a; input [31:0] b; input [31:0] c; input [31:0] d; // outputs output reg [31:0] w = 0; output reg [31:0] x = 0; output reg [31:0] y = 0; output reg [31:0] z = 0; always @(posedge clk) if (fire) begin begin case (box_n) ///////////////////////////////// 4'd0: begin w < = ( a & ~b & ~c & d) | (~a & c & d) | (~a & ~c & ~d) | ( b & ~d); x <= ( a & b & ~c & d) | ( a & c & ~d) | (~a & ~b ) | (~a & ~c & ~d); y <= ( a & b & c & d) | ( a & ~b & c & ~d) | (~a & b & ~d) | (~a & ~b & d) | (~a & ~c & d) | ( ~b & ~c & d); z <= ( a & b & c ) | ( a & ~b & ~c ) | (~a & b & ~c & ~d) | (~a & ~b & c & ~d) | ( b & c & d) | ( ~b & ~c & d); end ///////////////////////////////// 4'd1: begin w <= ( a & b & ~c & ~d) | ( a & ~b & d) | (~a & b & c ) | (~a & ~b & ~c ) | (~a & ~b & ~d); x <= ( a & b & ~d) | ( a & ~b & ~c & d) | (~a & b & d) | (~a & c & d) | (~a & ~c & ~d); y <= ( a & c & d) | ( a & ~c & ~d) | (~a & b & c & ~d) | (~a & b & ~c & d) | ( ~b & c & d) | ( ~b & ~c & ~d); z <= ( a & b & c & ~d) | ( a & ~b & d) | (~a & ~b & ~d) | ( b & ~c & d) | ( ~b & ~c & ~d); end ///////////////////////////////// 4'd2: begin w <= ( a & b & ~d) | ( a & ~b & d) | (~a & b & c & d) | (~a & ~b & c & ~d) | ( b & ~c & ~d) | ( ~b & ~c & d); x <= ( a & ~b & ~c & ~d) | ( a & c & d) | (~a & b & ~c ) | (~a & c & ~d) | ( b & c & ~d); y <= ( a & ~b & ~d) | ( a & c & ~d) | (~a & b & ~c ) | (~a & b & d) | (~a & ~c & d) | ( b & ~c & d); z <= ( a & b & ~d) | ( a & ~b & c ) | (~a & ~b & ~c ) | (~a & ~c & d) | ( b & c & ~d); end ///////////////////////////////// 4'd3: begin w <= ( a & ~b ) | ( a & c & ~d) | (~a & b & c & d) | (~a & b & ~c & ~d) | ( ~b & ~c & d); x <= ( a & b & c ) | ( a & ~b & ~c & ~d) | (~a & b & ~c ) | ( b & c & ~d) | ( ~b & c & d); y <= ( a & b & d) | ( a & ~b & ~c & ~d) | ( a & c & d) | (~a & b & c ) | (~a & ~b & ~c & d) | (~a & c & ~d); z <= ( a & b & c & d) | ( a & ~b & ~d) | (~a & ~b & d) | ( b & ~c & ~d) | ( ~b & c & ~d); end ///////////////////////////////// 4'd4: begin w <= ( a & ~b & ~c ) | ( a & ~c & ~d) | (~a & b & c ) | (~a & c & d) | ( b & c & d) | ( ~b & ~c & ~d); x <= ( a & b & ~c ) | ( a & ~b & c & d) | ( a & ~c & ~d) | (~a & b & c ) | (~a & ~b & ~c & d) | ( b & c & ~d); y <= ( a & b & c ) | ( a & ~b & ~c ) | ( a & ~b & d) | (~a & b & d) | (~a & ~b & c & ~d); z <= ( a & b & d) | ( a & ~b & ~c & ~d) | (~a & b & ~d) | (~a & ~b & c ) | ( ~b & c & d); end ///////////////////////////////// 4'd5: begin w <= ( a & ~b & ~c ) | ( a & ~c & ~d) | (~a & b & c ) | (~a & c & d) | ( b & c & d) | ( ~b & ~c & ~d); x <= ( a & ~b & c ) | ( a & ~b & d) | (~a & b & d) | (~a & ~c & ~d) | ( b & ~c & ~d); y <= ( a & b & c & ~d) | (~a & b & d) | (~a & ~b & c ) | ( ~b & c & d) | ( ~b & ~c & ~d); z <= ( a & b & ~c ) | ( a & c & ~d) | (~a & ~b & c & d) | (~a & ~b & ~c & ~d) | ( b & c & ~d) | ( b & ~c & d); end ///////////////////////////////// 4'd6: begin w <= ( a & b & ~d) | ( a & ~c & d) | (~a & ~b & ~c & ~d) | ( b & ~c & d) | ( ~b & c & d); x <= ( a & b & ~c & d) | ( a & ~b & c & d) | (~a & b & c ) | (~a & ~b & ~c ) | ( b & c & ~d) | ( ~b & ~c & ~d); y <= ( a & b & ~c ) | ( a & ~b & c & ~d) | (~a & b & ~d) | (~a & ~b & ~c ) | (~a & ~b & d); z <= ( a & b & c & ~d) | ( a & ~c & d) | (~a & b & ~c & ~d) | (~a & ~b & c ) | (~a & c & d) | ( ~b & ~c & d); end ///////////////////////////////// 4'd7: begin w <= ( a & b & c & ~d) | (~a & ~b & ~c ) | (~a & c & d) | (~a & ~c & ~d) | ( ~b & c & d) | ( ~b & ~c & ~d); x <= ( a & b & c ) | ( a & b & d) | ( a & c & d) | (~a & b & ~d) | (~a & ~b & ~c & d) | (~a & c & ~d); y <= ( a & ~b & ~c ) | (~a & b & ~c ) | (~a & ~b & c & ~d) | (~a & ~c & d) | ( b & c & d); z <= ( a & ~b & ~d) | ( a & c & ~d) | (~a & b & ~c ) | (~a & ~b & c ) | ( b & ~c & d); end ///////////////////////////////// endcase // case (box_n) end end endmodule
This formulation produces the same test output as previously noted.
Potentially this will make it possible to determine a more compact circuit representation (e.g. one making use of a RAM table populated with constants, on top of a MUX).
~To be continued!~