URL
https://opencores.org/ocsvn/simpletousesha2/simpletousesha2/trunk
Subversion Repositories simpletousesha2
[/] [simpletousesha2/] [trunk/] [src/] [sha2.vhd] - Rev 2
Compare with Previous | Blame | View Log
library ieee; use ieee.std_logic_1164.all; --use ieee.std_logic_misc.all; use ieee.numeric_std.all; library work; use work.shaPkg.all; entity sha2 is port ( clk : in std_logic; rst : in std_logic; chunk : in std_logic_vector(0 to CW-1); len : in std_logic_vector(0 to CLENBIT-1); load : in std_logic; --hash : out std_logic_vector(0 to OS-1); hash : out std_logic_vector(0 to WW-1); valid : out std_logic ); end sha2; architecture hash of sha2 is component stepCount port ( cnt : out integer range 0 to STMAX-1; clk : in std_logic; rst : in std_logic ); end component; component outCount port ( cnt : out integer range 0 to WOUT-1; clk : in std_logic; en : in std_logic ); end component; component romk port ( addr : in integer range 0 to STMAX-1; k : out std_logic_vector (0 to WW-1) ); end component; signal k : std_logic_vector(0 to WW-1); signal new_w : unsigned(0 to WW-1); -- nuova word del blocco Wt per t <= 15 signal cal_w : unsigned(0 to WW-1); -- nuova word calcolata Wt per t > 15 signal w : unsigned(0 to WW-1); -- word da utilizzare Wt signal wnd : unsigned(0 to BS-1); -- registro a scorrimento da Wt-16 a Wt-1 signal buf : unsigned(0 to BS-1); -- buffer blocco precedente signal h_vld : std_logic; -- hash valida signal blk_vld : std_logic; -- blocco elaborato signal loaded : std_logic; -- ho caricato signal loading : std_logic; -- sto caricando signal load_pad : std_logic; -- sto caricando signal load_rst : std_logic; -- comincia un nuovo messaggio signal step_rst : std_logic; -- comincio a elaborare un nuovo blocco signal step : integer range 0 to STMAX-1; -- contatore step (sha-224/256 = 64) signal w_out : integer range 0 to WOUT-1; -- contatore out word's (sha-224 = 7, 256 = 8) signal blk_num : unsigned(0 to MSGBIT-LENBIT-1); -- numero di blocchi da elaborare signal blk_ok : unsigned(0 to MSGBIT-LENBIT-1); -- numero di blocchi elaborati signal msg_len : unsigned(0 to MSGBIT-1); -- lunghezza messaggio -- Registri dell'algoritmo SHA-2 signal a : unsigned(0 to WW-1); signal b : unsigned(0 to WW-1); signal c : unsigned(0 to WW-1); signal d : unsigned(0 to WW-1); signal e : unsigned(0 to WW-1); signal f : unsigned(0 to WW-1); signal g : unsigned(0 to WW-1); signal h : unsigned(0 to WW-1); signal a_2 : unsigned(0 to WW-1); signal b_2 : unsigned(0 to WW-1); signal c_2 : unsigned(0 to WW-1); signal d_2 : unsigned(0 to WW-1); signal e_2 : unsigned(0 to WW-1); signal f_2 : unsigned(0 to WW-1); signal g_2 : unsigned(0 to WW-1); signal h_2 : unsigned(0 to WW-1); signal s0 : unsigned(0 to WW-1); -- sigma0 signal s1 : unsigned(0 to WW-1); -- sigma1 signal maj : unsigned(0 to WW-1); signal ch : unsigned(0 to WW-1); signal th0 : unsigned(0 to WW-1); -- theta0 signal th1 : unsigned(0 to WW-1); -- theta1 --signal t1 : unsigned(0 to WW-1); -- T1 --signal t2 : unsigned(0 to WW-1); -- T2 signal h0 : unsigned(0 to WW-1); signal h1 : unsigned(0 to WW-1); signal h2 : unsigned(0 to WW-1); signal h3 : unsigned(0 to WW-1); signal h4 : unsigned(0 to WW-1); signal h5 : unsigned(0 to WW-1); signal h6 : unsigned(0 to WW-1); signal h7 : unsigned(0 to WW-1); -- FSM signal first : std_logic; signal first2 : std_logic; type state_type is (s_idle, s_load, s_add_block, s_padding, s_compute); signal state : state_type; begin -- hash ----------------------------------------------------------------------------- -- CONNESSIONI PERMANENTI PER CALCOLO DI OGNI STEP ----------------------------------------------------------------------------- rom0 : romk port map ( addr => step, k => k ); step_count : stepCount port map ( cnt => step, clk => clk, rst => step_rst ); out_count : outCount port map ( cnt => w_out, clk => clk, en => h_vld ); -- Connessione digest -> hash, per sha-256/512 OS == ISS per 224/384 OS < ISS --hash <= std_logic_vector(h0) & std_logic_vector(h1) & std_logic_vector(h2) & std_logic_vector(h3) & std_logic_vector(h4) & std_logic_vector(h5) & std_logic_vector(h6) & std_logic_vector(h7); -- (0 to OS-1); with w_out select hash <= std_logic_vector(h0) when 0, std_logic_vector(h1) when 1, std_logic_vector(h2) when 2, std_logic_vector(h3) when 3, std_logic_vector(h4) when 4, std_logic_vector(h5) when 5, std_logic_vector(h6) when 6, std_logic_vector(h7) when others; valid <= h_vld; --s0 <= (a ror 2) xor (a ror 13) xor (a ror 22); --maj <= (a and b) xor (a and c) xor (b and c); --s1 <= (e ror 6) xor (e ror 11) xor (e ror 25); --ch <= (e and f) xor ((not e)and g); s0 <= ((a + a_2) ror 2) xor ((a + a_2) ror 13) xor ((a + a_2) ror 22); maj <= ((a + a_2) and (b + b_2)) xor ((a + a_2) and (c + c_2)) xor ((b + b_2) and (c + c_2)); s1 <= ((e + e_2) ror 6) xor ((e + e_2) ror 11) xor ((e + e_2) ror 25); ch <= ((e + e_2) and (f + f_2)) xor ((not (e + e_2))and (g + g_2)); -- tetha0(Wt-15) == tetha0(W1) sulla finestra mobile th0 <= (wnd(WW to 2*WW-1) ror 7) xor (wnd(WW to 2*WW-1) ror 18) xor (wnd(WW to 2*WW-1) srl 3); -- tetha1(Wt-2) == tetha0(W14) sulla finestra mobile th1 <= (wnd(14*WW to 15*WW-1) ror 17) xor (wnd(14*WW to 15*WW-1) ror 19) xor (wnd(14*WW to 15*WW-1) srl 10); -- Wt = tetha1(Wt-15) + Wt-7 + tetha0(Wt-2) + Wt-16 === Wt = tetha1(W1) + W9 + tetha0(Wt14) + W0 sulla finestra mobile cal_w <= th1 + wnd(9*WW to 10*WW-1) + th0 + wnd(0 to WW-1); -- NON SERVONO: Riduzione datapath --t1 <= h + s1 + ch + k[i] + w[i] --t1 <= h + s1 + ch + unsigned(k) + w; --t2 <= s0 + maj --t2 <= s0 + maj; -- VARIABILI CONTROLLER with state select load_pad <= '1' when s_add_block, '1' when s_padding, '1' when s_load, load when others; load_rst <= (loaded xor load_pad) and load_pad; -- ORA STO CARICANDO MA NEL CICLO PASSATO NO == PARTENZA step_rst <= load_rst or rst; -- RESET CONTATORE STEP SE E' IN RESET O COMINCIA UN NUOVO CARICAMENTO ----------------------------------------------------------------------------- -- SEGNALI PRIMO BLOCCO: Conversione bloccata per il riempimento buffer ----------------------------------------------------------------------------- first_blk: process (clk) begin if rising_edge(clk) then if rst = '1' then first <= '0'; first2 <= '0'; else first2 <= first; if load_rst = '1' then first <= '1'; elsif step = STMAX-1 and first = '1' then first <= '0'; end if; end if; end if; end process; ----------------------------------------------------------------------------- -- CONTROLLER NUMERO BLOCCHI ----------------------------------------------------------------------------- blk_counter: process (clk) begin if (rising_edge(clk)) then if ((load_rst or rst) = '1') then blk_num(MSGBIT-LENBIT-1) <= '1'; blk_num(0 to MSGBIT-LENBIT-2) <= (others => '0'); blk_ok <= (others => '0'); h_vld <= '0'; elsif blk_ok < blk_num then -- caricato un nuovo blocco del messaggio if (load_pad = '1' and blk_vld = '1') then blk_num <= blk_num + 1; end if; -- elaborato un blocco del messaggio if (first = '0' and step = STMAX-1) then blk_ok <= blk_ok + 1; end if; elsif state = s_compute and blk_ok = blk_num then if h_vld = '0' then h_vld <= '1'; end if; -- dopo aver mandato in out tutte le word della hash, metto h_vld = '0' elsif w_out = WOUT-1 then h_vld <= '0'; --blk_num <= (others => '0'); -- inibisce ulteriore modifica di h_vld end if; end if; end process; ----------------------------------------------------------------------------- -- SETTA blk_vld SE NON E' IN RESET E HA CARICATO UN BLOCCO PER INTERO ----------------------------------------------------------------------------- blk_validity: process (clk) begin if (rising_edge(clk)) then if ((load_rst or rst) = '1') then blk_vld <= '0'; elsif (step = STMAX-1) then blk_vld <= '1'; else blk_vld <= '0'; end if; end if; end process; -------------------------------------------------------------------------------------------------- -- FASE 0: PREPROCESSING - RIEMPIMENTO BUFFER + CONTROLLER STATO + INSERIMENTO PADDING E LUNGHEZZA -------------------------------------------------------------------------------------------------- p0_fill_buffer_and_padding: process (clk) variable len_i : integer range 0 to MSGBIT-1; variable clen : integer range 0 to CW; variable c : unsigned(0 to CW-1); begin if rising_edge(clk) then if rst = '1' then -- inizializza al reset buf <= (others => '0'); msg_len <= (others => '0'); state <= s_idle; else if load = '1' then state <= s_load; clen := to_integer(unsigned(len)); if clen = CW then c := unsigned(chunk); -- Carico messaggio msg_len <= msg_len + CW; -- chunk pieno else -- chunk partiale carico messaggio con padding di 1 e vado in stato padding direttamente c := (others => '0'); c(0 to clen-1) := unsigned(chunk(0 to clen-1)); c(clen) := '1'; msg_len <= msg_len + clen; -- chunk partiale (per forza ultimo) if (step+2)*CW + 1 >= BS-MSGBIT then -- SE >= 448 devo aggiungere un intero blocco di padding state <= s_add_block; else state <= s_padding; end if; end if; elsif state = s_load then -- se msg_len multipla di CW aggiungo un chunk di padding -- con bit 1 e zeri e poi vado in stato padding c(0) := '1'; c(1 to CW-1) := (others => '0'); if (step+2)*CW + 1 >= BS-MSGBIT then -- SE >= 448 devo aggiungere un intero blocco di padding state <= s_add_block; else state <= s_padding; end if; elsif state = s_add_block then -- finisco il blocco con il padding aggiungendone un altro c := (others => '0'); if step = STMAX-1 then state <= s_padding; end if; elsif state = s_padding then -- faccio padding di zeri fino agli ultimi 64 bit x la lunghezza if step = STMAX-1 then -- alla fine mette in IDLE state <= s_compute; c := (others => '0'); elsif step >= STMAX-4 and step < STMAX-2 then -- aggiunge chunk per chunk la lunghezza len_i := step*CW-(BS-MSGBIT-2*CW); c := msg_len(len_i to len_i+CW-1); else c := (others => '0'); end if; else -- re-inizializza a conversione effettuata buf <= (others => '0'); msg_len <= (others => '0'); c := (others => '0'); if state = s_compute and h_vld = '1' then state <= s_idle; end if; end if; -- shift del buffer buf(BS-CW to BS-1) <= c; buf(0 to BS-CW-1) <= buf(CW to BS-1); end if; end if; end process; -------------------------------------------------------------------------------------------------- -- CONTROLLER CARICAMENTO WORD -------------------------------------------------------------------------------------------------- fill_word: process (clk) begin if (rising_edge(clk)) then if (rst = '1') then loaded <= '0'; loading <= '0'; new_w <= (others => '0'); else loaded <= loading; -- SE HA CARICATO UNA WORD loading <= load_pad; -- SE STA CARICANDO UNA WORD -- LA NUOVA WORD IN INPUT (tiene conto del ciclo di clock per il caricamento) -- il buffer si riempie a CW bit per volta, leggo a WW, word corrente si sposta <-- CREA PROBLEMA DI CONNESSIONI? FORSE MIGLIORABILE if step = STMAX-2 then new_w <= buf(0 to WW-1); elsif step = STMAX-1 then new_w <= buf(WW-CW to (WW-CW)+WW-1); elsif step > 14 then new_w <= (others => '0'); else new_w <= buf((step+2)*(WW-CW) to (step+2)*(WW-CW)+WW-1); end if; end if; end if; end process; -------------------------------------------------------------------------------------------------- -- FASE 1: RIEMPIMENTO REGISTRO A SCORRIMENTO: ESPANSIONE -------------------------------------------------------------------------------------------------- p1_expansion: process (clk) begin if (rising_edge(clk)) then if (rst = '1') then w <= (others => '0'); wnd <= (others => '0'); elsif step < WBLK-1 or step = STMAX-1 then -- i da 1 a 16 w <= new_w; wnd(BS-WW to BS-1) <= new_w; wnd(0 to BS-WW-1) <= wnd(WW to BS-1); -- shift della finestra corrente else -- i da 17 a 64 w <= cal_w; wnd(BS-WW to BS-1) <= cal_w; wnd(0 to BS-WW-1) <= wnd(WW to BS-1); -- shift della finestra corrente end if; end if; end process; -------------------------------------------------------------------------------------------------- -- FASE 2: LOOP DI COMPRESSIONE -------------------------------------------------------------------------------------------------- p2_compression: process (clk) begin if (rising_edge(clk)) then -- inizializza a inizio messaggio if (load_rst or rst) = '1' then a <= (others => '0'); b <= (others => '0'); c <= (others => '0'); d <= (others => '0'); e <= (others => '0'); f <= (others => '0'); g <= (others => '0'); h <= (others => '0'); a_2 <= (others => '0'); b_2 <= (others => '0'); c_2 <= (others => '0'); d_2 <= (others => '0'); e_2 <= (others => '0'); f_2 <= (others => '0'); g_2 <= (others => '0'); h_2 <= (others => '0'); -- AI CICLI SUCCESSIVI IMPOSTO I REGISTRI CON LE FUNZIONI CORRETTI else -- al primo blocco la compressione č disabilitata (riempimento buffer) if first = '0' then -- T1 e T2 sono state espanse direttamente in a ed e -- T1 == h + s1(e) + ch(e, f, g) + k(t) + W(t) -- T2 == s0(a) + maj(a, b, c) -- ulteriore riduzione datapath, (a-g)_2 contengono 0 in tutti gli step tranne l'ultimo -- quando contengono il digest corrente e vengono direttamente sommati alle variabili (a-g) -- cosė da eliminare il ritardo di propagazione di un ciclo che sfaserebbe il sincronismo -- con il caricamento multiblocco h <= g + g_2; g <= f + f_2; f <= e + e_2; e <= d + d_2 + h + h_2 + s1 + ch + unsigned(k) + w; -- e <= d + T1; d <= c + c_2; c <= b + b_2; b <= a + a_2; a <= h + h_2 + s1 + ch + unsigned(k) + w + s0 + maj; -- a <= T1 + T2; end if; -- imposta all'ultimo step (a-g)_2 con il digest if step = STMAX-1 then a_2 <= h0; b_2 <= h1; c_2 <= h2; d_2 <= h3; e_2 <= h4; f_2 <= h5; g_2 <= h6; h_2 <= h7; else a_2 <= (others => '0'); b_2 <= (others => '0'); c_2 <= (others => '0'); d_2 <= (others => '0'); e_2 <= (others => '0'); f_2 <= (others => '0'); g_2 <= (others => '0'); h_2 <= (others => '0'); end if; end if; end if; end process; -------------------------------------------------------------------------------------------------- -- FASE 3: ELABORAZIONE (aggiornamento) DIGEST - HASH -------------------------------------------------------------------------------------------------- p3_digest_computation: process (clk) begin if (rising_edge(clk)) then -- reset a inizio messaggio if ((load_rst or rst) = '1') then h0 <= HASH0; h1 <= HASH1; h2 <= HASH2; h3 <= HASH3; h4 <= HASH4; h5 <= HASH5; h6 <= HASH6; h7 <= HASH7; -- nuova H cambia a ogni blocco elaborato e rimane fissa quando l'hash č valido elsif (blk_vld = '1' and first2 = '0') then h0 <= a + h0; h1 <= b + h1; h2 <= c + h2; h3 <= d + h3; h4 <= e + h4; h5 <= f + h5; h6 <= g + h6; h7 <= h + h7; end if; end if; end process; end hash;