mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-28 07:02:55 +08:00
588 lines
14 KiB
Verilog
588 lines
14 KiB
Verilog
// Copyright 2007 Altera Corporation. All rights reserved.
|
|
// Altera products are protected under numerous U.S. and foreign patents,
|
|
// maskwork rights, copyrights and other intellectual property laws.
|
|
//
|
|
// This reference design file, and your use thereof, is subject to and governed
|
|
// by the terms and conditions of the applicable Altera Reference Design
|
|
// License Agreement (either as signed by you or found at www.altera.com). By
|
|
// using this reference design file, you indicate your acceptance of such terms
|
|
// and conditions between you and Altera Corporation. In the event that you do
|
|
// not agree with such terms and conditions, you may not use the reference
|
|
// design file and please promptly destroy any copies you have made.
|
|
//
|
|
// This reference design file is being provided on an "as-is" basis and as an
|
|
// accommodation and therefore all warranties, representations or guarantees of
|
|
// any kind (whether express, implied or statutory) including, without
|
|
// limitation, warranties of merchantability, non-infringement, or fitness for
|
|
// a particular purpose, are specifically disclaimed. By making this reference
|
|
// design file available, Altera expressly does not recommend, suggest or
|
|
// require that this reference design file be used in combination with any
|
|
// other product not provided by Altera.
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// baeckler - 12-13-2006
|
|
// straight from FIPS 180
|
|
|
|
///////////////////////////////////////
|
|
|
|
module big_sigma_0_512 (x,result);
|
|
input [63:0] x;
|
|
output [63:0] result;
|
|
|
|
wire [63:0] ror28,ror34,ror39;
|
|
|
|
assign ror28 = {x[28-1:0],x[63:28]};
|
|
assign ror34 = {x[34-1:0],x[63:34]};
|
|
assign ror39 = {x[39-1:0],x[63:39]};
|
|
assign result = ror28 ^ ror34 ^ ror39;
|
|
|
|
endmodule
|
|
|
|
///////////////////////////////////////
|
|
|
|
module big_sigma_1_512 (x,result);
|
|
input [63:0] x;
|
|
output [63:0] result;
|
|
|
|
wire [63:0] ror14,ror18,ror41;
|
|
|
|
assign ror14 = {x[14-1:0],x[63:14]};
|
|
assign ror18 = {x[18-1:0],x[63:18]};
|
|
assign ror41 = {x[41-1:0],x[63:41]};
|
|
assign result = ror14 ^ ror18 ^ ror41;
|
|
|
|
endmodule
|
|
|
|
///////////////////////////////////////
|
|
|
|
module little_sigma_0_512 (x,result);
|
|
input [63:0] x;
|
|
output [63:0] result;
|
|
|
|
wire [63:0] ror1,ror8,shr7;
|
|
|
|
assign ror1 = {x[1-1:0],x[63:1]};
|
|
assign ror8 = {x[8-1:0],x[63:8]};
|
|
assign shr7 = {7'b0,x[63:7]};
|
|
assign result = ror1 ^ ror8 ^ shr7;
|
|
|
|
endmodule
|
|
|
|
///////////////////////////////////////
|
|
|
|
module little_sigma_1_512 (x,result);
|
|
input [63:0] x;
|
|
output [63:0] result;
|
|
|
|
wire [63:0] ror19,ror61,shr6;
|
|
|
|
assign ror19 = {x[19-1:0],x[63:19]};
|
|
assign ror61 = {x[61-1:0],x[63:61]};
|
|
assign shr6 = {6'b0,x[63:6]};
|
|
assign result = ror19 ^ ror61 ^ shr6;
|
|
|
|
endmodule
|
|
|
|
///////////////////////////////////////
|
|
|
|
module fn_ch (x,y,z,result);
|
|
input [63:0] x,y,z;
|
|
output [63:0] result;
|
|
assign result = (x & y) ^ (~x & z);
|
|
endmodule
|
|
|
|
///////////////////////////////////////
|
|
|
|
module fn_maj (x,y,z,result);
|
|
input [63:0] x,y,z;
|
|
output [63:0] result;
|
|
assign result = (x & y) ^ (x & z) ^ (y & z);
|
|
endmodule
|
|
|
|
///////////////////////////////////////
|
|
|
|
// this costs about 192 luts, depth 2 in raw SII cells
|
|
module k_table (idx,k);
|
|
input [6:0] idx;
|
|
output [63:0] k;
|
|
reg [63:0] k;
|
|
|
|
always @(*) begin
|
|
case (idx)
|
|
0 : k=64'h428a2f98d728ae22 ;
|
|
1 : k=64'h7137449123ef65cd ;
|
|
2 : k=64'hb5c0fbcfec4d3b2f ;
|
|
3 : k=64'he9b5dba58189dbbc ;
|
|
4 : k=64'h3956c25bf348b538 ;
|
|
5 : k=64'h59f111f1b605d019 ;
|
|
6 : k=64'h923f82a4af194f9b ;
|
|
7 : k=64'hab1c5ed5da6d8118 ;
|
|
8 : k=64'hd807aa98a3030242 ;
|
|
9 : k=64'h12835b0145706fbe ;
|
|
10 : k=64'h243185be4ee4b28c ;
|
|
11 : k=64'h550c7dc3d5ffb4e2 ;
|
|
12 : k=64'h72be5d74f27b896f ;
|
|
13 : k=64'h80deb1fe3b1696b1 ;
|
|
14 : k=64'h9bdc06a725c71235 ;
|
|
15 : k=64'hc19bf174cf692694 ;
|
|
16 : k=64'he49b69c19ef14ad2 ;
|
|
17 : k=64'hefbe4786384f25e3 ;
|
|
18 : k=64'h0fc19dc68b8cd5b5 ;
|
|
19 : k=64'h240ca1cc77ac9c65 ;
|
|
20 : k=64'h2de92c6f592b0275 ;
|
|
21 : k=64'h4a7484aa6ea6e483 ;
|
|
22 : k=64'h5cb0a9dcbd41fbd4 ;
|
|
23 : k=64'h76f988da831153b5 ;
|
|
24 : k=64'h983e5152ee66dfab ;
|
|
25 : k=64'ha831c66d2db43210 ;
|
|
26 : k=64'hb00327c898fb213f ;
|
|
27 : k=64'hbf597fc7beef0ee4 ;
|
|
28 : k=64'hc6e00bf33da88fc2 ;
|
|
29 : k=64'hd5a79147930aa725 ;
|
|
30 : k=64'h06ca6351e003826f ;
|
|
31 : k=64'h142929670a0e6e70 ;
|
|
32 : k=64'h27b70a8546d22ffc ;
|
|
33 : k=64'h2e1b21385c26c926 ;
|
|
34 : k=64'h4d2c6dfc5ac42aed ;
|
|
35 : k=64'h53380d139d95b3df ;
|
|
36 : k=64'h650a73548baf63de ;
|
|
37 : k=64'h766a0abb3c77b2a8 ;
|
|
38 : k=64'h81c2c92e47edaee6 ;
|
|
39 : k=64'h92722c851482353b ;
|
|
40 : k=64'ha2bfe8a14cf10364 ;
|
|
41 : k=64'ha81a664bbc423001 ;
|
|
42 : k=64'hc24b8b70d0f89791 ;
|
|
43 : k=64'hc76c51a30654be30 ;
|
|
44 : k=64'hd192e819d6ef5218 ;
|
|
45 : k=64'hd69906245565a910 ;
|
|
46 : k=64'hf40e35855771202a ;
|
|
47 : k=64'h106aa07032bbd1b8 ;
|
|
48 : k=64'h19a4c116b8d2d0c8 ;
|
|
49 : k=64'h1e376c085141ab53 ;
|
|
50 : k=64'h2748774cdf8eeb99 ;
|
|
51 : k=64'h34b0bcb5e19b48a8 ;
|
|
52 : k=64'h391c0cb3c5c95a63 ;
|
|
53 : k=64'h4ed8aa4ae3418acb ;
|
|
54 : k=64'h5b9cca4f7763e373 ;
|
|
55 : k=64'h682e6ff3d6b2b8a3 ;
|
|
56 : k=64'h748f82ee5defb2fc ;
|
|
57 : k=64'h78a5636f43172f60 ;
|
|
58 : k=64'h84c87814a1f0ab72 ;
|
|
59 : k=64'h8cc702081a6439ec ;
|
|
60 : k=64'h90befffa23631e28 ;
|
|
61 : k=64'ha4506cebde82bde9 ;
|
|
62 : k=64'hbef9a3f7b2c67915 ;
|
|
63 : k=64'hc67178f2e372532b ;
|
|
64 : k=64'hca273eceea26619c ;
|
|
65 : k=64'hd186b8c721c0c207 ;
|
|
66 : k=64'heada7dd6cde0eb1e ;
|
|
67 : k=64'hf57d4f7fee6ed178 ;
|
|
68 : k=64'h06f067aa72176fba ;
|
|
69 : k=64'h0a637dc5a2c898a6 ;
|
|
70 : k=64'h113f9804bef90dae ;
|
|
71 : k=64'h1b710b35131c471b ;
|
|
72 : k=64'h28db77f523047d84 ;
|
|
73 : k=64'h32caab7b40c72493 ;
|
|
74 : k=64'h3c9ebe0a15c9bebc ;
|
|
75 : k=64'h431d67c49c100d4c ;
|
|
76 : k=64'h4cc5d4becb3e42b6 ;
|
|
77 : k=64'h597f299cfc657e2a ;
|
|
78 : k=64'h5fcb6fab3ad6faec ;
|
|
79 : k=64'h6c44198c4a475817 ;
|
|
default : k = 64'h0;
|
|
endcase
|
|
end
|
|
endmodule
|
|
|
|
///////////////////////////////////////
|
|
|
|
module h_register (clk,reset,evolve,in,out,out_comb);
|
|
|
|
parameter HASH_SIZE = 384; // allowable 384,512
|
|
|
|
input [8*64-1:0] in;
|
|
output [8*64-1:0] out;
|
|
output [8*64-1:0] out_comb;
|
|
input clk,reset,evolve;
|
|
|
|
generate
|
|
initial begin
|
|
if (HASH_SIZE !== 384 && HASH_SIZE !== 512)
|
|
begin
|
|
$display ("Unsupported size %d",HASH_SIZE);
|
|
$stop();
|
|
end
|
|
end
|
|
endgenerate
|
|
|
|
genvar i;
|
|
reg [8*64-1:0] h_reg;
|
|
reg [8*64-1:0] h_comb;
|
|
|
|
assign out = h_reg;
|
|
assign out_comb = h_comb;
|
|
|
|
wire [511:0] init_val;
|
|
generate
|
|
if (HASH_SIZE == 384)
|
|
assign init_val = {
|
|
64'h47b5481dbefa4fa4,
|
|
64'hdb0c2e0d64f98fa7,
|
|
64'h8eb44a8768581511,
|
|
64'h67332667ffc00b31,
|
|
64'h152fecd8f70e5939,
|
|
64'h9159015a3070dd17,
|
|
64'h629a292a367cd507,
|
|
64'hcbbb9d5dc1059ed8};
|
|
else
|
|
assign init_val = {
|
|
64'h5be0cd19137e2179,
|
|
64'h1f83d9abfb41bd6b,
|
|
64'h9b05688c2b3e6c1f,
|
|
64'h510e527fade682d1,
|
|
64'ha54ff53a5f1d36f1,
|
|
64'h3c6ef372fe94f82b,
|
|
64'hbb67ae8584caa73b,
|
|
64'h6a09e667f3bcc908};
|
|
endgenerate
|
|
|
|
// order is h7 (MS end) .. h0 (LS end)
|
|
|
|
generate
|
|
for (i=0; i<8; i=i+1)
|
|
begin : hrlp
|
|
always @(*) begin
|
|
if (reset) begin
|
|
h_comb [64*i+63:64*i] = init_val[64*i+63:64*i];
|
|
end
|
|
else begin
|
|
h_comb [64*i+63:64*i] = h_reg[64*i+63:64*i] + in[64*i+63:64*i];
|
|
end
|
|
end
|
|
end
|
|
endgenerate
|
|
|
|
always @(posedge clk) begin
|
|
if (reset | evolve) h_reg <= h_comb;
|
|
end
|
|
|
|
endmodule
|
|
|
|
///////////////////////////////////////
|
|
|
|
module msg_schedule_reg (
|
|
clk,new_msg,
|
|
word_ack,m_in,
|
|
next_w,w_out,
|
|
msg_word_valid,enable_out
|
|
);
|
|
|
|
input clk,new_msg,next_w;
|
|
input [63:0] m_in;
|
|
input msg_word_valid;
|
|
output [63:0] w_out;
|
|
output word_ack;
|
|
output enable_out;
|
|
|
|
reg [63:0] w_out;
|
|
reg [63:0] w_tm1,w_tm2,w_tm15;
|
|
wire [63:0] w_tm6,w_tm14;
|
|
|
|
reg cntr_max;
|
|
reg [6:0] cntr;
|
|
|
|
wire enable_out;
|
|
|
|
// I want a message word.
|
|
wire internal_ack = (next_w & (cntr <= 15));
|
|
|
|
// If I want a msg word, and msg_word_valid is asserted
|
|
// then we need to stall the rest of the system.
|
|
assign enable_out = !internal_ack | msg_word_valid;
|
|
assign word_ack = internal_ack & msg_word_valid;
|
|
|
|
///////////////////
|
|
// Hybrid RAM / Reg shift regiter - 64bit x 16
|
|
always @(posedge clk) begin
|
|
if (next_w & enable_out) begin
|
|
w_tm1 <= w_out;
|
|
w_tm2 <= w_tm1;
|
|
w_tm15 <= w_tm14;
|
|
end
|
|
end
|
|
|
|
delay_reg dr0 (
|
|
.clock(clk),
|
|
.enable(next_w & enable_out),
|
|
.data_in(w_tm2),
|
|
.data_out(w_tm6)
|
|
);
|
|
defparam dr0 .DEPTH = 4;
|
|
defparam dr0 .WIDTH = 64;
|
|
|
|
delay_reg dr1 (
|
|
.clock(clk),
|
|
.enable(next_w & enable_out),
|
|
.data_in(w_tm6),
|
|
.data_out(w_tm14)
|
|
);
|
|
defparam dr1 .DEPTH = 8;
|
|
defparam dr1 .WIDTH = 64;
|
|
|
|
/////////////////
|
|
//
|
|
always @(posedge clk) begin
|
|
if (new_msg) begin
|
|
cntr <= 7'b0;
|
|
cntr_max <= 1'b0;
|
|
end
|
|
else if (enable_out) begin
|
|
cntr_max <= (cntr == 7'd79); // count should be 0 to 80 continuous
|
|
if (cntr_max) cntr <= 7'b0;
|
|
else cntr <= cntr + 1'b1;
|
|
end
|
|
end
|
|
|
|
/////////////////
|
|
// computation on the taps
|
|
// these are shifted a bit from the spec tap #'s due
|
|
// to latency
|
|
|
|
wire [63:0] w_val,w_valx,w_valy;
|
|
little_sigma_1_512 lsx (.x(w_tm1),.result(w_valx));
|
|
little_sigma_0_512 lsy (.x(w_tm14),.result(w_valy));
|
|
|
|
always @(posedge clk) begin
|
|
if (next_w & enable_out) begin
|
|
if (cntr_max || cntr < 16) w_out <= m_in;
|
|
else w_out <= w_valx + w_valy + w_tm6 + w_tm15;
|
|
end
|
|
end
|
|
|
|
endmodule
|
|
|
|
|
|
///////////////////////////////////////
|
|
|
|
// bit order is {h,g,f,e,d,c,b,a};
|
|
|
|
module ab_register (clk,load,evolve,in,out,round_k,round_w);
|
|
|
|
input [8*64-1:0] in;
|
|
output [8*64-1:0] out;
|
|
input clk,load,evolve;
|
|
input [63:0] round_k,round_w;
|
|
|
|
wire [63:0] t1, t2;
|
|
reg [63:0] a,b,c,d,e,f,g,h;
|
|
|
|
assign out = {h,g,f,e,d,c,b,a};
|
|
|
|
// knock out T1 pieces
|
|
wire [63:0] t1_ch,t1_sig,t1_round,t1_fns;
|
|
big_sigma_1_512 t1sig (.x(e),.result(t1_sig));
|
|
fn_ch t1ch (.x(e),.y(f),.z(g),.result(t1_ch));
|
|
// t1 = h + (t1_sig + t1_ch) + (round_k + round_w);
|
|
assign t1_round = round_k + round_w;
|
|
assign t1_fns = t1_sig + t1_ch; // this part is critical
|
|
|
|
// knock out T2
|
|
wire [63:0] t2_sig,t2_maj;
|
|
big_sigma_0_512 t2sig (.x(a),.result(t2_sig));
|
|
fn_maj t2maj (.x(a),.y(b),.z(c),.result(t2_maj));
|
|
assign t2 = t2_sig + t2_maj;
|
|
|
|
always @(posedge clk) begin
|
|
if (load) begin
|
|
{h,g,f,e,d,c,b,a} <= in;
|
|
end
|
|
else if (evolve) begin
|
|
h <= g;
|
|
g <= f;
|
|
f <= e;
|
|
e <= t1_fns + ((d + h) + t1_round); // get the critical part forward
|
|
d <= c;
|
|
c <= b;
|
|
b <= a;
|
|
a <= (t1_round + t1_fns) + (h + t2);
|
|
end
|
|
end
|
|
endmodule
|
|
|
|
///////////////////////////////////////
|
|
|
|
// new_msg is asserted to start running a fresh message
|
|
// complete indicates no more message blocks available
|
|
// msg_word must be advanced in immediate response to ack
|
|
|
|
// hash_out is { h7,6,5,4,3,2,1,h0 }
|
|
|
|
module sha512 (clk,reset,
|
|
new_msg,msg_complete,
|
|
msg_word,msg_word_ack,msg_word_valid,
|
|
hash_out,hash_ready);
|
|
|
|
parameter HASH_SIZE = 512;
|
|
// allowable sizes 384 and 512
|
|
// this changes the value used to initialize the hash register
|
|
// discard output bits [511:384] when using SHA 384 mode.
|
|
|
|
input clk,reset,new_msg,msg_complete,msg_word_valid;
|
|
input [63:0] msg_word;
|
|
output [511:0] hash_out;
|
|
output msg_word_ack,hash_ready;
|
|
|
|
reg[6:0] round, round_plus_one /* synthesis preserve */;
|
|
reg last_round;
|
|
|
|
reg last_new_msg;
|
|
always @(posedge clk) begin
|
|
if (reset) last_new_msg = 1'b0;
|
|
else last_new_msg <= new_msg;
|
|
end
|
|
|
|
wire [63:0] round_w, next_round_k;
|
|
reg [63:0] round_k /* synthesis preserve */;
|
|
wire [8*64-1:0] h_reg_comb, ab_reg;
|
|
|
|
reg h_reset,evolve_h;
|
|
reg clear_round,next_round;
|
|
reg load_ab_reg,evolve_ab;
|
|
reg next_w;
|
|
reg hash_ready;
|
|
|
|
// this enables evolution - generated by message availability
|
|
wire enable;
|
|
|
|
// generate K series
|
|
k_table kt (.idx(round_plus_one),.k(next_round_k));
|
|
always @(posedge clk) begin
|
|
if (enable) round_k <= next_round_k;
|
|
end
|
|
|
|
// generate W series
|
|
msg_schedule_reg sched (
|
|
.clk(clk),
|
|
.new_msg(new_msg),
|
|
.word_ack(msg_word_ack),
|
|
.m_in(msg_word),
|
|
.next_w(next_w),
|
|
.w_out(round_w),
|
|
.msg_word_valid(msg_word_valid),
|
|
.enable_out(enable)
|
|
);
|
|
|
|
// the hash register
|
|
h_register hreg (
|
|
.clk(clk),
|
|
.reset(h_reset),
|
|
.evolve(evolve_h & enable),
|
|
.in(ab_reg),
|
|
.out(hash_out),
|
|
.out_comb(h_reg_comb)
|
|
);
|
|
defparam hreg .HASH_SIZE = HASH_SIZE;
|
|
|
|
// the working abcdefgh register
|
|
ab_register abreg (
|
|
.clk(clk),
|
|
.load(load_ab_reg & enable),
|
|
.evolve(evolve_ab & enable),
|
|
.in(h_reg_comb),
|
|
.out(ab_reg),
|
|
.round_k(round_k),
|
|
.round_w(round_w)
|
|
);
|
|
|
|
// leading round counter for K computation
|
|
always @(posedge clk) begin
|
|
if (enable) begin
|
|
if (reset | new_msg) round_plus_one <= 7'b0;
|
|
else if (last_round) round_plus_one <= 7'b0;
|
|
else round_plus_one <= round_plus_one + 1'b1;
|
|
end
|
|
end
|
|
|
|
// round counter sweeps 0..80 inclusive (80 is evolve time)
|
|
always @(posedge clk) begin
|
|
if (enable) begin
|
|
if (clear_round) begin
|
|
round <= 0;
|
|
last_round <= 0;
|
|
end
|
|
else if (next_round) begin
|
|
round <= round + 1'b1;
|
|
last_round <= (round == 7'd78);
|
|
end
|
|
end
|
|
end
|
|
|
|
// little state machine control
|
|
reg [1:0] state,next_state;
|
|
parameter IDLE = 0, EVOLVE_H = 1, EVOLVE_AB = 2;
|
|
|
|
always @(*) begin
|
|
|
|
// defaults
|
|
h_reset = 1'b0;
|
|
evolve_h = 1'b0;
|
|
clear_round = 1'b0;
|
|
load_ab_reg = 1'b0;
|
|
next_round = 1'b0;
|
|
evolve_ab = 1'b0;
|
|
next_w = 1'b0;
|
|
next_state = state;
|
|
hash_ready = 1'b0;
|
|
|
|
case (state)
|
|
IDLE : begin
|
|
if (new_msg) next_state = EVOLVE_H;
|
|
hash_ready = 1'b1;
|
|
end
|
|
EVOLVE_H : begin // 1 tick
|
|
if (last_new_msg) begin
|
|
h_reset = 1'b1;
|
|
end else begin
|
|
evolve_h = 1'b1;
|
|
end
|
|
clear_round = 1'b1;
|
|
load_ab_reg = 1'b1;
|
|
if (msg_complete) next_state = IDLE;
|
|
else begin
|
|
next_w = 1'b1;
|
|
next_state = EVOLVE_AB;
|
|
end
|
|
end
|
|
EVOLVE_AB : begin // 80 ticks
|
|
next_round = 1'b1;
|
|
evolve_ab = 1'b1;
|
|
if (last_round) next_state = EVOLVE_H;
|
|
else next_w = 1'b1;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (reset) state = IDLE;
|
|
else if (enable) state <= next_state;
|
|
end
|
|
|
|
|
|
// synthesis translate_off
|
|
|
|
// Mimic FIPS example D2 printout
|
|
wire [63:0] ta,tb,tc,td,te,tf,tg,th;
|
|
assign {th,tg,tf,te,td,tc,tb,ta} = ab_reg;
|
|
always @(posedge clk) begin
|
|
#10 if (round >= 1) begin
|
|
$display ("t=%d : %x - %x - %x - %x",
|
|
round - 1, ta,tb,tc,td);
|
|
$display ("t=%d : %x - %x - %x - %x",
|
|
round - 1, te,tf,tg,th);
|
|
end
|
|
end
|
|
|
|
// synthesis translate_on
|
|
|
|
endmodule
|