@ -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 |