aboutsummaryrefslogtreecommitdiffstats
path: root/hdcp
diff options
context:
space:
mode:
authorbnewbold <bryan@octopart.com>2012-01-20 19:14:58 -0500
committerbnewbold <bryan@octopart.com>2012-01-20 19:14:58 -0500
commit889a5a5395872eeb3740d5d3281b56c7afa47a6f (patch)
treec0efd6404ffdbdfe7f88a173f0836919efdf0184 /hdcp
downloadnetv_fpga_hdmi_overlay-889a5a5395872eeb3740d5d3281b56c7afa47a6f.tar.gz
netv_fpga_hdmi_overlay-889a5a5395872eeb3740d5d3281b56c7afa47a6f.zip
initial import from NeTV archive
This repository is simply a mirror of the file fpga/hdmi_overlay_0xD_src.tgz downloaded from http://www.kosagi.com/netv_hardware/ on Jan 19th, 2011. It seems to contain all the verilog and scripts required to build FPGA firmware for the NeTV HDMI device from Chumby/Sutajio Ko-Usagi; see http://www.kosagi.com/blog/ for more information. Licensing is vague; see ip/license.txt
Diffstat (limited to 'hdcp')
-rwxr-xr-xhdcp/diff_network.v41
-rwxr-xr-xhdcp/hdcp_block.v728
-rwxr-xr-xhdcp/hdcp_cipher.v411
-rwxr-xr-xhdcp/hdcp_lfsr.v196
-rwxr-xr-xhdcp/shuffle_network.v59
5 files changed, 1435 insertions, 0 deletions
diff --git a/hdcp/diff_network.v b/hdcp/diff_network.v
new file mode 100755
index 0000000..1763a30
--- /dev/null
+++ b/hdcp/diff_network.v
@@ -0,0 +1,41 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2011, Andrew "bunnie" Huang
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+module diff_network (
+ input wire [6:0] i,
+ output wire [6:0] o,
+ input wire [6:0] k
+ );
+
+ assign o[0] = k[0] ^ ^ i[1] ^ i[2] ^ i[3] ^ i[4] ^ i[5] ^ i[6];
+ assign o[1] = k[1] ^ i[0] ^ ^ i[2] ^ i[3] ^ i[4] ^ i[5] ^ i[6];
+ assign o[2] = k[2] ^ i[0] ^ i[1] ^ ^ i[3] ^ i[4] ^ i[5] ^ i[6];
+ assign o[3] = k[3] ^ i[0] ^ i[1] ^ i[2] ^ ^ i[4] ^ i[5] ^ i[6];
+ assign o[4] = k[4] ^ i[0] ^ i[1] ^ i[2] ^ i[3] ^ ^ i[5] ^ i[6];
+ assign o[5] = k[5] ^ i[0] ^ i[1] ^ i[2] ^ i[3] ^ i[4] ^ ^ i[6];
+ assign o[6] = k[6] ^ i[0] ^ i[1] ^ i[2] ^ i[3] ^ i[4] ^ i[5] ^ i[6];
+
+endmodule // diff_network
diff --git a/hdcp/hdcp_block.v b/hdcp/hdcp_block.v
new file mode 100755
index 0000000..5f81279
--- /dev/null
+++ b/hdcp/hdcp_block.v
@@ -0,0 +1,728 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2011, Andrew "bunnie" Huang
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+module hdcp_block (
+ input wire clk,
+ input wire reset,
+
+ input wire load,
+ input wire [83:0] B,
+ input wire [83:0] K,
+
+ output wire [83:0] Bo,
+ input wire rekey,
+ input wire lfsr_in,
+
+ output reg [23:0] ostream,
+
+ input wire advance
+ );
+
+ reg [27:0] Bx;
+ reg [27:0] By;
+ reg [27:0] Bz;
+ wire [27:0] o_Bx;
+ wire [27:0] o_By;
+ wire [27:0] o_Bz;
+
+ reg [27:0] Kx;
+ reg [27:0] Ky;
+ reg [27:0] Kz;
+ wire [27:0] o_Kx;
+ wire [27:0] o_Ky;
+ wire o_Ky13; // bit 13 comes from lfsr_in when rekey is active
+ wire [27:0] o_Kz;
+
+ wire [23:0] ostream_r;
+
+ // semi-auto generated with a perl script
+ wire [3:0] SK0_in;
+ wire [3:0] SK1_in;
+ wire [3:0] SK2_in;
+ wire [3:0] SK3_in;
+ wire [3:0] SK4_in;
+ wire [3:0] SK5_in;
+ wire [3:0] SK6_in;
+
+ reg [3:0] SK0;
+ reg [3:0] SK1;
+ reg [3:0] SK2;
+ reg [3:0] SK3;
+ reg [3:0] SK4;
+ reg [3:0] SK5;
+ reg [3:0] SK6;
+
+ wire [3:0] SB0_in;
+ wire [3:0] SB1_in;
+ wire [3:0] SB2_in;
+ wire [3:0] SB3_in;
+ wire [3:0] SB4_in;
+ wire [3:0] SB5_in;
+ wire [3:0] SB6_in;
+
+ reg [3:0] SB0;
+ reg [3:0] SB1;
+ reg [3:0] SB2;
+ reg [3:0] SB3;
+ reg [3:0] SB4;
+ reg [3:0] SB5;
+ reg [3:0] SB6;
+
+ assign Bo = {Bz[27:0],By[27:0],Bx[27:0]};
+ always @(posedge clk or posedge reset) begin
+ if( reset ) begin
+ Bx <= 28'b0;
+ By <= 28'b0;
+ Bz <= 28'b0;
+ Kx <= 28'b0;
+ Ky <= 28'b0;
+ Kz <= 28'b0;
+ ostream <= 24'b0;
+ end else begin
+ if( load ) begin
+// Bz <= B[83:56];
+ Bz <= {19'b0,1'b0,B[63:56]}; // repeater is fixed to zero
+ By <= B[55:28];
+ Bx <= B[27:0];
+
+ Kz <= K[83:56];
+ Ky <= K[55:28];
+ Kx <= K[27:0];
+ ostream <= 24'b0;
+ end else if( advance ) begin
+ Bx <= o_Bx;
+ By <= o_By;
+ Bz <= o_Bz;
+
+ Kx <= o_Kx;
+ Ky <= o_Ky;
+ Kz <= o_Kz;
+ ostream <= ostream_r;
+ end else begin
+ Bx <= Bx;
+ By <= By;
+ Bz <= Bz;
+
+ Kx <= Kx;
+ Ky <= Ky;
+ Kz <= Kz;
+ ostream <= ostream;
+ end
+ end // else: !if( reset )
+ end // always @ (posedge clk or posedge reset)
+
+
+ ////////////
+ // bround linear transformation
+ // generated using perl script makebround.pl bround.csv > bround_code.txt
+ ////////////
+ diff_network bround1 ( .o({o_Bx[24],o_Bx[20],o_Bx[16],o_Bx[12],o_Bx[8],o_Bx[4],o_Bx[0]}),
+ .k({Ky[6],Ky[5],Ky[4],Ky[3],Ky[2],Ky[1],Ky[0]}),
+ .i({Bz[6],Bz[5],Bz[4],Bz[3],Bz[2],Bz[1],Bz[0]}) );
+
+ diff_network bround2 ( .o({o_By[24],o_By[20],o_By[16],o_By[12],o_By[8],o_By[4],o_By[0]}),
+ .k({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}),
+ .i({By[12],By[2],By[1],By[0],Bz[9],Bz[8],Bz[7]}) );
+
+ diff_network bround3 ( .o({o_By[25],o_By[21],o_By[17],o_By[13],o_By[9],o_By[5],o_By[1]}),
+ .k({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}),
+ .i({By[13],By[5],By[4],By[3],Bz[12],Bz[11],Bz[10]}) );
+
+ diff_network bround4 ( .o({o_By[26],o_By[22],o_By[18],o_By[14],o_By[10],o_By[6],o_By[2]}),
+ .k({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}),
+ .i({By[14],By[8],By[7],By[6],Bz[15],Bz[14],Bz[13]}) );
+
+ diff_network bround5 ( .o({o_By[27],o_By[23],o_By[19],o_By[15],o_By[11],o_By[7],o_By[3]}),
+ .k({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}),
+ .i({By[15],By[11],By[10],By[9],Bz[18],Bz[17],Bz[16]}) );
+
+ diff_network bround6 ( .o({o_Bx[25],o_Bx[21],o_Bx[17],o_Bx[13],o_Bx[9],o_Bx[5],o_Bx[1]}),
+ .k({Ky[13],Ky[12],Ky[11],Ky[10],Ky[9],Ky[8],Ky[7]}),
+ .i({Bz[21],Bz[20],Bz[19],By[19],By[18],By[17],By[16]}) );
+
+ diff_network bround7 ( .o({o_Bx[26],o_Bx[22],o_Bx[18],o_Bx[14],o_Bx[10],o_Bx[6],o_Bx[2]}),
+ .k({Ky[20],Ky[19],Ky[18],Ky[17],Ky[16],Ky[15],Ky[14]}),
+ .i({Bz[24],Bz[23],Bz[22],By[23],By[22],By[21],By[20]}) );
+
+ diff_network bround8 ( .o({o_Bx[27],o_Bx[23],o_Bx[19],o_Bx[15],o_Bx[11],o_Bx[7],o_Bx[3]}),
+ .k({Ky[27],Ky[26],Ky[25],Ky[24],Ky[23],Ky[22],Ky[21]}),
+ .i({Bz[27],Bz[26],Bz[25],By[27],By[26],By[25],By[24]}) );
+
+
+ ////////////
+ // kround linear transform
+ // generated using perl script makelinx.pl kround.csv > kround
+ ////////////
+
+ diff_network kround1 ( .o({o_Kx[24],o_Kx[20],o_Kx[16],o_Kx[12],o_Kx[8],o_Kx[4],o_Kx[0]}),
+ .i({Kz[6],Kz[5],Kz[4],Kz[3],Kz[2],Kz[1],Kz[0]}),
+ .k(7'b0) );
+
+ diff_network kround2 ( .o({o_Ky[24],o_Ky[20],o_Ky[16],o_Ky[12],o_Ky[8],o_Ky[4],o_Ky[0]}),
+ .i({Ky[12],Ky[2],Ky[1],Ky[0],Kz[9],Kz[8],Kz[7]}),
+ .k(7'b0) );
+
+ diff_network kround3 ( .o({o_Ky[25],o_Ky[21],o_Ky[17],o_Ky13,o_Ky[9],o_Ky[5],o_Ky[1]}),
+ .i({Ky[13],Ky[5],Ky[4],Ky[3],Kz[12],Kz[11],Kz[10]}),
+ .k(7'b0) );
+ assign o_Ky[13] = rekey ? lfsr_in : o_Ky13;
+
+ diff_network kround4 ( .o({o_Ky[26],o_Ky[22],o_Ky[18],o_Ky[14],o_Ky[10],o_Ky[6],o_Ky[2]}),
+ .i({Ky[14],Ky[8],Ky[7],Ky[6],Kz[15],Kz[14],Kz[13]}),
+ .k(7'b0) );
+
+ diff_network kround5 ( .o({o_Ky[27],o_Ky[23],o_Ky[19],o_Ky[15],o_Ky[11],o_Ky[7],o_Ky[3]}),
+ .i({Ky[15],Ky[11],Ky[10],Ky[9],Kz[18],Kz[17],Kz[16]}),
+ .k(7'b0) );
+
+ diff_network kround6 ( .o({o_Kx[25],o_Kx[21],o_Kx[17],o_Kx[13],o_Kx[9],o_Kx[5],o_Kx[1]}),
+ .i({Kz[21],Kz[20],Kz[19],Ky[19],Ky[18],Ky[17],Ky[16]}),
+ .k(7'b0) );
+
+ diff_network kround7 ( .o({o_Kx[26],o_Kx[22],o_Kx[18],o_Kx[14],o_Kx[10],o_Kx[6],o_Kx[2]}),
+ .i({Kz[24],Kz[23],Kz[22],Ky[23],Ky[22],Ky[21],Ky[20]}),
+ .k(7'b0) );
+
+ diff_network kround8 ( .o({o_Kx[27],o_Kx[23],o_Kx[19],o_Kx[15],o_Kx[11],o_Kx[7],o_Kx[3]}),
+ .i({Kz[27],Kz[26],Kz[25],Ky[27],Ky[26],Ky[25],Ky[24]}),
+ .k(7'b0) );
+
+ /////////////
+ // sboxes
+ // generated using script makeblock.pl sbox_src.txt > sbox_code.txt
+ /////////////
+ always @(SK0_in[3:0]) begin
+ case (SK0_in[3:0])
+ 4'h0: SK0 = 4'd8;
+ 4'h1: SK0 = 4'd14;
+ 4'h2: SK0 = 4'd5;
+ 4'h3: SK0 = 4'd9;
+ 4'h4: SK0 = 4'd3;
+ 4'h5: SK0 = 4'd0;
+ 4'h6: SK0 = 4'd12;
+ 4'h7: SK0 = 4'd6;
+ 4'h8: SK0 = 4'd1;
+ 4'h9: SK0 = 4'd11;
+ 4'hA: SK0 = 4'd15;
+ 4'hB: SK0 = 4'd2;
+ 4'hC: SK0 = 4'd4;
+ 4'hD: SK0 = 4'd7;
+ 4'hE: SK0 = 4'd10;
+ 4'hF: SK0 = 4'd13;
+ endcase // case (SK0_in[3:0])
+ end // always @ (SK0_in[3:0])
+
+ always @(SK0_in[3:0]) begin
+ case (SK0_in[3:0])
+ 4'h0: SK0 = 4'd8;
+ 4'h1: SK0 = 4'd14;
+ 4'h2: SK0 = 4'd5;
+ 4'h3: SK0 = 4'd9;
+ 4'h4: SK0 = 4'd3;
+ 4'h5: SK0 = 4'd0;
+ 4'h6: SK0 = 4'd12;
+ 4'h7: SK0 = 4'd6;
+ 4'h8: SK0 = 4'd1;
+ 4'h9: SK0 = 4'd11;
+ 4'hA: SK0 = 4'd15;
+ 4'hB: SK0 = 4'd2;
+ 4'hC: SK0 = 4'd4;
+ 4'hD: SK0 = 4'd7;
+ 4'hE: SK0 = 4'd10;
+ 4'hF: SK0 = 4'd13;
+ endcase // case (SK0_in[3:0])
+ end // always @ (SK0_in[3:0])
+
+ always @(SK1_in[3:0]) begin
+ case (SK1_in[3:0])
+ 4'h0: SK1 = 4'd1;
+ 4'h1: SK1 = 4'd6;
+ 4'h2: SK1 = 4'd4;
+ 4'h3: SK1 = 4'd15;
+ 4'h4: SK1 = 4'd8;
+ 4'h5: SK1 = 4'd3;
+ 4'h6: SK1 = 4'd11;
+ 4'h7: SK1 = 4'd5;
+ 4'h8: SK1 = 4'd10;
+ 4'h9: SK1 = 4'd0;
+ 4'hA: SK1 = 4'd9;
+ 4'hB: SK1 = 4'd12;
+ 4'hC: SK1 = 4'd7;
+ 4'hD: SK1 = 4'd13;
+ 4'hE: SK1 = 4'd14;
+ 4'hF: SK1 = 4'd2;
+ endcase // case (SK1_in[3:0])
+ end // always @ (SK1_in[3:0])
+
+ always @(SK2_in[3:0]) begin
+ case (SK2_in[3:0])
+ 4'h0: SK2 = 4'd13;
+ 4'h1: SK2 = 4'd11;
+ 4'h2: SK2 = 4'd8;
+ 4'h3: SK2 = 4'd6;
+ 4'h4: SK2 = 4'd7;
+ 4'h5: SK2 = 4'd4;
+ 4'h6: SK2 = 4'd2;
+ 4'h7: SK2 = 4'd15;
+ 4'h8: SK2 = 4'd1;
+ 4'h9: SK2 = 4'd12;
+ 4'hA: SK2 = 4'd14;
+ 4'hB: SK2 = 4'd0;
+ 4'hC: SK2 = 4'd10;
+ 4'hD: SK2 = 4'd3;
+ 4'hE: SK2 = 4'd9;
+ 4'hF: SK2 = 4'd5;
+ endcase // case (SK2_in[3:0])
+ end // always @ (SK2_in[3:0])
+
+ always @(SK3_in[3:0]) begin
+ case (SK3_in[3:0])
+ 4'h0: SK3 = 4'd0;
+ 4'h1: SK3 = 4'd14;
+ 4'h2: SK3 = 4'd11;
+ 4'h3: SK3 = 4'd7;
+ 4'h4: SK3 = 4'd12;
+ 4'h5: SK3 = 4'd3;
+ 4'h6: SK3 = 4'd2;
+ 4'h7: SK3 = 4'd13;
+ 4'h8: SK3 = 4'd15;
+ 4'h9: SK3 = 4'd4;
+ 4'hA: SK3 = 4'd8;
+ 4'hB: SK3 = 4'd1;
+ 4'hC: SK3 = 4'd9;
+ 4'hD: SK3 = 4'd10;
+ 4'hE: SK3 = 4'd5;
+ 4'hF: SK3 = 4'd6;
+ endcase // case (SK3_in[3:0])
+ end // always @ (SK3_in[3:0])
+
+ always @(SK4_in[3:0]) begin
+ case (SK4_in[3:0])
+ 4'h0: SK4 = 4'd12;
+ 4'h1: SK4 = 4'd7;
+ 4'h2: SK4 = 4'd15;
+ 4'h3: SK4 = 4'd8;
+ 4'h4: SK4 = 4'd11;
+ 4'h5: SK4 = 4'd14;
+ 4'h6: SK4 = 4'd1;
+ 4'h7: SK4 = 4'd4;
+ 4'h8: SK4 = 4'd6;
+ 4'h9: SK4 = 4'd10;
+ 4'hA: SK4 = 4'd3;
+ 4'hB: SK4 = 4'd5;
+ 4'hC: SK4 = 4'd0;
+ 4'hD: SK4 = 4'd9;
+ 4'hE: SK4 = 4'd13;
+ 4'hF: SK4 = 4'd2;
+ endcase // case (SK4_in[3:0])
+ end // always @ (SK4_in[3:0])
+
+ always @(SK5_in[3:0]) begin
+ case (SK5_in[3:0])
+ 4'h0: SK5 = 4'd1;
+ 4'h1: SK5 = 4'd12;
+ 4'h2: SK5 = 4'd7;
+ 4'h3: SK5 = 4'd2;
+ 4'h4: SK5 = 4'd8;
+ 4'h5: SK5 = 4'd3;
+ 4'h6: SK5 = 4'd4;
+ 4'h7: SK5 = 4'd14;
+ 4'h8: SK5 = 4'd11;
+ 4'h9: SK5 = 4'd5;
+ 4'hA: SK5 = 4'd0;
+ 4'hB: SK5 = 4'd15;
+ 4'hC: SK5 = 4'd13;
+ 4'hD: SK5 = 4'd6;
+ 4'hE: SK5 = 4'd10;
+ 4'hF: SK5 = 4'd9;
+ endcase // case (SK5_in[3:0])
+ end // always @ (SK5_in[3:0])
+
+ always @(SK6_in[3:0]) begin
+ case (SK6_in[3:0])
+ 4'h0: SK6 = 4'd10;
+ 4'h1: SK6 = 4'd7;
+ 4'h2: SK6 = 4'd6;
+ 4'h3: SK6 = 4'd1;
+ 4'h4: SK6 = 4'd0;
+ 4'h5: SK6 = 4'd14;
+ 4'h6: SK6 = 4'd3;
+ 4'h7: SK6 = 4'd13;
+ 4'h8: SK6 = 4'd12;
+ 4'h9: SK6 = 4'd9;
+ 4'hA: SK6 = 4'd11;
+ 4'hB: SK6 = 4'd2;
+ 4'hC: SK6 = 4'd15;
+ 4'hD: SK6 = 4'd5;
+ 4'hE: SK6 = 4'd4;
+ 4'hF: SK6 = 4'd8;
+ endcase // case (SK6_in[3:0])
+ end // always @ (SK6_in[3:0])
+
+ always @(SB0_in[3:0]) begin
+ case (SB0_in[3:0])
+ 4'h0: SB0 = 4'd12;
+ 4'h1: SB0 = 4'd9;
+ 4'h2: SB0 = 4'd3;
+ 4'h3: SB0 = 4'd0;
+ 4'h4: SB0 = 4'd11;
+ 4'h5: SB0 = 4'd5;
+ 4'h6: SB0 = 4'd13;
+ 4'h7: SB0 = 4'd6;
+ 4'h8: SB0 = 4'd2;
+ 4'h9: SB0 = 4'd4;
+ 4'hA: SB0 = 4'd14;
+ 4'hB: SB0 = 4'd7;
+ 4'hC: SB0 = 4'd8;
+ 4'hD: SB0 = 4'd15;
+ 4'hE: SB0 = 4'd1;
+ 4'hF: SB0 = 4'd10;
+ endcase // case (SB0_in[3:0])
+ end // always @ (SB0_in[3:0])
+
+ always @(SB1_in[3:0]) begin
+ case (SB1_in[3:0])
+ 4'h0: SB1 = 4'd3;
+ 4'h1: SB1 = 4'd8;
+ 4'h2: SB1 = 4'd14;
+ 4'h3: SB1 = 4'd1;
+ 4'h4: SB1 = 4'd5;
+ 4'h5: SB1 = 4'd2;
+ 4'h6: SB1 = 4'd11;
+ 4'h7: SB1 = 4'd13;
+ 4'h8: SB1 = 4'd10;
+ 4'h9: SB1 = 4'd4;
+ 4'hA: SB1 = 4'd9;
+ 4'hB: SB1 = 4'd7;
+ 4'hC: SB1 = 4'd6;
+ 4'hD: SB1 = 4'd15;
+ 4'hE: SB1 = 4'd12;
+ 4'hF: SB1 = 4'd0;
+ endcase // case (SB1_in[3:0])
+ end // always @ (SB1_in[3:0])
+
+ always @(SB2_in[3:0]) begin
+ case (SB2_in[3:0])
+ 4'h0: SB2 = 4'd7;
+ 4'h1: SB2 = 4'd4;
+ 4'h2: SB2 = 4'd1;
+ 4'h3: SB2 = 4'd10;
+ 4'h4: SB2 = 4'd11;
+ 4'h5: SB2 = 4'd13;
+ 4'h6: SB2 = 4'd14;
+ 4'h7: SB2 = 4'd3;
+ 4'h8: SB2 = 4'd12;
+ 4'h9: SB2 = 4'd15;
+ 4'hA: SB2 = 4'd6;
+ 4'hB: SB2 = 4'd0;
+ 4'hC: SB2 = 4'd2;
+ 4'hD: SB2 = 4'd8;
+ 4'hE: SB2 = 4'd9;
+ 4'hF: SB2 = 4'd5;
+ endcase // case (SB2_in[3:0])
+ end // always @ (SB2_in[3:0])
+
+ always @(SB3_in[3:0]) begin
+ case (SB3_in[3:0])
+ 4'h0: SB3 = 4'd6;
+ 4'h1: SB3 = 4'd3;
+ 4'h2: SB3 = 4'd1;
+ 4'h3: SB3 = 4'd4;
+ 4'h4: SB3 = 4'd10;
+ 4'h5: SB3 = 4'd12;
+ 4'h6: SB3 = 4'd15;
+ 4'h7: SB3 = 4'd2;
+ 4'h8: SB3 = 4'd5;
+ 4'h9: SB3 = 4'd14;
+ 4'hA: SB3 = 4'd11;
+ 4'hB: SB3 = 4'd8;
+ 4'hC: SB3 = 4'd9;
+ 4'hD: SB3 = 4'd7;
+ 4'hE: SB3 = 4'd0;
+ 4'hF: SB3 = 4'd13;
+ endcase // case (SB3_in[3:0])
+ end // always @ (SB3_in[3:0])
+
+ always @(SB4_in[3:0]) begin
+ case (SB4_in[3:0])
+ 4'h0: SB4 = 4'd3;
+ 4'h1: SB4 = 4'd6;
+ 4'h2: SB4 = 4'd15;
+ 4'h3: SB4 = 4'd12;
+ 4'h4: SB4 = 4'd4;
+ 4'h5: SB4 = 4'd1;
+ 4'h6: SB4 = 4'd9;
+ 4'h7: SB4 = 4'd2;
+ 4'h8: SB4 = 4'd5;
+ 4'h9: SB4 = 4'd8;
+ 4'hA: SB4 = 4'd10;
+ 4'hB: SB4 = 4'd7;
+ 4'hC: SB4 = 4'd11;
+ 4'hD: SB4 = 4'd13;
+ 4'hE: SB4 = 4'd0;
+ 4'hF: SB4 = 4'd14;
+ endcase // case (SB4_in[3:0])
+ end // always @ (SB4_in[3:0])
+
+ always @(SB5_in[3:0]) begin
+ case (SB5_in[3:0])
+ 4'h0: SB5 = 4'd11;
+ 4'h1: SB5 = 4'd14;
+ 4'h2: SB5 = 4'd6;
+ 4'h3: SB5 = 4'd8;
+ 4'h4: SB5 = 4'd5;
+ 4'h5: SB5 = 4'd2;
+ 4'h6: SB5 = 4'd12;
+ 4'h7: SB5 = 4'd7;
+ 4'h8: SB5 = 4'd1;
+ 4'h9: SB5 = 4'd4;
+ 4'hA: SB5 = 4'd15;
+ 4'hB: SB5 = 4'd3;
+ 4'hC: SB5 = 4'd10;
+ 4'hD: SB5 = 4'd13;
+ 4'hE: SB5 = 4'd9;
+ 4'hF: SB5 = 4'd0;
+ endcase // case (SB5_in[3:0])
+ end // always @ (SB5_in[3:0])
+
+ always @(SB6_in[3:0]) begin
+ case (SB6_in[3:0])
+ 4'h0: SB6 = 4'd1;
+ 4'h1: SB6 = 4'd11;
+ 4'h2: SB6 = 4'd7;
+ 4'h3: SB6 = 4'd4;
+ 4'h4: SB6 = 4'd2;
+ 4'h5: SB6 = 4'd5;
+ 4'h6: SB6 = 4'd12;
+ 4'h7: SB6 = 4'd9;
+ 4'h8: SB6 = 4'd13;
+ 4'h9: SB6 = 4'd6;
+ 4'hA: SB6 = 4'd8;
+ 4'hB: SB6 = 4'd15;
+ 4'hC: SB6 = 4'd14;
+ 4'hD: SB6 = 4'd0;
+ 4'hE: SB6 = 4'd3;
+ 4'hF: SB6 = 4'd10;
+ endcase // case (SB6_in[3:0])
+ end // always @ (SB6_in[3:0])
+
+ //////
+ /// Sbox wiring
+ /// generated by perl script ./make_sboxwires.pl
+ //////
+ assign SB0_in[0] = Bx[0];
+ assign SB0_in[1] = Bx[7];
+ assign SB0_in[2] = Bx[14];
+ assign SB0_in[3] = Bx[21];
+
+ assign SK0_in[0] = Kx[0];
+ assign SK0_in[1] = Kx[7];
+ assign SK0_in[2] = Kx[14];
+ assign SK0_in[3] = Kx[21];
+
+ assign o_Bz[0] = SB0[0];
+ assign o_Bz[7] = SB0[1];
+ assign o_Bz[14] = SB0[2];
+ assign o_Bz[21] = SB0[3];
+
+ assign o_Kz[0] = SK0[0];
+ assign o_Kz[7] = SK0[1];
+ assign o_Kz[14] = SK0[2];
+ assign o_Kz[21] = SK0[3];
+
+ assign SB1_in[0] = Bx[1];
+ assign SB1_in[1] = Bx[8];
+ assign SB1_in[2] = Bx[15];
+ assign SB1_in[3] = Bx[22];
+
+ assign SK1_in[0] = Kx[1];
+ assign SK1_in[1] = Kx[8];
+ assign SK1_in[2] = Kx[15];
+ assign SK1_in[3] = Kx[22];
+
+ assign o_Bz[1] = SB1[0];
+ assign o_Bz[8] = SB1[1];
+ assign o_Bz[15] = SB1[2];
+ assign o_Bz[22] = SB1[3];
+
+ assign o_Kz[1] = SK1[0];
+ assign o_Kz[8] = SK1[1];
+ assign o_Kz[15] = SK1[2];
+ assign o_Kz[22] = SK1[3];
+
+ assign SB2_in[0] = Bx[2];
+ assign SB2_in[1] = Bx[9];
+ assign SB2_in[2] = Bx[16];
+ assign SB2_in[3] = Bx[23];
+
+ assign SK2_in[0] = Kx[2];
+ assign SK2_in[1] = Kx[9];
+ assign SK2_in[2] = Kx[16];
+ assign SK2_in[3] = Kx[23];
+
+ assign o_Bz[2] = SB2[0];
+ assign o_Bz[9] = SB2[1];
+ assign o_Bz[16] = SB2[2];
+ assign o_Bz[23] = SB2[3];
+
+ assign o_Kz[2] = SK2[0];
+ assign o_Kz[9] = SK2[1];
+ assign o_Kz[16] = SK2[2];
+ assign o_Kz[23] = SK2[3];
+
+ assign SB3_in[0] = Bx[3];
+ assign SB3_in[1] = Bx[10];
+ assign SB3_in[2] = Bx[17];
+ assign SB3_in[3] = Bx[24];
+
+ assign SK3_in[0] = Kx[3];
+ assign SK3_in[1] = Kx[10];
+ assign SK3_in[2] = Kx[17];
+ assign SK3_in[3] = Kx[24];
+
+ assign o_Bz[3] = SB3[0];
+ assign o_Bz[10] = SB3[1];
+ assign o_Bz[17] = SB3[2];
+ assign o_Bz[24] = SB3[3];
+
+ assign o_Kz[3] = SK3[0];
+ assign o_Kz[10] = SK3[1];
+ assign o_Kz[17] = SK3[2];
+ assign o_Kz[24] = SK3[3];
+
+ assign SB4_in[0] = Bx[4];
+ assign SB4_in[1] = Bx[11];
+ assign SB4_in[2] = Bx[18];
+ assign SB4_in[3] = Bx[25];
+
+ assign SK4_in[0] = Kx[4];
+ assign SK4_in[1] = Kx[11];
+ assign SK4_in[2] = Kx[18];
+ assign SK4_in[3] = Kx[25];
+
+ assign o_Bz[4] = SB4[0];
+ assign o_Bz[11] = SB4[1];
+ assign o_Bz[18] = SB4[2];
+ assign o_Bz[25] = SB4[3];
+
+ assign o_Kz[4] = SK4[0];
+ assign o_Kz[11] = SK4[1];
+ assign o_Kz[18] = SK4[2];
+ assign o_Kz[25] = SK4[3];
+
+ assign SB5_in[0] = Bx[5];
+ assign SB5_in[1] = Bx[12];
+ assign SB5_in[2] = Bx[19];
+ assign SB5_in[3] = Bx[26];
+
+ assign SK5_in[0] = Kx[5];
+ assign SK5_in[1] = Kx[12];
+ assign SK5_in[2] = Kx[19];
+ assign SK5_in[3] = Kx[26];
+
+ assign o_Bz[5] = SB5[0];
+ assign o_Bz[12] = SB5[1];
+ assign o_Bz[19] = SB5[2];
+ assign o_Bz[26] = SB5[3];
+
+ assign o_Kz[5] = SK5[0];
+ assign o_Kz[12] = SK5[1];
+ assign o_Kz[19] = SK5[2];
+ assign o_Kz[26] = SK5[3];
+
+ assign SB6_in[0] = Bx[6];
+ assign SB6_in[1] = Bx[13];
+ assign SB6_in[2] = Bx[20];
+ assign SB6_in[3] = Bx[27];
+
+ assign SK6_in[0] = Kx[6];
+ assign SK6_in[1] = Kx[13];
+ assign SK6_in[2] = Kx[20];
+ assign SK6_in[3] = Kx[27];
+
+ assign o_Bz[6] = SB6[0];
+ assign o_Bz[13] = SB6[1];
+ assign o_Bz[20] = SB6[2];
+ assign o_Bz[27] = SB6[3];
+
+ assign o_Kz[6] = SK6[0];
+ assign o_Kz[13] = SK6[1];
+ assign o_Kz[20] = SK6[2];
+ assign o_Kz[27] = SK6[3];
+
+ //////
+ // output function
+ // generated by perl script ./makeofunc.pl ofunc.txt > ostream_code.txt
+ //////
+assign ostream_r[0] = (Bz[17] & Kz[3]) ^ (Bz[26] & Kz[6]) ^ (Bz[22] & Kz[0]) ^ (Bz[27] & Kz[9]) ^ (Bz[21] & Kz[4]) ^ (Bz[18] & Kz[22]) ^ (Bz[2] & Kz[5]) ^ By[5] ^ Ky[10];
+
+assign ostream_r[1] = (Bz[5] & Kz[20]) ^ (Bz[20] & Kz[18]) ^ (Bz[15] & Kz[7]) ^ (Bz[24] & Kz[23]) ^ (Bz[2] & Kz[15]) ^ (Bz[25] & Kz[5]) ^ (Bz[0] & Kz[3]) ^ By[16] ^ Ky[25];
+
+assign ostream_r[2] = (Bz[22] & Kz[7]) ^ (Bz[5] & Kz[19]) ^ (Bz[14] & Kz[2]) ^ (Bz[16] & Kz[10]) ^ (Bz[25] & Kz[22]) ^ (Bz[17] & Kz[4]) ^ (Bz[20] & Kz[13]) ^ By[11] ^ Ky[21];
+
+assign ostream_r[3] = (Bz[19] & Kz[6]) ^ (Bz[3] & Kz[14]) ^ (Bz[15] & Kz[9]) ^ (Bz[11] & Kz[8]) ^ (Bz[21] & Kz[17]) ^ (Bz[16] & Kz[18]) ^ (Bz[27] & Kz[12]) ^ By[1] ^ Ky[24];
+
+assign ostream_r[4] = (Bz[19] & Kz[25]) ^ (Bz[6] & Kz[6]) ^ (Bz[17] & Kz[5]) ^ (Bz[18] & Kz[2]) ^ (Bz[22] & Kz[10]) ^ (Bz[7] & Kz[15]) ^ (Bz[9] & Kz[21]) ^ By[12] ^ Ky[8];
+
+assign ostream_r[5] = (Bz[3] & Kz[27]) ^ (Bz[7] & Kz[14]) ^ (Bz[4] & Kz[2]) ^ (Bz[8] & Kz[4]) ^ (Bz[16] & Kz[24]) ^ (Bz[6] & Kz[19]) ^ (Bz[5] & Kz[1]) ^ By[17] ^ Ky[12];
+
+assign ostream_r[6] = (Bz[8] & Kz[17]) ^ (Bz[21] & Kz[26]) ^ (Bz[27] & Kz[4]) ^ (Bz[2] & Kz[16]) ^ (Bz[11] & Kz[27]) ^ (Bz[24] & Kz[7]) ^ (Bz[12] & Kz[22]) ^ By[3] ^ Ky[11];
+
+assign ostream_r[7] = (Bz[9] & Kz[9]) ^ (Bz[5] & Kz[10]) ^ (Bz[7] & Kz[19]) ^ (Bz[4] & Kz[11]) ^ (Bz[8] & Kz[7]) ^ (Bz[13] & Kz[6]) ^ (Bz[3] & Kz[8]) ^ By[15] ^ Ky[23];
+
+assign ostream_r[8] = (Bz[26] & Kz[13]) ^ (Bz[13] & Kz[12]) ^ (Bz[23] & Kz[18]) ^ (Bz[10] & Kz[24]) ^ (Bz[11] & Kz[15]) ^ (Bz[7] & Kz[23]) ^ (Bz[15] & Kz[7]) ^ By[19] ^ Ky[16];
+
+assign ostream_r[9] = (Bz[1] & Kz[0]) ^ (Bz[0] & Kz[5]) ^ (Bz[19] & Kz[20]) ^ (Bz[11] & Kz[25]) ^ (Bz[13] & Kz[1]) ^ (Bz[16] & Kz[24]) ^ (Bz[24] & Kz[9]) ^ By[18] ^ Ky[27];
+
+assign ostream_r[10] = (Bz[26] & Kz[14]) ^ (Bz[13] & Kz[23]) ^ (Bz[9] & Kz[27]) ^ (Bz[14] & Kz[25]) ^ (Bz[10] & Kz[17]) ^ (Bz[4] & Kz[19]) ^ (Bz[1] & Kz[1]) ^ By[2] ^ Ky[22];
+
+assign ostream_r[11] = (Bz[21] & Kz[6]) ^ (Bz[15] & Kz[21]) ^ (Bz[5] & Kz[17]) ^ (Bz[3] & Kz[15]) ^ (Bz[13] & Kz[26]) ^ (Bz[25] & Kz[11]) ^ (Bz[16] & Kz[16]) ^ By[27] ^ Ky[7];
+
+assign ostream_r[12] = (Bz[20] & Kz[11]) ^ (Bz[7] & Kz[22]) ^ (Bz[18] & Kz[20]) ^ (Bz[12] & Kz[0]) ^ (Bz[17] & Kz[26]) ^ (Bz[1] & Kz[23]) ^ (Bz[16] & Kz[17]) ^ By[0] ^ Ky[2];
+
+assign ostream_r[13] = (Bz[14] & Kz[8]) ^ (Bz[23] & Kz[4]) ^ (Bz[1] & Kz[3]) ^ (Bz[12] & Kz[14]) ^ (Bz[24] & Kz[20]) ^ (Bz[6] & Kz[26]) ^ (Bz[18] & Kz[23]) ^ By[9] ^ Ky[15];
+
+assign ostream_r[14] = (Bz[19] & Kz[19]) ^ (Bz[6] & Kz[0]) ^ (Bz[21] & Kz[18]) ^ (Bz[25] & Kz[2]) ^ (Bz[23] & Kz[13]) ^ (Bz[1] & Kz[8]) ^ (Bz[10] & Kz[24]) ^ By[8] ^ Ky[14];
+
+assign ostream_r[15] = (Bz[3] & Kz[16]) ^ (Bz[0] & Kz[21]) ^ (Bz[27] & Kz[24]) ^ (Bz[23] & Kz[25]) ^ (Bz[19] & Kz[12]) ^ (Bz[8] & Kz[27]) ^ (Bz[4] & Kz[15]) ^ By[7] ^ Ky[18];
+
+assign ostream_r[16] = (Bz[6] & Kz[3]) ^ (Bz[5] & Kz[5]) ^ (Bz[14] & Kz[8]) ^ (Bz[22] & Kz[25]) ^ (Bz[24] & Kz[7]) ^ (Bz[18] & Kz[27]) ^ (Bz[2] & Kz[2]) ^ By[21] ^ Ky[26];
+
+assign ostream_r[17] = (Bz[3] & Kz[11]) ^ (Bz[4] & Kz[14]) ^ (Bz[2] & Kz[23]) ^ (Bz[6] & Kz[17]) ^ (Bz[22] & Kz[22]) ^ (Bz[14] & Kz[13]) ^ (Bz[12] & Kz[19]) ^ By[26] ^ Ky[4];
+
+assign ostream_r[18] = (Bz[25] & Kz[1]) ^ (Bz[21] & Kz[16]) ^ (Bz[19] & Kz[14]) ^ (Bz[9] & Kz[11]) ^ (Bz[10] & Kz[12]) ^ (Bz[15] & Kz[6]) ^ (Bz[13] & Kz[10]) ^ By[22] ^ Ky[19];
+
+assign ostream_r[19] = (Bz[23] & Kz[21]) ^ (Bz[11] & Kz[1]) ^ (Bz[10] & Kz[10]) ^ (Bz[20] & Kz[20]) ^ (Bz[1] & Kz[18]) ^ (Bz[12] & Kz[26]) ^ (Bz[14] & Kz[9]) ^ By[4] ^ Ky[13];
+
+assign ostream_r[20] = (Bz[11] & Kz[20]) ^ (Bz[26] & Kz[21]) ^ (Bz[20] & Kz[9]) ^ (Bz[17] & Kz[25]) ^ (Bz[8] & Kz[12]) ^ (Bz[23] & Kz[3]) ^ (Bz[0] & Kz[15]) ^ By[24] ^ Ky[0];
+
+assign ostream_r[21] = (Bz[9] & Kz[18]) ^ (Bz[17] & Kz[12]) ^ (Bz[26] & Kz[21]) ^ (Bz[4] & Kz[27]) ^ (Bz[27] & Kz[1]) ^ (Bz[0] & Kz[16]) ^ (Bz[15] & Kz[24]) ^ By[6] ^ Ky[20];
+
+assign ostream_r[22] = (Bz[22] & Kz[13]) ^ (Bz[12] & Kz[0]) ^ (Bz[2] & Kz[3]) ^ (Bz[10] & Kz[16]) ^ (Bz[7] & Kz[22]) ^ (Bz[20] & Kz[11]) ^ (Bz[25] & Kz[26]) ^ By[13] ^ Ky[9];
+
+assign ostream_r[23] = (Bz[27] & Kz[2]) ^ (Bz[24] & Kz[0]) ^ (Bz[26] & Kz[13]) ^ (Bz[8] & Kz[5]) ^ (Bz[0] & Kz[4]) ^ (Bz[9] & Kz[8]) ^ (Bz[18] & Kz[10]) ^ By[23] ^ Ky[3];
+
+endmodule // hdcp_block
diff --git a/hdcp/hdcp_cipher.v b/hdcp/hdcp_cipher.v
new file mode 100755
index 0000000..9804d10
--- /dev/null
+++ b/hdcp/hdcp_cipher.v
@@ -0,0 +1,411 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2011, Andrew "bunnie" Huang
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+`timescale 1 ns / 1 ps
+
+// generates a stream of hdcp cipher data
+module hdcp_cipher(
+ input wire clk,
+ input reset,
+
+ input [55:0] Km, // shared secret value
+ input [63:0] An, // session random number
+
+ input hdcpBlockCipher_init, // pulsed only one cycle
+ input authentication, // pulsed one cycle same time as above
+ input hdcpRekeyCipher, // pulsed one cycle to initiate rekey
+ input hdcpStreamCipher,// advance cipher state one clock
+ output [23:0] pr_data, // pseudorandom data output
+ output reg stream_ready // asserted when stream is ready (after init seq)
+ );
+
+ wire lfsr_out;
+ wire [23:0] ostream;
+ wire [83:0] Bo_wire;
+
+ parameter INIT = 12'b1 << 0;
+ parameter BLOCK_1 = 12'b1 << 1;
+ parameter BLOCK_2 = 12'b1 << 2;
+ parameter BLOCK_3 = 12'b1 << 3;
+ parameter BLOCK_4 = 12'b1 << 4;
+ parameter BLOCK_5 = 12'b1 << 5;
+ parameter BLOCK_6 = 12'b1 << 6;
+ parameter BLOCK_7 = 12'b1 << 7;
+ parameter BLOCK_8 = 12'b1 << 8;
+ parameter BLOCK_9 = 12'b1 << 9;
+ parameter GET_M = 12'b1 << 10;
+ parameter STREAM = 12'b1 << 11;
+ parameter REKEY = 12'b1 << 12;
+ parameter nSTATES = 13;
+
+ reg [(nSTATES-1):0] cstate = {{(nSTATES-1){1'b0}},1'b1};
+ reg [(nSTATES-1):0] nstate;
+
+// `define SIMULATION 1
+`ifdef SIMULATION
+ // synthesis translate_off
+ reg [8*20:1] state_ascii = "INIT ";
+ always @(cstate) begin
+ if (cstate == INIT ) state_ascii <= "INIT ";
+ else if (cstate == BLOCK_1 ) state_ascii <= "BLOCK_1 ";
+ else if (cstate == BLOCK_2 ) state_ascii <= "BLOCK_2 ";
+ else if (cstate == BLOCK_3 ) state_ascii <= "BLOCK_3 ";
+ else if (cstate == BLOCK_4 ) state_ascii <= "BLOCK_4 ";
+ else if (cstate == BLOCK_5 ) state_ascii <= "BLOCK_5 ";
+ else if (cstate == BLOCK_6 ) state_ascii <= "BLOCK_6 ";
+ else if (cstate == BLOCK_7 ) state_ascii <= "BLOCK_7 ";
+ else if (cstate == BLOCK_8 ) state_ascii <= "BLOCK_8 ";
+ else if (cstate == BLOCK_9 ) state_ascii <= "BLOCK_9 ";
+ else if (cstate == GET_M ) state_ascii <= "GET_M ";
+ else if (cstate == STREAM ) state_ascii <= "STREAM ";
+ else if (cstate == REKEY ) state_ascii <= "REKEY ";
+ else state_ascii <= "WTF ";
+ end
+ // synthesis translate_on
+`endif // `ifdef SIMULATION
+
+ reg [5:0] statecnt;
+ reg rekey;
+ reg load_block;
+ reg load_56; // load 56 or 80 bits...
+ reg load_lfsr;
+ reg advance_lfsr;
+ reg advance_block;
+ reg [83:0] Ks;
+ reg [83:0] Ki;
+ reg [63:0] Mi;
+ reg load_ks;
+ reg auth_mode;
+ reg [83:0] Kmod;
+
+ always @ (posedge clk or posedge reset) begin
+ if (reset)
+ cstate <= INIT;
+ else
+ cstate <=#1 nstate;
+ end
+
+ hdcp_lfsr lfsr( .clk(clk), .reset(reset),
+ .iv(auth_mode ? Ks[55:0] : Ki[55:0]),
+ .init_iv(load_lfsr),
+ .advance(advance_lfsr),
+ .onebit(lfsr_out));
+
+ hdcp_block block( .clk(clk), .reset(reset),
+
+ .load(load_block),
+ .B(auth_mode ? {20'b0,An} : {20'b0,Mi}),
+ .K(Kmod),
+ .Bo(Bo_wire),
+ .rekey(rekey),
+ .lfsr_in(lfsr_out),
+ .ostream(ostream),
+ .advance(advance_block));
+ assign pr_data = ostream;
+
+ always @ (*) begin
+ case ({auth_mode,load_56}) //synthesis parallel_case full_case
+ 2'b00: begin // not auth mode, load 84 bits
+ Kmod = Ki;
+ end
+ 2'b01: begin // not auth mode, but load 56 bits only
+ Kmod = {28'b0,Ks[55:0]};
+ end
+ 2'b10: begin // auth mode, load 84 bits
+ Kmod = Ks;
+ end
+ 2'b11: begin // auth mode, load only 56 bits
+ Kmod = {28'b0,Km[55:0]};
+ end
+ endcase // case ({auth_mode,load_56})
+ end // always @ (*)
+
+
+ always @ (*) begin
+ case (cstate) //synthesis parallel_case full_case
+ INIT: begin
+ nstate = hdcpBlockCipher_init ? BLOCK_1 : INIT;
+ end
+ BLOCK_1: begin
+ nstate = BLOCK_2;
+ end
+ BLOCK_2: begin
+ nstate = (statecnt >= 6'd47) ? BLOCK_3: BLOCK_2;
+ end
+ BLOCK_3: begin
+ nstate = BLOCK_4;
+ end
+ BLOCK_4: begin
+ nstate = BLOCK_5;
+ end
+ BLOCK_5: begin
+ nstate = BLOCK_6;
+ end
+ BLOCK_6: begin
+ nstate = BLOCK_7;
+ end
+ BLOCK_7: begin
+ nstate = BLOCK_8;
+ end
+ BLOCK_8: begin
+ nstate = (statecnt >= 6'd55) ? BLOCK_9: BLOCK_8;
+ end
+ BLOCK_9: begin
+ nstate = GET_M;
+ end
+ GET_M: begin
+ nstate = STREAM;
+ end
+ STREAM: begin
+ if( hdcpBlockCipher_init ) begin
+ nstate = BLOCK_1;
+ end else if( hdcpRekeyCipher ) begin
+ nstate = REKEY;
+ end else begin
+ nstate = STREAM;
+ end
+ end
+ REKEY: begin
+ if( hdcpBlockCipher_init ) begin
+ nstate = BLOCK_1;
+ end else begin
+ nstate = (statecnt >= 6'd55) ? STREAM : REKEY;
+ end
+ end
+ endcase // case (cstate)
+ end
+
+ always @ (posedge clk or posedge reset) begin
+ if( reset ) begin
+ statecnt <=#1 6'b0;
+ rekey <=#1 1'b0;
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 1'b0;
+ advance_block <=#1 1'b0;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end else begin
+ case (cstate) // synthesis parallel_case full_case
+ INIT: begin
+ statecnt <=#1 6'b0;
+ rekey <=#1 1'b0;
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 1'b0;
+ advance_block <=#1 1'b0;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 authentication;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end
+ BLOCK_1: begin
+ statecnt <=#1 6'b0;
+ rekey <=#1 1'b0;
+ load_block <=#1 1'b1; // load B & K regs of block module
+ advance_lfsr <=#1 1'b0;
+ advance_block <=#1 1'b0;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 auth_mode;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b1;
+ end
+ BLOCK_2: begin
+ statecnt <=#1 statecnt + 1; // 48 clocks
+ rekey <=#1 1'b0;
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 1'b0;
+ advance_block <=#1 1'b1;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 auth_mode;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end
+ BLOCK_3: begin
+ statecnt <=#1 0;
+ rekey <=#1 1'b0;
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 1'b0;
+ advance_block <=#1 1'b0;
+ load_ks <=#1 1'b1; // save Ks, Ki, and B=>K
+ auth_mode <=#1 auth_mode;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end
+ BLOCK_4: begin
+ statecnt <=#1 0;
+ rekey <=#1 1'b0;
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 1'b0;
+ advance_block <=#1 1'b0;
+ load_ks <=#1 1'b1; // dup of above
+ auth_mode <=#1 auth_mode;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end
+ BLOCK_5: begin
+ statecnt <=#1 0;
+ rekey <=#1 1'b0;
+ load_block <=#1 1'b1; // reload block cipher
+ advance_lfsr <=#1 1'b0;
+ advance_block <=#1 1'b0;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 auth_mode;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end
+ BLOCK_6: begin
+ statecnt <=#1 0;
+ rekey <=#1 1'b0;
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 1'b0;
+ advance_block <=#1 1'b0;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 auth_mode;
+ load_lfsr <=#1 1'b1; // init lfsr
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end
+ BLOCK_7: begin
+ statecnt <=#1 0;
+ rekey <=#1 1'b1; // assert rekey
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 1'b0;
+ advance_block <=#1 1'b0;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 auth_mode;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end
+ BLOCK_8: begin
+ statecnt <=#1 statecnt + 1; // 56 clocks
+ rekey <=#1 1'b1;
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 1'b1;
+ advance_block <=#1 1'b1;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 auth_mode;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end
+ BLOCK_9: begin
+ statecnt <=#1 0;
+ rekey <=#1 1'b0; // de-assert rekey
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 1'b0;
+ advance_block <=#1 1'b0;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 auth_mode;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end // case: BLOCK_9
+ GET_M: begin // one cycle wait to get M register loaded properly
+ statecnt <=#1 0;
+ rekey <=#1 1'b0;
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 1'b0;
+ advance_block <=#1 1'b0;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 1'b0;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end
+ STREAM: begin
+ statecnt <=#1 0;
+ rekey <=#1 1'b0;
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 hdcpStreamCipher;
+ advance_block <=#1 hdcpStreamCipher;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 authentication;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b1;
+ load_56 <=#1 1'b0;
+ end
+ REKEY: begin
+ statecnt <=#1 statecnt + 1;
+ rekey <=#1 1'b1;
+ load_block <=#1 1'b0;
+ advance_lfsr <=#1 1'b1;
+ advance_block <=#1 1'b1;
+ load_ks <=#1 1'b0;
+ auth_mode <=#1 auth_mode;
+ load_lfsr <=#1 1'b0;
+ stream_ready <=#1 1'b0;
+ load_56 <=#1 1'b0;
+ end
+ endcase // case (cstate)
+ end
+ end // always @ (posedge clk or posedge reset)
+
+ always @(posedge clk or posedge reset) begin
+ if( reset ) begin
+ Ks <= 80'b0;
+ Ki <= 80'b0;
+ end else begin
+// if( hdcpBlockCipher_init ) begin
+// Ks <= (authentication | auth_mode) ? {28'b0,Km} : Ks;
+// Ki <= 80'b0;
+// end else if( load_ks && auth_mode ) begin
+ if( load_ks && auth_mode ) begin
+ Ks <= Bo_wire;
+ Ki <= 80'b0;
+ end else if( load_ks && !auth_mode ) begin
+ Ks <= Ks;
+ Ki <= Bo_wire;
+ end else begin
+ Ks <= Ks;
+ Ki <= Ki;
+ end
+ end
+ end // always @ (posedge clk or posedge reset)
+
+ always @(posedge clk or posedge reset) begin
+ if( reset ) begin
+ Mi <= 80'b0;
+ end else begin
+ if( (cstate == BLOCK_8) || (cstate == BLOCK_9) || (cstate == GET_M) ) begin
+ Mi[15:0] <= ostream[15:0];
+ Mi[31:16] <= Mi[15:0];
+ Mi[47:32] <= Mi[31:16];
+ Mi[63:48] <= Mi[47:32];
+ end else begin
+ Mi <= Mi;
+ end
+ end // else: !if( reset )
+ end // always @ (posedge clk or posedge reset)
+
+endmodule // hdcp_cipher
diff --git a/hdcp/hdcp_lfsr.v b/hdcp/hdcp_lfsr.v
new file mode 100755
index 0000000..a85d753
--- /dev/null
+++ b/hdcp/hdcp_lfsr.v
@@ -0,0 +1,196 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2011, Andrew "bunnie" Huang
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+`timescale 1 ns / 1 ps
+
+// lfsr module for hdcp cipher
+module hdcp_lfsr(
+ input wire clk,
+ input wire reset, // this is just a low-level reset
+
+ input wire [55:0] iv, // initial values
+
+ input wire init_iv, // load initial values
+ input wire advance, // advance state one cycle
+ output wire onebit // my one-bit output
+ );
+
+ reg [12:0] lfsr0;
+ reg [13:0] lfsr1;
+ reg [15:0] lfsr2;
+ reg [16:0] lfsr3;
+
+ wire [3:0] comb_tap0;
+ wire [3:0] comb_tap1;
+ wire [3:0] comb_tap2;
+
+ always @(posedge clk or posedge reset) begin
+ if( reset == 1 ) begin
+ lfsr0 <= 13'b0;
+ lfsr1 <= 14'b0;
+ lfsr2 <= 16'b0;
+ lfsr3 <= 17'b0;
+ end else begin
+ if( init_iv ) begin
+ // assume bit-offsets start from 0
+ lfsr0[12:0] <= {~iv[6],iv[11:0]};
+ lfsr1[13:0] <= {~iv[18],iv[24:12]};
+ lfsr2[15:0] <= {~iv[32],iv[39:25]};
+ lfsr3[16:0] <= {~iv[47],iv[55:40]};
+ end else if( advance ) begin
+ // 13 11 9 5
+ // 12 10 8 4
+ lfsr0[0 ] <= lfsr0[4] ^ lfsr0[8] ^ lfsr0[10] ^ lfsr0[12];
+ lfsr0[1 ] <= lfsr0[0 ];
+ lfsr0[2 ] <= lfsr0[1 ];
+ lfsr0[3 ] <= lfsr0[2 ];
+ lfsr0[4 ] <= lfsr0[3 ];
+ lfsr0[5 ] <= lfsr0[4 ];
+ lfsr0[6 ] <= lfsr0[5 ];
+ lfsr0[7 ] <= lfsr0[6 ];
+ lfsr0[8 ] <= lfsr0[7 ];
+ lfsr0[9 ] <= lfsr0[8 ];
+ lfsr0[10] <= lfsr0[9 ];
+ lfsr0[11] <= lfsr0[10];
+ lfsr0[12] <= lfsr0[11];
+
+ //4 6 7 10 11 14
+ //3 5 6 9 10 13
+ lfsr1[0 ] <= lfsr1[3] ^ lfsr1[5] ^ lfsr1[6] ^ lfsr1[9] ^ lfsr1[10] ^ lfsr1[13];
+ lfsr1[1 ] <= lfsr1[0 ];
+ lfsr1[2 ] <= lfsr1[1 ];
+ lfsr1[3 ] <= lfsr1[2 ];
+ lfsr1[4 ] <= lfsr1[3 ];
+ lfsr1[5 ] <= lfsr1[4 ];
+ lfsr1[6 ] <= lfsr1[5 ];
+ lfsr1[7 ] <= lfsr1[6 ];
+ lfsr1[8 ] <= lfsr1[7 ];
+ lfsr1[9 ] <= lfsr1[8 ];
+ lfsr1[10] <= lfsr1[9 ];
+ lfsr1[11] <= lfsr1[10];
+ lfsr1[12] <= lfsr1[11];
+ lfsr1[13] <= lfsr1[12];
+
+ //5 7 8 12 15 16
+ //4 6 7 11 14 15
+ lfsr2[0 ] <= lfsr2[4] ^ lfsr2[6] ^ lfsr2[7] ^ lfsr2[11] ^ lfsr2[14] ^ lfsr2[15];
+ lfsr2[1 ] <= lfsr2[0 ];
+ lfsr2[2 ] <= lfsr2[1 ];
+ lfsr2[3 ] <= lfsr2[2 ];
+ lfsr2[4 ] <= lfsr2[3 ];
+ lfsr2[5 ] <= lfsr2[4 ];
+ lfsr2[6 ] <= lfsr2[5 ];
+ lfsr2[7 ] <= lfsr2[6 ];
+ lfsr2[8 ] <= lfsr2[7 ];
+ lfsr2[9 ] <= lfsr2[8 ];
+ lfsr2[10] <= lfsr2[9 ];
+ lfsr2[11] <= lfsr2[10];
+ lfsr2[12] <= lfsr2[11];
+ lfsr2[13] <= lfsr2[12];
+ lfsr2[14] <= lfsr2[13];
+ lfsr2[15] <= lfsr2[14];
+
+ //5 11 15 17
+ //4 10 14 16
+ lfsr3[0 ] <= lfsr3[4] ^ lfsr3[10] ^ lfsr3[14] ^ lfsr3[16];
+ lfsr3[1 ] <= lfsr3[0 ];
+ lfsr3[2 ] <= lfsr3[1 ];
+ lfsr3[3 ] <= lfsr3[2 ];
+ lfsr3[4 ] <= lfsr3[3 ];
+ lfsr3[5 ] <= lfsr3[4 ];
+ lfsr3[6 ] <= lfsr3[5 ];
+ lfsr3[7 ] <= lfsr3[6 ];
+ lfsr3[8 ] <= lfsr3[7 ];
+ lfsr3[9 ] <= lfsr3[8 ];
+ lfsr3[10] <= lfsr3[9 ];
+ lfsr3[11] <= lfsr3[10];
+ lfsr3[12] <= lfsr3[11];
+ lfsr3[13] <= lfsr3[12];
+ lfsr3[14] <= lfsr3[13];
+ lfsr3[15] <= lfsr3[14];
+ lfsr3[16] <= lfsr3[15];
+ end else begin
+ // hold state
+ lfsr0 <= lfsr0;
+ lfsr1 <= lfsr1;
+ lfsr2 <= lfsr2;
+ lfsr3 <= lfsr3;
+ end
+ end // else: !if( reset == 1 )
+ end // always @ (posedge clk or posedge reset)
+
+ assign comb_tap0[0] = lfsr0[3];
+ assign comb_tap0[1] = lfsr1[4];
+ assign comb_tap0[2] = lfsr2[5];
+ assign comb_tap0[3] = lfsr3[5];
+
+ assign comb_tap1[0] = lfsr0[7];
+ assign comb_tap1[1] = lfsr1[8];
+ assign comb_tap1[2] = lfsr2[9];
+ assign comb_tap1[3] = lfsr3[11];
+
+ assign comb_tap2[0] = lfsr0[12];
+ assign comb_tap2[1] = lfsr1[13];
+ assign comb_tap2[2] = lfsr2[15];
+ assign comb_tap2[3] = lfsr3[16];
+
+ wire [3:0] sh_dout;
+ shuffle_network sh0 ( .clk(clk), .reset(reset),
+ .din(comb_tap0[0] ^ comb_tap0[1] ^ comb_tap0[2] ^ comb_tap0[3]),
+ .sel(comb_tap1[0]),
+ .advance(advance),
+ .init_iv(init_iv),
+ .dout(sh_dout[0])
+ );
+
+ shuffle_network sh1 ( .clk(clk), .reset(reset),
+ .din(sh_dout[0]),
+ .sel(comb_tap1[1]),
+ .advance(advance),
+ .init_iv(init_iv),
+ .dout(sh_dout[1])
+ );
+
+ shuffle_network sh2 ( .clk(clk), .reset(reset),
+ .din(sh_dout[1]),
+ .sel(comb_tap1[2]),
+ .advance(advance),
+ .init_iv(init_iv),
+ .dout(sh_dout[2])
+ );
+
+ shuffle_network sh3 ( .clk(clk), .reset(reset),
+ .din(sh_dout[2]),
+ .sel(comb_tap1[3]),
+ .advance(advance),
+ .init_iv(init_iv),
+ .dout(sh_dout[3])
+ );
+
+ assign onebit = sh_dout[3] ^ comb_tap2[0] ^ comb_tap2[1] ^ comb_tap2[2] ^ comb_tap2[3];
+
+endmodule // hdcp_lfsr
+
diff --git a/hdcp/shuffle_network.v b/hdcp/shuffle_network.v
new file mode 100755
index 0000000..f0c5315
--- /dev/null
+++ b/hdcp/shuffle_network.v
@@ -0,0 +1,59 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2011, Andrew "bunnie" Huang
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+module shuffle_network (
+ input wire clk,
+ input wire reset,
+ input wire din,
+ input wire sel,
+ input wire advance,
+ input wire init_iv,
+ output wire dout
+ );
+
+ reg a, b;
+
+ always @(posedge clk or posedge reset) begin
+ if( reset == 1 ) begin
+ a <= 1'b0;
+ b <= 1'b1;
+ end else begin
+ if( init_iv ) begin
+ a <= 1'b0;
+ b <= 1'b1;
+ end else if( advance ) begin
+ a <= sel ? din : b;
+ b <= sel ? a : din;
+ end else begin
+ a <= a;
+ b <= b;
+ end
+ end // else: !if( reset == 1 )
+ end // always @ (posedge clk or posedge reset)
+
+ assign dout = sel ? b : a;
+
+endmodule // shuffle_network