aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/synth/issue1390/aes_enc.vhdl
blob: ee51ae29cd578cad2372f88f0611af5af151033c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
-- ======================================================================
-- AES encryption/decryption
-- Copyright (C) 2019 Torsten Meissner
-------------------------------------------------------------------------
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.

-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.

-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-- ======================================================================


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

use work.aes_pkg.all;



entity aes_enc is
  generic (
    design_type : string  := "ITER"
  );
  port (
    reset_i     : in  std_logic;                   -- async reset
    clk_i       : in  std_logic;                   -- clock
    key_i       : in  std_logic_vector(0 to 127);  -- key input
    data_i      : in  std_logic_vector(0 to 127);  -- data input
    valid_i     : in  std_logic;                   -- input key/data valid flag
    accept_o    : out std_logic;
    data_o      : out std_logic_vector(0 to 127);  -- data output
    valid_o     : out std_logic;                   -- output data valid flag
    accept_i    : in  std_logic
  );
end entity aes_enc;



architecture rtl of aes_enc is


begin


  IterG : if design_type = "ITER" generate


    signal s_round : t_enc_rounds;


  begin


    CryptP : process (reset_i, clk_i) is
      variable v_state : t_datatable2d;
      variable v_key   : t_key;
    begin
      if (reset_i = '0') then
        v_state  := (others => (others => (others => '0')));
        v_key    := (others => (others => '0'));
        s_round  <= 0;
        accept_o <= '0';
        data_o   <= (others => '0');
        valid_o  <= '0';
      elsif (rising_edge(clk_i)) then
        case s_round is

          when 0 =>
            accept_o <= '1';
            if (accept_o = '1' and valid_i = '1') then
              accept_o <= '0';
              v_state  := set_state(data_i);
              v_key    := set_key(key_i);
              s_round  <= s_round + 1;
            end if;

          when 1 =>
            v_state := addroundkey(v_state, v_key);
            v_key   := key_round(v_key, s_round-1);
            s_round <= s_round + 1;

          when t_enc_rounds'high-1 =>
            v_state := subbytes(v_state);
            v_state := shiftrow(v_state);
            v_state := addroundkey(v_state, v_key);
            s_round <= s_round + 1;
            -- set data & valid to save one cycle
            valid_o <= '1';
            data_o  <= get_state(v_state);

          when t_enc_rounds'high =>
            if (valid_o = '1' and accept_i = '1') then
              valid_o <= '0';
              data_o  <= (others => '0');
              s_round <= 0;
              -- Set accept to save one cycle
              accept_o <= '1';
            end if;

          when others =>
            v_state := subbytes(v_state);
            v_state := shiftrow(v_state);
            v_state := mixcolumns(v_state);
            v_state := addroundkey(v_state, v_key);
            v_key   := key_round(v_key, s_round-1);
            s_round <= s_round + 1;

        end case;
      end if;
    end process CryptP;


    psl : block is

      signal s_key , s_din, s_dout : std_logic_vector(0 to 127) := (others => '0');

    begin

      process (clk_i) is
      begin
        if (rising_edge(clk_i)) then
          s_key  <= key_i;
          s_din  <= data_i;
          s_dout <= data_o;
        end if;
      end process;

      default clock is rising_edge(clk_i);

      -- initial reset
      restrict {not reset_i; reset_i[+]}[*1];

      -- constraints
      assume always (valid_i and not accept_o -> next valid_i);
      assume always (valid_i and not accept_o -> next key_i = s_key);
      assume always (valid_i and not accept_o -> next data_i = s_din);

      ACCEPTO_c : cover {accept_o};
      ACCEPT_IN_ROUND_0_ONLY_a : assert always (accept_o -> s_round = 0);

      VALIDI_AND_ACCEPTO_c : cover {valid_i and accept_o};
      ACCEPT_OFF_WHEN_VALID_a : assert always (valid_i and accept_o -> next not accept_o);

      VALIDO_c : cover {valid_o};
      VALID_IN_LAST_ROUND_ONLY_a : assert always (valid_o -> s_round = t_enc_rounds'high);

      VALIDO_AND_ACCEPTI_c : cover {valid_o and accept_i};
      VALID_OFF_WHEN_ACCEPTED_a : assert always (valid_o and accept_i -> next not valid_o);

      VALIDO_AND_NOT_ACCEPTI_c : cover {valid_o and not accept_i};
      VALID_STABLE_WHEN_NOT_ACCEPTED_a : assert always (valid_o and not accept_i -> next valid_o);
      DATA_STABLE_WHEN_NOT_ACCEPTED_a : assert always (valid_o and not accept_i -> next data_o = s_dout);

    end block psl;


  end generate IterG;



end architecture rtl;