@ -0,0 +1,155 @@ | |||||
-- This design implements a register file which can | |||||
-- be accessed by an UART with 9600 baud | |||||
-- | |||||
-- See into uart_ctrl.vhd for documentation of the protocol | |||||
-- used to read / write the register file. | |||||
library ieee ; | |||||
use ieee.std_logic_1164.all; | |||||
use ieee.numeric_std.all; | |||||
library gatemate; | |||||
use gatemate.components.all; | |||||
library cryptocores; | |||||
use work.uart_aes_types.all; | |||||
entity uart_aes is | |||||
port ( | |||||
clk_i : in std_logic; -- 10 MHz clock | |||||
rst_n_i : in std_logic; -- SW3 button | |||||
uart_rx_i : in std_logic; -- PMODA IO3 | |||||
uart_tx_o : out std_logic; -- PMODA IO5 | |||||
led_n_o : out std_logic_vector(3 downto 0) | |||||
); | |||||
end entity uart_aes; | |||||
architecture rtl of uart_aes is | |||||
signal s_pll_clk : std_logic; | |||||
signal s_pll_lock : std_logic; | |||||
signal s_rst_n : std_logic; | |||||
signal s_cfg_end : std_logic; | |||||
signal s_uart_rx_tdata : std_logic_vector(7 downto 0); | |||||
signal s_uart_rx_tvalid : std_logic; | |||||
signal s_uart_rx_tready : std_logic; | |||||
signal s_uart_tx_tdata : std_logic_vector(7 downto 0); | |||||
signal s_uart_tx_tvalid : std_logic; | |||||
signal s_uart_tx_tready : std_logic; | |||||
signal s_ctrl_aes_m2s : t_axis_ctrl_aes_m2s; | |||||
signal s_ctrl_aes_s2m : t_axis_s2m; | |||||
signal s_aes_ctrl_m2s : t_axis_aes_ctrl_m2s; | |||||
signal s_aes_ctrl_s2m : t_axis_s2m; | |||||
begin | |||||
pll : CC_PLL | |||||
generic map ( | |||||
REF_CLK => "10", | |||||
OUT_CLK => "10", | |||||
PERF_MD => "SPEED" | |||||
) | |||||
port map ( | |||||
CLK_REF => clk_i, | |||||
CLK_FEEDBACK => '0', | |||||
USR_CLK_REF => '0', | |||||
USR_LOCKED_STDY_RST => '0', | |||||
USR_PLL_LOCKED_STDY => open, | |||||
USR_PLL_LOCKED => s_pll_lock, | |||||
CLK270 => open, | |||||
CLK180 => open, | |||||
CLK0 => s_pll_clk, | |||||
CLK90 => open, | |||||
CLK_REF_OUT => open | |||||
); | |||||
cfg_end_inst : CC_CFG_END | |||||
port map ( | |||||
CFG_END => s_cfg_end | |||||
); | |||||
uart_rx : entity work.uart_rx | |||||
generic map ( | |||||
CLK_DIV => 1040 | |||||
) | |||||
port map ( | |||||
-- globals | |||||
rst_n_i => s_rst_n, | |||||
clk_i => s_pll_clk, | |||||
-- axis user interface | |||||
tdata_o => s_uart_rx_tdata, | |||||
tvalid_o => s_uart_rx_tvalid, | |||||
tready_i => s_uart_rx_tready, | |||||
-- uart interface | |||||
rx_i => uart_rx_i | |||||
); | |||||
uart_ctrl : entity work.uart_ctrl | |||||
port map ( | |||||
-- globals | |||||
rst_n_i => s_rst_n, | |||||
clk_i => s_pll_clk, | |||||
-- uart rx interface | |||||
tdata_i => s_uart_rx_tdata, | |||||
tvalid_i => s_uart_rx_tvalid, | |||||
tready_o => s_uart_rx_tready, | |||||
-- uart tx interface | |||||
tdata_o => s_uart_tx_tdata, | |||||
tvalid_o => s_uart_tx_tvalid, | |||||
tready_i => s_uart_tx_tready, | |||||
-- aes out | |||||
ctrl_aes_o => s_ctrl_aes_m2s, | |||||
ctrl_aes_i => s_ctrl_aes_s2m, | |||||
-- aes in | |||||
aes_ctrl_i => s_aes_ctrl_m2s, | |||||
aes_ctrl_o => s_aes_ctrl_s2m | |||||
); | |||||
aes_inst : entity cryptocores.ctraes | |||||
port map ( | |||||
reset_i => s_rst_n, | |||||
clk_i => s_pll_clk, | |||||
start_i => s_ctrl_aes_m2s.tuser.start, | |||||
nonce_i => s_ctrl_aes_m2s.tuser.nonce, | |||||
key_i => s_ctrl_aes_m2s.tuser.key, | |||||
data_i => s_ctrl_aes_m2s.tdata, | |||||
valid_i => s_ctrl_aes_m2s.tvalid, | |||||
accept_o => s_ctrl_aes_s2m.tready, | |||||
data_o => s_aes_ctrl_m2s.tdata, | |||||
valid_o => s_aes_ctrl_m2s.tvalid, | |||||
accept_i => s_aes_ctrl_s2m.tready | |||||
); | |||||
uart_tx : entity work.uart_tx | |||||
generic map ( | |||||
CLK_DIV => 1040 | |||||
) | |||||
port map ( | |||||
-- globals | |||||
rst_n_i => s_rst_n, | |||||
clk_i => s_pll_clk, | |||||
-- axis user interface | |||||
tdata_i => s_uart_tx_tdata, | |||||
tvalid_i => s_uart_tx_tvalid, | |||||
tready_o => s_uart_tx_tready, | |||||
-- uart interface | |||||
tx_o => uart_tx_o | |||||
); | |||||
s_rst_n <= rst_n_i and s_pll_lock and s_cfg_end; | |||||
-- Lets some LEDs blink | |||||
led_n_o(0) <= rst_n_i; -- reset button | |||||
led_n_o(1) <= s_uart_rx_tready and s_uart_tx_tvalid; -- uart ctrl ready | |||||
led_n_o(2) <= not s_uart_rx_tready; -- uart received | |||||
led_n_o(3) <= not s_uart_tx_tvalid; -- uart send | |||||
end architecture; |
@ -0,0 +1,40 @@ | |||||
library ieee; | |||||
use ieee.std_logic_1164.all; | |||||
package uart_aes_types is | |||||
type t_axis_ctrl_aes_tuser is record | |||||
start : std_logic; | |||||
key : std_logic_vector(0 to 127); | |||||
nonce : std_logic_vector(0 to 95); | |||||
end record; | |||||
type t_axis_ctrl_aes_m2s is record | |||||
tuser : t_axis_ctrl_aes_tuser; | |||||
tdata : std_logic_vector(0 to 127); | |||||
tvalid : std_logic; | |||||
end record; | |||||
type t_axis_m2s is record | |||||
tdata : std_logic_vector(0 to 127); | |||||
tvalid : std_logic; | |||||
end record; | |||||
alias t_axis_aes_ctrl_m2s is t_axis_m2s; | |||||
type t_axis_s2m is record | |||||
tready : std_logic; | |||||
end record; | |||||
-- No dout reg necessary, as we simply use AES tdata output | |||||
type t_reg_file is record | |||||
ctrl : std_logic_vector(7 downto 0); | |||||
key : std_logic_vector(0 to 127); | |||||
nonce : std_logic_vector(0 to 95); | |||||
din : std_logic_vector(0 to 127); | |||||
end record; | |||||
constant c_reg_file_init : t_reg_file := (8x"0", 128x"0", 96x"0", 128x"0"); | |||||
end package; |
@ -0,0 +1,209 @@ | |||||
-- UART register | |||||
-- Register file with 8 registers storing values of one byte each. | |||||
-- | |||||
-- The first received byte on the axis in port contains command & address: | |||||
-- | |||||
-- 7 reserved | |||||
-- 6:4 register address | |||||
-- 3:0 command | |||||
-- 0x0 read | |||||
-- 0x1 write | |||||
-- | |||||
-- In case of a write command, the payload has to follow | |||||
-- with the next byte. | |||||
-- | |||||
-- In case of a read command, the value of the addressed | |||||
-- register is returned on the axis out port. | |||||
-- | |||||
-- Register at address 0 is special. It contains the version | |||||
-- and is read-only. Writes to that register are ignored. | |||||
library ieee; | |||||
use ieee.std_logic_1164.all; | |||||
use ieee.numeric_std.all; | |||||
use work.uart_aes_types.all; | |||||
entity uart_ctrl is | |||||
port ( | |||||
-- globals | |||||
rst_n_i : in std_logic; | |||||
clk_i : in std_logic; | |||||
-- axis in | |||||
tdata_i : in std_logic_vector(7 downto 0); | |||||
tvalid_i : in std_logic; | |||||
tready_o : out std_logic; | |||||
-- axis out | |||||
tdata_o : out std_logic_vector(7 downto 0); | |||||
tvalid_o : out std_logic; | |||||
tready_i : in std_logic; | |||||
-- aes out | |||||
ctrl_aes_o : out t_axis_ctrl_aes_m2s; | |||||
ctrl_aes_i : in t_axis_s2m; | |||||
-- aes in | |||||
aes_ctrl_i : in t_axis_aes_ctrl_m2s; | |||||
aes_ctrl_o : out t_axis_s2m | |||||
); | |||||
end entity uart_ctrl; | |||||
architecture rtl of uart_ctrl is | |||||
type t_state is (IDLE, GET_CMD, RECV_DATA, SEND_DATA); | |||||
signal s_state : t_state; | |||||
signal s_reg_file : t_reg_file; | |||||
signal s_reg_addr : natural range 0 to 7; | |||||
signal s_reg_data : std_logic_vector(7 downto 0); | |||||
subtype t_cmd is std_ulogic_vector(3 downto 0); | |||||
constant c_read : t_cmd := x"0"; | |||||
constant c_write : t_cmd := x"1"; | |||||
alias a_tdata_cmd is tdata_i(3 downto 0); | |||||
alias a_tdata_addr is tdata_i(6 downto 4); | |||||
constant c_ctrl_addr : natural := 0; | |||||
constant c_key_addr : natural := 1; | |||||
constant c_nonce_addr : natural := 2; | |||||
constant c_din_addr : natural := 3; | |||||
constant c_out_addr : natural := 4; | |||||
constant AES_RESET : natural := 0; -- Reset key & din registers | |||||
constant CTR_START : natural := 1; -- 1st round of counter mode | |||||
constant AES_START : natural := 2; -- start AES engine (cleared with AES_END) | |||||
constant AES_END : natural := 3; -- AES engine finished | |||||
type reg_acc_cnt_t is array (natural range <>) of unsigned(3 downto 0); | |||||
signal read_acc_cnt : reg_acc_cnt_t(0 to 3); | |||||
signal write_acc_cnt : reg_acc_cnt_t(0 to 2); | |||||
begin | |||||
-- Register memory | |||||
process (clk_i, rst_n_i) is | |||||
begin | |||||
if (not rst_n_i) then | |||||
s_reg_data <= (others => '0'); | |||||
s_reg_file <= c_reg_file_init; | |||||
read_acc_cnt <= (others => x"0"); | |||||
write_acc_cnt <= (others => x"0"); | |||||
elsif (rising_edge(clk_i)) then | |||||
-- Register write | |||||
if (s_state = RECV_DATA and tvalid_i = '1') then | |||||
case s_reg_addr is | |||||
when 0 => s_reg_file.ctrl <= tdata_i; | |||||
-- Clear all regs when AES_RESET bit set | |||||
if (tdata_i(AES_RESET)) then | |||||
s_reg_file.ctrl <= (others => '0'); | |||||
s_reg_file.key <= (others => '0'); | |||||
s_reg_file.nonce <= (others => '0'); | |||||
s_reg_file.din <= (others => '0'); | |||||
write_acc_cnt <= (others => x"0"); | |||||
read_acc_cnt <= (others => x"0"); | |||||
end if; | |||||
when 1 => write_acc_cnt(0) <= write_acc_cnt(0) + 1; | |||||
s_reg_file.key(to_integer(write_acc_cnt(0))*8 to to_integer(write_acc_cnt(0))*8+7) <= tdata_i; | |||||
when 2 => if (write_acc_cnt(1) = 11) then | |||||
write_acc_cnt(1) <= x"0"; | |||||
else | |||||
write_acc_cnt(1) <= write_acc_cnt(1) + 1; | |||||
end if; | |||||
s_reg_file.nonce(to_integer(write_acc_cnt(1))*8 to to_integer(write_acc_cnt(1))*8+7) <= tdata_i; | |||||
when 3 => write_acc_cnt(2) <= write_acc_cnt(2) + 1; | |||||
s_reg_file.din(to_integer(write_acc_cnt(2))*8 to to_integer(write_acc_cnt(2))*8+7) <= tdata_i; | |||||
when others => null; | |||||
end case; | |||||
end if; | |||||
-- Register read | |||||
aes_ctrl_o.tready <= '0'; | |||||
if (s_state = GET_CMD and a_tdata_cmd = c_read) then | |||||
case s_reg_addr is | |||||
when 0 => s_reg_data <= s_reg_file.ctrl; | |||||
when 1 => read_acc_cnt(0) <= read_acc_cnt(0) + 1; | |||||
s_reg_data <= s_reg_file.key(to_integer(read_acc_cnt(0))*8 to to_integer(read_acc_cnt(0))*8+7); | |||||
when 2 => if (read_acc_cnt(1) = 11) then | |||||
read_acc_cnt(1) <= x"0"; | |||||
else | |||||
read_acc_cnt(1) <= read_acc_cnt(1) + 1; | |||||
end if; | |||||
s_reg_data <= s_reg_file.nonce(to_integer(read_acc_cnt(1))*8 to to_integer(read_acc_cnt(1))*8+7); | |||||
when 3 => read_acc_cnt(2) <= read_acc_cnt(2) + 1; | |||||
s_reg_data <= s_reg_file.din(to_integer(read_acc_cnt(2))*8 to to_integer(read_acc_cnt(2))*8+7); | |||||
when 4 => read_acc_cnt(3) <= read_acc_cnt(3) + 1; | |||||
s_reg_data <= aes_ctrl_i.tdata(to_integer(read_acc_cnt(3))*8 to to_integer(read_acc_cnt(3))*8+7); | |||||
if (read_acc_cnt(3) = 15) then | |||||
aes_ctrl_o.tready <= aes_ctrl_i.tvalid; | |||||
end if; | |||||
when others => s_reg_data <= (others => '0'); | |||||
end case; | |||||
end if; | |||||
-- Set AES_END when AES out data is valid | |||||
-- Reset when AES out data was accepted (all 16 bytes of AES output data were read) | |||||
if (aes_ctrl_o.tready) then | |||||
s_reg_file.ctrl(AES_END) <= '0'; | |||||
elsif (aes_ctrl_i.tvalid) then | |||||
s_reg_file.ctrl(AES_END) <= '1'; | |||||
end if; | |||||
-- Reset AES_START & CTR_START when AES engine accepts in data | |||||
if (ctrl_aes_i.tready and s_reg_file.ctrl(AES_START)) then | |||||
s_reg_file.ctrl(AES_START) <= '0'; | |||||
s_reg_file.ctrl(CTR_START) <= '0'; | |||||
end if; | |||||
end if; | |||||
end process; | |||||
-- Control state machine | |||||
process (clk_i, rst_n_i) is | |||||
begin | |||||
if (not rst_n_i) then | |||||
s_state <= IDLE; | |||||
s_reg_addr <= 0; | |||||
elsif (rising_edge(clk_i)) then | |||||
case s_state is | |||||
when IDLE => | |||||
if (tvalid_i) then | |||||
s_state <= GET_CMD; | |||||
s_reg_addr <= to_integer(unsigned(a_tdata_addr)); | |||||
end if; | |||||
when GET_CMD => | |||||
if (a_tdata_cmd = c_read) then | |||||
s_state <= SEND_DATA; | |||||
elsif (a_tdata_cmd = c_write) then | |||||
s_state <= RECV_DATA; | |||||
else | |||||
s_state <= IDLE; | |||||
end if; | |||||
when RECV_DATA => | |||||
if (tvalid_i) then | |||||
s_state <= IDLE; | |||||
end if; | |||||
when SEND_DATA => | |||||
if (tready_i) then | |||||
s_state <= IDLE; | |||||
end if; | |||||
when others => | |||||
null; | |||||
end case; | |||||
end if; | |||||
end process; | |||||
tready_o <= '1' when s_state = GET_CMD or s_state = RECV_DATA else '0'; | |||||
tdata_o <= s_reg_data; | |||||
tvalid_o <= '1' when s_state = SEND_DATA else '0'; | |||||
ctrl_aes_o.tuser.start <= s_reg_file.ctrl(CTR_START); | |||||
ctrl_aes_o.tuser.key <= s_reg_file.key; | |||||
ctrl_aes_o.tuser.nonce <= s_reg_file.nonce; | |||||
ctrl_aes_o.tdata <= s_reg_file.din; | |||||
ctrl_aes_o.tvalid <= s_reg_file.ctrl(AES_START); | |||||
end architecture; |
@ -0,0 +1,105 @@ | |||||
-- Copyright (c) 2022 by Torsten Meissner | |||||
-- | |||||
-- Licensed under the Apache License, Version 2.0 (the "License"); | |||||
-- you may not use this file except in compliance with the License. | |||||
-- You may obtain a copy of the License at | |||||
-- | |||||
-- https://www.apache.org/licenses/LICENSE-2.0 | |||||
-- | |||||
-- Unless required by applicable law or agreed to in writing, software | |||||
-- distributed under the License is distributed on an "AS IS" BASIS, | |||||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
-- See the License for the specific language governing permissions and | |||||
-- limitations under the License. | |||||
library ieee; | |||||
use ieee.std_logic_1164.all; | |||||
use ieee.numeric_std.all; | |||||
entity uart_rx is | |||||
generic ( | |||||
CLK_DIV : natural := 10 | |||||
); | |||||
port ( | |||||
-- globals | |||||
rst_n_i : in std_logic; | |||||
clk_i : in std_logic; | |||||
-- axis user interface | |||||
tdata_o : out std_logic_vector(7 downto 0); | |||||
tvalid_o : out std_logic; | |||||
tready_i : in std_logic; | |||||
-- uart interface | |||||
rx_i : in std_logic | |||||
); | |||||
end entity uart_rx; | |||||
architecture rtl of uart_rx is | |||||
type t_uart_state is (IDLE, RECEIVE, VALID); | |||||
signal s_uart_state : t_uart_state; | |||||
signal s_clk_en : std_logic; | |||||
signal s_clk_cnt : natural range 0 to CLK_DIV-1; | |||||
signal s_bit_cnt : natural range 0 to tdata_o'length+1; | |||||
signal s_rx_d : std_logic_vector(3 downto 0); | |||||
begin | |||||
ClkDivP : process (clk_i, rst_n_i) is | |||||
begin | |||||
if (not rst_n_i) then | |||||
s_clk_cnt <= CLK_DIV-1; | |||||
elsif (rising_edge(clk_i)) then | |||||
if (s_uart_state = IDLE) then | |||||
s_clk_cnt <= CLK_DIV-2; | |||||
elsif (s_uart_state = RECEIVE) then | |||||
if (s_clk_cnt = 0) then | |||||
s_clk_cnt <= CLK_DIV-1; | |||||
else | |||||
s_clk_cnt <= s_clk_cnt - 1; | |||||
end if; | |||||
end if; | |||||
end if; | |||||
end process ClkDivP; | |||||
s_clk_en <= '1' when s_uart_state = RECEIVE and s_clk_cnt = CLK_DIV/2-1 else '0'; | |||||
RxP : process (clk_i, rst_n_i) is | |||||
begin | |||||
if (not rst_n_i) then | |||||
s_uart_state <= IDLE; | |||||
tdata_o <= (others => '0'); | |||||
s_rx_d <= x"1"; | |||||
s_bit_cnt <= 0; | |||||
elsif (rising_edge(clk_i)) then | |||||
s_rx_d <= s_rx_d(2 downto 0) & rx_i; | |||||
FsmL : case s_uart_state is | |||||
when IDLE => | |||||
s_bit_cnt <= tdata_o'length+1; | |||||
if (s_rx_d = "1000") then | |||||
s_uart_state <= RECEIVE; | |||||
end if; | |||||
when RECEIVE => | |||||
if (s_clk_en) then | |||||
if (s_bit_cnt = 0) then | |||||
s_uart_state <= VALID; | |||||
else | |||||
tdata_o <= s_rx_d(3) & tdata_o(tdata_o'length-1 downto 1); | |||||
s_bit_cnt <= s_bit_cnt - 1; | |||||
end if; | |||||
end if; | |||||
when VALID => | |||||
if (tready_i) then | |||||
s_uart_state <= IDLE; | |||||
end if; | |||||
end case; | |||||
end if; | |||||
end process RxP; | |||||
tvalid_o <= '1' when s_uart_state = VALID else '0'; | |||||
end architecture rtl; |
@ -0,0 +1,102 @@ | |||||
-- Copyright (c) 2022 by Torsten Meissner | |||||
-- | |||||
-- Licensed under the Apache License, Version 2.0 (the "License"); | |||||
-- you may not use this file except in compliance with the License. | |||||
-- You may obtain a copy of the License at | |||||
-- | |||||
-- https://www.apache.org/licenses/LICENSE-2.0 | |||||
-- | |||||
-- Unless required by applicable law or agreed to in writing, software | |||||
-- distributed under the License is distributed on an "AS IS" BASIS, | |||||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
-- See the License for the specific language governing permissions and | |||||
-- limitations under the License. | |||||
library ieee; | |||||
use ieee.std_logic_1164.all; | |||||
use ieee.numeric_std.all; | |||||
entity uart_tx is | |||||
generic ( | |||||
CLK_DIV : natural := 10 | |||||
); | |||||
port ( | |||||
-- globals | |||||
rst_n_i : in std_logic; | |||||
clk_i : in std_logic; | |||||
-- axis user interface | |||||
tdata_i : in std_logic_vector(7 downto 0); | |||||
tvalid_i : in std_logic; | |||||
tready_o : out std_logic; | |||||
-- uart interface | |||||
tx_o : out std_logic | |||||
); | |||||
end entity uart_tx; | |||||
architecture rtl of uart_tx is | |||||
type t_uart_state is (IDLE, SEND); | |||||
signal s_uart_state : t_uart_state; | |||||
signal s_data : std_logic_vector(tdata_i'length+1 downto 0); | |||||
signal s_clk_cnt : natural range 0 to CLK_DIV-1; | |||||
signal s_clk_en : std_logic; | |||||
signal s_bit_cnt : natural range 0 to s_data'length-1; | |||||
begin | |||||
ClkDivP : process (clk_i, rst_n_i) is | |||||
begin | |||||
if (not rst_n_i) then | |||||
s_clk_cnt <= CLK_DIV-1; | |||||
elsif (rising_edge(clk_i)) then | |||||
if (s_uart_state = IDLE) then | |||||
s_clk_cnt <= CLK_DIV-2; | |||||
elsif (s_uart_state = SEND) then | |||||
if (s_clk_cnt = 0) then | |||||
s_clk_cnt <= CLK_DIV-1; | |||||
else | |||||
s_clk_cnt <= s_clk_cnt - 1; | |||||
end if; | |||||
end if; | |||||
end if; | |||||
end process ClkDivP; | |||||
s_clk_en <= '1' when s_uart_state = SEND and s_clk_cnt = 0 else '0'; | |||||
TxP : process (clk_i, rst_n_i) is | |||||
begin | |||||
if (not rst_n_i) then | |||||
s_uart_state <= IDLE; | |||||
s_data <= (0 => '1', others => '0'); | |||||
s_bit_cnt <= 0; | |||||
elsif (rising_edge(clk_i)) then | |||||
FsmL : case s_uart_state is | |||||
when IDLE => | |||||
s_bit_cnt <= s_data'length-1; | |||||
if (tvalid_i) then | |||||
s_data <= '1' & tdata_i & '0'; | |||||
s_uart_state <= SEND; | |||||
end if; | |||||
when SEND => | |||||
if (s_clk_en) then | |||||
s_data <= '1' & s_data(s_data'length-1 downto 1); | |||||
if (s_bit_cnt = 0) then | |||||
s_uart_state <= IDLE; | |||||
else | |||||
s_bit_cnt <= s_bit_cnt - 1; | |||||
end if; | |||||
end if; | |||||
end case; | |||||
end if; | |||||
end process TxP; | |||||
tready_o <= '1' when s_uart_state = IDLE else '0'; | |||||
tx_o <= s_data(0); | |||||
end architecture rtl; |
@ -0,0 +1,57 @@ | |||||
DESIGN_NAME := uart_aes | |||||
AES_DIR := ../../cryptocores/aes/rtl/vhdl | |||||
CRYPTO_SRC := \ | |||||
$(AES_DIR)/aes_pkg.vhd \ | |||||
$(AES_DIR)/aes_enc.vhd \ | |||||
$(AES_DIR)/aes_dec.vhd \ | |||||
$(AES_DIR)/aes.vhd \ | |||||
$(AES_DIR)/../../../ctraes/rtl/vhdl/ctraes.vhd | |||||
WORK_FILES := \ | |||||
../rtl/uart_aes_types.vhd \ | |||||
../rtl/uart_tx.vhd \ | |||||
../rtl/uart_rx.vhd \ | |||||
../rtl/uart_ctrl.vhd \ | |||||
../rtl/${DESIGN_NAME}.vhd \ | |||||
uart_aes_sim.vhd \ | |||||
uart_aes_ref.vhd \ | |||||
tb_${DESIGN_NAME}.vhd | |||||
GM_FILES := ../../lib/rtl_components.vhd ../../lib/sim_components.vhd | |||||
SIM_SRC := tb_${DESIGN_NAME}.vhd | |||||
SIM_FLAGS := --std=08 -fpsl --workdir=work -Pwork | |||||
.PHONY: all compile sim clean | |||||
all: sim | |||||
compile: tb_${DESIGN_NAME} | |||||
work/work-obj08.cf: ${WORK_FILES} work/gatemate-obj08.cf work/cryptocores-obj08.cf | |||||
mkdir -p work | |||||
ghdl -a ${SIM_FLAGS} --work=work ${WORK_FILES} | |||||
work/cryptocores-obj08.cf: ${CRYPTO_SRC} | |||||
mkdir -p work | |||||
ghdl -a $(SIM_FLAGS) --work=cryptocores ${CRYPTO_SRC} | |||||
work/gatemate-obj08.cf: ${GM_FILES} | |||||
mkdir -p work | |||||
ghdl -a ${SIM_FLAGS} --work=gatemate ${GM_FILES} | |||||
tb_${DESIGN_NAME}: work/work-obj08.cf uart_aes_ref.c | |||||
@echo "Elaborate testbench & design ..." | |||||
ghdl -e ${SIM_FLAGS} -Wl,uart_aes_ref.c -Wl,-lcrypto -Wl,-lssl $@ | |||||
sim: tb_${DESIGN_NAME} | |||||
@echo "Run testbench ..." | |||||
ghdl -r ${SIM_FLAGS} tb_${DESIGN_NAME} --assert-level=error --ieee-asserts=disable --wave=tb_${DESIGN_NAME}.ghw | |||||
work: | |||||
mkdir $@ | |||||
clean: | |||||
@echo "Cleaning simulation files ..." | |||||
rm -rf tb_${DESIGN_NAME} tb_${DESIGN_NAME}.ghw *.o work/ |
@ -0,0 +1,13 @@ | |||||
set signals [list] | |||||
lappend signals "top.tb_uart_aes.dut.aes_inst.reset_i" | |||||
lappend signals "top.tb_uart_aes.dut.aes_inst.clk_i" | |||||
lappend signals "top.tb_uart_aes.dut.aes_inst.valid_i" | |||||
lappend signals "top.tb_uart_aes.dut.aes_inst.accept_o" | |||||
lappend signals "top.tb_uart_aes.dut.aes_inst.start_i" | |||||
lappend signals "top.tb_uart_aes.dut.aes_inst.key_i" | |||||
lappend signals "top.tb_uart_aes.dut.aes_inst.nonce_i" | |||||
lappend signals "top.tb_uart_aes.dut.aes_inst.data_i" | |||||
lappend signals "top.tb_uart_aes.dut.aes_inst.valid_o" | |||||
lappend signals "top.tb_uart_aes.dut.aes_inst.accept_i" | |||||
lappend signals "top.tb_uart_aes.dut.aes_inst.data_o" | |||||
set num_added [ gtkwave::addSignalsFromList $signals ] |
@ -0,0 +1,73 @@ | |||||
library ieee ; | |||||
use ieee.std_logic_1164.all; | |||||
use ieee.numeric_std.all; | |||||
use std.env.all; | |||||
use work.uart_aes_ref.all; | |||||
entity tb_uart_aes is | |||||
end entity tb_uart_aes; | |||||
architecture sim of tb_uart_aes is | |||||
signal s_clk : std_logic := '1'; | |||||
signal s_rst_n : std_logic := '0'; | |||||
signal s_uart_rx : std_logic := '1'; | |||||
signal s_uart_tx : std_logic; | |||||
constant c_baudrate : natural := 9600; | |||||
constant c_period_ns : time := 1_000_000_000 / c_baudrate * ns; | |||||
package uart_aes_sim_inst is new work.uart_aes_sim | |||||
generic map (period_ns => c_period_ns); | |||||
use uart_aes_sim_inst.all; | |||||
begin | |||||
dut : entity work.uart_aes | |||||
port map ( | |||||
clk_i => s_clk, | |||||
rst_n_i => s_rst_n, | |||||
uart_rx_i => s_uart_rx, | |||||
uart_tx_o => s_uart_tx | |||||
); | |||||
s_rst_n <= '1' after 120 ns; | |||||
s_clk <= not s_clk after 50 ns; | |||||
TestP : process is | |||||
variable v_data : std_logic_vector(7 downto 0); | |||||
variable v_uart_data : std_logic_vector(0 to 127); | |||||
variable v_key : std_logic_vector(0 to 127); | |||||
variable v_nonce : std_logic_vector(0 to 95); | |||||
variable v_in_data : std_logic_vector(0 to 127); | |||||
variable v_ref_data : std_logic_vector(0 to 127); | |||||
begin | |||||
wait until s_rst_n; | |||||
wait until rising_edge(s_clk); | |||||
wait for 200 us; | |||||
v_key := x"0123456789ABCDEF0123456789ABCDEF"; | |||||
v_nonce := x"0123456789ABCDEF01234567"; | |||||
aes_setup(v_key, v_nonce, s_uart_rx); | |||||
for i in 0 to 7 loop | |||||
report "Test round " & to_string(i); | |||||
v_in_data := x"0123456789ABCDEF0123456789ABCDEF"; | |||||
aes_write(v_in_data, s_uart_rx); | |||||
aes_crypt(s_uart_rx, s_uart_tx); | |||||
aes_read(v_uart_data, s_uart_rx, s_uart_tx); | |||||
-- Calc reference data | |||||
cryptData(swap(v_in_data), swap(v_key), swap(v_nonce & 32x"0"), i=0, i=7, v_ref_data, v_in_data'length/8); | |||||
assert v_uart_data = swap(v_ref_data) | |||||
report "Encryption error: Expected 0x" & to_hstring(swap(v_ref_data)) & ", got 0x" & to_hstring(v_uart_data) | |||||
severity failure; | |||||
end loop; | |||||
wait for 100 us; | |||||
report "Simulation finished without errors"; | |||||
stop(0); | |||||
end process; | |||||
end architecture; |
@ -0,0 +1,164 @@ | |||||
#include <stdio.h> | |||||
#include <string.h> | |||||
#include <openssl/conf.h> | |||||
#include <openssl/evp.h> | |||||
#include <openssl/err.h> | |||||
static const char HDL_LOGIC_CHAR[] = { 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'}; | |||||
enum HDL_LOGIC_STATES { | |||||
HDL_U = 0, | |||||
HDL_X = 1, | |||||
HDL_0 = 2, | |||||
HDL_1 = 3, | |||||
HDL_Z = 4, | |||||
HDL_W = 5, | |||||
HDL_L = 6, | |||||
HDL_H = 7, | |||||
HDL_D = 8, | |||||
}; | |||||
EVP_CIPHER_CTX *ctx; | |||||
void slv_to_uchar(char* datain, unsigned char* dataout, int bytelen) { | |||||
for (int i = 0; i < bytelen; i++) { | |||||
for (int y = 0; y < 8; y++) { | |||||
if (*datain == HDL_1) { | |||||
*dataout |= 1 << y; | |||||
} else if (*datain == HDL_0) { | |||||
*dataout &= ~(1 << y); | |||||
} | |||||
datain++; | |||||
} | |||||
dataout++; | |||||
} | |||||
return; | |||||
} | |||||
void slv_to_string(char* datain, char* dataout, int bytelen) { | |||||
for (int i = 0; i < bytelen; i++) { | |||||
*dataout = HDL_LOGIC_CHAR[*datain]; | |||||
datain++; | |||||
dataout++; | |||||
} | |||||
return; | |||||
} | |||||
void uchar_to_slv(unsigned char* datain, char* dataout, int bytelen) { | |||||
for (int i = 0; i < bytelen; i++) { | |||||
for (int y = 0; y < 8; y++) { | |||||
if ((*datain >> y) & 1 == 1) { | |||||
*dataout = HDL_1 ; | |||||
} else { | |||||
*dataout = HDL_0; | |||||
} | |||||
dataout++; | |||||
} | |||||
datain++; | |||||
} | |||||
return; | |||||
} | |||||
void handleErrors(void) { | |||||
ERR_print_errors_fp(stderr); | |||||
abort(); | |||||
} | |||||
void init(unsigned char *key, unsigned char *iv) { | |||||
// Create and initialise the context | |||||
if(!(ctx = EVP_CIPHER_CTX_new())) | |||||
handleErrors(); | |||||
// Initialise the encryption operation, no IV needed in CTR mode | |||||
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv)) | |||||
handleErrors(); | |||||
// We don't want padding | |||||
if(1 != EVP_CIPHER_CTX_set_padding(ctx, 0)) | |||||
handleErrors(); | |||||
} | |||||
int encrypt(unsigned char *plaintext, | |||||
int plaintext_len, | |||||
unsigned char *ciphertext) { | |||||
int len = 0; | |||||
// Provide the message to be encrypted, and obtain the encrypted output | |||||
if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) | |||||
handleErrors(); | |||||
return len; | |||||
} | |||||
int finalize(void) { | |||||
int len = 0; | |||||
unsigned char data[16]; | |||||
// Finalise the encryption. No further bytes are written as padding is switched off | |||||
if (1 != EVP_EncryptFinal_ex(ctx, data, &len)) | |||||
handleErrors(); | |||||
// Clean up | |||||
EVP_CIPHER_CTX_free(ctx); | |||||
return len; | |||||
} | |||||
void cryptData(char* datain, char* key, char* iv, char start, char final, char* dataout, int bytelen) { | |||||
int crypt_len; | |||||
unsigned char c_din[bytelen]; | |||||
unsigned char c_key[bytelen]; | |||||
unsigned char c_iv[bytelen]; | |||||
unsigned char c_dout[bytelen]; | |||||
slv_to_uchar(datain, c_din, bytelen); | |||||
slv_to_uchar(key, c_key, bytelen); | |||||
slv_to_uchar(iv, c_iv, bytelen); | |||||
if (start) { | |||||
init(c_key, c_iv); | |||||
} | |||||
crypt_len = encrypt(c_din, bytelen, c_dout); | |||||
if (crypt_len != bytelen) { | |||||
printf("Warning: encrypt() returned with unexpected length %d\n", crypt_len); | |||||
} | |||||
if (final) { | |||||
crypt_len = finalize(); | |||||
if (crypt_len != 0) { | |||||
printf("Warning: finalize() returned with unexpected length %d\n", crypt_len); | |||||
} | |||||
} | |||||
uchar_to_slv(c_dout, dataout, bytelen); | |||||
return; | |||||
} |
@ -0,0 +1,46 @@ | |||||
library ieee ; | |||||
use ieee.std_logic_1164.all; | |||||
package uart_aes_ref is | |||||
procedure cryptData(datain : in std_logic_vector(0 to 127); | |||||
key : in std_logic_vector(0 to 127); | |||||
iv : in std_logic_vector(0 to 127); | |||||
start : in boolean; | |||||
final : in boolean; | |||||
dataout : out std_logic_vector(0 to 127); | |||||
bytelen : in integer); | |||||
attribute foreign of cryptData: procedure is "VHPIDIRECT cryptData"; | |||||
function swap (datain : std_logic_vector(0 to 127)) return std_logic_vector; | |||||
end package; | |||||
package body uart_aes_ref is | |||||
procedure cryptData(datain : in std_logic_vector(0 to 127); | |||||
key : in std_logic_vector(0 to 127); | |||||
iv : in std_logic_vector(0 to 127); | |||||
start : in boolean; | |||||
final : in boolean; | |||||
dataout : out std_logic_vector(0 to 127); | |||||
bytelen : in integer) is | |||||
begin | |||||
report "VHPIDIRECT cryptData" severity failure; | |||||
end procedure; | |||||
function swap (datain : std_logic_vector(0 to 127)) return std_logic_vector is | |||||
variable v_data : std_logic_vector(0 to 127); | |||||
begin | |||||
for i in 0 to 15 loop | |||||
for y in 0 to 7 loop | |||||
v_data((i*8)+y) := datain((i*8)+7-y); | |||||
end loop; | |||||
end loop; | |||||
return v_data; | |||||
end function; | |||||
end package body; |
@ -0,0 +1,125 @@ | |||||
library ieee ; | |||||
use ieee.std_logic_1164.all; | |||||
package uart_aes_sim is | |||||
generic ( | |||||
period_ns : time | |||||
); | |||||
procedure uart_send ( data : in std_logic_vector(7 downto 0); | |||||
signal tx : out std_logic); | |||||
procedure uart_recv ( data : out std_logic_vector(7 downto 0); | |||||
signal rx : in std_logic); | |||||
procedure aes_setup ( key : in std_logic_vector(0 to 127); | |||||
nonce : in std_logic_vector(0 to 95); | |||||
signal tx : out std_logic); | |||||
procedure aes_write ( data : in std_logic_vector(0 to 127); | |||||
signal tx : out std_logic); | |||||
procedure aes_read ( data : out std_logic_vector(0 to 127); | |||||
signal tx : out std_logic; | |||||
signal rx : in std_logic); | |||||
procedure aes_crypt (signal tx : out std_logic; | |||||
signal rx : in std_logic); | |||||
end package; | |||||
package body uart_aes_sim is | |||||
procedure uart_send ( data : in std_logic_vector(7 downto 0); | |||||
signal tx : out std_logic) is | |||||
begin | |||||
report "UART send: 0x" & to_hstring(data); | |||||
wait for period_ns; | |||||
tx <= '0'; | |||||
wait for period_ns; | |||||
for i in 0 to 7 loop | |||||
tx <= data(i); | |||||
wait for period_ns; | |||||
end loop; | |||||
tx <= '1'; | |||||
wait for 0 ns; | |||||
end procedure; | |||||
procedure uart_recv ( data : out std_logic_vector(7 downto 0); | |||||
signal rx : in std_logic) is | |||||
begin | |||||
wait until not rx; | |||||
wait for period_ns; -- Skip start bit | |||||
wait for period_ns/2; | |||||
for i in 0 to 7 loop | |||||
data(i) := rx; | |||||
wait for period_ns; | |||||
end loop; | |||||
report "UART recv: 0x" & to_hstring(data); | |||||
end procedure; | |||||
procedure aes_setup ( key : in std_logic_vector(0 to 127); | |||||
nonce : in std_logic_vector(0 to 95); | |||||
signal tx : out std_logic) is | |||||
begin | |||||
-- Reset control register | |||||
uart_send(x"01", tx); | |||||
uart_send(x"01", tx); | |||||
-- Write key register | |||||
for i in 0 to 15 loop | |||||
uart_send(x"11", tx); | |||||
uart_send(key(i*8 to i*8+7), tx); | |||||
end loop; | |||||
-- Write nonce register | |||||
for i in 0 to 11 loop | |||||
uart_send(x"21", tx); | |||||
uart_send(nonce(i*8 to i*8+7), tx); | |||||
end loop; | |||||
-- Set control registers CTR_START bit | |||||
uart_send(x"01", tx); | |||||
uart_send(x"02", tx); | |||||
end procedure; | |||||
procedure aes_write ( data : in std_logic_vector(0 to 127); | |||||
signal tx : out std_logic) is | |||||
begin | |||||
-- Write din register | |||||
for i in 0 to 15 loop | |||||
uart_send(x"31", tx); | |||||
uart_send(data(i*8 to i*8+7), tx); | |||||
end loop; | |||||
end procedure; | |||||
procedure aes_read ( data : out std_logic_vector(0 to 127); | |||||
signal tx : out std_logic; | |||||
signal rx : in std_logic) is | |||||
variable v_data : std_logic_vector(7 downto 0); | |||||
begin | |||||
-- Check for valid AES output data | |||||
loop | |||||
uart_send(x"00", tx); | |||||
uart_recv(v_data, rx); | |||||
exit when v_data(3); | |||||
end loop; | |||||
-- Read dout register | |||||
for i in 0 to 15 loop | |||||
uart_send(x"40", tx); | |||||
uart_recv(data(i*8 to i*8+7), rx); | |||||
end loop; | |||||
end procedure; | |||||
procedure aes_crypt (signal tx : out std_logic; | |||||
signal rx : in std_logic) is | |||||
variable v_data : std_logic_vector(7 downto 0); | |||||
begin | |||||
uart_send(x"00", tx); | |||||
uart_recv(v_data, rx); | |||||
v_data(2) := '1'; | |||||
-- Set control registers CTR_START bit | |||||
uart_send(x"01", tx); | |||||
uart_send(v_data, tx); | |||||
end procedure; | |||||
end package body; |
@ -0,0 +1,72 @@ | |||||
DESIGN_NAME := uart_aes | |||||
AES_DIR := ../../cryptocores/aes/rtl/vhdl | |||||
CRYPTO_SRC := \ | |||||
$(AES_DIR)/aes_pkg.vhd \ | |||||
$(AES_DIR)/aes_enc.vhd \ | |||||
$(AES_DIR)/aes_dec.vhd \ | |||||
$(AES_DIR)/aes.vhd \ | |||||
$(AES_DIR)/../../../ctraes/rtl/vhdl/ctraes.vhd | |||||
WORK_FILES := \ | |||||
../rtl/uart_aes_types.vhd \ | |||||
../rtl/uart_tx.vhd \ | |||||
../rtl/uart_rx.vhd \ | |||||
../rtl/uart_ctrl.vhd \ | |||||
../rtl/${DESIGN_NAME}.vhd | |||||
GM_FILES := ../../lib/rtl_components.vhd | |||||
GHDL_FLAGS := --std=08 --workdir=build -Pbuild | |||||
ICARUSFLAGS := -Wall -Winfloop -g2012 -gspecify -Ttyp | |||||
YOSYSPIPE := -nomx8 | |||||
PNRFLAGS := -om 3 -cCP on | |||||
PNRTOOL := $(shell which p_r) | |||||
.PHONY: all syn imp prog syn_sim imp_sim | |||||
all: imp | |||||
syn: ${DESIGN_NAME}.v | |||||
imp: ${DESIGN_NAME}.bit | |||||
build/work-obj08.cf: ${WORK_FILES} build/gatemate-obj08.cf build/cryptocores-obj08.cf | |||||
ghdl -a ${GHDL_FLAGS} --work=work ${WORK_FILES} | |||||
build/cryptocores-obj08.cf: ${CRYPTO_SRC} | |||||
ghdl -a $(GHDL_FLAGS) --work=cryptocores ${CRYPTO_SRC} | |||||
build/gatemate-obj08.cf: ${GM_FILES} | |||||
mkdir -p build | |||||
ghdl -a ${GHDL_FLAGS} --work=gatemate ${GM_FILES} | |||||
# Synthesis target for implementation | |||||
${DESIGN_NAME}.v: build/work-obj08.cf | |||||
yosys -m ghdl -p 'ghdl ${GHDL_FLAGS} --warn-no-binding --no-formal ${DESIGN_NAME}; synth_gatemate -top $(DESIGN_NAME) ${YOSYSPIPE} -vlog $@' \ | |||||
2>&1 | tee build/yosys-report.txt | |||||
# Implementation target for FPGA | |||||
${DESIGN_NAME}.bit: ${DESIGN_NAME}.v ${DESIGN_NAME}.ccf | |||||
cd build && \ | |||||
${PNRTOOL} -i ../${DESIGN_NAME}.v -o $@ --ccf ../${DESIGN_NAME}.ccf $(PNRFLAGS) \ | |||||
2>&1 | tee p_r-report.txt && \ | |||||
mv ${DESIGN_NAME}*.bit ../$@ | |||||
# Post-synthesis simulation target | |||||
syn_sim: ${DESIGN_NAME}.v | |||||
iverilog ${ICARUSFLAGS} -o tb_${DESIGN_NAME}_syn.vvp ${DESIGN_NAME}.v tb_${DESIGN_NAME}.v /usr/local/share/yosys/gatemate/cells_sim.v | |||||
vvp -N tb_${DESIGN_NAME}_syn.vvp -fst | |||||
# Post-implementation simulation target | |||||
imp_sim: ${DESIGN_NAME}.bit | |||||
iverilog ${ICARUSFLAGS} -o tb_${DESIGN_NAME}_imp.vvp build/${DESIGN_NAME}_00.v tb_${DESIGN_NAME}.v /opt/cc-toolchain-linux/bin/p_r/cpelib.v | |||||
vvp -N tb_${DESIGN_NAME}_imp.vvp -fst | |||||
# FPGA FW load per JTAG | |||||
prog: ${DESIGN_NAME}.bit | |||||
openFPGALoader -b gatemate_evb_jtag $< | |||||
clean : | |||||
echo "# Cleaning files" | |||||
rm -rf build ${DESIGN_NAME}.v ${DESIGN_NAME}_sim.v ${DESIGN_NAME}.vhd ${DESIGN_NAME}.bit *.vvp *.fst |
@ -0,0 +1,16 @@ | |||||
A0 | |||||
55 | |||||
A0 | |||||
62 | |||||
BC | |||||
DD | |||||
C3 | |||||
4C | |||||
33 | |||||
FE | |||||
9F | |||||
A6 | |||||
0C | |||||
FB | |||||
6F | |||||
2D |
@ -0,0 +1,149 @@ | |||||
`timescale 1 ns/100 ps // time-unit = 1 ns, precision = 10 ps | |||||
// simplified CC_PLL model | |||||
module CC_PLL #( | |||||
parameter REF_CLK = "", // e.g. "10.0" | |||||
parameter OUT_CLK = "", // e.g. "50.0" | |||||
parameter PERF_MD = "", // LOWPOWER, ECONOMY, SPEED | |||||
parameter LOW_JITTER = 1, | |||||
parameter CI_FILTER_CONST = 2, | |||||
parameter CP_FILTER_CONST = 4 | |||||
)( | |||||
input CLK_REF, CLK_FEEDBACK, USR_CLK_REF, | |||||
input USR_LOCKED_STDY_RST, USR_SET_SEL, | |||||
output USR_PLL_LOCKED_STDY, USR_PLL_LOCKED, | |||||
output CLK270, CLK180, CLK90, CLK0, CLK_REF_OUT | |||||
); | |||||
reg r_pll_clk; | |||||
reg r_user_pll_locked; | |||||
// OUT_FREQ = 10 MHz | |||||
integer clk_half_period = 50; | |||||
initial begin | |||||
r_pll_clk = 1'b0; | |||||
r_user_pll_locked = 1'b1; | |||||
end | |||||
always #clk_half_period r_pll_clk = ~r_pll_clk; | |||||
assign CLK0 = r_pll_clk; | |||||
assign USR_PLL_LOCKED = r_user_pll_locked; | |||||
endmodule | |||||
// simplified CC_CFG_END model | |||||
module CC_CFG_END ( | |||||
output CFG_END | |||||
); | |||||
assign CFG_END = 1'b1; | |||||
endmodule | |||||
module tb_uart_aes; | |||||
// DUT in/out | |||||
reg clk = 1'b0; | |||||
reg rst_n = 1'b1; | |||||
reg uart_rx; | |||||
wire uart_tx; | |||||
wire [3:0] led_n; | |||||
// Testbench variables | |||||
reg [7:0] tx_data = 8'h0; | |||||
reg [7:0] rx_data = 8'h0; | |||||
// Testbench 1/2 clock period | |||||
localparam clk_half_period = 50; | |||||
// UART period calculation (9600 baud) | |||||
localparam uart_bit_period = 1000000000 / 9600; | |||||
localparam uart_bit_half_period = uart_bit_period/2; | |||||
uart_aes UUT (.clk_i(clk), .rst_n_i(rst_n), .uart_rx_i(uart_rx), .uart_tx_o(uart_tx), .led_n_o(led_n)); | |||||
// set dumpfile | |||||
initial begin | |||||
$dumpfile ("tb_uart_aes.fst"); | |||||
$dumpvars (0, tb_uart_aes); | |||||
end | |||||
// Setup simulation | |||||
initial begin | |||||
uart_rx = 1'b1; | |||||
#1 rst_n = 1'b0; | |||||
#120 rst_n = 1'b1; | |||||
end | |||||
// Generate 10 mhz clock | |||||
always #clk_half_period clk = !clk; | |||||
reg [7:0] write_cmds [0:89]; | |||||
reg [7:0] read_data [0:15]; | |||||
// read in test data files | |||||
initial begin | |||||
$readmemh("write_cmds.txt", write_cmds); | |||||
$readmemh("read_data.txt", read_data); | |||||
end | |||||
// Stimuli generator | |||||
initial | |||||
forever @(posedge rst_n) begin | |||||
uart_rx = 1'b1; | |||||
#uart_bit_period; | |||||
// start crypto | |||||
for (integer i = 0; i < $size(write_cmds); i = i + 1) begin | |||||
tx_data = write_cmds[i]; | |||||
$display ("UART send: 0x%h", tx_data); | |||||
uart_rx = 1'b0; | |||||
#uart_bit_period; | |||||
for (integer i = 0; i <= 7; i = i + 1) begin | |||||
uart_rx = tx_data[i]; | |||||
#uart_bit_period; | |||||
end | |||||
uart_rx = 1'b1; | |||||
#uart_bit_period; | |||||
#uart_bit_period; | |||||
end | |||||
// Request read of data out register | |||||
for (integer i = 0; i <= 15; i = i + 1) begin | |||||
tx_data = 8'h40; | |||||
$display ("UART send: 0x%h", tx_data); | |||||
uart_rx = 1'b0; | |||||
#uart_bit_period; | |||||
for (integer i = 0; i <= 7; i = i + 1) begin | |||||
uart_rx = tx_data[i]; | |||||
#uart_bit_period; | |||||
end | |||||
uart_rx = 1'b1; | |||||
#uart_bit_period; | |||||
#uart_bit_period; | |||||
end | |||||
end | |||||
// Checker | |||||
initial begin | |||||
@(posedge rst_n) | |||||
for (integer i = 0; i <= 15; i = i + 1) begin | |||||
@(negedge uart_tx) | |||||
#uart_bit_period; | |||||
#uart_bit_half_period; | |||||
for (integer i = 0; i <= 7; i = i + 1) begin | |||||
rx_data[i] = uart_tx; | |||||
#uart_bit_period; | |||||
end | |||||
assert (rx_data == read_data[i]) | |||||
$display("UART recv: 0x%h", rx_data); | |||||
else | |||||
$error("UART receive error, got 0x%h, expected 0x%h", rx_data, read_data[i]); | |||||
end | |||||
$display ("UART tests finished"); | |||||
$finish; | |||||
end | |||||
endmodule |
@ -0,0 +1,21 @@ | |||||
# Configuration for the Gatemate eval board | |||||
Pin_in "clk_i" Loc = "IO_SB_A8" | SCHMITT_TRIGGER=true; | |||||
Pin_in "rst_n_i" Loc = "IO_EB_B0"; # SW3 | |||||
Pin_in "uart_rx_i" Loc = "IO_NB_A1"; # PMODA IO3 | |||||
Pin_out "uart_tx_o" Loc = "IO_NB_A0"; # PMODA IO1 | |||||
Pin_out "led_n_o[0]" Loc = "IO_EB_B1"; # LED D1 | |||||
Pin_out "led_n_o[1]" Loc = "IO_EB_B2"; # LED D2 | |||||
Pin_out "led_n_o[2]" Loc = "IO_EB_B3"; # LED D3 | |||||
Pin_out "led_n_o[3]" Loc = "IO_EB_B4"; # LED D4 | |||||
#Pin_out "debug_o[0]" Loc = "IO_NB_A4"; | |||||
#Pin_out "debug_o[1]" Loc = "IO_NB_A5"; | |||||
#Pin_out "debug_o[2]" Loc = "IO_NB_A6"; | |||||
#Pin_out "debug_o[3]" Loc = "IO_NB_A7"; | |||||
#Pin_out "debug_o[4]" Loc = "IO_NB_B4"; | |||||
#Pin_out "debug_o[5]" Loc = "IO_NB_B5"; | |||||
#Pin_out "debug_o[6]" Loc = "IO_NB_B6"; | |||||
#Pin_out "debug_o[7]" Loc = "IO_NB_B7"; |
@ -0,0 +1,90 @@ | |||||
11 | |||||
01 | |||||
11 | |||||
23 | |||||
11 | |||||
45 | |||||
11 | |||||
67 | |||||
11 | |||||
89 | |||||
11 | |||||
AB | |||||
11 | |||||
CD | |||||
11 | |||||
EF | |||||
11 | |||||
01 | |||||
11 | |||||
23 | |||||
11 | |||||
45 | |||||
11 | |||||
67 | |||||
11 | |||||
89 | |||||
11 | |||||
AB | |||||
11 | |||||
CD | |||||
11 | |||||
EF | |||||
21 | |||||
01 | |||||
21 | |||||
23 | |||||
21 | |||||
45 | |||||
21 | |||||
67 | |||||
21 | |||||
89 | |||||
21 | |||||
AB | |||||
21 | |||||
CD | |||||
21 | |||||
EF | |||||
21 | |||||
01 | |||||
21 | |||||
23 | |||||
21 | |||||
45 | |||||
21 | |||||
67 | |||||
31 | |||||
01 | |||||
31 | |||||
23 | |||||
31 | |||||
45 | |||||
31 | |||||
67 | |||||
31 | |||||
89 | |||||
31 | |||||
AB | |||||
31 | |||||
CD | |||||
31 | |||||
EF | |||||
31 | |||||
01 | |||||
31 | |||||
23 | |||||
31 | |||||
45 | |||||
31 | |||||
67 | |||||
31 | |||||
89 | |||||
31 | |||||
AB | |||||
31 | |||||
CD | |||||
31 | |||||
EF | |||||
01 | |||||
06 |