/*
 * structural verilog implementation of CSS decryption tables
 * believe it or not, this takes 22+7+0+0+8=37 gates.
 * i leave it as an exercise for the reader to implement the 
 * css statemachine in a synthesizable form also.
 *
 * 040401ajb bybell@xxedgexx.com
 */


module top;				// exercise modules for verification
reg[8:0] j;				// that tables produced are correct...
wire [7:0] i,o1,o2,o3,o4,o5;

assign i=j[7:0];

CSSTAB1 c1(i,o1);
CSSTAB2 c2(i,o2);
CSSTAB3 c3(i[2:0],o3);
CSSTAB4 c4(i,o4);
CSSTAB5 c5(i,o5);

initial
	begin
	$display("NDX C1 C2 C3 C4 C5");
	$display("--- -- -- -- -- --");
	for(j=0;j<256;j=j+1)
		begin
		$display("%x: %x %x %x %x %x",i,o1,o2,o3,o4,o5);
		end
	end

endmodule



/*
 * table1: the so-called substitution cipher
 * thanks to charles hannum's mathematical description
 * for making this manageable and not need a 256*8 ROM..
 * this requires just 22 gates with max of 5 gate delays
 * (or 4 if you have inverting xors in your library
 * which is most likely the case for CMOS).
 */
module CSSTAB1(i, o);
input [7:0] i;
output [7:0] o;
wire a, b, c, d, e, f, g, h;

assign a = i[0];
assign b = i[1];
assign c = i[2];
assign d = i[3];
assign e = i[4];
assign f = i[5];
assign g = i[6];
assign h = i[7];

assign anb=a&b;
assign ANB=A&B;

assign A = ~(anb ^ d);
assign B = ~((e & f) ^ g);
assign C = ~(ANB ^ f);
assign D = ~(ANB ^ b);
assign E = ~(anb ^ c);
assign F = ~((e | f) ^ h);
assign G = ~((E & F) ^ a);
assign H = ~((E | F) ^ e);

assign o={H,G,F,E,D,C,B,A};

endmodule


/*
 * table2: out=in^(in>>3)^(in>>6)
 * this requires seven gates
 */
module CSSTAB2(i,o);
input [7:0] i;
output [7:0] o;
wire [4:0]t1;
wire [1:0]t2;

assign t1=i[4:0]^i[7:3];
assign t2=t1[1:0]^i[7:6];

assign o={i[7:5],t1[4:2],t2[1:0]};

endmodule


/*
 * table3: repeating sequence of {00 24 49 6d 92 b6 db ff}
 * with n&7 as the index.
 */
module CSSTAB3(i,o);
input [2:0]i;
output [7:0]o;
wire a,b,c;

//
// the following unminimized PLA...
//
// .i 3 
// .o 8
// 000 00000000
// 001 00100100
// 010 01001001
// 011 01101101
// 100 10010010
// 101 10110110
// 110 11011011
// 111 11111111
//
// results in this very interesting *zero gate* minimization:
//
// % espresso z.pla
// .i 3
// .o 8
// .p 3
// --1 00100100
// 1-- 10010010
// -1- 01001001
// .e

assign a=i[2];
assign b=i[1];
assign c=i[0];

// therefore simply..
assign o={a,b,c,a,b,c,a,b};
endmodule


/*
 * reverse bits.  this requires no gates..
 */
module CSSTAB4(i,o);
input [7:0] i;
output [7:0] o;

assign o={i[0],i[1],i[2],i[3],i[4],i[5],i[6],i[7]};
endmodule


/*
 * reverse complemented bits.  this requires 8 gates..
 */
module CSSTAB5(i,o);
input [7:0] i;
output [7:0] o;

assign o=~{i[0],i[1],i[2],i[3],i[4],i[5],i[6],i[7]};
endmodule
