15

I am trying to implement a 3-stage MD5 pipeline according to this link. In particular the algoritms on page 31. There is also another document which describes data forwarding. The MD5 algoritm is described in RFC1321. This is done in an FPGA (Terasic DE2-115). There is no schematics in this project, only 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;

Using this code, I get correct values for b in the first stage of round 0, but thereafter nothing seems to fit. As seen in this simulation, first stage in round 0 is correct, but thereafter not. This is when using a in this expression:

ak <= std_logic_vector(unsigned(K(0)) + unsigned(a)); -- using a

simulation

But... If I understand the second document correctly I should be using c instead of a (data forwarding), but then the first stage in round 0 doesn't work either. I.e when I do this, the first stage in round 0 gets the wrong numbers too.

ak <= std_logic_vector(unsigned(K(0)) + unsigned(c)); -- changed to c

For the particular string in the code (helloo) the following values are correct (all stages).

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
i:3 => a:3679623978, b:2813098031, c:566857930, d:268703616, f:3658619808, g:3
i:4 => a:268703616, b:3540887984, c:2813098031, d:566857930, f:831002506, g:4
i:5 => a:566857930, b:1416558949, c:3540887984, d:2813098031, f:2748069994, g:5
i:6 => a:2813098031, b:1417573490, c:1416558949, d:3540887984, f:4086081834, g:6
i:7 => a:3540887984, b:412978483, c:1417573490, d:1416558949, f:3614439904, g:7
i:8 => a:1416558949, b:2667121787, c:412978483, d:1417573490, f:1417573494, g:8
i:9 => a:1417573490, b:3587014656, c:2667121787, d:412978483, f:1486847027, g:9
i:10 => a:412978483, b:2424005293, c:3587014656, d:2667121787, f:2631470387, g:10
i:11 => a:2667121787, b:3779826569, c:2424005293, d:3587014656, f:2663976018, g:11
i:12 => a:3587014656, b:2371593944, c:3779826569, d:2424005293, f:2496594569, g:12
i:13 => a:2424005293, b:2829036837, c:2371593944, d:3779826569, f:2439758509, g:13
i:14 => a:3779826569, b:1652927941, c:2829036837, d:2371593944, f:3378230920, g:14
i:15 => a:2371593944, b:343664023, c:1652927941, d:2829036837, f:2917117725, g:15
i:16 => a:2829036837, b:3610776431, c:343664023, d:1652927941, f:1109108165, g:1
i:17 => a:1652927941, b:2356907245, c:3610776431, d:343664023, f:1450852695, g:6
i:18 => a:343664023, b:1950114052, c:2356907245, d:3610776431, f:3346765549, g:11
i:19 => a:3610776431, b:1998115502, c:1950114052, d:2356907245, f:1551601028, g:0
i:20 => a:2356907245, b:2811855282, c:1998115502, d:1950114052, f:1948049836, g:5
i:21 => a:1950114052, b:1476613917, c:2811855282, d:1998115502, f:655922090, g:10
i:22 => a:1998115502, b:1051434612, c:1476613917, d:2811855282, f:3498136348, g:15
i:23 => a:2811855282, b:2313778686, c:1051434612, d:1476613917, f:2123093565, g:4
i:24 => a:1476613917, b:2391742621, c:2313778686, d:1051434612, f:782884220, g:9
i:25 => a:1051434612, b:2587925491, c:2391742621, d:2313778686, f:2412476830, g:14
i:26 => a:2313778686, b:1270631524, c:2587925491, d:2391742621, f:2386958835, g:3
i:27 => a:2391742621, b:2967137637, c:1270631524, d:2587925491, f:449612646, g:8
i:28 => a:2587925491, b:4275359302, c:2967137637, d:1270631524, f:3523005797, g:13
i:29 => a:1270631524, b:221196138, c:4275359302, d:2967137637, f:4208389445, g:2
i:30 => a:2967137637, b:1826025400, c:221196138, d:4275359302, f:1309552482, g:7
i:31 => a:4275359302, b:4266766346, c:1826025400, d:221196138, f:1845489448, g:12
i:32 => a:221196138, b:3855169043, c:4266766346, d:1826025400, f:2678616280, g:5
i:33 => a:1826025400, b:1648727666, c:3855169043, d:4266766346, f:2001627553, g:8
i:34 => a:4266766346, b:3280661187, c:1648727666, d:3855169043, f:2044530795, g:11
i:35 => a:3855169043, b:933955932, c:3280661187, d:1648727666, f:1141263010, g:14
i:36 => a:1648727666, b:1316709518, c:933955932, d:3280661187, f:2523166189, g:1
i:37 => a:3280661187, b:1172621265, c:1316709518, d:933955932, f:3126494993, g:4
i:38 => a:933955932, b:638303819, c:1172621265, d:1316709518, f:1010084355, g:7
i:39 => a:1316709518, b:2518531516, c:638303819, d:1172621265, f:764681492, g:10
i:40 => a:1172621265, b:1723348322, c:2518531516, d:638303819, f:4126327846, g:13
i:41 => a:638303819, b:1796634879, c:1723348322, d:2518531516, f:3601741461, g:0
i:42 => a:2518531516, b:1242042285, c:1796634879, d:1723348322, f:2612260897, g:3
i:43 => a:1723348322, b:3271112123, c:1242042285, d:1796634879, f:1202078256, g:6
i:44 => a:1796634879, b:171818493, c:3271112123, d:1242042285, f:3823583977, g:9
i:45 => a:1242042285, b:4279516322, c:171818493, d:3271112123, f:2194442219, g:12
i:46 => a:3271112123, b:1084087837, c:4279516322, d:171818493, f:936424676, g:15
i:47 => a:171818493, b:4055665426, c:1084087837, d:4279516322, f:3048496962, g:2
i:48 => a:4279516322, b:4279453145, c:4055665426, d:1084087837, f:2975995202, g:0
i:49 => a:1084087837, b:1002426141, c:4279453145, d:4055665426, f:248508137, g:7
i:50 => a:4055665426, b:2580293036, c:1002426141, d:4279453145, f:3236739620, g:14
i:51 => a:4279453145, b:429799967, c:2580293036, d:1002426141, f:2723377331, g:5
i:52 => a:1002426141, b:969799177, c:429799967, d:2580293036, f:1142038355, g:12
i:53 => a:2580293036, b:4081959629, c:969799177, d:429799967, f:1717683268, g:3
i:54 => a:429799967, b:424965883, c:4081959629, d:969799177, f:3466605028, g:10
i:55 => a:969799177, b:2878206675, c:424965883, d:4081959629, f:742112562, g:1
i:56 => a:4081959629, b:3289205483, c:2878206675, d:424965883, f:3068889352, g:8
i:57 => a:424965883, b:932769765, c:3289205483, d:2878206675, f:1294088508, g:15
i:58 => a:2878206675, b:3877873675, c:932769765, d:3289205483, f:3019351302, g:6
i:59 => a:3289205483, b:3573278773, c:3877873675, d:932769765, f:3362476794, g:13
i:60 => a:932769765, b:2755809458, c:3573278773, d:3877873675, f:1004294196, g:4
i:61 => a:3877873675, b:2328479269, c:2755809458, d:3573278773, f:1747304387, g:11
i:62 => a:3573278773, b:198924010, c:2328479269, d:2755809458, f:261064541, g:2
i:63 => a:2755809458, b:3186462216, c:198924010, d:2328479269, f:3509991882, g:9

By the way, AKM in the document is akw in the code.

Any tips or suggestions on bringing me in the right direction would be very appreciated. Code would be ideal. If something is unclear, I'll edit the question and try to rectify that.

jgr
  • 3,914
  • 2
  • 24
  • 28
  • 2
    When you see that many conversions, it's a clue that tmp_b, a, b, etc should probably be unsigned in the first place... –  Jan 25 '13 at 18:23
  • No advice on pipelining here; I don't have a clear idea of the feedback paths. (I have used a spreadsheet to design a pipeline before now, to keep me straight on which cycles contained which step's values!) but I'm going to observe that it's probably the barrel shifter that's the holdup rather than the chain of sums... Incidentally I think the r_array element range should be slv(4 downto 0) I can't see any value > 31 in there. –  Jan 25 '13 at 18:36
  • I've used the spreadsheet thing too, but now I dont know where to start. I've looked at the paths and there is a lot of adders in there, won't fit onto the screen actually :/. Thanks for spotting the slv(4 downto 0)! – jgr Jan 25 '13 at 18:48
  • Follow the variable f and see if it changes state as expected on each clock tick. – Farrukh Subhani Feb 04 '13 at 00:22

1 Answers1

3

the problem is, that you have a pipeline of two in your "b-path" (--> 1st stage is b_tmp, 2nd stage is b) while the allocation pipeline has one stage (e.g. a<=d) only. I did some changes to the code and marked them with "--***". with this code, you get the first results right...

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)--*** removed: , 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 <= BB;--*** changed, was: b_tmp
        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(d));--*** changed, was: unsigned(a));
                akw <= std_logic_vector(unsigned(W(0)) + unsigned(ak));
            elsif i = 2 then
                ak <= std_logic_vector(unsigned(K(2)) + unsigned(c));--*** changed, was: unsigned(a));
                akw <= std_logic_vector(unsigned(W(1)) + unsigned(ak));
                b <= std_logic_vector(unsigned(b) + (rotate_left(unsigned(akw) + unsigned(f), to_integer(unsigned(R(0))))));--*** changed, was: b_tmp
            else
                ak <= std_logic_vector(unsigned(K(i)) + unsigned(c));--*** changed, was:  unsigned(a));
                akw <= std_logic_vector(unsigned(W(g_arr(i-1))) + unsigned(ak));
                b <= std_logic_vector(unsigned(b) + (rotate_left(unsigned(akw) + unsigned(f), to_integer(unsigned(R(i-2))))));--*** changed, was: b_tmp
            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----*** removed
                    f <= (b and c) or ((not b) and d);
                    g <= g_arr(i);
                -- end if;----*** removed

            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)----*** removed: , a, b, c, d, f, g)
     begin
        if SW(17) = '0' then
            state <= start;
                i <= 0;
                a <= AA;
            -- b <= BB; ----*** removed
            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 > 1 then----*** changed, was: --if i > 2 then
                                    --tmp_b := b;
                                    a <= d;
                                    c <= b;
                                    d <= c;
                                    -- b <= b_tmp; --*** removed

--                                  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;--*** removed
                                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;----*** removed
                                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;----*** removed
                        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;

enter image description here

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 65 := 0;--**** changed, was: to 64
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)--*** removed: , 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 <= BB;--*** changed, was: b_tmp
        elsif rising_edge(CLOCK_50) then --**** removed: and state = state_1 then
                --**** added start
                if state = done then
                    b<=b;
                    ak<=ak;
                    akw<=akw;
                --**** added stop
            elsif i = 0 then
                ak <= std_logic_vector(unsigned(K(0)) + unsigned(a));
            elsif i = 1 then
                ak <= std_logic_vector(unsigned(K(1)) + unsigned(d));--*** changed, was: unsigned(a));
                akw <= std_logic_vector(unsigned(W(0)) + unsigned(ak));
            elsif i = 2 then
                ak <= std_logic_vector(unsigned(K(2)) + unsigned(c));--*** changed, was: unsigned(a));
                akw <= std_logic_vector(unsigned(W(1)) + unsigned(ak));
                b <= std_logic_vector(unsigned(b) + (rotate_left(unsigned(akw) + unsigned(f), to_integer(unsigned(R(0))))));--*** changed, was: b_tmp
            else
                ak <= std_logic_vector(unsigned(K(i)) + unsigned(c));--*** changed, was:  unsigned(a));
                akw <= std_logic_vector(unsigned(W(g_arr(i-1))) + unsigned(ak));
                b <= std_logic_vector(unsigned(b) + (rotate_left(unsigned(akw) + unsigned(f), to_integer(unsigned(R(i-2))))));--*** changed, was: b_tmp
            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----*** removed
                    f <= (b and c) or ((not b) and d);
--                    g <= g_arr(i);--**** removed
                -- end if;----*** removed

            when state_2 =>
            f <= (d and b) or ((not d) and c);
--                g <= g_arr(i);--**** removed

            when state_3 =>
                f <= b xor c xor d;
--            g <= g_arr(i);--**** removed

            when state_4 =>
                f <= c xor (b or (not d));
--            g <= g_arr(i);--**** removed

            when others =>
                f <= x"00000000";
--                g <= 0;       --**** removed      

        end case;
    end process md5_f_p;

     md5_p : process(CLOCK_50, SW)----*** removed: , a, b, c, d, f, g)
     begin
        if SW(17) = '0' then
            state <= start;
                i <= 0;
                a <= AA;
            -- b <= BB; ----*** removed
            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 = 17 then--**** changed, was: 16
                              state <= state_2;
                                    end if; --****added
--                          else --**** removed
                        if i > 1 then----*** changed, was: --if i > 2 then
                                    --tmp_b := b;
                                    a <= d;
                                    c <= b;
                                    d <= c;
                                    -- b <= b_tmp; --*** removed

--                                  d <= c;
--                                  b <= b_tmp;
--                                  c <= b;
--                                  a <= d;
                                end if;
                                i <= i + 1;
--                    end if;--**** removed

                when state_2 =>
                    if i = 33 then--**** changed, was: 32
                        state <= state_3;
                            end if; --****added
--                    else --**** removed                 
                        d <= c;
                        -- b <= b_tmp;--*** removed
                        c <= b;
                        a <= d;
                        i <= i + 1;
--                    end if;--**** removed  

                when state_3 =>
                    if i = 49 then--**** changed, was: 48
                                state <= state_4;
                            end if; --****added
--                          else--**** removed  
                        d <= c;
                        -- b <= b_tmp;----*** removed
                        c <= b;
                        a <= d;
                        i <= i + 1;
--                    end if;--**** removed  

                when state_4 =>
                    if i = 65 then--**** changed, was: 64
--                                res_A <= std_logic_vector(unsigned(AA) + unsigned(a));--**** removed  
--                                res_B <= std_logic_vector(unsigned(BB) + unsigned(b));--**** removed  
--                                res_C <= std_logic_vector(unsigned(CC) + unsigned(c));--**** removed  
--                                res_D <= std_logic_vector(unsigned(DD) + unsigned(d));--**** removed  
                                  state <= done;
                            end if; --****added
--                    else--**** removed  
                        d <= c;
                        c <= b;
                        -- b <= b_tmp;----*** removed
                        a <= d;
                        i <= i + 1;
--                    end if;--**** removed  

                when done =>
                          res_A <= std_logic_vector(unsigned(AA) + unsigned(a));--****added
                          res_B <= std_logic_vector(unsigned(BB) + unsigned(b));--****added
                          res_C <= std_logic_vector(unsigned(CC) + unsigned(c));--****added
                          res_D <= std_logic_vector(unsigned(DD) + unsigned(d));    --****added              
                    state <= done;

                when others =>
                    state <= done;

            end case;
        end if;
    end process md5_p;
end architecture md5core_rtl;
baldyHDL
  • 1,387
  • 1
  • 10
  • 16
  • Thanks for the reply! I'll check this in the next couple of days. However, just glancing over it - aren't "f" wrong (or shifted)? – jgr Feb 27 '13 at 14:35
  • 1
    yes, 'f' is shifted! this is necessary, because 'f' is needed to calculate the correct new 'b' value. 'f' must be available BEFORE the clock edge that defines the new 'b' value. – baldyHDL Feb 27 '13 at 15:24
  • Thats makes sense now. I'll check tomorrow to verify this. Thanks! – jgr Feb 27 '13 at 18:37
  • This approach workes for state_1, but the other states won't fit in. Any pointers on how to proceed to make them work too? Do I need to "redo" the pipe for each state? – jgr Mar 02 '13 at 11:32
  • first of all, remove in the line the part. in addition, please provide the data that you expect for the other states... – baldyHDL Mar 02 '13 at 18:44
  • I updated the answer with the revised code... this time, changes are marked with "--****". good luck! – baldyHDL Mar 02 '13 at 20:00
  • Awesome job! One thing I don't understand is why `g` can be omitted all together? – jgr Mar 02 '13 at 20:18
  • Ah, sorry, now I saw how you did it. very clever, thanks a bunch again! – jgr Mar 02 '13 at 20:26