właśnie skończyłem pisać w VHDL generator zawartości Sboxów do algorytmu kryptograficznego AES. Jest on złożony z 9-stopniowego potoku i zajmuje 160 LE. Wszystkie działania teoretycznie są wykonywane w ciele Galois GF(2^8), a tak naprawdę w izomorficznym z nim ciele złożonym GF(2^4)^2, co dzięki paru sztuczkom algebraicznym pozwoliło 4-krotnie zmniejszyć układ. Dodawanie to xor, więc spodziewałem się że układ będzie dość szybki, ale przy docelowym układzie Cyclone
1C3-6 Timing Analyzer Quartusa 5.0 zwraca mi szokującą informację, że:
"Info: Clock "clk" has Internal fmax of 398.09 MHz between source register "SBOX_Generator:inst|d_latch:X11|r[2]" and destination register "SBOX_Generator:inst|gf24_multiply:X21|a2[0]" (period= 2.512 ns) Info: + Longest register to register delay is 2.310 ns"
Przecież to fizycznie niemożliwe. :-) BTW, w symulatorze wszystko działa wprost modelowo, więc na pewno nie zapomniałem podłączyć zegara do układu.
Pozdrawiam Piotr Wyderski
Didn't find your answer? Ask the community — no account required.
P
Piotr Wyderski
Trochę poprawiłem wskazaną ścieżkę krytyczną i dostałem:
"Info: Clock "clk" Internal fmax is restricted to 405.19 MHz between source register "SBOX_Generator:inst|d_latch:X11|r[1]" and destination register "SBOX_Generator:inst|gf24_multiply:X21|a2[1]" Info: fmax restricted to Clock High delay (1.234 ns) plus Clock Low delay (1.234 ns) : restricted to 2.468 ns. Expand message to see actual delay path. Info: + Longest register to register delay is 2.052 ns"
Hmm, przecież to o 2,2MHz szybciej, niż tak kość ma fmax w datasheecie... :-/ Ale działa... Co tu jest grane? :-)
H
HaMMeR
(...)
ciach
Z kiciorem, grypserze...! ;)))
Kristo
G
Greg
no nie, troche ci ten wynik za duzy wyszedl.. no ale w 1C6-8 wychodzily mi po 5..7ns dla dosyc glebokich ukladow kombinacyjnych.. wiec skoro masz wersje -6 to bedzie troche wiecej.. a czy ustawiles wobec czego ma analyser liczyc ten czas? posprawdzaj czasy dla wszystkich kombinacji wejsc/wyjsc..gdzies powinna byc taka opcja.. wtedy juz nei jest tak rozowo:)
P
Piotr Wyderski
Greg wrote:
"Trochê"... :-> To ju¿ drugi raz. Wówczas (256MHz) pyta³em o to samo i kazali¶cie mi wierzyæ Quartusowi. To teraz sami mu wierzcie. :->
Jak to wzglêdem czego?
Ten uk³ad praktycznie nie ma wej¶æ (tj. ma reset i taktowanie), sam sobie generuje wektory "wej¶ciowe" i je nastêpnie transformuje. Poni¿ej za³±czam kod w wersji mocno beta -- na symulatorze dzia³a doskonale, wiêc chyba niczego nie zapomnia³em pod³±czyæ. Poniewa¿ VHDL w sumie siê dopiero uczê, proszê wskazaæ, co zrobi³em ¼le (oprócz zapisu tego uk³adu licz±cego odwrotno¶æ multiplikatywn± w GF(2^8)-- to w ogóle da siê czytelnie zapisaæ?).
Pozdrawiam Piotr Wyderski
---------------8<----------------------
-- WARNING: Do NOT edit the input and output ports in this file in a text
-- editor if you plan to continue editing the block that represents it in
-- the Block Editor! File corruption is VERY likely to occur.
-- Copyright (C) 1991-2005 Altera Corporation
-- Your use of Altera Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
-- Generated by Quartus II Version 5.0 (Build Build 148 04/26/2005)
-- Created on Sat Jun 25 16:28:37 2005
library ieee; use ieee.std_logic_1164.all;
entity d_latch is
generic (
N : positive );
port (
clk : in std_logic; v : in std_logic_vector(N-1 downto 0); r : out std_logic_vector(N-1 downto 0) );
end d_latch;
-- -------------------
architecture implementation of d_latch is
-- This block latches N bits of information
begin
process(clk, v) is begin
if rising_edge(clk) then r <= v; end if; end process; end implementation;
-- -------------------
library ieee; use ieee.std_logic_1164.all;
entity gf24_square is
port (
v : in std_logic_vector(3 downto 0); r : out std_logic_vector(3 downto 0) );
end gf24_square;
-- -------------------
architecture implementation of gf24_square is
-- This block computes the value of v^2 in GF(2^4)
begin
process(v) is begin
case v is
when "0000" => r <= "0000"; when "0001" => r <= "0001"; when "0010" => r <= "0100"; when "0011" => r <= "0101"; when "0100" => r <= "0011"; when "0101" => r <= "0010"; when "0110" => r <= "0111"; when "0111" => r <= "0110"; when "1000" => r <= "1100"; when "1001" => r <= "1101"; when "1010" => r <= "1000"; when "1011" => r <= "1001"; when "1100" => r <= "1111"; when "1101" => r <= "1110"; when "1110" => r <= "1011"; when "1111" => r <= "1010";
end case; end process; end implementation;
-- -------------------
library ieee; use ieee.std_logic_1164.all;
entity gf24_inverse is
port (
v : in std_logic_vector(3 downto 0); r : out std_logic_vector(3 downto 0) );
end gf24_inverse;
-- -------------------
architecture implementation of gf24_inverse is
-- This block computes the value of v^(-1) in GF(2^4)
begin
process(v) is begin
case v is
when "0000" => r <= "0000"; when "0001" => r <= "0001"; when "0010" => r <= "1001"; when "0011" => r <= "1110"; when "0100" => r <= "1101"; when "0101" => r <= "1011"; when "0110" => r <= "0111"; when "0111" => r <= "0110"; when "1000" => r <= "1111"; when "1001" => r <= "0010"; when "1010" => r <= "1100"; when "1011" => r <= "0101"; when "1100" => r <= "1010"; when "1101" => r <= "0100"; when "1110" => r <= "0011"; when "1111" => r <= "1000";
end case; end process; end implementation;
-- -------------------
library ieee; use ieee.std_logic_1164.all;
entity gf28_to_gf24 is
port (
v : in std_logic_vector(7 downto 0); r : out std_logic_vector(7 downto 0) );
end gf28_to_gf24;
-- -------------------
architecture implementation of gf28_to_gf24 is
-- This block transforms a given v from GF(2^8) into GF(2^4)^2
v : in std_logic_vector(3 downto 0); r : out std_logic_vector(3 downto 0) );
end gf24_multiply_by_8;
-- -------------------
architecture implementation of gf24_multiply_by_8 is
-- This block computes the value of v*8 in GF(2^4)
begin
process(v) is begin
case v is
when "0000" => r <= "0000"; when "0001" => r <= "1000"; when "0010" => r <= "0011"; when "0011" => r <= "1011"; when "0100" => r <= "0110"; when "0101" => r <= "1110"; when "0110" => r <= "0101"; when "0111" => r <= "1101"; when "1000" => r <= "1100"; when "1001" => r <= "0100"; when "1010" => r <= "1111"; when "1011" => r <= "0111"; when "1100" => r <= "1010"; when "1101" => r <= "0010"; when "1110" => r <= "1001"; when "1111" => r <= "0001";
end case; end process; end implementation;
-- -------------------
library ieee; use ieee.std_logic_1164.all;
entity sbox_affine_transform is
port (
v : in std_logic_vector(7 downto 0); r : out std_logic_vector(7 downto 0) );
end sbox_affine_transform;
-- -------------------
architecture implementation of sbox_affine_transform is
-- This block transforms a given multiplicative
-- inverse element v from GF(2^8) into a valid
-- AES sbox output
begin
-- Transform a given inverse element using the following affine mapping
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all;
-- Entity Declaration
entity SBOX_Generator is
-- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
port (
clk : in std_logic; mode_select : in std_logic; reset : in std_logic; sbox_index : out std_logic_vector(7 downto 0); sbox_value : out std_logic_vector(7 downto 0); stall : out std_logic );
-- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
end SBOX_Generator;
-- Architecture Body
architecture SBOX_Generator_architecture of SBOX_Generator is
component d_latch is
generic (
N : positive );
port (
clk : in std_logic; v : in std_logic_vector(N-1 downto 0); r : out std_logic_vector(N-1 downto 0) );
end component;
component gf24_square is port (
v : in std_logic_vector(3 downto 0); r : out std_logic_vector(3 downto 0)
); end component;
component gf24_inverse is port (
v : in std_logic_vector(3 downto 0); r : out std_logic_vector(3 downto 0)
); end component;
component gf24_multiply is port (
clk : in std_logic; x, y : in std_logic_vector(3 downto 0); r : out std_logic_vector(3 downto 0)
); end component;
component gf24_multiply_by_8 is port (
v : in std_logic_vector(3 downto 0); r : out std_logic_vector(3 downto 0)
); end component;
component gf28_to_gf24 is port (
v : in std_logic_vector(7 downto 0); r : out std_logic_vector(7 downto 0)
); end component;
component gf24_to_gf28 is port (
v : in std_logic_vector(7 downto 0); r : out std_logic_vector(7 downto 0)
); end component;
component sbox_affine_transform is port (
v : in std_logic_vector(7 downto 0); r : out std_logic_vector(7 downto 0)
); end component;
signal index_generator : std_logic_vector(7 downto 0);
signal s01, s02 : std_logic_vector(7 downto 0); signal b01, c01 : std_logic_vector(3 downto 0); signal b02, c02, d02 : std_logic_vector(3 downto 0); signal b03, c03, d03 : std_logic_vector(3 downto 0); signal b04, c04, d04 : std_logic_vector(3 downto 0); signal b05, c05, d05 : std_logic_vector(3 downto 0); signal b06, c06, d06 : std_logic_vector(3 downto 0); signal b07, c07, d07 : std_logic_vector(3 downto 0); signal b08, c08 : std_logic_vector(3 downto 0); signal b09, c09 : std_logic_vector(3 downto 0); signal b10, c10 : std_logic_vector(3 downto 0); signal b11, c11 : std_logic_vector(3 downto 0); signal b12, c12 : std_logic_vector(3 downto 0); signal v0, v1, v2 : std_logic_vector(7 downto 0);
begin
X00 : gf28_to_gf24 port map (v => index_generator, r => s01); X01 : d_latch generic map (N => 8) port map (v => s01, r(7 downto 4) => b01, r(3 downto 0) => c01, clk => clk); X02 : gf24_square port map (v => b01, r => b02); X03 : gf24_square port map (v => c01, r => c02); X04 : gf24_multiply port map (x => b01, y => c01, r => d02, clk => clk); X05 : d_latch generic map (N => 4) port map (v => b02, r => b03, clk => clk); X06 : d_latch generic map (N => 4) port map (v => c02, r => c03, clk => clk); X07 : gf24_multiply_by_8 port map (v => b03, r => b04); X08 : d_latch generic map (N => 4) port map (v => b04, r => b05, clk => clk); X09 : d_latch generic map (N => 4) port map (v => c03, r => c04, clk => clk); c05 <= b05 xor c04; X10 : d_latch generic map (N => 4) port map (v => c05, r => c06, clk => clk); d03 <= d02 xor c06; X11 : d_latch generic map (N => 4) port map (v => d03, r => d04, clk => clk); X12 : gf24_inverse port map (v => d04, r => d05); c07 <= c01 xor b01; X13 : d_latch generic map (N => 4) port map (v => c07, r => c08, clk => clk); X14 : d_latch generic map (N => 4) port map (v => b01, r => b08, clk => clk); X15 : d_latch generic map (N => 4) port map (v => c08, r => c09, clk => clk); X16 : d_latch generic map (N => 4) port map (v => b08, r => b09, clk => clk); X17 : d_latch generic map (N => 4) port map (v => c09, r => c10, clk => clk); X18 : d_latch generic map (N => 4) port map (v => b09, r => b10, clk => clk); X19 : d_latch generic map (N => 4) port map (v => c10, r => c11, clk => clk); X20 : d_latch generic map (N => 4) port map (v => b10, r => b11, clk => clk); X21 : gf24_multiply port map (x => d05, y => b11, r => d06, clk => clk); X22 : gf24_multiply port map (x => d05, y => c11, r => d07, clk => clk); X23 : gf24_to_gf28 port map (v(7 downto 4) => d06, v(3 downto 0) => d07, r => v0); X24 : d_latch generic map (N => 8) port map (v => v0, r => v1, clk => clk); -- v1 = the multiplicative inverse X26 : sbox_affine_transform port map (v => v1, r => v2);
Ustawi³em teraz w symulatorze okres zegara na 2,5ns i wyniki dalej s± poprawne, tylko wynik symulacji wygl±da do¶æ zabawnie przed ostatnim latchem -- przez prawie ca³y czas na wyj¶ciu panuje stan nieustalony, uk³ad nie mo¿e zdecydowaæ siê na podanie w³a¶ciwego wyniku. Jednak o w³os przed up³ywem timeoutu nagle wyskakuje jak zaj±c w³a¶ciwa odpowied¼. :-)
Po latchu wszystko jest oczywi¶cie bardzo ³adne. ;-)
Pozdrawiam Piotr Wyderski
P
Piotr Wyderski
Siê garowa³o na algebrze, to siê ma bajerê skrañcowan±. ;-)))
Pozdrawiam Piotr Wyderski
J
J.F.
Temperature ustaw inna :-)
W zasadzie co sie dziwic ze proste operacje w pipeline daja taki szybki szyfrator ? I tak nie podasz danych wystarczajaco szybko :-)
J.
P
Piotr Wyderski
Nie szyfrator, tylko jego fragment. A co do zdziwienia, to ja rozumiem 200 MHz, nad 300 MHz bym siê zastanawia³, czy to naprawdê dzia³a, a tu dosta³em 405 MHz. :-)
Ten uk³ad nie do tego s³u¿y.
Pozdrawiam Piotr Wyderski
J
JA
"Piotr Wyderski":
[...]
timing analizer po prostu liczy opoznienia, czy tez propagacje sygnalu miedzy wyjsciem Q FF, a wejsciem D nastepnego FF i na podstawie maksymalnego czasu podaje maksymalna czestotliwosc zegara; to, ze fpga 'sama z siebie' ma inna max. zegara to zupelnie inna sprawa :) nadal uwazam, ze analizator czasowy quartusa jest godny zaufania, i jesli uklad dziala w symulatorze, to bedzie dzialal w rzeczywistosci, pod warunkiem nie przekroczenia maksymalnej czestotliwosci zegara dla danej rodziny fpga;
JA
P
Piotr Wyderski
I chyba masz rację: przeniosłem ten kod na ProASIC+ Actela i analizator z pakietu Libero daje mu 178MHz, rónież prawie na styk z teoretyczną wydajnością kości APA075. Widać rzeczywiście grunt to dobry algorytm, a ja chyba zaczynam być dobry w te klocki. ;->
Pozdrawiam Piotr Wyderski
J
JA
"Piotr Wyderski":
[,,,]
nie watpie :) jedna z oznak 'bycia dobrym' jest zauwazenie, ze ' if else' jest bardzo niewydajne w hardware, a zagniezdzonie 'if - else if' to juz tragedia; 'case' sobie radzi znacznie lepiej w takich przypadkach;
JA
J
jerry1111
Wszystko prawda. Tylko ze Twoj uklad jest teraz bezuzyteczny... Dolozysz mu wejscia/wyjscia, cos tam jeszcze, w rezultacie do tego neta CLK od szyfratora podlaczysz 10x wieksze obciazenie i Fmax spadnie o polowe. Potem cos jeszcze dodasz, zacznie byc ciasno w kosci, brakowac interconnectow i nagle zacznie Fmax leciec na pysk (jak duzo zajetego miejsca w FPGA, tak >85% to zauwazylem ze Fmax zmienia sie szybko tylko w jedna strone... zabawa z kilkoma kompilacjami troszke to poprawia, ale naprawde tylko troszke).
Sprobuj tak z ciekawosci do tego dolozyc cos duzego (50% kosci) - nawet na innym zegarze. Pewnie bedzie wolniej.
P
Piotr Wyderski
To jest testbed, on z założenia jest bezużyteczny, choćby z tego powodu, że kostka nie jest zabezpieczona. :-) Napisałem to w Quartusie, bo po prostu już się go nauczyłem. ;-)
Ten moduł w docelowym układzie miałby osobnego neta, 4x szybszego niż reszta kostki, dzieliłby go tylko z FIFO.
Biorąc pod uwagę, że celem było osiągnięcie 132MHz (4x33), to i tak byłoby 70MHz zapasu. :-) Po prostu widząc nierealne w moim pojęciu wyniki analizatora timingów (jakieś 330MHz) postanowiłem się poznęcać nad układem i poprawić wskazane ścieżki, co w końcu doprowadziło mnie do tego 405,2MHz. :->>>
Ustaw maksymalny odpowiedni poziom optymalizacji. Co prawda układ (mieszacz kwadratuowy) kompiluje się wtedy 15 minut zamiast
3,5, ale fmax mu wzrosło z 218 na 256MHz (zaczął limitować dostęp do RAMu). Biorąc pod uwagę to, że i tak będzie chodził na 130MHz, to ta różnica nie ma technicznego znaczenia, ale za to można się bardziej chwalić -- IMVHO to całkiem niezły wynik jak na amatora. :-)
Trudno się z tym nie zgodzić -- szybciej niż 405MHz już raczej nie będzie. ;-)))
Pozdrawiam Piotr Wyderski
Join the Discussion
Have something to add? Share your thoughts — no account required.
Didn't find your answer?
Ask the community — no account required
Report Content
You are reporting this content to the moderators. They will look at it
ASAP.