summaryrefslogblamecommitdiff
path: root/streebog_hash/streebog_rom_a_matrix.v
blob: ba3607b717463d60268f2a21d9e7c1360d1b4d82 (plain) (tree)























































































































































                                                                                                                                                       
`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