summaryrefslogtreecommitdiff
path: root/streebog_hash/streebog_rom_a_matrix.v
diff options
context:
space:
mode:
Diffstat (limited to 'streebog_hash/streebog_rom_a_matrix.v')
-rw-r--r--streebog_hash/streebog_rom_a_matrix.v152
1 files changed, 152 insertions, 0 deletions
diff --git a/streebog_hash/streebog_rom_a_matrix.v b/streebog_hash/streebog_rom_a_matrix.v
new file mode 100644
index 0000000..ba3607b
--- /dev/null
+++ b/streebog_hash/streebog_rom_a_matrix.v
@@ -0,0 +1,152 @@
+`timescale 1ns / 1ps
+
+module streebog_rom_a_matrix
+ (
+ clk,
+ din, dout
+ );
+
+
+ //
+ // Ports
+ //
+ input wire clk;
+ input wire [ 5: 0] din;
+ output wire [63: 0] dout;
+
+
+ //
+ // Output Register
+ //
+ reg [63: 0] dout_reg;
+ assign dout = dout_reg;
+
+
+ //
+ // A Transformation Matrix
+ //
+
+ /*
+ * Original matrix from the standard was transformed to allow efficient implementation of
+ * hardware multiplication. The following matrix is effectively the transposed version
+ * of the original matrix A with reversed row order.
+ *
+ * Original 64x64 bit matrix from the standard has the following form:
+ *
+ * a[i,j] is 1-bit matrix element
+ *
+ * A_row(i) is 64-bit row of matrix
+ * A_col(j) is 64-bit column of matrix
+ *
+ *
+ * A_col(0) A_col(1) A_col(62) A_col(63)
+ * | | | |
+ * | | | |
+ * +----------------------------------------------+
+ * | a[ 0,63] a[ 0,62] ... a[ 0, 1] a[ 0, 0] | --A_row(0)
+ * | a[ 1,63] a[ 1,62] ... a[ 1, 1] a[ 1, 0] | --A_row(1)
+ * | ... |
+ * | a[62,63] a[62,62] ... a[62, 1] a[62, 0] | --A_row(62)
+ * | a[63,63] a[63,62] ... a[63, 1] a[63, 0] | --A_row(63)
+ * +----------------------------------------------+
+ *
+ *
+ * A_row(0)...A_row(63) are given in the original specification. Instead of row vectors we need a set of
+ * column vectors A_col(0)...A_col(63). A_col() can be obtained by transposing A_row().
+ *
+ *
+ * A_row(0) A_row(1) A_row(62) A_row(63)
+ * | | | |
+ * | | | |
+ * +---------------------------------------------+
+ * | a[ 0,63] a[ 1,63] ... a[62,63] a[63,63] | --A_col(0)
+ * | a[ 0,62] a[ 1,62] ... a[62,62] a[63,62] | --A_col(1)
+ * | ... |
+ * | a[ 0, 1] a[ 1, 1] ... a[62, 1] a[63, 1] | --A_col(62)
+ * | a[ 0, 0] a[ 1, 0] ... a[62, 0] a[63, 0] | --A_col(63)
+ * +---------------------------------------------+
+ *
+ *
+ * The only problem with A_col() is that original 64-bit A_row() values in the standard are written from MSB to LSB. That implies that
+ * original matrix columns are numbered from 63 to 0, while matrix rows are numbered from 0 to 63. Because of that we need to reverse
+ * row order after transposition. Original matrix had element a[0,0] in A_row(0), but after transposition element a[0,0] turns out
+ * to be in A_col(63), not in A_col(0). Because of that addresses inside of case() below are reversed. This effectively reverses
+ * the order in which A_col() follow.
+ *
+ */
+
+ always @(posedge clk) begin
+ //
+ case (din)
+ //
+ 6'h3F: dout_reg <= 64'hB18285C0BA4F9506;
+ 6'h3E: dout_reg <= 64'h584142605DA7CA83;
+ 6'h3D: dout_reg <= 64'h2CA021302E53E5C1;
+ 6'h3C: dout_reg <= 64'h16509098172972E0;
+ 6'h3B: dout_reg <= 64'hBA2A4D8C315B2C76;
+ 6'h3A: dout_reg <= 64'hEC172386A2E2833D;
+ 6'h39: dout_reg <= 64'hC7091403EB3E5418;
+ 6'h38: dout_reg <= 64'h63040A81759F2A0C;
+ 6'h37: dout_reg <= 64'h025DA344601EA1B8;
+ 6'h36: dout_reg <= 64'h012ED1A2308FD05C;
+ 6'h35: dout_reg <= 64'h8017685198C7E8AE;
+ 6'h34: dout_reg <= 64'h408BB4284C63F457;
+ 6'h33: dout_reg <= 64'h2218F9D046AFDB13;
+ 6'h32: dout_reg <= 64'h13515FACC3C94CB1;
+ 6'h31: dout_reg <= 64'h0B758C12817A87E0;
+ 6'h30: dout_reg <= 64'h05BA4689C03D4370;
+ 6'h2F: dout_reg <= 64'hA1F0C986411102CC;
+ 6'h2E: dout_reg <= 64'hD0F864C3A0080166;
+ 6'h2D: dout_reg <= 64'hE87CB2E1508480B3;
+ 6'h2C: dout_reg <= 64'hF4BED9F0A8C24059;
+ 6'h2B: dout_reg <= 64'hDB2F257E95702260;
+ 6'h2A: dout_reg <= 64'h4C67DB398BA913FC;
+ 6'h29: dout_reg <= 64'h87C3241A04450B32;
+ 6'h28: dout_reg <= 64'h43E1920D82220599;
+ 6'h27: dout_reg <= 64'hE0802541868B1232;
+ 6'h26: dout_reg <= 64'h704012A0C3458999;
+ 6'h25: dout_reg <= 64'hB8208950E12244CC;
+ 6'h24: dout_reg <= 64'h5C1044A8F011A266;
+ 6'h23: dout_reg <= 64'h4E0887957E834381;
+ 6'h22: dout_reg <= 64'hC704668B394AB3F2;
+ 6'h21: dout_reg <= 64'h830296041A2E4BCB;
+ 6'h20: dout_reg <= 64'hC1014B820D172565;
+ 6'h1F: dout_reg <= 64'h7DD80C6D98218914;
+ 6'h1E: dout_reg <= 64'h3E6C06B64C90440A;
+ 6'h1D: dout_reg <= 64'h9F36835B26C8A285;
+ 6'h1C: dout_reg <= 64'h4F1BC1AD93E45142;
+ 6'h1B: dout_reg <= 64'hDA55ECBBD1D3A135;
+ 6'h1A: dout_reg <= 64'h10727AB0F048598E;
+ 6'h19: dout_reg <= 64'hF56131B560852553;
+ 6'h18: dout_reg <= 64'hFAB018DA30421229;
+ 6'h17: dout_reg <= 64'h82B12139880C7F01;
+ 6'h16: dout_reg <= 64'h4158909CC4063F80;
+ 6'h15: dout_reg <= 64'hA02CC8CEE2831F40;
+ 6'h14: dout_reg <= 64'h5016E46771C10F20;
+ 6'h13: dout_reg <= 64'h2ABAD30AB0ECF811;
+ 6'h12: dout_reg <= 64'h17EC48BC507A0309;
+ 6'h11: dout_reg <= 64'h09C785E72031FE05;
+ 6'h10: dout_reg <= 64'h046342731018FF02;
+ 6'h0F: dout_reg <= 64'h91E9E113A54E2B57;
+ 6'h0E: dout_reg <= 64'h4874F009522715AB;
+ 6'h0D: dout_reg <= 64'hA43AF804A9138A55;
+ 6'h0C: dout_reg <= 64'hD21D7C825409C5AA;
+ 6'h0B: dout_reg <= 64'h78E75F528F4A4982;
+ 6'h0A: dout_reg <= 64'hAD9ACEBA62EB0F16;
+ 6'h09: dout_reg <= 64'h47A4864E943BAC5C;
+ 6'h08: dout_reg <= 64'h23D2C3274A9D56AE;
+ 6'h07: dout_reg <= 64'h06016A5C89D498B1;
+ 6'h06: dout_reg <= 64'h8380B5AE446A4C58;
+ 6'h05: dout_reg <= 64'hC140DA57A2B5262C;
+ 6'h04: dout_reg <= 64'hE0206DAB51DA9316;
+ 6'h03: dout_reg <= 64'h7611DC09A1B9D1BA;
+ 6'h02: dout_reg <= 64'h3D0984585908F0EC;
+ 6'h01: dout_reg <= 64'h1805A870255060C7;
+ 6'h00: dout_reg <= 64'h0C02D4B812A83063;
+ //
+ endcase // case(din)
+ //
+ end // always @(posedge clk)
+
+
+endmodule