Ich versuche, eine 3-stufige MD5-Pipeline gemäß diesem Link zu implementieren . Insbesondere die Algorithmen auf Seite 31. Es gibt auch ein weiteres Dokument , das die Datenweiterleitung beschreibt. Dies geschieht in einem FPGA (Terasic DE2-115). In diesem Projekt gibt es keine Schaltpläne, nur VHDL-Code.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity md5core is
port (
CLOCK_50 : in std_logic;
SW : in std_logic_vector(17 downto 17)
);
end entity md5core;
architecture md5core_rtl of md5core is
type r_array is array(0 to 64) of std_logic_vector(7 downto 0);
constant R : r_array := ( x"07", x"0c", x"11", x"16", x"07", x"0c", x"11", x"16", x"07", x"0c", x"11", x"16", x"07", x"0c", x"11",
x"16", x"05", x"09", x"0e", x"14", x"05", x"09", x"0e", x"14", x"05", x"09", x"0e", x"14", x"05", x"09",
x"0e", x"14", x"04", x"0b", x"10", x"17", x"04", x"0b", x"10", x"17", x"04", x"0b", x"10", x"17", x"04",
x"0b", x"10", x"17", x"06", x"0a", x"0f", x"15", x"06", x"0a", x"0f", x"15", x"06", x"0a", x"0f", x"15",
x"06", x"0a", x"0f", x"15", others => x"00");
type k_array is array(0 to 66) of std_logic_vector(31 downto 0);
constant K : k_array := (x"d76aa478", x"e8c7b756", x"242070db", x"c1bdceee",
x"f57c0faf", x"4787c62a", x"a8304613", x"fd469501",
x"698098d8", x"8b44f7af", x"ffff5bb1", x"895cd7be",
x"6b901122", x"fd987193", x"a679438e", x"49b40821",
x"f61e2562", x"c040b340", x"265e5a51", x"e9b6c7aa",
x"d62f105d", x"02441453", x"d8a1e681", x"e7d3fbc8",
x"21e1cde6", x"c33707d6", x"f4d50d87", x"455a14ed",
x"a9e3e905", x"fcefa3f8", x"676f02d9", x"8d2a4c8a",
x"fffa3942", x"8771f681", x"6d9d6122", x"fde5380c",
x"a4beea44", x"4bdecfa9", x"f6bb4b60", x"bebfbc70",
x"289b7ec6", x"eaa127fa", x"d4ef3085", x"04881d05",
x"d9d4d039", x"e6db99e5", x"1fa27cf8", x"c4ac5665",
x"f4292244", x"432aff97", x"ab9423a7", x"fc93a039",
x"655b59c3", x"8f0ccc92", x"ffeff47d", x"85845dd1",
x"6fa87e4f", x"fe2ce6e0", x"a3014314", x"4e0811a1",
x"f7537e82", x"bd3af235", x"2ad7d2bb", x"eb86d391", others => x"00000000");
type g_array is array(0 to 64) of integer range 0 to 15;
constant g_arr : g_array := (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,
5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9, 0);
type w_array is array(0 to 15) of std_logic_vector(31 downto 0);
signal W : w_array;
constant AA : std_logic_vector(31 downto 0) := x"67452301";
constant BB : std_logic_vector(31 downto 0) := x"EFCDAB89";
constant CC : std_logic_vector(31 downto 0) := x"98BADCFE";
constant DD : std_logic_vector(31 downto 0) := x"10325476";
signal res_A : std_logic_vector(31 downto 0) := x"00000000";
signal res_B : std_logic_vector(31 downto 0) := x"00000000";
signal res_C : std_logic_vector(31 downto 0) := x"00000000";
signal res_D : std_logic_vector(31 downto 0) := x"00000000";
type in_str_t is array(0 to 5) of std_logic_vector(7 downto 0);
constant in_str : in_str_t := (x"68", x"65", x"6c", x"6c", x"6f", x"6f");
type pad_str_t is array(0 to 63) of std_logic_vector(7 downto 0);
signal pad_str : pad_str_t;
type state_t is (start, padding, init_w, state_1, state_2, state_3, state_4, done);
signal state : state_t;
signal a, b, c, d, f : std_logic_vector(31 downto 0) := x"00000000";
signal i : integer range 0 to 64 := 0;
signal g : integer range 0 to 15 := 0;
--signal tmp_b : std_logic_vector(31 downto 0);
signal akw : std_logic_vector(31 downto 0);
signal ak : std_logic_vector(31 downto 0);
signal b_tmp : std_logic_vector(31 downto 0);
begin
--tmp_b <= std_logic_vector(unsigned(b) + rotate_left(unsigned(a) + unsigned(f) + unsigned(K(i)) + unsigned(W(g)), to_integer(unsigned(R(i)))));
pipe_p : process(CLOCK_50, SW, a, b, c, d, i)
begin
if SW(17) = '0' then
-- ak <= std_logic_vector(unsigned(K(2)) + unsigned(BB));
-- akw <= std_logic_vector(unsigned(W(0)) + 1 + unsigned(K(2)) + unsigned(BB));
b_tmp <= BB;
elsif rising_edge(CLOCK_50) and state = state_1 then
if i = 0 then
ak <= std_logic_vector(unsigned(K(0)) + unsigned(a));
elsif i = 1 then
ak <= std_logic_vector(unsigned(K(1)) + unsigned(a));
akw <= std_logic_vector(unsigned(W(0)) + unsigned(ak));
elsif i = 2 then
ak <= std_logic_vector(unsigned(K(2)) + unsigned(a));
akw <= std_logic_vector(unsigned(W(1)) + unsigned(ak));
b_tmp <= std_logic_vector(unsigned(b) + (rotate_left(unsigned(akw) + unsigned(f), to_integer(unsigned(R(0))))));
else
ak <= std_logic_vector(unsigned(K(i)) + unsigned(a));
akw <= std_logic_vector(unsigned(W(g_arr(i-1))) + unsigned(ak));
b_tmp <= std_logic_vector(unsigned(b) + (rotate_left(unsigned(akw) + unsigned(f), to_integer(unsigned(R(i-2))))));
end if;
end if;
end process pipe_p;
md5_f_p : process(state, a, b, c, d, i)
begin
case state is
when state_1 =>
if i = 0 or i > 4 then
f <= (b and c) or ((not b) and d);
g <= g_arr(i);
end if;
when state_2 =>
f <= (d and b) or ((not d) and c);
g <= g_arr(i);
when state_3 =>
f <= b xor c xor d;
g <= g_arr(i);
when state_4 =>
f <= c xor (b or (not d));
g <= g_arr(i);
when others =>
f <= x"00000000";
g <= 0;
end case;
end process md5_f_p;
md5_p : process(CLOCK_50, SW, a, b, c, d, f, g)
begin
if SW(17) = '0' then
state <= start;
i <= 0;
a <= AA;
b <= BB;
c <= CC;
d <= DD;
W <= (others => x"00000000");
pad_str <= (others => x"00");
--tmp_b := BB;
elsif rising_edge(CLOCK_50) then
case state is
when start =>
pad_str(0) <= in_str(0);
pad_str(1) <= in_str(1);
pad_str(2) <= in_str(2);
pad_str(3) <= in_str(3);
pad_str(4) <= in_str(4);
pad_str(5) <= in_str(5);
state <= padding;
when padding =>
pad_str(6) <= "10000000";
pad_str(56) <= std_logic_vector(to_unsigned(in_str'length*8, 8));
state <= init_w;
when init_w =>
W(0) <= pad_str(3) & pad_str(2) & pad_str(1) & pad_str(0);
W(1) <= pad_str(7) & pad_str(6) & pad_str(5) & pad_str(4);
W(14) <= pad_str(59) & pad_str(58) & pad_str(57) & pad_str(56);
state <= state_1;
when state_1 =>
if i = 16 then
state <= state_2;
else
if i > 2 then
--tmp_b := b;
a <= d;
c <= b;
d <= c;
b <= b_tmp;
-- d <= c;
-- b <= b_tmp;
-- c <= b;
-- a <= d;
end if;
i <= i + 1;
end if;
when state_2 =>
if i = 32 then
state <= state_3;
else
d <= c;
b <= b_tmp;
c <= b;
a <= d;
i <= i + 1;
end if;
when state_3 =>
if i = 48 then
state <= state_4;
else
d <= c;
b <= b_tmp;
c <= b;
a <= d;
i <= i + 1;
end if;
when state_4 =>
if i = 64 then
res_A <= std_logic_vector(unsigned(AA) + unsigned(a));
res_B <= std_logic_vector(unsigned(BB) + unsigned(b));
res_C <= std_logic_vector(unsigned(CC) + unsigned(c));
res_D <= std_logic_vector(unsigned(DD) + unsigned(d));
state <= done;
else
d <= c;
c <= b;
b <= b_tmp;
a <= d;
i <= i + 1;
end if;
when done =>
state <= done;
when others =>
state <= done;
end case;
end if;
end process md5_p;
end architecture md5core_rtl;
Mit diesem Code erhalte ich b
in der ersten Phase von Runde 0 korrekte Werte, aber danach scheint nichts mehr zu passen. Wie in dieser Simulation zu sehen ist, ist die erste Phase in Runde 0 korrekt, aber danach nicht. Dies ist bei Verwendung a
in diesem Ausdruck:
ak <= std_logic_vector(unsigned(K(0)) + unsigned(a)); -- using a
Aber ... Wenn ich das zweite Dokument richtig verstehe, sollte ich c
statt a
(Datenweiterleitung) verwenden, aber dann funktioniert die erste Stufe in Runde 0 auch nicht. Dh wenn ich das mache, bekommt auch die erste Stufe in Runde 0 die falschen Zahlen.
ak <= std_logic_vector(unsigned(K(0)) + unsigned(c)); -- changed to c
Für die jeweilige Zeichenfolge im Code ( helloo
) sind die folgenden Werte korrekt (erste 3 Stufen von Runde 0).
i:0 => a:271733878, b:3679623978, c:4023233417, d:2562383102, f:2562383102, g:0
i:1 => a:2562383102, b:268703616, c:3679623978, d:4023233417, f:3421032412, g:1
i:2 => a:4023233417, b:566857930, c:268703616, d:3679623978, f:4291410697, g:2
By the way, AKM
in dem Dokument ist akw
im Code.
Irgendwelche Tipps oder Vorschläge, mich in die richtige Richtung zu bringen, wären sehr dankbar. Code wäre ideal. Wenn etwas unklar ist, werde ich die Frage bearbeiten und versuchen, das zu korrigieren.
Ich glaube, Sie haben die Kommentare des Autors des Papiers zum Pipelining des Algorithmus missverstanden. Sie können die Berechnung für B nicht einfach weiterleiten, ohne auch den Rest des Prozesses weiterzuleiten.
Ich würde für den Anfang empfehlen, den Pipeline-Ansatz ganz zu vergessen und den Algorithmus einfach mit einer nicht-pipelined Implementierung der B-Berechnung zum Laufen zu bringen.
Sobald Sie korrekte Ergebnisse erhalten und mehr Leistung benötigen, können Sie sich mit dem Pipelining befassen. Dann können Sie sehen, wie sich die Zwischenergebnisse bei jedem Taktzyklus ausrichten und was erforderlich ist, um sie synchron zu halten.
b
, meinten Sie, was sie in der Zeitung Datenweiterleitung nennen (für A
)?AK
ist es wirklich CK
. Das wird immer komplexer :/
Benutzer17592
jgr
David Tweed
jgr