/*
|
/*
|
Copyright 2012 Homer Hsing
|
* Copyright 2012, Homer Hsing <homer.hsing@gmail.com>
|
|
*
|
This file is part of Tiny Tate Bilinear Pairing Core.
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
Tiny Tate Bilinear Pairing Core is free software: you can redistribute it and/or modify
|
* You may obtain a copy of the License at
|
it under the terms of the GNU Lesser General Public License as published by
|
*
|
the Free Software Foundation, either version 3 of the License, or
|
* http://www.apache.org/licenses/LICENSE-2.0
|
(at your option) any later version.
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
Tiny Tate Bilinear Pairing Core is distributed in the hope that it will be useful,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* See the License for the specific language governing permissions and
|
GNU Lesser General Public License for more details.
|
* limitations under the License.
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with Tiny Tate Bilinear Pairing Core. If not, see http://www.gnu.org/licenses/lgpl.txt
|
|
*/
|
*/
|
|
|
`define M 593 // M is the degree of the irreducible polynomial
|
`define M 593 // M is the degree of the irreducible polynomial
|
`define WIDTH (2*`M-1) // width for a GF(3^M) element
|
`define WIDTH (2*`M-1) // width for a GF(3^M) element
|
`define WIDTH_D0 1187
|
`define WIDTH_D0 1187
|
|
|
/* PE: processing element */
|
/* PE: processing element */
|
module PE(clk, reset, ctrl, d0, d1, d2, out);
|
module PE(clk, reset, ctrl, d0, d1, d2, out);
|
input clk;
|
input clk;
|
input reset;
|
input reset;
|
input [10:0] ctrl;
|
input [10:0] ctrl;
|
input [`WIDTH_D0:0] d0;
|
input [`WIDTH_D0:0] d0;
|
input [`WIDTH:0] d1, d2;
|
input [`WIDTH:0] d1, d2;
|
output [`WIDTH:0] out;
|
output [`WIDTH:0] out;
|
|
|
reg [`WIDTH_D0:0] R0;
|
reg [`WIDTH_D0:0] R0;
|
reg [`WIDTH:0] R1, R2, R3;
|
reg [`WIDTH:0] R1, R2, R3;
|
wire [1:0] e0, e1, e2; /* part of R0 */
|
wire [1:0] e0, e1, e2; /* part of R0 */
|
wire [`WIDTH:0] ppg0, ppg1, ppg2, /* output of PPG */
|
wire [`WIDTH:0] ppg0, ppg1, ppg2, /* output of PPG */
|
mx0, mx1, mx2, mx3, mx4, mx5, mx6, /* output of MUX */
|
mx0, mx1, mx2, mx3, mx4, mx5, mx6, /* output of MUX */
|
ad0, ad1, ad2, /* output of GF(3^m) adder */
|
ad0, ad1, ad2, /* output of GF(3^m) adder */
|
cu0, cu1, cu2, /* output of cubic */
|
cu0, cu1, cu2, /* output of cubic */
|
mo0, mo1, mo2, /* output of mod_p */
|
mo0, mo1, mo2, /* output of mod_p */
|
t0, t1, t2;
|
t0, t1, t2;
|
wire c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10;
|
wire c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10;
|
|
|
assign {c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10} = ctrl;
|
assign {c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10} = ctrl;
|
assign mx0 = c0 ? d1 : ad2;
|
assign mx0 = c0 ? d1 : ad2;
|
assign mx1 = c2 ? d2 : ad2;
|
assign mx1 = c2 ? d2 : ad2;
|
always @ (posedge clk)
|
always @ (posedge clk)
|
if(reset) R1 <= 0;
|
if(reset) R1 <= 0;
|
else if (c1) R1 <= mx0;
|
else if (c1) R1 <= mx0;
|
always @ (posedge clk)
|
always @ (posedge clk)
|
if(reset) R2 <= 0;
|
if(reset) R2 <= 0;
|
else if (c3) R2 <= mx1;
|
else if (c3) R2 <= mx1;
|
always @ (posedge clk)
|
always @ (posedge clk)
|
if(reset) R0 <= 0;
|
if(reset) R0 <= 0;
|
else if (c4) R0 <= d0;
|
else if (c4) R0 <= d0;
|
else if (c5) R0 <= R0 << 6;
|
else if (c5) R0 <= R0 << 6;
|
assign {e2,e1,e0} = R0[`WIDTH_D0:(`WIDTH_D0-5)];
|
assign {e2,e1,e0} = R0[`WIDTH_D0:(`WIDTH_D0-5)];
|
PPG
|
PPG
|
ppg_0 (e0, R1, ppg0),
|
ppg_0 (e0, R1, ppg0),
|
ppg_1 (e1, R2, ppg1),
|
ppg_1 (e1, R2, ppg1),
|
ppg_2 (e2, R1, ppg2);
|
ppg_2 (e2, R1, ppg2);
|
v0 v0_ (ppg0, cu0);
|
v0 v0_ (ppg0, cu0);
|
v1 v1_ (ppg1, cu1);
|
v1 v1_ (ppg1, cu1);
|
v2 v2_ (ppg2, cu2);
|
v2 v2_ (ppg2, cu2);
|
assign mx2 = c6 ? ppg0 : cu0;
|
assign mx2 = c6 ? ppg0 : cu0;
|
assign mx3 = c6 ? ppg1 : cu1;
|
assign mx3 = c6 ? ppg1 : cu1;
|
assign mx4 = c6 ? mo1 : cu2;
|
assign mx4 = c6 ? mo1 : cu2;
|
assign mx5 = c7 ? mo2 : R3;
|
assign mx5 = c7 ? mo2 : R3;
|
mod_p
|
mod_p
|
mod_p_0 (mx3, mo0),
|
mod_p_0 (mx3, mo0),
|
mod_p_1 (ppg2, t0),
|
mod_p_1 (ppg2, t0),
|
mod_p_2 (t0, mo1),
|
mod_p_2 (t0, mo1),
|
mod_p_3 (R3, t1),
|
mod_p_3 (R3, t1),
|
mod_p_4 (t1, t2),
|
mod_p_4 (t1, t2),
|
mod_p_5 (t2, mo2);
|
mod_p_5 (t2, mo2);
|
assign mx6 = c9 ? mo0 : mx3;
|
assign mx6 = c9 ? mo0 : mx3;
|
f3m_add
|
f3m_add
|
f3m_add_0 (mx2, mx6, ad0),
|
f3m_add_0 (mx2, mx6, ad0),
|
f3m_add_1 (mx4, c8 ? mx5 : 0, ad1),
|
f3m_add_1 (mx4, c8 ? mx5 : 0, ad1),
|
f3m_add_2 (ad0, ad1, ad2);
|
f3m_add_2 (ad0, ad1, ad2);
|
always @ (posedge clk)
|
always @ (posedge clk)
|
if (reset) R3 <= 0;
|
if (reset) R3 <= 0;
|
else if (c10) R3 <= ad2;
|
else if (c10) R3 <= ad2;
|
else R3 <= 0; /* change */
|
else R3 <= 0; /* change */
|
assign out = R3;
|
assign out = R3;
|
endmodule
|
endmodule
|
|
|
// C = (x*B mod p(x))
|
// C = (x*B mod p(x))
|
module mod_p(B, C);
|
module mod_p(B, C);
|
input [`WIDTH:0] B;
|
input [`WIDTH:0] B;
|
output [`WIDTH:0] C;
|
output [`WIDTH:0] C;
|
wire [`WIDTH+2:0] A;
|
wire [`WIDTH+2:0] A;
|
assign A = {B[`WIDTH:0], 2'd0}; // A == B*x
|
assign A = {B[`WIDTH:0], 2'd0}; // A == B*x
|
wire [1:0] w0;
|
wire [1:0] w0;
|
f3_mult m0 (A[1187:1186], 2'd2, w0);
|
f3_mult m0 (A[1187:1186], 2'd2, w0);
|
f3_sub s0 (A[1:0], w0, C[1:0]);
|
f3_sub s0 (A[1:0], w0, C[1:0]);
|
assign C[223:2] = A[223:2];
|
assign C[223:2] = A[223:2];
|
wire [1:0] w112;
|
wire [1:0] w112;
|
f3_mult m112 (A[1187:1186], 2'd1, w112);
|
f3_mult m112 (A[1187:1186], 2'd1, w112);
|
f3_sub s112 (A[225:224], w112, C[225:224]);
|
f3_sub s112 (A[225:224], w112, C[225:224]);
|
assign C[1185:226] = A[1185:226];
|
assign C[1185:226] = A[1185:226];
|
endmodule
|
endmodule
|
|
|
// PPG: partial product generator, C == A*d in GF(3^m)
|
// PPG: partial product generator, C == A*d in GF(3^m)
|
module PPG(d, A, C);
|
module PPG(d, A, C);
|
input [1:0] d;
|
input [1:0] d;
|
input [`WIDTH:0] A;
|
input [`WIDTH:0] A;
|
output [`WIDTH:0] C;
|
output [`WIDTH:0] C;
|
genvar i;
|
genvar i;
|
generate
|
generate
|
for (i=0; i < `M; i=i+1)
|
for (i=0; i < `M; i=i+1)
|
begin: ppg0
|
begin: ppg0
|
f3_mult f3_mult_0 (d, A[2*i+1:2*i], C[2*i+1:2*i]);
|
f3_mult f3_mult_0 (d, A[2*i+1:2*i], C[2*i+1:2*i]);
|
end
|
end
|
endgenerate
|
endgenerate
|
endmodule
|
endmodule
|
|
|
// f3m_add: C = A + B, in field F_{3^M}
|
// f3m_add: C = A + B, in field F_{3^M}
|
module f3m_add(A, B, C);
|
module f3m_add(A, B, C);
|
input [`WIDTH : 0] A, B;
|
input [`WIDTH : 0] A, B;
|
output [`WIDTH : 0] C;
|
output [`WIDTH : 0] C;
|
genvar i;
|
genvar i;
|
generate
|
generate
|
for(i=0; i<`M; i=i+1) begin: aa
|
for(i=0; i<`M; i=i+1) begin: aa
|
f3_add aa(A[(2*i+1) : 2*i], B[(2*i+1) : 2*i], C[(2*i+1) : 2*i]);
|
f3_add aa(A[(2*i+1) : 2*i], B[(2*i+1) : 2*i], C[(2*i+1) : 2*i]);
|
end
|
end
|
endgenerate
|
endgenerate
|
endmodule
|
endmodule
|
|
|
// f3_add: C == A+B (mod 3)
|
// f3_add: C == A+B (mod 3)
|
module f3_add(A, B, C);
|
module f3_add(A, B, C);
|
input [1:0] A, B;
|
input [1:0] A, B;
|
output [1:0] C;
|
output [1:0] C;
|
wire a0, a1, b0, b1, c0, c1;
|
wire a0, a1, b0, b1, c0, c1;
|
assign {a1, a0} = A;
|
assign {a1, a0} = A;
|
assign {b1, b0} = B;
|
assign {b1, b0} = B;
|
assign C = {c1, c0};
|
assign C = {c1, c0};
|
assign c0 = ( a0 & ~a1 & ~b0 & ~b1) |
|
assign c0 = ( a0 & ~a1 & ~b0 & ~b1) |
|
(~a0 & ~a1 & b0 & ~b1) |
|
(~a0 & ~a1 & b0 & ~b1) |
|
(~a0 & a1 & ~b0 & b1) ;
|
(~a0 & a1 & ~b0 & b1) ;
|
assign c1 = (~a0 & a1 & ~b0 & ~b1) |
|
assign c1 = (~a0 & a1 & ~b0 & ~b1) |
|
( a0 & ~a1 & b0 & ~b1) |
|
( a0 & ~a1 & b0 & ~b1) |
|
(~a0 & ~a1 & ~b0 & b1) ;
|
(~a0 & ~a1 & ~b0 & b1) ;
|
endmodule
|
endmodule
|
|
|
// f3_sub: C == A-B (mod 3)
|
// f3_sub: C == A-B (mod 3)
|
module f3_sub(A, B, C);
|
module f3_sub(A, B, C);
|
input [1:0] A, B;
|
input [1:0] A, B;
|
output [1:0] C;
|
output [1:0] C;
|
f3_add a0(A, {B[0],B[1]}, C);
|
f3_add a0(A, {B[0],B[1]}, C);
|
endmodule
|
endmodule
|
|
|
// f3_mult: C = A*B (mod 3)
|
// f3_mult: C = A*B (mod 3)
|
module f3_mult(A, B, C);
|
module f3_mult(A, B, C);
|
input [1:0] A;
|
input [1:0] A;
|
input [1:0] B;
|
input [1:0] B;
|
output [1:0] C;
|
output [1:0] C;
|
wire a0, a1, b0, b1;
|
wire a0, a1, b0, b1;
|
assign {a1, a0} = A;
|
assign {a1, a0} = A;
|
assign {b1, b0} = B;
|
assign {b1, b0} = B;
|
assign C[0] = (~a1 & a0 & ~b1 & b0) | (a1 & ~a0 & b1 & ~b0);
|
assign C[0] = (~a1 & a0 & ~b1 & b0) | (a1 & ~a0 & b1 & ~b0);
|
assign C[1] = (~a1 & a0 & b1 & ~b0) | (a1 & ~a0 & ~b1 & b0);
|
assign C[1] = (~a1 & a0 & b1 & ~b0) | (a1 & ~a0 & ~b1 & b0);
|
endmodule
|
endmodule
|
|
|