Commit 3acb0fce by Enrico Pozzobon

removing hardware (Verilog and VHDL) implementations

parent 04be7d51

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

-- This work is licensed under a Creative Commons
-- Attribution-NonCommercial-ShareAlike 4.0 International License.
-- http://creativecommons.org/licenses/by-nc-sa/4.0
-- Mark D. Aagaard
-- Riham AlTawy
-- Guang Gong
-- Kalikinkar Mandal
-- Raghvendra Rohit
-- Marat Sattarov
-- Nusa Zidaric
-- http://uwaterloo.ca/communications-security-lab/lwc/ace
-- This is a human-readable summary of (and not a substitute for) the license.
-- You are free to:
-- Share: copy and redistribute the material in any medium or format
-- Adapt: remix, transform, and build upon the material
-- The licensor cannot revoke these freedoms as long as you follow
-- the license terms.
-- Under the following terms:
-- Attribution — You must give appropriate credit, provide a link to
-- the license, and indicate if changes were made. You may do so in
-- any reasonable manner, but not in any way that suggests the
-- licensor endorses you or your use.
-- NonCommercial — You may not use the material for commercial
-- purposes.
-- ShareAlike — If you remix, transform, or build upon the material,
-- you must distribute your contributions under the same license as
-- the original.
-- No additional restrictions — You may not apply legal terms or
-- technological measures that legally restrict others from doing
-- anything the license permits.
architecture rtl of ace is
signal ctl_control : ace_ctl_ty;
signal ctl_onehot : onehot_ty;
signal ctl_lfsr_en : std_logic;
signal ctl_lfsr_reset : std_logic;
begin
u_dp :
entity work.dp port map
( clk => clk
, reset => reset
, i_mode => i_mode
, i_control => ctl_control
, i_onehot => ctl_onehot
, i_dom_sep => i_dom_sep
, i_valid => i_valid
, i_data => i_data
, i_padding => i_padding
, o_data => o_data
);
u_ctl :
entity work.ctl port map
( clk => clk
, reset => reset
, i_mode => i_mode
, i_dom_sep => i_dom_sep
, i_valid => i_valid
, i_padding => i_padding
, o_valid => o_valid
, o_onehot => ctl_onehot
, o_ready => o_ready
, o_control => ctl_control
);
end architecture;
LIB_VHDL =+ ace_pkg.vhd
TB_ENTITY = ace_tb
TB_ARCH = main
TB_VHDL =+ util_unsynth.vhd
TB_VHDL =+ ace_unsynth.vhd
TB_VHDL =+ ace_tb.vhd
SIM_SCRIPT = ace_tb.sim
DESIGN_ARCH = rtl
DESIGN_ENTITY = ace
DESIGN_VHDL =+ sb_64.vhd
DESIGN_VHDL =+ lfsr_c.vhd
DESIGN_VHDL =+ ctl.vhd
DESIGN_VHDL =+ dp.vhd
ENTITY_VHDL =+ ace.vhd
DESIGN_VHDL =+ ace-rtl.vhd
-- This work is licensed under a Creative Commons
-- Attribution-NonCommercial-ShareAlike 4.0 International License.
-- http://creativecommons.org/licenses/by-nc-sa/4.0
-- Mark D. Aagaard
-- Riham AlTawy
-- Guang Gong
-- Kalikinkar Mandal
-- Raghvendra Rohit
-- Marat Sattarov
-- Nusa Zidaric
-- http://uwaterloo.ca/communications-security-lab/lwc/ace
-- This is a human-readable summary of (and not a substitute for) the license.
-- You are free to:
-- Share: copy and redistribute the material in any medium or format
-- Adapt: remix, transform, and build upon the material
-- The licensor cannot revoke these freedoms as long as you follow
-- the license terms.
-- Under the following terms:
-- Attribution — You must give appropriate credit, provide a link to
-- the license, and indicate if changes were made. You may do so in
-- any reasonable manner, but not in any way that suggests the
-- licensor endorses you or your use.
-- NonCommercial — You may not use the material for commercial
-- purposes.
-- ShareAlike — If you remix, transform, or build upon the material,
-- you must distribute your contributions under the same license as
-- the original.
-- No additional restrictions — You may not apply legal terms or
-- technological measures that legally restrict others from doing
-- anything the license permits.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.ace_pkg.all;
entity ace is
port
( clk : in std_logic;
reset : in std_logic;
i_mode : in mode_ty;
i_dom_sep : in domsep_ty;
i_valid : in std_logic;
i_data : in word;
i_padding : in std_logic;
o_valid : out std_logic;
o_ready : out std_logic;
o_data : out word
);
end entity;
-- This work is licensed under a Creative Commons
-- Attribution-NonCommercial-ShareAlike 4.0 International License.
-- http://creativecommons.org/licenses/by-nc-sa/4.0
-- Mark D. Aagaard
-- Riham AlTawy
-- Guang Gong
-- Kalikinkar Mandal
-- Raghvendra Rohit
-- Marat Sattarov
-- Nusa Zidaric
-- http://uwaterloo.ca/communications-security-lab/lwc/ace
-- This is a human-readable summary of (and not a substitute for) the license.
-- You are free to:
-- Share: copy and redistribute the material in any medium or format
-- Adapt: remix, transform, and build upon the material
-- The licensor cannot revoke these freedoms as long as you follow
-- the license terms.
-- Under the following terms:
-- Attribution — You must give appropriate credit, provide a link to
-- the license, and indicate if changes were made. You may do so in
-- any reasonable manner, but not in any way that suggests the
-- licensor endorses you or your use.
-- NonCommercial — You may not use the material for commercial
-- purposes.
-- ShareAlike — If you remix, transform, or build upon the material,
-- you must distribute your contributions under the same license as
-- the original.
-- No additional restrictions — You may not apply legal terms or
-- technological measures that legally restrict others from doing
-- anything the license permits.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package ace_pkg is
--for constants
constant lfsr_c_sz : integer := 7;
subtype lfsr_c_output is std_logic_vector(0 to lfsr_c_sz+2);
------------------------------------------------------------
constant half_word_sz : natural := 32;
constant word_sz : natural := 2*half_word_sz;
subtype half_word is std_logic_vector( 0 to half_word_sz - 1 );
subtype word is std_logic_vector( 0 to word_sz - 1 );
type word_vector is array( natural range <> ) of word;
type half_word_vector is array( natural range <> ) of half_word;
------------------------------------------------------------
-- A, B, C, D, E
constant state_sz : natural := 320;
constant word_max_idx : natural := state_sz / word_sz - 1;
constant half_word_max_idx : natural := state_sz / half_word_sz - 1;
constant key_sz : natural := 128;
constant nonce_sz : natural := 128;
subtype word_state_ty is word_vector ( 0 to word_max_idx );
constant a_idx : natural := 0;
constant b_idx : natural := 1;
constant c_idx : natural := 2;
constant d_idx : natural := 3;
constant e_idx : natural := 4;
subtype half_word_data is half_word_vector ( 0 to 1 );
subtype half_word_state_ty is half_word_vector ( 0 to half_word_max_idx );
constant a0_idx : natural := 1;
constant a1_idx : natural := 0;
constant b0_idx : natural := 3;
constant b1_idx : natural := 2;
constant c0_idx : natural := 5;
constant c1_idx : natural := 4;
constant d0_idx : natural := 7;
constant d1_idx : natural := 6;
constant e0_idx : natural := 9;
constant e1_idx : natural := 8;
function b2x( b : boolean ) return std_logic;
function half_words_to_words( st : half_word_state_ty ) return word_state_ty;
function words_to_half_words( st : word_state_ty ) return half_word_state_ty;
------------------------------------------------------------
-- mode
subtype mode_ty is std_logic_vector( 1 downto 0 ); -- top lvl input
constant encrypt_mode : mode_ty := ( 1 => '0', 0 => '0' );
constant decrypt_mode : mode_ty := ( 1 => '0', 0 => '1' );
constant absorb_mode : mode_ty := ( 1 => '1', 0 => '0' );
constant squeeze_mode : mode_ty := ( 1 => '1', 0 => '1' );
subtype domsep_ty is std_logic_vector( 1 downto 0 ); -- top lvl input
-- derived control (from counter and more)
subtype ace_ctl_ty is std_logic_vector( 7 downto 0 );
constant absorb_idx : natural := 0;
constant replace_idx : natural := 1;
constant output_idx : natural := 2;
constant endstep_idx : natural := 3;
constant permoff_idx : natural := 4;
constant squeeze_idx : natural := 5;
constant lfsr_c_reset_idx : natural := 6;
constant lfsr_c_en_idx : natural := 7;
-- extras cntl for load, init, fin, tag, sqeeze
subtype onehot_ty is std_logic_vector( 3 downto 0); -- extrs cntl for load, init, fin, tag, sqeeze
------------------------------------------------------------
-- round and step counters
-- use last bit for end ACE perm - for o_ready
-- -> i_valid will reset the counter!
-- counter only runs if msb = 0
constant bits_counter : natural := 8;
subtype count_ty is unsigned( bits_counter - 1 downto 0 );
----------------------------------------------------------------------
-- standard vhdl operators
-- function "sll"( a : half_word; n : natural ) return half_word;
function onehot_rotate (a : onehot_ty) return onehot_ty;
function vector_to_data ( st : half_word_data ) return word;
function data_to_vector ( st : word ) return half_word_data;
----------------------------------------------------------------------
end package;
----------------------------------------------------------------------
--
----------------------------------------------------------------------
package body ace_pkg is
function onehot_rotate (a : onehot_ty)
return onehot_ty
is
variable z : onehot_ty;
begin
z(onehot_ty'high downto 1) := a(onehot_ty'high - 1 downto 0);
z(0) := a(onehot_ty'high);
return z;
end function;
function b2x( b : boolean ) return std_logic is
begin
if b then
return '1';
else
return '0';
end if;
end function;
------------------------------------------------------------
-- standard vhdl operators cast to state
------------------------------------------------------------
-- function "sll"( a : half_word; n : natural ) return half_word is
-- begin
-- return half_word( std_logic_vector( a ) sll n );
-- end function;
------------------------------------------------------------
-- state functions
------------------------------------------------------------
function half_words_to_words( st : half_word_state_ty ) ---- CHECK THIS!!!!!! PLEASE
return word_state_ty
is
variable i : natural;
variable z : word_state_ty;
begin
main_loop : for i in 0 to word_max_idx loop
z(i)(0 to half_word_sz - 1) := st(2*i);
z(i)(half_word_sz to word_sz - 1) := st(2*i+1);
end loop;
return z;
end function;
function words_to_half_words( st : word_state_ty )
return half_word_state_ty
is
variable i : natural;
variable z : half_word_state_ty;
begin
main_loop : for i in 0 to word_max_idx loop
z(2*i) := st(i)(0 to half_word_sz - 1);
z(2*i+1) := st(i)(half_word_sz to word_sz - 1);
end loop;
return z;
end function;
function data_to_vector( st : word )
return half_word_data
is
variable z : half_word_data;
begin
z(0) := st(0 to half_word_sz - 1);
z(1) := st(half_word_sz to word_sz - 1);
return z;
end function;
function vector_to_data( st : half_word_data )
return word
is
variable z : word;
begin
z(0 to half_word_sz - 1) := st(0);
z(half_word_sz to word_sz - 1) := st(1);
return z;
end function;
end package body;
if { $gui_mode } {
add wave clk
add wave reset
add wave i_mode
add wave i_dom_sep
add wave o_ready
add wave i_valid
add wave i_data
add wave i_padding
add wave o_valid
add wave o_data
if { $sim_mode eq "PROG_MODE" } then {
add wave -noupdate -divider -height 32 STUFF
add wave /uut/u_ctl/state
add wave /uut/u_ctl/o_ready
add wave /uut/u_ctl/i_valid
add wave /uut/u_dp/i_data
add wave /uut/u_ctl/o_valid
add wave /uut/u_dp/o_data
add wave -noupdate -divider -height 32 DP
add wave -radix binary /uut/u_dp/ctl_const
add wave /uut/u_dp/i_data
add wave /uut/u_dp/o_data
add wave -radix binary /uut/u_dp/ctl_const
add wave /uut/u_dp/lfsr_c_en
add wave /uut/u_dp/lfsr_c_reset
add wave /uut/u_dp/permoff
add wave /uut/u_dp/endstep
add wave /uut/u_dp/absorb
add wave /uut/u_dp/replace
add wave /uut/u_dp/output
add wave /uut/u_dp/dsxor
add wave /uut/u_dp/post_input
add wave /uut/u_dp/pre_round
add wave /uut/u_dp/post_round
add wave /uut/u_dp/post_xor
add wave /uut/u_dp/post_step_const
add wave /uut/u_dp/post_linear
add wave /uut/u_dp/ace_path
add wave /uut/u_dp/ace_state
add wave -noupdate -divider -height 32 CTL
add wave /uut/u_ctl/state
add wave -radix unsigned /uut/u_ctl/count
add wave /uut/u_ctl/i_valid
add wave /uut/u_ctl/o_valid
add wave /uut/u_ctl/o_ready
add wave -radix binary /uut/u_ctl/onehot
add wave /uut/u_ctl/lfsr_c_reset
add wave -radix binary /uut/u_ctl/i_mode
add wave -radix binary /uut/u_ctl/i_dom_sep
}
}
vcd file uw_tmp/ace.vcd
vcd add /ace_tb/uut/*
vcd add -r *
vcd on
run -all
vcd checkpoint
vcd off
vcd flush
if { $gui_mode } {
wave zoom full
} else {
exit
}
**** Line 63 (old) / 63 (new) ****
Description:
Moved EDH to the list of generics
Change:
; EDH : std_logic_vector(0 to 2) := "111" -- ENCRYPTION, DECRYPTION, HASH bits. example: 'xx0' = don't do HASH, 'xx1' = do HASH
**** Line 68 (old) / 69 (new) ****
Description:
Removed EDH signal declaration
**** Line 91,96 (old) / 92,98 (new) ****
Description:
Added new signal declarations to delay primary inputs after clock edge
Change:
signal i_mode_buf : mode_ty;
signal i_dom_sep_buf : domsep_ty;
**** Line 114 (old) / 117 - 125 (new) ****
Description:
added new processes to delay a change in primary inputs after clock edge
Change:
i_dom_sep_proc : process(i_dom_sep_buf)
begin
i_dom_sep <= i_dom_sep_buf after hold;
end process;
i_mode_proc : process(i_mode_buf)
begin
i_mode <= i_mode_buf after hold;
end process;
**** Line 199 (old) / 212 (new) ****
**** Line 285 (old) / 304 (new) ****
**** Line 370 (old) / 395 (new) ****
**** Line 390 (old) / 416 (new) ****
Description:
changed signal name
Change:
was
i_mode
now
i_mode_buf
**** Line 216 (old) / 229 (new) ****
**** Line 226 (old) / 241 (new) ****
**** Line 234 (old) / 250 (new) ****
**** Line 239 (old) / 256 (new) ****
**** Line 265 (old) / 284 (new) ****
**** Line 303 (old) / 322 (new) ****
**** Line 314 (old) / 335 (new) ****
**** Line 324 (old) / 346 (new) ****
**** Line 330 (old) / 353 (new) ****
**** Line 358 (old) / 383 (new) ****
**** Line 382 (old) / 406 (new) ****
Description:
changed signal name
Change:
was
i_dom_sep
now
i_dom_sep_buf
**** Line 202 (old) / 215 (new) ****
**** Line 287 (old) / 306 (new) ****
**** Line 372 (old) / 396 (new) ****
**** Line 387 (old) / 413 (new) ****
Description:
Hold statements are now in ace_unsynth.vhd
Change:
removed
wait for hold;
**** Line 383 (old) / 407 (new) ****
Description
Added a report
Change:
report( "HASH DRIVE ALL" );
**** Line 130 (old), 132 (new) ****
**** Line 198 (old), 200 (new) ****
**** Line 227 (old), 230 (new) ****
Description:
added a hold statement to delay primary inputs from clock edge
Change:
wait for hold;
The file dp_pure.vhd was removed from the submission, because it is not part of the functional complete cipher.
-- This work is licensed under a Creative Commons
-- Attribution-NonCommercial-ShareAlike 4.0 International License.
-- http://creativecommons.org/licenses/by-nc-sa/4.0
-- Mark D. Aagaard
-- Riham AlTawy
-- Guang Gong
-- Kalikinkar Mandal
-- Raghvendra Rohit
-- Marat Sattarov
-- Nusa Zidaric
-- http://uwaterloo.ca/communications-security-lab/lwc/ace
-- This is a human-readable summary of (and not a substitute for) the license.
-- You are free to:
-- Share: copy and redistribute the material in any medium or format
-- Adapt: remix, transform, and build upon the material
-- The licensor cannot revoke these freedoms as long as you follow
-- the license terms.
-- Under the following terms:
-- Attribution — You must give appropriate credit, provide a link to
-- the license, and indicate if changes were made. You may do so in
-- any reasonable manner, but not in any way that suggests the
-- licensor endorses you or your use.
-- NonCommercial — You may not use the material for commercial
-- purposes.
-- ShareAlike — If you remix, transform, or build upon the material,
-- you must distribute your contributions under the same license as
-- the original.
-- No additional restrictions — You may not apply legal terms or
-- technological measures that legally restrict others from doing
-- anything the license permits.
library ieee;
use ieee.std_logic_1164.all;
use work.ace_pkg.all;
entity lfsr_c is
port
( clk : in std_logic
; lfsr_c_en : in std_logic
; lfsr_c_reset : in std_logic
; o_const : out lfsr_c_output
);
end lfsr_c;
architecture rtl of lfsr_c is
signal sa: std_logic_vector(lfsr_c_sz - 1 downto 0);
signal xa: std_logic_vector(lfsr_c_sz + 2 downto 0);
begin
-- 10 output bits for the constants
o_const <= xa; -- "to" type <= "downto" type. Index flip intended
-- just rename signal
xa(lfsr_c_sz-1 downto 0) <= sa(lfsr_c_sz-1 downto 0);
-- for updates and outputs
xa(lfsr_c_sz + 2 downto lfsr_c_sz) <= xa(3 downto 1) xor xa(2 downto 0);
lfsr_shift: for i in lfsr_c_sz-1 downto 0 generate
lfsr_step: process(clk) begin
if rising_edge(clk) then
if lfsr_c_reset ='1' then
sa(i) <= '1';
elsif lfsr_c_en ='1' then
sa(i) <= xa(i+3);
end if;
end if;
end process;
end generate lfsr_shift;
end;
------------ ACE readme file ---------------
----- list of files for ACE synthesis: -----
ace_pkg.vhd -- main package
sb_64.vhd -- s-box with simeck
lfsr.vhd -- lfsr for step / round constant generation
ctl.vhd -- control (FSM)
dp.vhd -- datapath
ace.vhd -- top level entity declaration
ace-rtl.vhd -- top level architecture
----- additional files for simulation: -----
util_unsynth.vhd -- functions used in TB (general purpose)
ace_unsynth.vhd -- specific ACE functions and procedures used in TB
ace_tb.vhd -- ACE testbench
-------------- pure datapath ---------------
dp_pure.vhd -- datapath with most input/output multiplexers removed
----------- TB info (ace_tb.vhd): ----------
********
EDH is a 3-bit constant used to select which modes to test
"100" - encryption only
"010" - decyption only
"001" - hash only
"110" - encryption and decryption
etc.
********
stim_file_path -- stimulus file
output_file_path -- output file
********
------------ stimulus file format --------------
1 file = 1 set of Key, Nonce, AD, Plaintext and Ciphertext
K 00111122335588DD00111122335588DD <--- 128 bits of Key (all 128 bits in a single line)
N 111122335588DD00111122335588DD00 <--- 128 bits of Nonce (all 128 bits in a single line)
A 1122335588DD00111122335588DD00 <--- from 4 to 128 bits of AD
P 335588DD00111122335588DD001111 <--- from 4 to 128 bits of Plaintext
C F9362385DC213A07CEFEF38C34CEFF <--- from 4 to 128 bits of Ciphertext
--- padding is done by testbench
--- multiple lines for AD, Plaintext and Ciphertext are supported
-- This work is licensed under a Creative Commons
-- Attribution-NonCommercial-ShareAlike 4.0 International License.
-- http://creativecommons.org/licenses/by-nc-sa/4.0
-- Mark D. Aagaard
-- Riham AlTawy
-- Guang Gong
-- Kalikinkar Mandal
-- Raghvendra Rohit
-- Marat Sattarov
-- Nusa Zidaric
-- http://uwaterloo.ca/communications-security-lab/lwc/ace
-- This is a human-readable summary of (and not a substitute for) the license.
-- You are free to:
-- Share: copy and redistribute the material in any medium or format
-- Adapt: remix, transform, and build upon the material
-- The licensor cannot revoke these freedoms as long as you follow
-- the license terms.
-- Under the following terms:
-- Attribution — You must give appropriate credit, provide a link to
-- the license, and indicate if changes were made. You may do so in
-- any reasonable manner, but not in any way that suggests the
-- licensor endorses you or your use.
-- NonCommercial — You may not use the material for commercial
-- purposes.
-- ShareAlike — If you remix, transform, or build upon the material,
-- you must distribute your contributions under the same license as
-- the original.
-- No additional restrictions — You may not apply legal terms or
-- technological measures that legally restrict others from doing
-- anything the license permits.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.ace_pkg.all;
entity sb_64 is
port
( i_state : in word
; i_rc : in std_logic
; o_state : out word
);
end entity;
architecture rtl of sb_64 is
signal x0, x1, z0, z1 : half_word;
signal rc : half_word;
begin
x1 <= i_state( 0 to half_word_sz-1 );
x0 <= i_state( half_word_sz to word_sz - 1 );
rc <= ( 0 to half_word_sz - 2 => '1', half_word_sz - 1 => i_rc );
z0 <= x1;
z1 <= ( ( x1(5 to half_word_sz - 1) & x1 (0 to 4) ) and x1)
xor ( x1(1 to half_word_sz - 1) & x1 (0) )
xor x0
xor rc;
o_state <= z1 & z0;
end architecture;
-- This work is licensed under a Creative Commons
-- Attribution-NonCommercial-ShareAlike 4.0 International License.
-- http://creativecommons.org/licenses/by-nc-sa/4.0
-- Mark D. Aagaard
-- Riham AlTawy
-- Guang Gong
-- Kalikinkar Mandal
-- Raghvendra Rohit
-- Marat Sattarov
-- Nusa Zidaric
-- http://uwaterloo.ca/communications-security-lab/lwc/ace
-- This is a human-readable summary of (and not a substitute for) the license.
-- You are free to:
-- Share: copy and redistribute the material in any medium or format
-- Adapt: remix, transform, and build upon the material
-- The licensor cannot revoke these freedoms as long as you follow
-- the license terms.
-- Under the following terms:
-- Attribution — You must give appropriate credit, provide a link to
-- the license, and indicate if changes were made. You may do so in
-- any reasonable manner, but not in any way that suggests the
-- licensor endorses you or your use.
-- NonCommercial — You may not use the material for commercial
-- purposes.
-- ShareAlike — If you remix, transform, or build upon the material,
-- you must distribute your contributions under the same license as
-- the original.
-- No additional restrictions — You may not apply legal terms or
-- technological measures that legally restrict others from doing
-- anything the license permits.
architecture rtl of ace is
signal ctl_control : ace_ctl_ty;
signal ctl_onehot : onehot_ty;
signal ctl_lfsr_en : std_logic;
signal ctl_lfsr_reset : std_logic;
begin
u_dp :
entity work.dp port map
( clk => clk
, reset => reset
, i_mode => i_mode
, i_control => ctl_control
, i_onehot => ctl_onehot
, i_dom_sep => i_dom_sep
, i_valid => i_valid
, i_data => i_data
, i_padding => i_padding
, o_data => o_data
);
u_ctl :
entity work.ctl port map
( clk => clk
, reset => reset
, i_mode => i_mode
, i_dom_sep => i_dom_sep
, i_valid => i_valid
, i_padding => i_padding
, o_valid => o_valid
, o_onehot => ctl_onehot
, o_ready => o_ready
, o_control => ctl_control
);
end architecture;
-- This work is licensed under a Creative Commons
-- Attribution-NonCommercial-ShareAlike 4.0 International License.
-- http://creativecommons.org/licenses/by-nc-sa/4.0
-- Mark D. Aagaard
-- Riham AlTawy
-- Guang Gong
-- Kalikinkar Mandal
-- Raghvendra Rohit
-- Marat Sattarov
-- Nusa Zidaric
-- http://uwaterloo.ca/communications-security-lab/lwc/ace
-- This is a human-readable summary of (and not a substitute for) the license.
-- You are free to:
-- Share: copy and redistribute the material in any medium or format
-- Adapt: remix, transform, and build upon the material
-- The licensor cannot revoke these freedoms as long as you follow
-- the license terms.
-- Under the following terms:
-- Attribution — You must give appropriate credit, provide a link to
-- the license, and indicate if changes were made. You may do so in
-- any reasonable manner, but not in any way that suggests the
-- licensor endorses you or your use.
-- NonCommercial — You may not use the material for commercial
-- purposes.
-- ShareAlike — If you remix, transform, or build upon the material,
-- you must distribute your contributions under the same license as
-- the original.
-- No additional restrictions — You may not apply legal terms or
-- technological measures that legally restrict others from doing
-- anything the license permits.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.ace_pkg.all;
entity ace is
port
( clk : in std_logic;
reset : in std_logic;
i_mode : in mode_ty;
i_dom_sep : in domsep_ty;
i_valid : in std_logic;
i_data : in word;
i_padding : in std_logic;
o_valid : out std_logic;
o_ready : out std_logic;
o_data : out word
);
end entity;
-- This work is licensed under a Creative Commons
-- Attribution-NonCommercial-ShareAlike 4.0 International License.
-- http://creativecommons.org/licenses/by-nc-sa/4.0
-- Mark D. Aagaard
-- Riham AlTawy
-- Guang Gong
-- Kalikinkar Mandal
-- Raghvendra Rohit
-- Marat Sattarov
-- Nusa Zidaric
-- http://uwaterloo.ca/communications-security-lab/lwc/ace
-- This is a human-readable summary of (and not a substitute for) the license.
-- You are free to:
-- Share: copy and redistribute the material in any medium or format
-- Adapt: remix, transform, and build upon the material
-- The licensor cannot revoke these freedoms as long as you follow
-- the license terms.
-- Under the following terms:
-- Attribution — You must give appropriate credit, provide a link to
-- the license, and indicate if changes were made. You may do so in
-- any reasonable manner, but not in any way that suggests the
-- licensor endorses you or your use.
-- NonCommercial — You may not use the material for commercial
-- purposes.
-- ShareAlike — If you remix, transform, or build upon the material,
-- you must distribute your contributions under the same license as
-- the original.
-- No additional restrictions — You may not apply legal terms or
-- technological measures that legally restrict others from doing
-- anything the license permits.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package ace_pkg is
--for constants
constant lfsr_c_sz : integer := 7;
subtype lfsr_c_output is std_logic_vector(0 to lfsr_c_sz+2);
------------------------------------------------------------
constant half_word_sz : natural := 32;
constant word_sz : natural := 2*half_word_sz;
subtype half_word is std_logic_vector( 0 to half_word_sz - 1 );
subtype word is std_logic_vector( 0 to word_sz - 1 );
type word_vector is array( natural range <> ) of word;
type half_word_vector is array( natural range <> ) of half_word;
------------------------------------------------------------
-- A, B, C, D, E
constant state_sz : natural := 320;
constant word_max_idx : natural := state_sz / word_sz - 1;
constant half_word_max_idx : natural := state_sz / half_word_sz - 1;
constant key_sz : natural := 128;
constant nonce_sz : natural := 128;
subtype word_state_ty is word_vector ( 0 to word_max_idx );
constant a_idx : natural := 0;
constant b_idx : natural := 1;
constant c_idx : natural := 2;
constant d_idx : natural := 3;
constant e_idx : natural := 4;
subtype half_word_data is half_word_vector ( 0 to 1 );
subtype half_word_state_ty is half_word_vector ( 0 to half_word_max_idx );
constant a0_idx : natural := 1;
constant a1_idx : natural := 0;
constant b0_idx : natural := 3;
constant b1_idx : natural := 2;
constant c0_idx : natural := 5;
constant c1_idx : natural := 4;
constant d0_idx : natural := 7;
constant d1_idx : natural := 6;
constant e0_idx : natural := 9;
constant e1_idx : natural := 8;
function b2x( b : boolean ) return std_logic;
function half_words_to_words( st : half_word_state_ty ) return word_state_ty;
function words_to_half_words( st : word_state_ty ) return half_word_state_ty;
------------------------------------------------------------
-- mode
subtype mode_ty is std_logic_vector( 1 downto 0 ); -- top lvl input
constant encrypt_mode : mode_ty := ( 1 => '0', 0 => '0' );
constant decrypt_mode : mode_ty := ( 1 => '0', 0 => '1' );
constant absorb_mode : mode_ty := ( 1 => '1', 0 => '0' );
constant squeeze_mode : mode_ty := ( 1 => '1', 0 => '1' );
subtype domsep_ty is std_logic_vector( 1 downto 0 ); -- top lvl input
-- derived control (from counter and more)
subtype ace_ctl_ty is std_logic_vector( 7 downto 0 );
constant absorb_idx : natural := 0;
constant replace_idx : natural := 1;
constant output_idx : natural := 2;
constant endstep_idx : natural := 3;
constant permoff_idx : natural := 4;
constant squeeze_idx : natural := 5;
constant lfsr_c_reset_idx : natural := 6;
constant lfsr_c_en_idx : natural := 7;
-- extras cntl for load, init, fin, tag, sqeeze
subtype onehot_ty is std_logic_vector( 3 downto 0); -- extrs cntl for load, init, fin, tag, sqeeze
------------------------------------------------------------
-- round and step counters
-- use last bit for end ACE perm - for o_ready
-- -> i_valid will reset the counter!
-- counter only runs if msb = 0
constant bits_counter : natural := 8;
subtype count_ty is unsigned( bits_counter - 1 downto 0 );
----------------------------------------------------------------------
-- standard vhdl operators
-- function "sll"( a : half_word; n : natural ) return half_word;
function onehot_rotate (a : onehot_ty) return onehot_ty;
function vector_to_data ( st : half_word_data ) return word;
function data_to_vector ( st : word ) return half_word_data;
----------------------------------------------------------------------
end package;
----------------------------------------------------------------------
--
----------------------------------------------------------------------
package body ace_pkg is
function onehot_rotate (a : onehot_ty)
return onehot_ty
is
variable z : onehot_ty;
begin
z(onehot_ty'high downto 1) := a(onehot_ty'high - 1 downto 0);
z(0) := a(onehot_ty'high);
return z;
end function;
function b2x( b : boolean ) return std_logic is
begin
if b then
return '1';
else
return '0';
end if;
end function;
------------------------------------------------------------
-- standard vhdl operators cast to state
------------------------------------------------------------
-- function "sll"( a : half_word; n : natural ) return half_word is
-- begin
-- return half_word( std_logic_vector( a ) sll n );
-- end function;
------------------------------------------------------------
-- state functions
------------------------------------------------------------
function half_words_to_words( st : half_word_state_ty ) ---- CHECK THIS!!!!!! PLEASE
return word_state_ty
is
variable i : natural;
variable z : word_state_ty;
begin
main_loop : for i in 0 to word_max_idx loop
z(i)(0 to half_word_sz - 1) := st(2*i);
z(i)(half_word_sz to word_sz - 1) := st(2*i+1);
end loop;
return z;
end function;
function words_to_half_words( st : word_state_ty )
return half_word_state_ty
is
variable i : natural;
variable z : half_word_state_ty;
begin
main_loop : for i in 0 to word_max_idx loop
z(2*i) := st(i)(0 to half_word_sz - 1);
z(2*i+1) := st(i)(half_word_sz to word_sz - 1);
end loop;
return z;
end function;
function data_to_vector( st : word )
return half_word_data
is
variable z : half_word_data;
begin
z(0) := st(0 to half_word_sz - 1);
z(1) := st(half_word_sz to word_sz - 1);
return z;
end function;
function vector_to_data( st : half_word_data )
return word
is
variable z : word;
begin
z(0 to half_word_sz - 1) := st(0);
z(half_word_sz to word_sz - 1) := st(1);
return z;
end function;
end package body;
if { $gui_mode } {
add wave clk
add wave reset
add wave i_mode
add wave i_dom_sep
add wave o_ready
add wave i_valid
add wave i_data
add wave i_padding
add wave o_valid
add wave o_data
if { $sim_mode eq "PROG_MODE" } then {
add wave -noupdate -divider -height 32 STUFF
add wave /uut/u_ctl/state
add wave /uut/u_ctl/o_ready
add wave /uut/u_ctl/i_valid
add wave /uut/u_dp/i_data
add wave /uut/u_ctl/o_valid
add wave /uut/u_dp/o_data
add wave -noupdate -divider -height 32 DP
add wave -radix binary /uut/u_dp/ctl_const
add wave /uut/u_dp/i_data
add wave /uut/u_dp/o_data
add wave -radix binary /uut/u_dp/ctl_const
add wave /uut/u_dp/lfsr_c_en
add wave /uut/u_dp/lfsr_c_reset
add wave /uut/u_dp/permoff
add wave /uut/u_dp/endstep
add wave /uut/u_dp/absorb
add wave /uut/u_dp/replace
add wave /uut/u_dp/output
add wave /uut/u_dp/dsxor
add wave /uut/u_dp/post_input
add wave /uut/u_dp/pre_round
add wave /uut/u_dp/post_round
add wave /uut/u_dp/post_xor
add wave /uut/u_dp/post_step_const
add wave /uut/u_dp/post_linear
add wave /uut/u_dp/ace_path
add wave /uut/u_dp/ace_state
add wave -noupdate -divider -height 32 CTL
add wave /uut/u_ctl/state
add wave -radix unsigned /uut/u_ctl/count
add wave /uut/u_ctl/i_valid
add wave /uut/u_ctl/o_valid
add wave /uut/u_ctl/o_ready
add wave -radix binary /uut/u_ctl/onehot
add wave /uut/u_ctl/lfsr_c_reset
add wave -radix binary /uut/u_ctl/i_mode
add wave -radix binary /uut/u_ctl/i_dom_sep
}
}
vcd file uw_tmp/ace.vcd
vcd add /ace_tb/uut/*
vcd add -r *
vcd on
run -all
vcd checkpoint
vcd off
vcd flush
if { $gui_mode } {
wave zoom full
} else {
exit
}
**** Line 63 (old) / 63 (new) ****
Description:
Moved EDH to the list of generics
Change:
; EDH : std_logic_vector(0 to 2) := "111" -- ENCRYPTION, DECRYPTION, HASH bits. example: 'xx0' = don't do HASH, 'xx1' = do HASH
**** Line 68 (old) / 69 (new) ****
Description:
Removed EDH signal declaration
**** Line 91,96 (old) / 92,98 (new) ****
Description:
Added new signal declarations to delay primary inputs after clock edge
Change:
signal i_mode_buf : mode_ty;
signal i_dom_sep_buf : domsep_ty;
**** Line 114 (old) / 117 - 125 (new) ****
Description:
added new processes to delay a change in primary inputs after clock edge
Change:
i_dom_sep_proc : process(i_dom_sep_buf)
begin
i_dom_sep <= i_dom_sep_buf after hold;
end process;
i_mode_proc : process(i_mode_buf)
begin
i_mode <= i_mode_buf after hold;
end process;
**** Line 199 (old) / 212 (new) ****
**** Line 285 (old) / 304 (new) ****
**** Line 370 (old) / 395 (new) ****
**** Line 390 (old) / 416 (new) ****
Description:
changed signal name
Change:
was
i_mode
now
i_mode_buf
**** Line 216 (old) / 229 (new) ****
**** Line 226 (old) / 241 (new) ****
**** Line 234 (old) / 250 (new) ****
**** Line 239 (old) / 256 (new) ****
**** Line 265 (old) / 284 (new) ****
**** Line 303 (old) / 322 (new) ****
**** Line 314 (old) / 335 (new) ****
**** Line 324 (old) / 346 (new) ****
**** Line 330 (old) / 353 (new) ****
**** Line 358 (old) / 383 (new) ****
**** Line 382 (old) / 406 (new) ****
Description:
changed signal name
Change:
was
i_dom_sep
now
i_dom_sep_buf
**** Line 202 (old) / 215 (new) ****
**** Line 287 (old) / 306 (new) ****
**** Line 372 (old) / 396 (new) ****
**** Line 387 (old) / 413 (new) ****
Description:
Hold statements are now in ace_unsynth.vhd
Change:
removed
wait for hold;
**** Line 383 (old) / 407 (new) ****
Description
Added a report
Change:
report( "HASH DRIVE ALL" );
**** Line 130 (old), 132 (new) ****
**** Line 198 (old), 200 (new) ****
**** Line 227 (old), 230 (new) ****
Description:
added a hold statement to delay primary inputs from clock edge
Change:
wait for hold;
The file dp_pure.vhd was removed from the submission, because it is not part of the functional complete cipher.
-- This work is licensed under a Creative Commons
-- Attribution-NonCommercial-ShareAlike 4.0 International License.
-- http://creativecommons.org/licenses/by-nc-sa/4.0
-- Mark D. Aagaard
-- Riham AlTawy
-- Guang Gong
-- Kalikinkar Mandal
-- Raghvendra Rohit
-- Marat Sattarov
-- Nusa Zidaric
-- http://uwaterloo.ca/communications-security-lab/lwc/ace
-- This is a human-readable summary of (and not a substitute for) the license.
-- You are free to:
-- Share: copy and redistribute the material in any medium or format
-- Adapt: remix, transform, and build upon the material
-- The licensor cannot revoke these freedoms as long as you follow
-- the license terms.
-- Under the following terms:
-- Attribution — You must give appropriate credit, provide a link to
-- the license, and indicate if changes were made. You may do so in
-- any reasonable manner, but not in any way that suggests the
-- licensor endorses you or your use.
-- NonCommercial — You may not use the material for commercial
-- purposes.
-- ShareAlike — If you remix, transform, or build upon the material,
-- you must distribute your contributions under the same license as
-- the original.
-- No additional restrictions — You may not apply legal terms or
-- technological measures that legally restrict others from doing
-- anything the license permits.
library ieee;
use ieee.std_logic_1164.all;
use work.ace_pkg.all;
entity lfsr_c is
port
( clk : in std_logic
; lfsr_c_en : in std_logic
; lfsr_c_reset : in std_logic
; o_const : out lfsr_c_output
);
end lfsr_c;
architecture rtl of lfsr_c is
signal sa: std_logic_vector(lfsr_c_sz - 1 downto 0);
signal xa: std_logic_vector(lfsr_c_sz + 2 downto 0);
begin
-- 10 output bits for the constants
o_const <= xa; -- "to" type <= "downto" type. Index flip intended
-- just rename signal
xa(lfsr_c_sz-1 downto 0) <= sa(lfsr_c_sz-1 downto 0);
-- for updates and outputs
xa(lfsr_c_sz + 2 downto lfsr_c_sz) <= xa(3 downto 1) xor xa(2 downto 0);
lfsr_shift: for i in lfsr_c_sz-1 downto 0 generate
lfsr_step: process(clk) begin
if rising_edge(clk) then
if lfsr_c_reset ='1' then
sa(i) <= '1';
elsif lfsr_c_en ='1' then
sa(i) <= xa(i+3);
end if;
end if;
end process;
end generate lfsr_shift;
end;
------------ ACE readme file ---------------
----- list of files for ACE synthesis: -----
ace_pkg.vhd -- main package
sb_64.vhd -- s-box with simeck
lfsr.vhd -- lfsr for step / round constant generation
ctl.vhd -- control (FSM)
dp.vhd -- datapath
ace.vhd -- top level entity declaration
ace-rtl.vhd -- top level architecture
----- additional files for simulation: -----
util_unsynth.vhd -- functions used in TB (general purpose)
ace_unsynth.vhd -- specific ACE functions and procedures used in TB
ace_tb.vhd -- ACE testbench
-------------- pure datapath ---------------
dp_pure.vhd -- datapath with most input/output multiplexers removed
----------- TB info (ace_tb.vhd): ----------
********
EDH is a 3-bit constant used to select which modes to test
"100" - encryption only
"010" - decyption only
"001" - hash only
"110" - encryption and decryption
etc.
********
stim_file_path -- stimulus file
output_file_path -- output file
********
------------ stimulus file format --------------
1 file = 1 set of Key, Nonce, AD, Plaintext and Ciphertext
K 00111122335588DD00111122335588DD <--- 128 bits of Key (all 128 bits in a single line)
N 111122335588DD00111122335588DD00 <--- 128 bits of Nonce (all 128 bits in a single line)
A 1122335588DD00111122335588DD00 <--- from 4 to 128 bits of AD
P 335588DD00111122335588DD001111 <--- from 4 to 128 bits of Plaintext
C F9362385DC213A07CEFEF38C34CEFF <--- from 4 to 128 bits of Ciphertext
--- padding is done by testbench
--- multiple lines for AD, Plaintext and Ciphertext are supported
-- This work is licensed under a Creative Commons
-- Attribution-NonCommercial-ShareAlike 4.0 International License.
-- http://creativecommons.org/licenses/by-nc-sa/4.0
-- Mark D. Aagaard
-- Riham AlTawy
-- Guang Gong
-- Kalikinkar Mandal
-- Raghvendra Rohit
-- Marat Sattarov
-- Nusa Zidaric
-- http://uwaterloo.ca/communications-security-lab/lwc/ace
-- This is a human-readable summary of (and not a substitute for) the license.
-- You are free to:
-- Share: copy and redistribute the material in any medium or format
-- Adapt: remix, transform, and build upon the material
-- The licensor cannot revoke these freedoms as long as you follow
-- the license terms.
-- Under the following terms:
-- Attribution — You must give appropriate credit, provide a link to
-- the license, and indicate if changes were made. You may do so in
-- any reasonable manner, but not in any way that suggests the
-- licensor endorses you or your use.
-- NonCommercial — You may not use the material for commercial
-- purposes.
-- ShareAlike — If you remix, transform, or build upon the material,
-- you must distribute your contributions under the same license as
-- the original.
-- No additional restrictions — You may not apply legal terms or
-- technological measures that legally restrict others from doing
-- anything the license permits.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.ace_pkg.all;
entity sb_64 is
port
( i_state : in word
; i_rc : in std_logic
; o_state : out word
);
end entity;
architecture rtl of sb_64 is
signal x0, x1, z0, z1 : half_word;
signal rc : half_word;
begin
x1 <= i_state( 0 to half_word_sz-1 );
x0 <= i_state( half_word_sz to word_sz - 1 );
rc <= ( 0 to half_word_sz - 2 => '1', half_word_sz - 1 => i_rc );
z0 <= x1;
z1 <= ( ( x1(5 to half_word_sz - 1) & x1 (0 to 4) ) and x1)
xor ( x1(1 to half_word_sz - 1) & x1 (0) )
xor x0
xor rc;
o_state <= z1 & z0;
end architecture;
#!/bin/sh
tgpp -file drygascon128.tgpp.v
FILES="tb_drygascon128.v drygascon128.v"
FLAGS="+interp +dump2fst +fst+parallel2=on"
#cvc64 +xprop2 +dump2fst +fst+parallel2=on tb_data_path.v ctrl.v gf2m_alu.v gf2m_mul.v
cvc64 $FLAGS $FILES
FILES="tb_drygascon128.v drygascon128_ACC_PIPE.v"
cvc64 $FLAGS $FILES
FILES="tb_drygascon128.v drygascon128_ACC_PIPE_MIX_SHIFT_REG.v"
cvc64 $FLAGS $FILES
#!/bin/sh
FILES="tb_drygascon128.v drygascon128_use_funcs.v"
FLAGS="+interp +dump2fst +fst+parallel2=on"
cvc64 $FLAGS $FILES
#!/bin/sh
PATH=/opt/Xilinx/Vivado/2018.3/bin:$PATH
mkdir -p xsim
cd xsim
../xsim.py --top tb_drygascon128 --src ../tb_drygascon128.v --src ../drygascon128.v --log ../xsim.log
#!/bin/sh
FILES="tb_wrapper.v wrapper.v drygascon128_use_funcs.v"
FLAGS="+interp +dump2fst +fst+parallel2=on"
cvc64 $FLAGS $FILES
//Configuration flags: ""
`timescale 1ns / 1ps
`default_nettype none
module birotr(
input wire [64-1:0] din,
input wire [ 6-1:0] shift,
output reg [64-1:0] out
);
wire [32-1:0] i0 = din[0*32+:32];
wire [32-1:0] i1 = din[1*32+:32];
wire [ 6-1:0] shift2 = shift>>1;
wire [ 6-1:0] shift3 = (shift2 + 1'b1) % 6'd32;
always @* begin
if(shift & 1'b1) begin
out[ 0+:32] = (i1>>shift2) | (i1 << (6'd32-shift2));
out[32+:32] = (i0>>shift3) | (i0 << (6'd32-shift3));
end else begin
out[ 0+:32] = (i0>>shift2) | (i0 << (6'd32-shift2));
out[32+:32] = (i1>>shift2) | (i1 << (6'd32-shift2));
end
end
endmodule
module gascon5_round(
input wire [320-1:0] din,
input wire [4-1:0] round,
output reg [320-1:0] out
);
wire [5*6-1:0] rot_lut0 = {6'd07,6'd10,6'd01,6'd61,6'd19};
wire [5*6-1:0] rot_lut1 = {6'd40,6'd17,6'd06,6'd38,6'd28};
reg [7:0] round_constant;
always @* round_constant = (((4'hf - round)<<4) | round);
reg [320-1:0] add_constant_out;
always @* add_constant_out = din ^ {{5*64-8-2*64{1'b0}},round_constant,{2*64{1'b0}}};
reg [320-1:0] sbox_stage0;
always @* begin
sbox_stage0 = add_constant_out;
sbox_stage0[0*64+:64] = add_constant_out[0*64+:64] ^ add_constant_out[4*64+:64];
sbox_stage0[2*64+:64] = add_constant_out[2*64+:64] ^ add_constant_out[1*64+:64];
sbox_stage0[4*64+:64] = add_constant_out[4*64+:64] ^ add_constant_out[3*64+:64];
end
reg [320-1:0] t;
always @* begin
t[0*64+:64] = (~sbox_stage0[0*64+:64]) & sbox_stage0[1*64+:64];
t[1*64+:64] = (~sbox_stage0[1*64+:64]) & sbox_stage0[2*64+:64];
t[2*64+:64] = (~sbox_stage0[2*64+:64]) & sbox_stage0[3*64+:64];
t[3*64+:64] = (~sbox_stage0[3*64+:64]) & sbox_stage0[4*64+:64];
t[4*64+:64] = (~sbox_stage0[4*64+:64]) & sbox_stage0[0*64+:64];
end
reg [320-1:0] sbox_stage1;
always @* begin
sbox_stage1[0*64+:64] = sbox_stage0[0*64+:64] ^ t[1*64+:64];
sbox_stage1[1*64+:64] = sbox_stage0[1*64+:64] ^ t[2*64+:64];
sbox_stage1[2*64+:64] = sbox_stage0[2*64+:64] ^ t[3*64+:64];
sbox_stage1[3*64+:64] = sbox_stage0[3*64+:64] ^ t[4*64+:64];
sbox_stage1[4*64+:64] = sbox_stage0[4*64+:64] ^ t[0*64+:64];
end
reg [320-1:0] sbox_stage2;
always @* begin
sbox_stage2 = sbox_stage1;
sbox_stage2[1*64+:64] = sbox_stage1[1*64+:64] ^ sbox_stage1[0*64+:64];
sbox_stage2[3*64+:64] = sbox_stage1[3*64+:64] ^ sbox_stage1[2*64+:64];
sbox_stage2[0*64+:64] = sbox_stage1[0*64+:64] ^ sbox_stage1[4*64+:64];
end
reg [320-1:0] sbox_stage3;
always @* begin
sbox_stage3 = sbox_stage2;
sbox_stage3[2*64+:64] = ~sbox_stage2[2*64+:64];
end
wire [320-1:0] lin_layer_r0;
wire [320-1:0] lin_layer_r1;
birotr u_birotr00(.out(lin_layer_r0[0*64+:64]), .din(sbox_stage3[0*64+:64]), .shift(6'd19));
birotr u_birotr10(.out(lin_layer_r1[0*64+:64]), .din(sbox_stage3[0*64+:64]), .shift(6'd28));
birotr u_birotr01(.out(lin_layer_r0[1*64+:64]), .din(sbox_stage3[1*64+:64]), .shift(6'd61));
birotr u_birotr11(.out(lin_layer_r1[1*64+:64]), .din(sbox_stage3[1*64+:64]), .shift(6'd38));
birotr u_birotr02(.out(lin_layer_r0[2*64+:64]), .din(sbox_stage3[2*64+:64]), .shift(6'd01));
birotr u_birotr12(.out(lin_layer_r1[2*64+:64]), .din(sbox_stage3[2*64+:64]), .shift(6'd06));
birotr u_birotr03(.out(lin_layer_r0[3*64+:64]), .din(sbox_stage3[3*64+:64]), .shift(6'd10));
birotr u_birotr13(.out(lin_layer_r1[3*64+:64]), .din(sbox_stage3[3*64+:64]), .shift(6'd17));
birotr u_birotr04(.out(lin_layer_r0[4*64+:64]), .din(sbox_stage3[4*64+:64]), .shift(6'd07));
birotr u_birotr14(.out(lin_layer_r1[4*64+:64]), .din(sbox_stage3[4*64+:64]), .shift(6'd40));
reg [320-1:0] lin_layer;
always @* begin
lin_layer[0*64+:64] = sbox_stage3[0*64+:64] ^ lin_layer_r0[0*64+:64] ^ lin_layer_r1[0*64+:64];
lin_layer[1*64+:64] = sbox_stage3[1*64+:64] ^ lin_layer_r0[1*64+:64] ^ lin_layer_r1[1*64+:64];
lin_layer[2*64+:64] = sbox_stage3[2*64+:64] ^ lin_layer_r0[2*64+:64] ^ lin_layer_r1[2*64+:64];
lin_layer[3*64+:64] = sbox_stage3[3*64+:64] ^ lin_layer_r0[3*64+:64] ^ lin_layer_r1[3*64+:64];
lin_layer[4*64+:64] = sbox_stage3[4*64+:64] ^ lin_layer_r0[4*64+:64] ^ lin_layer_r1[4*64+:64];
end
always @* out = lin_layer;
endmodule
module mixsx32(
input wire [320-1:0] c,
input wire [128-1:0] x,
input wire [10-1:0] d,
output reg [320-1:0] out
);
reg [2-1:0] idx0;
reg [32-1:0] xw0;
always @* idx0 = d[0*2+:2];
always @* xw0 = x[idx0*32+:32];
always @* out[0*64+:64] = c[0*64+:64] ^ {{32{1'b0}},xw0};
reg [2-1:0] idx1;
reg [32-1:0] xw1;
always @* idx1 = d[1*2+:2];
always @* xw1 = x[idx1*32+:32];
always @* out[1*64+:64] = c[1*64+:64] ^ {{32{1'b0}},xw1};
reg [2-1:0] idx2;
reg [32-1:0] xw2;
always @* idx2 = d[2*2+:2];
always @* xw2 = x[idx2*32+:32];
always @* out[2*64+:64] = c[2*64+:64] ^ {{32{1'b0}},xw2};
reg [2-1:0] idx3;
reg [32-1:0] xw3;
always @* idx3 = d[3*2+:2];
always @* xw3 = x[idx3*32+:32];
always @* out[3*64+:64] = c[3*64+:64] ^ {{32{1'b0}},xw3};
reg [2-1:0] idx4;
reg [32-1:0] xw4;
always @* idx4 = d[4*2+:2];
always @* xw4 = x[idx4*32+:32];
always @* out[4*64+:64] = c[4*64+:64] ^ {{32{1'b0}},xw4};
endmodule
module accumulate(
input wire [256-1:0] din,
input wire [128-1:0] r,
output reg [128-1:0] out
);
always @* out = r ^ din[0+:128] ^ {din[128+:32],din[128+32+:96]};
endmodule
//F and G
module drygascon128(
input wire clk,
input wire clk_en,
input wire rst,
input wire [31:0] din,
input wire [3:0] ds,
input wire wr_i,
input wire wr_c,
input wire wr_x,
input wire [3:0] rounds,
input wire start,
input wire rd_r,
input wire rd_c,
output reg [31:0] dout,
output reg idle
);
localparam C_QWORDS = 5;
localparam X_QWORDS = 2;
localparam R_QWORDS = 2;
localparam CIDX_WIDTH = 3;//log2(X_QWORDS)
localparam XIDX_WIDTH = 2;//log2(X_QWORDS*2)
localparam C_DWORDS = C_QWORDS * 2;
localparam C_WIDTH = C_QWORDS * 64;
localparam X_DWORDS = X_QWORDS * 2;
localparam X_WIDTH = X_QWORDS * 64;
localparam R_DWORDS = R_QWORDS*2;
localparam R_WIDTH = R_QWORDS*64;
reg [C_WIDTH-1:0] c;
reg [X_WIDTH-1:0] x;
reg [R_WIDTH-1:0] r;
reg absorb;
reg [3:0] cnt;
always @(posedge clk) begin
if(clk_en) begin
case(1'b1)
rd_c: dout <= c[cnt*32+:32];
rd_r: dout <= r[cnt*32+:32];
default: dout <= {32{1'b0}};
endcase
end
end
localparam D_WIDTH = C_QWORDS*XIDX_WIDTH;
localparam MIX_ROUNDS = (R_WIDTH+4+D_WIDTH-1)/D_WIDTH;
reg [D_WIDTH-1:0] d;
wire [C_WIDTH-1:0] mixsx32_out;
reg [C_WIDTH-1:0] core_in;
reg [3:0] core_round;
wire [C_WIDTH-1:0] core_out;
wire [128-1:0] accu_out;
localparam MIX_I_PAD = D_WIDTH*MIX_ROUNDS - R_WIDTH+4;
reg [D_WIDTH*MIX_ROUNDS-1:0] mix_i;
always @* mix_i = {{MIX_I_PAD{1'b0}},ds,r};
always @* d = mix_i[cnt*D_WIDTH+:D_WIDTH];
mixsx32 u_mixsx32(.out(mixsx32_out), .c(c), .x(x), .d(d));
always @* core_in = absorb ? mixsx32_out : c;
always @* core_round = absorb ? {4{1'b0}} : cnt;
gascon5_round u_gascon5_round(.out(core_out), .din(core_in), .round(core_round));
accumulate u_accumulate(.out(accu_out), .din(core_out[0+:256]), .r(r));
localparam STATE_WIDTH = 2;
localparam STATE_IDLE = 2'b00;
localparam STATE_MIX_ENTRY = 2'b01;
localparam STATE_G_ENTRY = 2'b10;
reg [STATE_WIDTH-1:0] state;
always @(posedge clk) begin
if(clk_en) begin
if(rst) begin
state <= STATE_IDLE;
absorb <= 1'b0;
cnt <= {4{1'b0}};
idle <= 1'b1;
end else begin
case(state)
STATE_IDLE: begin
if(wr_i) begin
r[cnt*32+:32] <= din;
absorb <= 1'b1;
end
if(wr_c) begin
c[cnt*32+:32] <= din;
end
if(wr_x) begin
x <= {din,x[32+:X_WIDTH-32]};
end
case(1'b1)
wr_c,rd_c: cnt <= (cnt + 1'b1) % C_DWORDS;
wr_x: cnt <= (cnt + 1'b1) % X_DWORDS;
wr_i,rd_r: cnt <= (cnt + 1'b1) % R_DWORDS;
endcase
if(start) begin
if(absorb) begin
state <= STATE_MIX_ENTRY;
end else begin
r <= {R_WIDTH{1'b0}};
state <= STATE_G_ENTRY;
end
cnt <= {4{1'b0}};
idle <= 1'b0;
end
end
STATE_MIX_ENTRY: begin
c <= core_out;
if(MIX_ROUNDS-2==cnt) begin
r <= {R_WIDTH{1'b0}};
cnt <= cnt +1'b1;//to get last chunk
state <= STATE_G_ENTRY;//let absorb for the first round to consume last chunk
end else begin
cnt <= cnt +1'b1;
end
end
STATE_G_ENTRY: begin
//$display("round = %d",core_round);
//$display("core_in: %X",int_to_le(core_in));
//$display("core_out: %X",int_to_le(core_out));
//$display("accu_out: %X",int128_to_le(accu_out));
absorb <= 1'b0;
c <= core_out;
r <= accu_out;
if(rounds-1==cnt) begin
cnt <= {4{1'b0}};
state <= STATE_IDLE;
idle <= 1'b1;
end else begin
cnt <= absorb ? {{3{1'b0}},1'b1} : cnt +1'b1;
end
end
//default: begin
//end
endcase
end
end
end
endmodule
`default_nettype wire
//module generated using Spinal HDL, verified using VexRiscv - Murax SOC
module drygascon128_apb3 (
input [7:0] io_apb_PADDR,
input [0:0] io_apb_PSEL,
input io_apb_PENABLE,
output io_apb_PREADY,
input io_apb_PWRITE,
input [31:0] io_apb_PWDATA,
output reg [31:0] io_apb_PRDATA,
output io_apb_PSLVERROR,
input toplevel_resetCtrl_systemReset,
input toplevel_io_mainClk);
wire _zz_1_;
wire [31:0] core_dout;
wire core_idle;
wire selected;
wire askWrite;
wire askRead;
wire doWrite;
wire doRead;
reg start;
reg [3:0] ds;
reg [3:0] rounds;
reg rd_c;
reg wr_c;
reg rd_r;
reg wr_x;
reg wr_i;
wire [31:0] ctrl;
wire [31:0] zeroes;
wire ctrl_hit;
drygascon128 core (
.clk(toplevel_io_mainClk),
.clk_en(_zz_1_),
.rst(toplevel_resetCtrl_systemReset),
.din(io_apb_PWDATA),
.ds(ds),
.wr_i(wr_i),
.wr_c(wr_c),
.wr_x(wr_x),
.rounds(rounds),
.start(start),
.rd_r(rd_r),
.rd_c(rd_c),
.dout(core_dout),
.idle(core_idle)
);
assign _zz_1_ = 1'b1;
assign selected = (io_apb_PSEL[0] && io_apb_PENABLE);
assign askWrite = (selected && io_apb_PWRITE);
assign askRead = (selected && (! io_apb_PWRITE));
assign doWrite = ((selected && io_apb_PREADY) && io_apb_PWRITE);
assign doRead = ((selected && io_apb_PREADY) && (! io_apb_PWRITE));
assign zeroes = (1'b0 ? (32'b11111111111111111111111111111111) : (32'b00000000000000000000000000000000));
assign ctrl = {{{{core_idle,zeroes[30 : 9]},start},ds},rounds};
assign io_apb_PSLVERROR = 1'b0;
assign io_apb_PREADY = 1'b1;
always @ (*) begin
rd_c = 1'b0;
wr_c = 1'b0;
rd_r = 1'b0;
wr_x = 1'b0;
wr_i = 1'b0;
io_apb_PRDATA = (32'b00001110101011011011111011101111);
if(selected)begin
case(io_apb_PADDR)
8'b00000000 : begin
io_apb_PRDATA = ctrl;
end
8'b00000100 : begin
io_apb_PRDATA = core_dout;
rd_c = (! doWrite);
wr_c = doWrite;
end
8'b00001000 : begin
io_apb_PRDATA = core_dout;
rd_r = (! doWrite);
wr_i = doWrite;
end
8'b00001100 : begin
wr_x = doWrite;
end
default : begin
end
endcase
end
end
assign ctrl_hit = (selected && (io_apb_PADDR == (8'b00000000)));
always @ (posedge toplevel_io_mainClk or posedge toplevel_resetCtrl_systemReset) begin
if (toplevel_resetCtrl_systemReset) begin
start <= 1'b0;
ds <= (4'b0000);
rounds <= (4'b1011);
end else begin
start <= 1'b0;
if((doWrite && ctrl_hit))begin
rounds <= io_apb_PWDATA[3 : 0];
ds <= io_apb_PWDATA[7 : 4];
start <= io_apb_PWDATA[8];
end
end
end
endmodule
`ifndef __DRYGASCON128_FUNCTIONS__
`define __DRYGASCON128_FUNCTIONS__
function [320-1:0] int_to_le;
input [320-1:0] din;
reg [320-1:0] o;
integer i;
begin
o = {320{1'b0}};
for(i=0;i<8*5;i=i+1) begin
o[320-1-i*8-:8] = din[i*8+:8];
end
int_to_le = o;
end
endfunction
function [320-1:0] le_to_int;
input [320-1:0] din;
reg [320-1:0] o;
integer i;
begin
o = {320{1'b0}};
for(i=0;i<8*5;i=i+1) begin
o[i*8+:8] = din[320-1-i*8-:8];
end
le_to_int = o;
end
endfunction
function [128-1:0] int128_to_le;
input [128-1:0] din;
reg [128-1:0] o;
integer i;
begin
o = {128{1'b0}};
for(i=0;i<8*4;i=i+1) begin
o[128-1-i*8-:8] = din[i*8+:8];
end
int128_to_le = o;
end
endfunction
function [128-1:0] le_to_int128;
input [128-1:0] din;
reg [128-1:0] o;
integer i;
begin
o = {128{1'b0}};
for(i=0;i<8*4;i=i+1) begin
o[i*8+:8] = din[128-1-i*8-:8];
end
le_to_int128 = o;
end
endfunction
function [64-1:0] int64_to_le;
input [64-1:0] din;
reg [64-1:0] o;
integer i;
begin
o = {64{1'b0}};
for(i=0;i<8;i=i+1) begin
o[64-1-i*8-:8] = din[i*8+:8];
end
int64_to_le = o;
end
endfunction
function [64-1:0] le_to_int64;
input [64-1:0] din;
reg [64-1:0] o;
integer i;
begin
o = {64{1'b0}};
for(i=0;i<8;i=i+1) begin
o[i*8+:8] = din[64-1-i*8-:8];
end
le_to_int64 = o;
end
endfunction
function [128-1:0] accumulate;
input [256-1:0] din;
input [128-1:0] r;
reg [128-1:0] o;
begin
accumulate = r ^ din[0+:128] ^ {din[128+:32],din[128+32+:96]};
end
endfunction
function [32-1:0] rotr32;
input [32-1:0] din;
input [ 5-1:0] shift;
reg [5:0] i;
reg [32-1:0] o;
begin
o = {32{1'b0}};
for(i=0;i<32;i=i+1'b1) begin
//o[(i+32-shift)%32] = din[i];
o[i] = din[(i+shift)%32];
end
rotr32 = o;
end
endfunction
function [64-1:0] birotr;
input [64-1:0] din;
input [ 6-1:0] shift;
reg [32-1:0] i0;
reg [32-1:0] i1;
reg [32-1:0] t;
integer shift2;
begin
shift2 = shift>>1;
i0 = din[0*32+:32];
i1 = din[1*32+:32];
if(shift & 1'b1) begin
t = rotr32(i1,shift2);
i1 = rotr32(i0,(shift2+1'b1)%32);
i0 = t;
end else begin
i0 = rotr32(i0,shift2);
i1 = rotr32(i1,shift2);
end
birotr = {i1,i0};
end
endfunction
wire [5*6-1:0] rot_lut0 = {6'd07,6'd10,6'd01,6'd61,6'd19};
wire [5*6-1:0] rot_lut1 = {6'd40,6'd17,6'd06,6'd38,6'd28};
//function print_words64;
// input [320-1:0] c;
// integer i;
//begin
// for(i=0;i<5;i=i+1) begin
// $display("%x",c[i*64+:64]);
// end
// print_words64 = 0;
//end
//endfunction
function [320-1:0] gascon5_round;
input [320-1:0] din;
input [4-1:0] round;
reg [4-1:0] r;
integer i;
integer mid;
integer cwords;
integer d;
integer s;
reg [64-1:0] wi;
reg [64-1:0] ws;
reg [320-1:0] t;
reg [320-1:0] c;
integer dummy;
begin
c = din;
mid = 2;
cwords = 5;
//$display("i: %x",c);
//add constant
r = round;
c[mid*64+:64] = c[mid*64+:64] ^ (((4'hf - r)<<4) | r);
//$display("c mid: %x, r=%x",c[mid*64+:64],r);
//$display("c: %x",c);
//sbox
for(i=0;i<=2;i=i+1'b1) begin
d = 2*i;
s = (cwords + d - 1'b1) % cwords;
c[d*64+:64] = c[d*64+:64] ^ c[s*64+:64];
end
for(i=0;i<cwords;i=i+1'b1) begin
s = (i+1) % cwords;
wi = c[i*64+:64];
ws = c[s*64+:64];
t[i*64+:64] = (~wi) & ws;
end
for(i=0;i<cwords;i=i+1'b1) begin
s = (i+1) % cwords;
c[i*64+:64] = c[i*64+:64] ^ t[s*64+:64];
end
for(i=0;i<=2;i=i+1'b1) begin
s = 2*i;
d = (s + 1'b1) % cwords;
c[d*64+:64] = c[d*64+:64] ^ c[s*64+:64];
end
c[mid*64+:64] = ~c[mid*64+:64];
//$display("c: %x",c);
//linlayer
for(i=0;i<3'd5;i=i+1'b1) begin
c[i*64+:64] = c[i*64+:64] ^ birotr(c[i*64+:64],rot_lut0[i*6+:6]) ^ birotr(c[i*64+:64],rot_lut1[i*6+:6]);
end
//$display("c: %x",c);
//$display("c: ");dummy=print_words64(c);
gascon5_round = c;
end
endfunction
function [320-1:0] mixsx32;
input [320-1:0] c;
input [128-1:0] x;
input [10-1:0] d;
reg [320-1:0] co;
reg [2-1:0] idx;
reg [32-1:0] xw;
integer j;
begin
co = c;
for(j=0;j<5;j=j+1) begin
idx = d[j*2+:2];
xw = x[idx*32+:32];
co[j*2*32+:32] = co[j*2*32+:32] ^ xw;
end
mixsx32 = co;
end
endfunction
function [3:0] compute_ds;
input padded;
input [1:0] domain;
input finalize;
begin
compute_ds = {domain,finalize,padded};
end
endfunction
`endif
`timescale 1ns / 1ps
`default_nettype none
//F and G
module drygascon128(
input wire clk,
input wire clk_en,
input wire rst,
input wire [31:0] din,
input wire [3:0] ds,
input wire wr_i,
input wire wr_c,
input wire wr_x,
input wire [3:0] rounds,
input wire start,
input wire rd_r,
input wire rd_c,
output reg [31:0] dout,
output reg idle
);
`include "drygascon128_functions.v"
localparam C_QWORDS = 5;
localparam X_QWORDS = 2;
localparam R_QWORDS = 2;
localparam CIDX_WIDTH = 3;//log2(X_QWORDS)
localparam XIDX_WIDTH = 2;//log2(X_QWORDS*2)
localparam C_DWORDS = C_QWORDS * 2;
localparam C_WIDTH = C_QWORDS * 64;
localparam X_DWORDS = X_QWORDS * 2;
localparam X_WIDTH = X_QWORDS * 64;
localparam R_DWORDS = R_QWORDS*2;
localparam R_WIDTH = R_QWORDS*64;
reg [C_WIDTH-1:0] c;
reg [X_WIDTH-1:0] x;
reg [R_WIDTH-1:0] r;
reg absorb;
reg [3:0] cnt;
always @(posedge clk) begin
if(clk_en) begin
case(1'b1)
rd_c: dout <= c[cnt*32+:32];
rd_r: dout <= r[cnt*32+:32];
default: dout <= {32{1'b0}};
endcase
end
end
localparam D_WIDTH = C_QWORDS*XIDX_WIDTH;
localparam MIX_ROUNDS = (R_WIDTH+4+D_WIDTH-1)/D_WIDTH;
localparam MIX_I_PAD = D_WIDTH*MIX_ROUNDS - R_WIDTH+4;
wire [D_WIDTH*MIX_ROUNDS-1:0] mix_i = {{MIX_I_PAD{1'b0}},ds,r};
wire [D_WIDTH-1:0] d = mix_i[cnt*D_WIDTH+:D_WIDTH];
wire [C_WIDTH-1:0] mixsx32_out = mixsx32(c,x,d);
wire [C_WIDTH-1:0] core_in = absorb ? mixsx32_out : c;
wire [3:0] core_round = absorb ? {4{1'b0}} : cnt;
wire [C_WIDTH-1:0] core_out = gascon5_round(core_in,core_round);
wire [128-1:0] accu_out = accumulate(core_out[0+:256],r);//free pipelining can be done here by taking c instead
localparam STATE_WIDTH = 2;
localparam STATE_IDLE = 2'b00;
localparam STATE_MIX_ENTRY = 2'b01;
localparam STATE_G_ENTRY = 2'b10;
reg [STATE_WIDTH-1:0] state;
always @(posedge clk) begin
if(clk_en) begin
if(rst) begin
state <= STATE_IDLE;
absorb <= 1'b0;
cnt <= {4{1'b0}};
idle <= 1'b1;
end else begin
case(state)
STATE_IDLE: begin
if(wr_i) begin
r[cnt*32+:32] <= din;
absorb <= 1'b1;
end
if(wr_c) begin
c[cnt*32+:32] <= din;
end
if(wr_x) begin
x <= {din,x[32+:X_WIDTH-32]};
end
case(1'b1)
wr_c,rd_c: cnt <= (cnt + 1'b1) % C_DWORDS;
wr_x: cnt <= (cnt + 1'b1) % X_DWORDS;
wr_i,rd_r: cnt <= (cnt + 1'b1) % R_DWORDS;
endcase
if(start) begin
if(absorb) begin
state <= STATE_MIX_ENTRY;
end else begin
r <= {R_WIDTH{1'b0}};
state <= STATE_G_ENTRY;
end
cnt <= {4{1'b0}};
idle <= 1'b0;
end
end
STATE_MIX_ENTRY: begin
c <= core_out;
if(MIX_ROUNDS-2==cnt) begin
r <= {R_WIDTH{1'b0}};
cnt <= cnt +1'b1;//to get last chunk
state <= STATE_G_ENTRY;//let absorb for the first round to consume last chunk
end else begin
cnt <= cnt +1'b1;
end
end
STATE_G_ENTRY: begin
//$display("round = %d",core_round);
//$display("core_in: %X",int_to_le(core_in));
//$display("core_out: %X",int_to_le(core_out));
//$display("accu_out: %X",int128_to_le(accu_out));
absorb <= 1'b0;
c <= core_out;
r <= accu_out;
if(rounds-1==cnt) begin
cnt <= {4{1'b0}};
state <= STATE_IDLE;
idle <= 1'b1;
end else begin
cnt <= absorb ? {{3{1'b0}},1'b1} : cnt +1'b1;
end
end
endcase
end
end
end
endmodule
`default_nettype wire
`timescale 1ns / 1ps
`default_nettype none
`define assert(signal, value) \
if (signal !== value) begin \
$display("%t ASSERTION FAILED in %m: %x != %x",$realtime,signal,value); \
#100; \
$finish; \
end
module tb_drygascon128();
//`define func_path u_dut
`ifndef func_path
`define func_path tb_drygascon128
`include "drygascon128_functions.v"
`endif
reg clk;
reg clk_en;
reg reset;
reg [31:0] din;
reg [3:0] ds;
reg wr_i;
reg wr_c;
reg wr_x;
reg [3:0] rounds;
reg start;
reg rd_r;
reg rd_c;
wire [31:0] dout;
wire idle;
drygascon128 u_dut(
.clk(clk),
.clk_en(clk_en),
.rst(reset),
.din(din),
.ds(ds),
.wr_i(wr_i),
.wr_c(wr_c),
.wr_x(wr_x),
.rounds(rounds),
.start(start),
.rd_r(rd_r),
.rd_c(rd_c),
.dout(dout),
.idle(idle)
);
wire [63:0] c0 = u_dut.c[0*64+:64];
wire [63:0] c1 = u_dut.c[1*64+:64];
wire [63:0] c2 = u_dut.c[2*64+:64];
wire [63:0] c3 = u_dut.c[3*64+:64];
wire [63:0] c4 = u_dut.c[4*64+:64];
reg [320-1:0] c_out;
reg [128-1:0] r_out;
wire done = idle;
task wait_clock;
begin
@ (negedge clk);
end
endtask
task reset_dut;
begin
wait_clock();
reset = 1;
wait_clock();
reset = 0;
end
endtask
task wait_clocks;
input integer nclocks;
integer i;
begin
for(i=0;i < nclocks; i= i+1) begin
wait_clock();
end
end
endtask
task start_op;
begin
start = 1;
@(negedge clk);
start = 0;
end
endtask
reg done_reg;
always @(posedge clk) done_reg <= done;
task wait_done;
begin
wait_clock();
while(!done) begin
wait_clock();
end
end
endtask
task write_x;
input [128-1:0] x;
integer i;
begin
wr_x = 1;
for(i=0;i<4;i=i+1) begin
din = x[i*32+:32];
wait_clock();
end
wr_x=0;
end
endtask
task write_x_le;
input [128-1:0] x;
begin
write_x(`func_path.le_to_int128(x));
end
endtask
task write_c;
input [320-1:0] c;
integer i;
begin
wr_c = 1;
for(i=0;i<10;i=i+1) begin
din = c[i*32+:32];
wait_clock();
end
wr_c=0;
end
endtask
task write_c_le;
input [320-1:0] c;
begin
write_c(`func_path.le_to_int(c));
end
endtask
task read_c;
integer i;
begin
rd_c = 1;
for(i=0;i<10;i=i+1) begin
wait_clock();
c_out[i*32+:32] = dout;
end
rd_c=0;
end
endtask
task check_c;
input [320-1:0] expected;
begin
read_c();
`assert(c_out,expected)
end
endtask
task check_c_le;
input [320-1:0] expected;
begin
check_c(`func_path.le_to_int(expected));
end
endtask
task write_i;
input [128-1:0] di;
integer i;
begin
wr_i = 1;
for(i=0;i<4;i=i+1) begin
din = di[i*32+:32];
wait_clock();
end
wr_i=0;
end
endtask
task write_i_le;
input [128-1:0] i;
begin
write_i(`func_path.le_to_int128(i));
end
endtask
task read_r;
integer i;
begin
rd_r = 1;
for(i=0;i<4;i=i+1) begin
wait_clock();
r_out[i*32+:32] = dout;
end
rd_r=0;
end
endtask
task check_r;
input [128-1:0] expected;
begin
read_r();
`assert(r_out,expected)
end
endtask
task check_r_le;
input [128-1:0] expected;
begin
check_r(`func_path.le_to_int128(expected));
end
endtask
task gascon128_f;
input [3:0] ds_in;
input [3:0] rounds_in;
input [128-1:0] i;
begin
rounds=rounds_in;
ds = ds_in;
write_i(i);
start_op();
wait_done();
end
endtask
task gascon128_g;
input [3:0] rounds_in;
begin
rounds=rounds_in;
start_op();
wait_done();
end
endtask
task gascon128_f_le;
input [3:0] ds_in;
input [3:0] rounds_in;
input [128-1:0] i;
begin
gascon128_f(ds_in,rounds_in,`func_path.le_to_int128(i));
end
endtask
task check_gascon128_f_le;
input [3:0] ds_in;
input [3:0] rounds_in;
input [128-1:0] i;
input [128-1:0] expected;
begin
gascon128_f_le(ds_in,rounds_in,i);
check_r_le(expected);
end
endtask
task check_gascon128_g_le;
input [3:0] rounds_in;
input [128-1:0] expected;
begin
gascon128_g(rounds_in);
check_r_le(expected);
end
endtask
initial begin
clk = 0;
forever #5 clk = ~clk;
end
`define DRYGASCON128_IROUNDS 11
`define DRYGASCON128_ROUNDS 7
task init_dut;
begin
start = 0;
clk_en = 1;
wr_c=0;
wr_x=0;
wr_i=0;
rd_c=0;
rd_r=0;
ds=0;
rounds=11;
reset_dut();
end
endtask
task basic_test;
begin
init_dut();
write_x_le(128'h28292A2B2C2D2E2F3031323334353637);
`assert(u_dut.x,`func_path.le_to_int128(128'h28292A2B2C2D2E2F3031323334353637))
write_c_le(320'h000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627);
`assert(u_dut.c,`func_path.le_to_int(320'h000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627))
check_c_le(320'h000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627);
check_gascon128_f_le(6,`DRYGASCON128_IROUNDS,128'hF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF,128'hF1FBA3D719B00A49BF170F832EB7649F);
write_c_le(320'h000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627);
check_gascon128_f_le(6,`DRYGASCON128_IROUNDS,128'hF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF,128'hF1FBA3D719B00A49BF170F832EB7649F);
end
endtask
`define PAD 1
`define FINAL 1
`define DS_S 2
`define DS_D 1
`define DS_A 2
`define DS_M 3
task init_hash;
begin
init_dut();
write_x_le(128'hA4093822299F31D0082EFA98EC4E6C89);
`assert(u_dut.x,`func_path.le_to_int128(128'hA4093822299F31D0082EFA98EC4E6C89))
write_c_le(320'h243F6A8885A308D313198A2E03707344243F6A8885A308D313198A2E03707344243F6A8885A308D3);
`assert(u_dut.c,`func_path.le_to_int(320'h243F6A8885A308D313198A2E03707344243F6A8885A308D313198A2E03707344243F6A8885A308D3))
check_c_le(320'h243F6A8885A308D313198A2E03707344243F6A8885A308D313198A2E03707344243F6A8885A308D3);
end
endtask
task hash_null;
begin
init_hash();
check_gascon128_f_le(`func_path.compute_ds(`PAD,`DS_S,`FINAL),`DRYGASCON128_ROUNDS,128'h01000000000000000000000000000000,128'h1EDC77386E20A37C721D6E77ADABB9C4);
check_gascon128_g_le(`DRYGASCON128_ROUNDS,128'h830F199F5ED25284A13C1D84B9FC257A);
end
endtask
task hash_detailed_tv;
begin
init_hash();
check_gascon128_f_le(`func_path.compute_ds(`PAD,`DS_S,`FINAL),`DRYGASCON128_ROUNDS,128'h00010203040506070100000000000000,128'hCDE2DEE0235345CBFA51EC2CE5743571);
check_gascon128_g_le(`DRYGASCON128_ROUNDS,128'h8EC0133EC2756E035FA404C1CE511E24);
end
endtask
task hash_tv17;
begin
init_hash();
gascon128_f_le(0,`DRYGASCON128_ROUNDS,128'h000102030405060708090A0B0C0D0E0F);
check_gascon128_f_le(`func_path.compute_ds(`PAD,`DS_S,`FINAL),`DRYGASCON128_ROUNDS,128'h10010000000000000000000000000000,128'h20CDB78974D692100612978096CCFE82);
check_gascon128_g_le(`DRYGASCON128_ROUNDS,128'hE39F15969F493FAD8FA870F93B7252EA);
end
endtask
initial begin
basic_test();
hash_null();
hash_detailed_tv();
hash_tv17();
$display("sim pass");
$finish();
end
endmodule
`default_nettype wire
`timescale 1ns / 1ps
`default_nettype none
`define assert(signal, value) \
if (signal !== value) begin \
$display("%t ASSERTION FAILED in %m: %x != %x",$realtime,signal,value); \
#100; \
$finish; \
end
module tb_wrapper();
reg clk;
reg reset;
reg [31:0] din;
reg [3:0] ds;
reg wr_i;
reg wr_c;
reg wr_x;
reg [3:0] rounds;
reg start;
reg rd_r;
reg rd_c;
reg [31:0] dout;
reg idle;
reg tc;
reg ts;
reg di;
wire do;
wrapper u_dut(
.clk(clk),
.tc(tc),
.ts(ts),
.di(di),
.do(do)
);
wire [63:0] c0 = u_dut.u_impl.c[0*64+:64];
wire [63:0] c1 = u_dut.u_impl.c[1*64+:64];
wire [63:0] c2 = u_dut.u_impl.c[2*64+:64];
wire [63:0] c3 = u_dut.u_impl.c[3*64+:64];
wire [63:0] c4 = u_dut.u_impl.c[4*64+:64];
reg [320-1:0] c_out;
reg [128-1:0] r_out;
wire done = ts ? 0 : do;
localparam INPUT_WIDTH = 1+32+4+3+4+3;
localparam OUTPUT_WIDTH = 32+1;
localparam IOS_WIDTH = OUTPUT_WIDTH+INPUT_WIDTH;
reg [IOS_WIDTH-1:0] ios;
task wait_clock;
begin
@ (negedge clk);
end
endtask
task io;
integer i;
begin
ios = {{OUTPUT_WIDTH{1'b0}},reset,din,ds,wr_i,wr_c,wr_x,rounds,start,rd_r,rd_c};
tc=0;
ts=1;
//shift data in
for(i=0;i<IOS_WIDTH;i=i+1) begin
di = ios[IOS_WIDTH-1];
wait_clock();
ios = {ios[0+:IOS_WIDTH-1],di};
end
ts=0;
tc=0;
//set next clock as functional clock cycle
wait_clock();
tc=1;
wait_clock();//actual functional clock
wait_clock();//actual capture clock cycle
ts=1;
tc=0;
//shift data out (set same data in)
ios = {{OUTPUT_WIDTH{1'b0}},reset,din,ds,wr_i,wr_c,wr_x,rounds,start,rd_r,rd_c};
for(i=0;i<IOS_WIDTH;i=i+1) begin
di = ios[IOS_WIDTH-1];
wait_clock();
ios = {ios[0+:IOS_WIDTH-1],do};
end
{idle,dout} = ios[INPUT_WIDTH+:OUTPUT_WIDTH];
//any cycle done outside this task is a functional clock cycle
ts=0;
tc=0;
end
endtask
task reset_dut;
begin
wait_clock();
reset = 1;
io();
reset = 0;
io();
end
endtask
task wait_clocks;
input integer nclocks;
integer i;
begin
for(i=0;i < nclocks; i= i+1) begin
wait_clock();
end
end
endtask
task start_op;
begin
start = 1;
io();
start = 0;
io();
end
endtask
task wait_done;
begin
io();//ensure that any input change is taken into account
while(!done) begin
wait_clock();
end
end
endtask
task write_x;
input [128-1:0] x;
integer i;
begin
wr_x = 1;
for(i=0;i<4;i=i+1) begin
din = x[i*32+:32];
io();
end
wr_x=0;
end
endtask
task write_x_le;
input [128-1:0] x;
begin
write_x(u_dut.u_impl.le_to_int128(x));
end
endtask
task write_c;
input [320-1:0] c;
integer i;
begin
wr_c = 1;
for(i=0;i<10;i=i+1) begin
din = c[i*32+:32];
io();
end
wr_c=0;
end
endtask
task write_c_le;
input [320-1:0] c;
begin
write_c(u_dut.u_impl.le_to_int(c));
end
endtask
task read_c;
integer i;
begin
rd_c = 1;
for(i=0;i<10;i=i+1) begin
io();
c_out[i*32+:32] = dout;
end
rd_c=0;
end
endtask
task check_c;
input [320-1:0] expected;
begin
read_c();
`assert(c_out,expected)
end
endtask
task check_c_le;
input [320-1:0] expected;
begin
check_c(u_dut.u_impl.le_to_int(expected));
end
endtask
task write_i;
input [128-1:0] di;
integer i;
begin
wr_i = 1;
for(i=0;i<4;i=i+1) begin
din = di[i*32+:32];
io();
end
wr_i=0;
end
endtask
task write_i_le;
input [128-1:0] i;
begin
write_i(u_dut.u_impl.le_to_int128(i));
end
endtask
task read_r;
integer i;
begin
rd_r = 1;
for(i=0;i<4;i=i+1) begin
io();
r_out[i*32+:32] = dout;
end
rd_r=0;
end
endtask
task check_r;
input [128-1:0] expected;
begin
read_r();
`assert(r_out,expected)
end
endtask
task check_r_le;
input [128-1:0] expected;
begin
check_r(u_dut.u_impl.le_to_int128(expected));
end
endtask
task gascon128_f;
input [3:0] ds_in;
input [3:0] rounds_in;
input [128-1:0] i;
begin
rounds=rounds_in;
ds = ds_in;
write_i(i);
start_op();
wait_done();
end
endtask
task gascon128_g;
input [3:0] rounds_in;
begin
rounds=rounds_in;
start_op();
wait_done();
end
endtask
task gascon128_f_le;
input [3:0] ds_in;
input [3:0] rounds_in;
input [128-1:0] i;
begin
gascon128_f(ds_in,rounds_in,u_dut.u_impl.le_to_int128(i));
end
endtask
task check_gascon128_f_le;
input [3:0] ds_in;
input [3:0] rounds_in;
input [128-1:0] i;
input [128-1:0] expected;
begin
gascon128_f_le(ds_in,rounds_in,i);
check_r_le(expected);
end
endtask
task check_gascon128_g_le;
input [3:0] rounds_in;
input [128-1:0] expected;
begin
gascon128_g(rounds_in);
check_r_le(expected);
end
endtask
initial begin
clk = 0;
forever #5 clk = ~clk;
end
`define DRYGASCON128_IROUNDS 11
`define DRYGASCON128_ROUNDS 7
task init_dut;
begin
start = 0;
wr_c=0;
wr_x=0;
wr_i=0;
rd_c=0;
rd_r=0;
ds=0;
din = 0;
rounds=11;
tc=0;
ts=0;
reset_dut();
end
endtask
task basic_test;
begin
init_dut();
write_x_le(128'h28292A2B2C2D2E2F3031323334353637);
`assert(u_dut.u_impl.x,u_dut.u_impl.le_to_int128(128'h28292A2B2C2D2E2F3031323334353637))
write_c_le(320'h000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627);
`assert(u_dut.u_impl.c,u_dut.u_impl.le_to_int(320'h000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627))
check_c_le(320'h000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627);
check_gascon128_f_le(6,`DRYGASCON128_IROUNDS,128'hF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF,128'hF1FBA3D719B00A49BF170F832EB7649F);
write_c_le(320'h000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627);
check_gascon128_f_le(6,`DRYGASCON128_IROUNDS,128'hF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF,128'hF1FBA3D719B00A49BF170F832EB7649F);
end
endtask
`define PAD 1
`define FINAL 1
`define DS_S 2
`define DS_D 1
`define DS_A 2
`define DS_M 3
task init_hash;
begin
init_dut();
write_x_le(128'hA4093822299F31D0082EFA98EC4E6C89);
`assert(u_dut.u_impl.x,u_dut.u_impl.le_to_int128(128'hA4093822299F31D0082EFA98EC4E6C89))
write_c_le(320'h243F6A8885A308D313198A2E03707344243F6A8885A308D313198A2E03707344243F6A8885A308D3);
`assert(u_dut.u_impl.c,u_dut.u_impl.le_to_int(320'h243F6A8885A308D313198A2E03707344243F6A8885A308D313198A2E03707344243F6A8885A308D3))
check_c_le(320'h243F6A8885A308D313198A2E03707344243F6A8885A308D313198A2E03707344243F6A8885A308D3);
end
endtask
task hash_null;
begin
init_hash();
check_gascon128_f_le(u_dut.u_impl.compute_ds(`PAD,`DS_S,`FINAL),`DRYGASCON128_ROUNDS,128'h01000000000000000000000000000000,128'h1EDC77386E20A37C721D6E77ADABB9C4);
check_gascon128_g_le(`DRYGASCON128_ROUNDS,128'h830F199F5ED25284A13C1D84B9FC257A);
end
endtask
task hash_detailed_tv;
begin
init_hash();
check_gascon128_f_le(u_dut.u_impl.compute_ds(`PAD,`DS_S,`FINAL),`DRYGASCON128_ROUNDS,128'h00010203040506070100000000000000,128'hCDE2DEE0235345CBFA51EC2CE5743571);
check_gascon128_g_le(`DRYGASCON128_ROUNDS,128'h8EC0133EC2756E035FA404C1CE511E24);
end
endtask
task hash_tv17;
begin
init_hash();
gascon128_f_le(0,`DRYGASCON128_ROUNDS,128'h000102030405060708090A0B0C0D0E0F);
check_gascon128_f_le(u_dut.u_impl.compute_ds(`PAD,`DS_S,`FINAL),`DRYGASCON128_ROUNDS,128'h10010000000000000000000000000000,128'h20CDB78974D692100612978096CCFE82);
check_gascon128_g_le(`DRYGASCON128_ROUNDS,128'hE39F15969F493FAD8FA870F93B7252EA);
end
endtask