`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