diff --git a/string_sender.gtkw b/string_sender.gtkw new file mode 100644 index 0000000..f5cf0cf --- /dev/null +++ b/string_sender.gtkw @@ -0,0 +1,27 @@ +[*] +[*] GTKWave Analyzer v3.3.98 (w)1999-2019 BSI +[*] Sat Jul 11 11:53:05 2020 +[*] +[dumpfile] "/home/maximilian/vga_uart_grabber_vhdl/string_sender.vcd" +[dumpfile_mtime] "Sat Jul 11 11:50:19 2020" +[dumpfile_size] 410742 +[savefile] "/home/maximilian/vga_uart_grabber_vhdl/string_sender.gtkw" +[timestart] 0 +[size] 1366 703 +[pos] -1 -1 +*-30.103638 200000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] string_sender_tb. +[sst_width] 212 +[signals_width] 299 +[sst_expanded] 1 +[sst_vpaned_height] 179 +@28 +string_sender_tb.tb_i_clk +string_sender_tb.tb_i_reset_n +string_sender_tb.tb_o_send +@22 +string_sender_tb.tb_o_char[7:0] +@29 +string_sender_tb.tb_i_sent +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/string_sender.vhdl b/string_sender.vhdl new file mode 100644 index 0000000..b29c3a0 --- /dev/null +++ b/string_sender.vhdl @@ -0,0 +1,77 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity string_sender is + port ( + i_clk :in std_logic; + i_send_clk :in std_logic; + i_sent :in std_logic; + i_reset_n :in std_logic; + o_send :out std_logic; + o_char :out std_logic_vector(7 downto 0) + ); +end; + +architecture string_sender_rtl of string_sender is + type z_sender_t is ( + idle, + wait_for_transmission, + sending + ); + --Function to convert one char to std_logic_vector with 8 bit + function f_char_to_vector( + i_char : in character) + return std_logic_vector is + variable v_ret : std_logic_vector(7 downto 0); + begin + v_ret := std_logic_vector( + to_unsigned(natural(character'pos(i_char)),8) + ); + return v_ret; + end function f_char_to_vector; + +begin + string_sender_main_proc: process(i_clk) + constant c_msg : string(1 to 13) := "Hello World!" & LF; + variable v_ind : integer range 0 to c_msg'length := 1; + variable v_old_clk : std_logic := '1'; + variable z_sender : z_sender_t := idle; + begin + if rising_edge(i_clk) then + if i_reset_n = '0' then + v_ind := 1; + v_old_clk := i_send_clk; + z_sender := idle; + o_send <= '0'; + o_char <= (others => '0'); + else + case z_sender is + when idle => + if (i_send_clk /= v_old_clk) then + v_old_clk := i_send_clk; + if (i_sent = '1') then + o_char <= f_char_to_vector(c_msg(v_ind)); + o_send <= '1'; + if v_ind = c_msg'length then + v_ind := 1; + else + v_ind := v_ind + 1; + end if; + z_sender := wait_for_transmission; + end if; + end if; + when wait_for_transmission => + if i_sent = '0' then + o_send <= '0'; + z_sender := sending; + end if; + when sending => + if (i_sent = '1') then + z_sender := idle; + end if; + end case; + end if; -- reset + end if; -- clk + end process string_sender_main_proc; +end; diff --git a/string_sender_tb.vhdl b/string_sender_tb.vhdl new file mode 100644 index 0000000..cc9a906 --- /dev/null +++ b/string_sender_tb.vhdl @@ -0,0 +1,100 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity string_sender_tb is +end string_sender_tb; + +architecture string_sender_tb_rtl of string_sender_tb is + -- 10 MHz clock + constant c_CLK_PERIOD : time := 100 ns; + signal tb_i_clk : std_logic := '0'; + signal tb_i_send_clk : std_logic := '0'; + signal tb_i_sent : std_logic := '1'; + signal tb_i_reset_n : std_logic := '1'; + signal tb_o_send : std_logic := '0'; + signal tb_o_char : std_logic_vector(7 downto 0) := (others => '0'); + signal tb_done : std_logic := '0'; +begin + string_send_0: entity work.string_sender(string_sender_rtl) + port map ( + i_clk => tb_i_clk, + i_send_clk => tb_i_send_clk, + i_sent => tb_i_sent, + i_reset_n => tb_i_reset_n, + o_send => tb_o_send, + o_char => tb_o_char + ); + -- Generate clock. + p_clock : process is + begin + if (tb_done = '0') then + tb_i_clk <= '0'; + wait for c_CLK_PERIOD/2; + tb_i_clk <= '1'; + wait for c_CLK_PERIOD/2; + elsif tb_done = '1' then + wait; + end if; + end process p_clock; + -- Generate send clock. + p_sclock : process is + begin + if (tb_done = '0') then + tb_i_send_clk <= '0'; + wait for 10*(c_CLK_PERIOD/2); + tb_i_send_clk <= '1'; + wait for 10*(c_CLK_PERIOD/2); + elsif tb_done = '1' then + wait; + end if; + end process p_sclock; + -- Process for stimuli. + p_stimuli : process is + begin + tb_i_reset_n <= '0'; + wait for 2*c_CLK_PERIOD; + tb_i_reset_n <= '1'; + wait for 1 ms; + tb_done <= '1'; + assert false report "end of test" severity note; + wait; + end process p_stimuli; + + p_ssp: process(tb_i_clk) + type z_ssp_t is ( + idle, + busy, + sending + ); + variable v_cnt : integer range 0 to 20 := 0; + variable z_ssp : z_ssp_t := idle; + begin + if rising_edge(tb_i_clk) then + case z_ssp is + when idle => + if tb_o_send = '1' then + v_cnt := 0; + tb_i_sent <= '1'; + z_ssp := busy; + end if; + when busy => + if v_cnt = 10 then + v_cnt := 0; + tb_i_sent <= '0'; + z_ssp := sending; + else + v_cnt := v_cnt + 1; + end if; + when sending => + if v_cnt = 20 then + v_cnt := 0; + tb_i_sent <= '1'; + z_ssp := idle; + else + v_cnt := v_cnt + 1; + end if; + end case; + end if; + end process p_ssp; +end;