diff options
-rw-r--r-- | README.md | 34 | ||||
-rw-r--r-- | src/rtl/sha1_core.v | 10 | ||||
-rw-r--r-- | src/rtl/sha1_w_mem.v | 218 | ||||
-rw-r--r-- | src/tb/tb_sha1_w_mem.v | 92 |
4 files changed, 216 insertions, 138 deletions
@@ -11,21 +11,43 @@ https://github.com/secworks/sha1 ## Implementation details ## -### Altera Cyclone IV GX ### -Implementation using Altera Quartus-II 13.1 with a EP4CGX22CF19C6 device -as target. -* 10718 LEs -* 3575 Regs -* 103 MHz +### Altera Cyclone FPGAs ### +Implementation results using Altera Quartus-II 13.1. + +***Altera Cyclone IV E*** +- EP4CE6F17C6 +- 2913 LEs +- 1527 regs +- 107 MHz + +***Altera Cyclone IV GX*** +- EP4CGX22CF19C6 +- 2814 LEs +- 1527 regs +- 105 MHz + +***Altera Cyclone V*** +- 5CGXFC7C7F23C8 +- 1124 ALMs +- 1527 regs +- 104 MHz ## TODO ## * Extensive functional verification in real HW. * Add Wishbone interface. +* Add results for Xilinx and possibly some other FPGA device. * Documentation ## Status ## +***(2014-02-23):*** + +New version of the W memory module that quite drastically improves +resource utilization. And a bit better performance too. Also added some +new results for other Altera devices. + + ***(2014-02-21):*** Moved the core to Cryptech. diff --git a/src/rtl/sha1_core.v b/src/rtl/sha1_core.v index be83b52..aae578c 100644 --- a/src/rtl/sha1_core.v +++ b/src/rtl/sha1_core.v @@ -120,6 +120,7 @@ module sha1_core( reg first_block; reg ready_flag; reg w_init; + reg w_next; wire w_ready; wire [31 : 0] w; @@ -131,10 +132,11 @@ module sha1_core( .clk(clk), .reset_n(reset_n), - .init(w_init), .block(block), + + .init(w_init), + .next(w_next), - .addr(round_ctr_reg), .w(w) ); @@ -365,6 +367,7 @@ module sha1_core( first_block = 0; ready_flag = 0; w_init = 0; + w_next = 0; round_ctr_inc = 0; round_ctr_rst = 0; digest_valid_new = 0; @@ -407,7 +410,8 @@ module sha1_core( begin state_update = 1; round_ctr_inc = 1; - + w_next = 1; + if (round_ctr_reg == SHA1_ROUNDS) begin sha1_ctrl_new = CTRL_DONE; diff --git a/src/rtl/sha1_w_mem.v b/src/rtl/sha1_w_mem.v index 9aaa403..7b30683 100644 --- a/src/rtl/sha1_w_mem.v +++ b/src/rtl/sha1_w_mem.v @@ -2,8 +2,9 @@ // // sha1_w_mem_reg.v // ----------------- -// The SHA-1 W memory. This memory includes functionality to -// expand the block into 80 words. +// The SHA-1 W memory. This memory is based around a sliding window +// of 16 32-bit registers that are used to create the w words +// needed by the core during the 80 rounds. // // // Author: Joachim Strombergson @@ -40,10 +41,11 @@ module sha1_w_mem( input wire clk, input wire reset_n, - input wire init, input wire [511 : 0] block, - input wire [6 : 0] addr, + input wire init, + input wire next, + output wire [31 : 0] w ); @@ -60,15 +62,30 @@ module sha1_w_mem( //---------------------------------------------------------------- // Registers including update variables and write enable. //---------------------------------------------------------------- - reg [31 : 0] w_mem [0 : 79]; - reg [31 : 0] w_mem_new; + reg [31 : 0] w_mem [0 : 15]; + reg [31 : 0] w_mem00_new; + reg [31 : 0] w_mem01_new; + reg [31 : 0] w_mem02_new; + reg [31 : 0] w_mem03_new; + reg [31 : 0] w_mem04_new; + reg [31 : 0] w_mem05_new; + reg [31 : 0] w_mem06_new; + reg [31 : 0] w_mem07_new; + reg [31 : 0] w_mem08_new; + reg [31 : 0] w_mem09_new; + reg [31 : 0] w_mem10_new; + reg [31 : 0] w_mem11_new; + reg [31 : 0] w_mem12_new; + reg [31 : 0] w_mem13_new; + reg [31 : 0] w_mem14_new; + reg [31 : 0] w_mem15_new; reg w_mem_we; reg [6 : 0] w_ctr_reg; reg [6 : 0] w_ctr_new; reg w_ctr_we; reg w_ctr_inc; - reg w_ctr_set; + reg w_ctr_rst; reg sha1_w_mem_ctrl_reg; reg sha1_w_mem_ctrl_new; @@ -80,14 +97,13 @@ module sha1_w_mem( //---------------------------------------------------------------- reg [31 : 0] w_tmp; reg [31 : 0] w_new; - reg [6 : 0] w_addr; - reg w_update; + reg mem_update; //---------------------------------------------------------------- // Concurrent connectivity for ports etc. //---------------------------------------------------------------- - assign w = w_tmp; + assign w = w_tmp; //---------------------------------------------------------------- @@ -101,34 +117,45 @@ module sha1_w_mem( begin : reg_update if (!reset_n) begin + w_mem[00] <= 32'h00000000; + w_mem[01] <= 32'h00000000; + w_mem[02] <= 32'h00000000; + w_mem[03] <= 32'h00000000; + w_mem[04] <= 32'h00000000; + w_mem[05] <= 32'h00000000; + w_mem[06] <= 32'h00000000; + w_mem[07] <= 32'h00000000; + w_mem[08] <= 32'h00000000; + w_mem[09] <= 32'h00000000; + w_mem[10] <= 32'h00000000; + w_mem[11] <= 32'h00000000; + w_mem[12] <= 32'h00000000; + w_mem[13] <= 32'h00000000; + w_mem[14] <= 32'h00000000; + w_mem[15] <= 32'h00000000; w_ctr_reg <= 7'b0000000; sha1_w_mem_ctrl_reg <= CTRL_IDLE; end else begin - if (init) - begin - w_mem[00] <= block[511 : 480]; - w_mem[01] <= block[479 : 448]; - w_mem[02] <= block[447 : 416]; - w_mem[03] <= block[415 : 384]; - w_mem[04] <= block[383 : 352]; - w_mem[05] <= block[351 : 320]; - w_mem[06] <= block[319 : 288]; - w_mem[07] <= block[287 : 256]; - w_mem[08] <= block[255 : 224]; - w_mem[09] <= block[223 : 192]; - w_mem[10] <= block[191 : 160]; - w_mem[11] <= block[159 : 128]; - w_mem[12] <= block[127 : 96]; - w_mem[13] <= block[95 : 64]; - w_mem[14] <= block[63 : 32]; - w_mem[15] <= block[31 : 0]; - end - if (w_mem_we) begin - w_mem[w_addr] <= w_mem_new; + w_mem[00] <= w_mem00_new; + w_mem[01] <= w_mem01_new; + w_mem[02] <= w_mem02_new; + w_mem[03] <= w_mem03_new; + w_mem[04] <= w_mem04_new; + w_mem[05] <= w_mem05_new; + w_mem[06] <= w_mem06_new; + w_mem[07] <= w_mem07_new; + w_mem[08] <= w_mem08_new; + w_mem[09] <= w_mem09_new; + w_mem[10] <= w_mem10_new; + w_mem[11] <= w_mem11_new; + w_mem[12] <= w_mem12_new; + w_mem[13] <= w_mem13_new; + w_mem[14] <= w_mem14_new; + w_mem[15] <= w_mem15_new; end if (w_ctr_we) @@ -146,40 +173,105 @@ module sha1_w_mem( //---------------------------------------------------------------- - // external_addr_mux + // select_w // - // Mux for the external read operation. This is where we exract - // the W variable. + // W word selection logic. Returns either directly from the + // memory or the next w value calculated. //---------------------------------------------------------------- always @* - begin : external_addr_mux - w_tmp = w_mem[addr]; - end // external_addr_mux - + begin : w_schedule + if (w_ctr_reg < 16) + begin + w_tmp = w_mem[w_ctr_reg[3 : 0]]; + end + else + begin + w_tmp = w_new; + end + end // w_schedule + //---------------------------------------------------------------- - // w_schedule + // w_mem_update_logic // - // W word expansion logic. + // Update logic for the W memory. This is where the scheduling + // based on a sliding window is implemented. //---------------------------------------------------------------- always @* - begin : w_schedule - reg [31 : 0] w_new_tmp; + begin : w_mem_update_logic + reg [31 : 0] w_0; + reg [31 : 0] w_2; + reg [31 : 0] w_8; + reg [31 : 0] w_13; + reg [31 : 0] w_16; + + w_mem00_new = 32'h00000000; + w_mem01_new = 32'h00000000; + w_mem02_new = 32'h00000000; + w_mem03_new = 32'h00000000; + w_mem04_new = 32'h00000000; + w_mem05_new = 32'h00000000; + w_mem06_new = 32'h00000000; + w_mem07_new = 32'h00000000; + w_mem08_new = 32'h00000000; + w_mem09_new = 32'h00000000; + w_mem10_new = 32'h00000000; + w_mem11_new = 32'h00000000; + w_mem12_new = 32'h00000000; + w_mem13_new = 32'h00000000; + w_mem14_new = 32'h00000000; + w_mem15_new = 32'h00000000; + w_mem_we = 0; + + w_0 = w_mem[0]; + w_2 = w_mem[2]; + w_8 = w_mem[8]; + w_13 = w_mem[13]; + w_16 = w_13 ^ w_8 ^ w_2 ^ w_0; + w_new = {w_16[30 : 0], w_16[31]}; - w_mem_we = 0; - w_new_tmp = 32'h00000000; - w_mem_new = 32'h00000000; - w_addr = 0; + if (init) + begin + w_mem00_new = block[511 : 480]; + w_mem01_new = block[479 : 448]; + w_mem02_new = block[447 : 416]; + w_mem03_new = block[415 : 384]; + w_mem04_new = block[383 : 352]; + w_mem05_new = block[351 : 320]; + w_mem06_new = block[319 : 288]; + w_mem07_new = block[287 : 256]; + w_mem08_new = block[255 : 224]; + w_mem09_new = block[223 : 192]; + w_mem10_new = block[191 : 160]; + w_mem11_new = block[159 : 128]; + w_mem12_new = block[127 : 96]; + w_mem13_new = block[95 : 64]; + w_mem14_new = block[63 : 32]; + w_mem15_new = block[31 : 0]; + w_mem_we = 1; + end - if (w_update) + else if (w_ctr_reg > 15) begin - w_new_tmp = w_mem[(w_ctr_reg - 3)] ^ w_mem[(w_ctr_reg - 8)] ^ - w_mem[(w_ctr_reg - 14)] ^ w_mem[(w_ctr_reg - 16)]; - w_mem_new = {w_new_tmp[30 : 0], w_new_tmp[31]}; - w_addr = w_ctr_reg; - w_mem_we = 1; + w_mem00_new = w_mem[01]; + w_mem01_new = w_mem[02]; + w_mem02_new = w_mem[03]; + w_mem03_new = w_mem[04]; + w_mem04_new = w_mem[05]; + w_mem05_new = w_mem[06]; + w_mem06_new = w_mem[07]; + w_mem07_new = w_mem[08]; + w_mem08_new = w_mem[09]; + w_mem09_new = w_mem[10]; + w_mem10_new = w_mem[11]; + w_mem11_new = w_mem[12]; + w_mem12_new = w_mem[13]; + w_mem13_new = w_mem[14]; + w_mem14_new = w_mem[15]; + w_mem15_new = w_new; + w_mem_we = 1; end - end // w_schedule + end // w_mem_update_logic //---------------------------------------------------------------- @@ -193,9 +285,9 @@ module sha1_w_mem( w_ctr_new = 0; w_ctr_we = 0; - if (w_ctr_set) + if (w_ctr_rst) begin - w_ctr_new = 6'h10; + w_ctr_new = 6'h00; w_ctr_we = 1; end @@ -214,10 +306,8 @@ module sha1_w_mem( //---------------------------------------------------------------- always @* begin : sha1_w_mem_fsm - w_ctr_set = 0; - w_ctr_inc = 0; - w_update = 0; - + w_ctr_rst = 0; + w_ctr_inc = 0; sha1_w_mem_ctrl_new = CTRL_IDLE; sha1_w_mem_ctrl_we = 0; @@ -226,7 +316,7 @@ module sha1_w_mem( begin if (init) begin - w_ctr_set = 1; + w_ctr_rst = 1; sha1_w_mem_ctrl_new = CTRL_UPDATE; sha1_w_mem_ctrl_we = 1; end @@ -234,9 +324,11 @@ module sha1_w_mem( CTRL_UPDATE: begin - w_update = 1; - w_ctr_inc = 1; - + if (next) + begin + w_ctr_inc = 1; + end + if (w_ctr_reg == SHA1_ROUNDS) begin sha1_w_mem_ctrl_new = CTRL_IDLE; diff --git a/src/tb/tb_sha1_w_mem.v b/src/tb/tb_sha1_w_mem.v index 233e409..9ad16da 100644 --- a/src/tb/tb_sha1_w_mem.v +++ b/src/tb/tb_sha1_w_mem.v @@ -3,7 +3,6 @@ // Tb_sha1_w_mem.v // --------------- // Testbench for the SHA-1 W memory module. -// This testbench is currently not self testing. // // // Author: Joachim Strombergson @@ -64,8 +63,8 @@ module tb_sha1_w_mem(); reg tb_clk; reg tb_reset_n; reg tb_init; + reg tb_next; reg [511 : 0] tb_block; - reg [6 : 0] tb_addr; wire [31 : 0] tb_w; reg [63 : 0] cycle_ctr; @@ -80,10 +79,11 @@ module tb_sha1_w_mem(); .clk(tb_clk), .reset_n(tb_reset_n), - .init(tb_init), .block(tb_block), + + .init(tb_init), + .next(tb_next), - .addr(tb_addr), .w(tb_w) ); @@ -113,13 +113,10 @@ module tb_sha1_w_mem(); begin $display("cycle = %016x:", cycle_ctr); end - + if (DEBUG) begin - $display("addr: 0x%02x:", dut.addr); - $display("addr4: 0x%02x:", dut.addr[3 : 0]); - $display("w_mem_new: 0x%08x:", dut.w_mem_new); - $display("w_mem_we: 0x%x:", dut.w_mem_we); + dump_w_state(); end end // dut_monitor @@ -132,7 +129,14 @@ module tb_sha1_w_mem(); task dump_w_state(); begin $display("W state:"); + + $display("ctrl_reg = %01x, w_ctr_reg = %02x, mem_update = %01x, init = %01x, next = %01x", + dut.sha1_w_mem_ctrl_reg, dut.w_ctr_reg, dut.mem_update, + dut.init, dut.next); + + $display("w_tmp = %08x, w_new = %08x", dut.w_tmp, dut.w_new); + $display("w0_reg = %08x, w1_reg = %08x, w2_reg = %08x, w3_reg = %08x", dut.w_mem[00], dut.w_mem[01], dut.w_mem[02], dut.w_mem[03]); @@ -145,54 +149,6 @@ module tb_sha1_w_mem(); $display("w12_reg = %08x, w13_reg = %08x, w14_reg = %08x, w15_reg = %08x", dut.w_mem[12], dut.w_mem[13], dut.w_mem[14], dut.w_mem[15]); - $display("w16_reg = %08x, w17_reg = %08x, w18_reg = %08x, w19_reg = %08x", - dut.w_mem[16], dut.w_mem[17], dut.w_mem[18], dut.w_mem[19]); - - $display("w20_reg = %08x, w21_reg = %08x, w22_reg = %08x, w23_reg = %08x", - dut.w_mem[20], dut.w_mem[21], dut.w_mem[22], dut.w_mem[23]); - - $display("w24_reg = %08x, w25_reg = %08x, w26_reg = %08x, w27_reg = %08x", - dut.w_mem[24], dut.w_mem[25], dut.w_mem[26], dut.w_mem[27]); - - $display("w28_reg = %08x, w29_reg = %08x, w30_reg = %08x, w31_reg = %08x", - dut.w_mem[28], dut.w_mem[29], dut.w_mem[30], dut.w_mem[31]); - - $display("w32_reg = %08x, w33_reg = %08x, w34_reg = %08x, w35_reg = %08x", - dut.w_mem[32], dut.w_mem[33], dut.w_mem[34], dut.w_mem[35]); - - $display("w36_reg = %08x, w37_reg = %08x, w38_reg = %08x, w39_reg = %08x", - dut.w_mem[36], dut.w_mem[37], dut.w_mem[38], dut.w_mem[39]); - - $display("w40_reg = %08x, w41_reg = %08x, w42_reg = %08x, w43_reg = %08x", - dut.w_mem[40], dut.w_mem[41], dut.w_mem[42], dut.w_mem[43]); - - $display("w44_reg = %08x, w45_reg = %08x, w46_reg = %08x, w47_reg = %08x", - dut.w_mem[44], dut.w_mem[45], dut.w_mem[46], dut.w_mem[47]); - - $display("w48_reg = %08x, w49_reg = %08x, w50_reg = %08x, w51_reg = %08x", - dut.w_mem[48], dut.w_mem[49], dut.w_mem[50], dut.w_mem[51]); - - $display("w52_reg = %08x, w53_reg = %08x, w54_reg = %08x, w55_reg = %08x", - dut.w_mem[52], dut.w_mem[53], dut.w_mem[54], dut.w_mem[55]); - - $display("w56_reg = %08x, w57_reg = %08x, w58_reg = %08x, w59_reg = %08x", - dut.w_mem[56], dut.w_mem[57], dut.w_mem[58], dut.w_mem[59]); - - $display("w60_reg = %08x, w61_reg = %08x, w62_reg = %08x, w63_reg = %08x", - dut.w_mem[60], dut.w_mem[61], dut.w_mem[62], dut.w_mem[63]); - - $display("w64_reg = %08x, w65_reg = %08x, w66_reg = %08x, w67_reg = %08x", - dut.w_mem[64], dut.w_mem[65], dut.w_mem[66], dut.w_mem[67]); - - $display("w68_reg = %08x, w69_reg = %08x, w70_reg = %08x, w71_reg = %08x", - dut.w_mem[68], dut.w_mem[69], dut.w_mem[70], dut.w_mem[71]); - - $display("w72_reg = %08x, w73_reg = %08x, w74_reg = %08x, w75_reg = %08x", - dut.w_mem[72], dut.w_mem[73], dut.w_mem[74], dut.w_mem[75]); - - $display("w76_reg = %08x, w77_reg = %08x, w78_reg = %08x, w79_reg = %08x", - dut.w_mem[76], dut.w_mem[77], dut.w_mem[78], dut.w_mem[79]); - $display(""); end endtask // dump_state @@ -217,13 +173,12 @@ module tb_sha1_w_mem(); task init_sim(); begin $display("*** Simulation init."); - tb_clk = 0; + tb_clk = 0; tb_reset_n = 1; - cycle_ctr = 0; - - tb_init = 0; - tb_block = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; - tb_addr = 0; + cycle_ctr = 0; + tb_init = 0; + tb_next = 0; + tb_block = 512'h00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000; end endtask // reset_dut @@ -272,8 +227,9 @@ module tb_sha1_w_mem(); #(4 * CLK_HALF_PERIOD); tb_init = 0; + tb_next = 1; #(200 * CLK_HALF_PERIOD); - + dump_w_state(); end endtask // test_w_schedule @@ -290,10 +246,14 @@ module tb_sha1_w_mem(); begin $display("*** Test of W read operations. --"); i = 0; + tb_init = 1; + #(2 * CLK_HALF_PERIOD); + tb_init = 0; + while (i < 80) begin - tb_addr = i; - $display("API: w%02x, internal w%02x = 0x%02x", tb_addr, dut.addr, dut.w_tmp); + tb_next = i; + $display("API: w%02x = 0x%02x", i, dut.w_tmp); i = i + 1; #(2 * CLK_HALF_PERIOD); end |