3-stage MD5 pipeline in VHDL - md5
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
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.
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;
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;
Related
How to iterate an array in Go, starting from the index middle and then continue from index 0?
My goal is to iterate an array from the middle, and then continue from index 0. full code The current solution is to duplicate the body block for _, daysInMonth := range daysInMonths[a.Month()-1:] { daysDiff -= float64(daysInMonth) if daysDiff < 0 { daysDiff += float64(daysInMonth) break } monthsDiff += 1 } for _, daysInMonth := range daysInMonths { daysDiff -= float64(daysInMonth) if daysDiff < 0 { daysDiff += float64(daysInMonth) break } monthsDiff += 1 }
It should work if you set monthDiff back to zero once your month reaches twelve. monthsDiff = 0 // i.e. a.Month() is 10 // then subtract daysDiff with days of Month 10, 11, 12, 1, 2, and so on. for _, daysInMonth := range daysInMonths[a.Month()-1:] { daysDiff -= float64(daysInMonth) if daysDiff < 0 { daysDiff += float64(daysInMonth) break } if monthDiff == 12 { monthsDiff = 0 } else { monthsDiff += 1 } }
Asynchronous load data in counter bug
I build a counter with asynchronous load in VHDL. When i press the button(which should load data in counter) it will not increment the data but it will go like that: if the counter displays 10 -> 1, 11->2, etc.. It works fine when i press the button repeatedly but if i left the button a while the next time when i press it will not work fine. My counter: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity countfeed is Port ( Clock : in STD_LOGIC; Num_out : out STD_LOGIC_VECTOR (15 downto 0); ECU : in STD_LOGIC; ALoad: in STD_LOGIC; data : in STD_LOGIC_VECTOR(15 downto 0); ECD : in STD_LOGIC); end countfeed; architecture Behavioral of countfeed is signal count : STD_LOGIC_VECTOR(15 downto 0) := X"0000"; begin Num_out <= count; process(Clock,ALoad) begin if(ALoad = '1') then count <= data; elsif(rising_edge(Clock)) then if(ECU = '1') then if(count(3 downto 0) = X"9") then count(3 downto 0) <= X"0"; count(7 downto 4) <= count(7 downto 4) + 1; else count(3 downto 0) <= count(3 downto 0) + 1; end if; if(count(7 downto 0) = X"59") then count(7 downto 0) <= X"00"; count(11 downto 8) <= count(11 downto 8) + 1; end if; if(count(11 downto 0) = X"959") then count(11 downto 0) <= X"000"; count(15 downto 12) <= count(15 downto 12) + 1; end if; if(count(15 downto 0) = X"9959") then count(15 downto 0) <= X"0000"; end if; elsif(ECD = '1') then if(count(3 downto 0) = X"0") then if(count(15 downto 4) /= X"0") then count(3 downto 0) <= X"9"; count(7 downto 4) <= count(7 downto 4) - 1; if(count(7 downto 4) = X"0") then if(count(15 downto 8) /= X"0") then count(7 downto 4) <= X"5"; count(11 downto 8) <= count(11 downto 8) - 1; if(count(11 downto 8) = X"0") then if(count(15 downto 12) /= X"0") then count(11 downto 8) <= X"9"; count(15 downto 12) <= count(15 downto 12) - 1; end if; end if; end if; end if; end if; else count(3 downto 0) <= count(3 downto 0) - 1; end if; end if; end if; end process; end Behavioral; My data processing(where bS is the button, disp_n the output of the counter, data is the data to load: process(bS) begin if(rising_edge(bS)) then data(15 downto 8) <= disp_n(15 downto 8); if(disp_n(7 downto 0) = X"59") then data(7 downto 0) <= X"00"; elsif(disp_n(3 downto 0) = X"9") then data(3 downto 0) <= X"0"; data(7 downto 4) <= disp_n(7 downto 4) + 1; else data(3 downto 0) <= disp_n(3 downto 0) + 1; end if; end if; end process; Load: ALoad <= bS; toplevel: architecture Behavioral of toplevel is Component ClockDivider is... Component BCD is... Component DebouncerC is... Component edge_det is... Component countfeed is Port ( Clock : in STD_LOGIC; Num_out : out STD_LOGIC_VECTOR (15 downto 0); ECU : in STD_LOGIC; ALoad: in STD_LOGIC; data: in STD_LOGIC_VECTOR(15 downto 0); ECD: in STD_LOGIC); end Component; signal bSS,bS,bM : STD_LOGIC; --Debounced buttons signal clk1s : STD_LOGIC; -- 1 Hz Clock signal ECU,ECD : STD_LOGIC; -- Enable Count Up/Down signal Reset : STD_LOGIC; -- Reset signal disp_n: STD_LOGIC_VECTOR(15 downto 0); signal ALoad: STD_LOGIC; signal data: STD_LOGIC_VECTOR(15 downto 0); signal btS,btM: STD_LOGIC; signal dataS: STD_LOGIC_VECTOR(15 downto 0); begin --Execution Unit-- E0: ClockDivider port map( Clock => Clock, ClockDiv => clk1s); E1: BCD port map( Number => disp_n, Clock => Clock, Anod => Anod, Segment => seg); E2: DebouncerC port map( Clock => Clock, Button_in => StartStop, Button_out => bSS); E3: DebouncerC port map( Clock => Clock, Button_in => Seconds, Button_out => bS); E4: DebouncerC port map( Clock => Clock, Button_in => Minutes, Button_out => bM); E5: Reset <= bS and bM; E6: countfeed port map(Clock => clk1s, Num_out => disp_n,ECU => ECU, ECD => ECD,ALoad => ALoad, data => data); E7: edge_det port map (Clock => Clock, Signal_in => bS, Signal_out => btS); E8: edge_det port map (Clock => Clock, Signal_in => bM, Signal_out => btM); ALoad <= btS or btM; process(bS) begin if(rising_edge(bS)) then data(15 downto 8) <= disp_n(15 downto 8); if(disp_n(7 downto 0) = X"59") then data(7 downto 0) <= X"00"; elsif(disp_n(3 downto 0) = X"9") then data(3 downto 0) <= X"0"; data(7 downto 4) <= disp_n(7 downto 4) + 1; else data(3 downto 0) <= disp_n(3 downto 0) + 1; end if; end if; end process; process(bSS) begin if(rising_edge(bSS)) then ECU <= not ECU; end if; end process; end Behavioral;
multidimensional arrays in VHDL
I want to do multiplication of 2 matrix,and I am trying to make an array of std_logic_vectors in VHDL. package matrice is type t11 is array (32 downto 0,0 downto 19) of unsigned(7 downto 0);< type t1 is array (0 downto 19) of t11; type t2 is array (0 downto 194) of unsigned(7 downto 0); entity matrice_test is Port (clk : in STD_LOGIC;a : in t1;b : in t2;multi :out t2); end matrice_test; architecture Behavioral of matrice_test is type t11 is array (M_MAX-1 downto 0,0 downto O_MAX-1) of unsigned(N-1 downto 0); type t1 is array (0 downto O_MAX-1) of t11; type t2 is array (0 downto N_MAX-1) of unsigned(N-1 downto 0); The error that I am getting: indexed name prefix type t11 expects 2 dimensions
I can't reproduce your error (how about submitting an MCVE), but this type t11 is array (323 downto 0,0 downto 19) of unsigned(7 downto 0); should be this type t11 is array (323 downto 0,0 to 19) of unsigned(7 downto 0); -- ^ -- |
5 seconds Timer in VHDL
I am using 50MHz clock in fpga and trying make 5 seconds timer. below cnt_t reach to 5 x 50MHz (x"0EE6B280" --> 250,000,000) then make time_tick_32 to 1 and make cnt_t <= x"00000000";. The code below did not work never time_tick_32 gets 1. signal cnt_t : STD_LOGIC_VECTOR(31 DOWNTO 0) := x"00000000"; signal time_tick : STD_LOGIC:= '0' ; signal time_tick_32 : STD_LOGIC_VECTOR(31 DOWNTO 0):= x"00000000"; process (clk_50) IS begin if falling_edge(clk_50) then cnt_t <= cnt_t + '1'; end if; if (cnt_t = x"0EE6B280") then --if 5 seconds time_tick <= '1'; cnt_t <= x"00000000"; time_tick_32(0)<=time_tick; else time_tick <= '0'; time_tick_32(0)<=time_tick; end if; end process;
Try: signal cnt_t : STD_LOGIC_VECTOR(31 DOWNTO 0) := x"00000000"; signal time_tick : STD_LOGIC:= '0' ; signal time_tick_32 : STD_LOGIC_VECTOR(31 DOWNTO 0):= x"00000000"; -- I assume you begin your architecture somewhere -- Can make the following a concurrent statement -- (unless it is some kind of shift reg assigned in a diff process... -- then you will get multiple driver issues) time_tick_32(0) <= time_tick; process (clk_50) IS begin if rising_edge(clk_50) then -- Changed to rising_edge; -- Any particular reason you are using falling_edge? if (cnt_t = x"0EE6B280") then --if 5 seconds time_tick <= '1'; cnt_t <= x"00000000"; else time_tick <= '0'; cnt_t <= cnt_t + '1'; end if; end if; end process;
All values changes in array using vhdl
I'm trying to make brick break in VHDL. Everything went well but I have a weird problem. In a piece of my code you see below I change the value to '0' at index (y,x) in my array when the ball reaches the edges of a brick. The problem is that all the values in my array change to 0, even when the ball is not moving (When the program start up, the ball is not moving). process(Ball_x1,Ball_x2,Ball_y1,Ball_y2) begin x1 <= 280 + (x * 55); --edges of my brick x2 <= 280 + ((x + 1) * 55); y1 <= 108 + (y * 13); y2 <= 108 + ((y + 1) * 13); waardeArray := level1(y,x); if (vcnt >= y1) and (vcnt <= y2) then if (Ball_x1 >= x1) and (Ball_x1 <= x2) then -- edges of my ball if waardeArray = '1' then level1(y,x) := '0'; end if; end if; end if; end process; The declaration of my array is type levels is array ( 0 to 3, 0 to 5 ) of bit; shared variable level1 : levels := ( ('1','0','0','0','0','1'), ('0','1','0','0','1','0'), ('0','0','1','1','0','0'), ('0','0','1','1','0','0') ); Next variable is used to store the value of the array at place (y,x) shared variable waardeArray: bit; It's the intention to use Ball_x2 etc too but I just tried with 1 edge of my ball to test the code. Update process(Ball_x1,Ball_x2,Ball_y1,Ball_y2) begin x1 <= 280 + (x * 55); -- edges of my brick x2 <= 280 + ((x + 1) * 55); y1 <= 108 + (y * 13); y2 <= 108 + ((y + 1) * 13); if (vcnt >= y1) and (vcnt <= y2) then --vcnt is from another component where I send my data to my screen if (Ball_x1 >= x1) and (Ball_x1 <= x2) then -- left edge of my ball if level1(y)(x) = '1' then level1(y)(x) <= '1'; --I do this to test if the elements with value 1 stay 1 and the 0 stay 0 ata initialization, but every element in my array change to 1. else level1(y)(x) <= level1(y)(x); end if; end if; end if; end process; Declarations signal x: integer range 0 to 6 := 0; --Six is used for something else. signal y: integer range 0 to 3 := 0; signal x1: integer range 279 to 616; signal x2: integer range 279 to 616; signal y1: integer range 107 to 228; signal y2: integer range 107 to 228; signal color: std_logic_vector (7 downto 0) := "00000111"; type levels is array ( 0 to 3) of std_logic_vector (5 downto 0); signal level1 : levels := ("101101", "010010", "001100", "001100"); This is my intention
Don't use shared variables. If you need to communicate a value between processes, use a signal. You can't be sure of the order at which updates compared to reads occur using shared variables. Well, you can, but you have to use protected types. Also, in your process, you are looking at the values of x, y and vcnt. But those signals (I hope they are signals not shared variables :) are not in the sensitivity list of the process, so when they change, your process will not be triggered.