From 5c8671e7e317805720de54682fecf56efbf51d42 Mon Sep 17 00:00:00 2001 From: Maximilian Stiefel Date: Sat, 11 Jul 2020 22:03:39 +0200 Subject: [PATCH] Top design for UART hello_world seems to work --- clock_divider.vhdl | 6 ++-- string_sender.gtkw | 16 +++++----- string_sender.vhdl | 30 +++++++++++-------- string_sender_tb.vhdl | 4 +-- top.gtkw | 26 ++++++++++++++++ top.vhdl | 70 +++++++++++++++++++++++++++++++++++++++++++ top_tb.vhdl | 48 +++++++++++++++++++++++++++++ 7 files changed, 176 insertions(+), 24 deletions(-) create mode 100644 top.gtkw create mode 100644 top.vhdl create mode 100644 top_tb.vhdl diff --git a/clock_divider.vhdl b/clock_divider.vhdl index 7d19588..1f15077 100644 --- a/clock_divider.vhdl +++ b/clock_divider.vhdl @@ -17,9 +17,9 @@ end; architecture clock_divider_rtl of clock_divider is begin clock_divider_main_proc: process(i_clk) - variable v_cnt : integer range 0 to 2**(N-1) := 0; - variable v_cnt_max : integer range 0 to (2**(N-1))/2 := 0; - variable v_clk : std_logic := '0'; + variable v_cnt : integer range 0 to 2**N := 1; + variable v_cnt_max : integer range 0 to 2**N := 1; + variable v_clk : std_logic := '0'; begin if rising_edge(i_clk) then if (i_reset_n = '0') then diff --git a/string_sender.gtkw b/string_sender.gtkw index f5cf0cf..8e5e2ba 100644 --- a/string_sender.gtkw +++ b/string_sender.gtkw @@ -1,27 +1,29 @@ [*] [*] GTKWave Analyzer v3.3.98 (w)1999-2019 BSI -[*] Sat Jul 11 11:53:05 2020 +[*] Sat Jul 11 17:55:22 2020 [*] [dumpfile] "/home/maximilian/vga_uart_grabber_vhdl/string_sender.vcd" -[dumpfile_mtime] "Sat Jul 11 11:50:19 2020" -[dumpfile_size] 410742 +[dumpfile_mtime] "Sat Jul 11 17:52:42 2020" +[dumpfile_size] 404232 [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 +[pos] 3 0 +*-35.103638 692000000 -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 +[sst_vpaned_height] 300 @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 +@28 string_sender_tb.tb_i_sent +@29 +string_sender_tb.tb_done [pattern_trace] 1 [pattern_trace] 0 diff --git a/string_sender.vhdl b/string_sender.vhdl index b29c3a0..937708e 100644 --- a/string_sender.vhdl +++ b/string_sender.vhdl @@ -16,7 +16,8 @@ end; architecture string_sender_rtl of string_sender is type z_sender_t is ( idle, - wait_for_transmission, + init_transmission, + wait_for_transmission_start, sending ); --Function to convert one char to std_logic_vector with 8 bit @@ -48,27 +49,32 @@ begin else case z_sender is when idle => - if (i_send_clk /= v_old_clk) then + if i_send_clk /= v_old_clk then v_old_clk := i_send_clk; - if (i_sent = '1') then + z_sender := init_transmission; + end if; + when init_transmission => + 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; + z_sender := wait_for_transmission_start; end if; - end if; - when wait_for_transmission => + when wait_for_transmission_start => if i_sent = '0' then o_send <= '0'; z_sender := sending; end if; when sending => if (i_sent = '1') then - z_sender := idle; + if v_ind = c_msg'length then + v_ind := 1; + -- String has been sent entirely + -- Go back to IDLE + z_sender := idle; + else + v_ind := v_ind + 1; + z_sender := init_transmission; + end if; end if; end case; end if; -- reset diff --git a/string_sender_tb.vhdl b/string_sender_tb.vhdl index cc9a906..0b30e56 100644 --- a/string_sender_tb.vhdl +++ b/string_sender_tb.vhdl @@ -42,9 +42,9 @@ begin begin if (tb_done = '0') then tb_i_send_clk <= '0'; - wait for 10*(c_CLK_PERIOD/2); + wait for 100 us; tb_i_send_clk <= '1'; - wait for 10*(c_CLK_PERIOD/2); + wait for 100 us; elsif tb_done = '1' then wait; end if; diff --git a/top.gtkw b/top.gtkw new file mode 100644 index 0000000..1000d5d --- /dev/null +++ b/top.gtkw @@ -0,0 +1,26 @@ +[*] +[*] GTKWave Analyzer v3.3.98 (w)1999-2019 BSI +[*] Sat Jul 11 19:58:56 2020 +[*] +[dumpfile] "/home/maximilian/vga_uart_grabber_vhdl/top.vcd" +[dumpfile_mtime] "Sat Jul 11 19:57:41 2020" +[dumpfile_size] 844762900 +[savefile] "/home/maximilian/vga_uart_grabber_vhdl/top.gtkw" +[timestart] 0 +[size] 1920 1051 +[pos] -1 -1 +*-47.083782 364693745000 -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] top_tb. +[treeopen] top_tb.top_0. +[sst_width] 212 +[signals_width] 179 +[sst_expanded] 1 +[sst_vpaned_height] 300 +@28 +top_tb.tb_clk_12mhz +top_tb.tb_done +top_tb.tb_led +@29 +top_tb.top_0.clock_divider_1.o_clk +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/top.vhdl b/top.vhdl new file mode 100644 index 0000000..2e31109 --- /dev/null +++ b/top.vhdl @@ -0,0 +1,70 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity top is + port ( + i_clk_12mhz : in std_logic; + i_reset_n : in std_logic; + o_tx_pin : out std_logic; + o_led : out std_logic + ); +end top; + +architecture top_rtl of top is + constant c_N_0 : integer := 30; + constant c_divisor_0 : integer := 12e6; + constant c_divisor_1 : integer := 1250; + constant s_divisor_vec_0 : std_logic_vector(c_N_0-1 downto 0) + := std_logic_vector(to_unsigned(c_divisor_0, c_N_0)); + constant s_divisor_vec_1 : std_logic_vector(c_N_0-1 downto 0) + := std_logic_vector(to_unsigned(c_divisor_1, c_N_0)); + + signal s_send_clk : std_logic := '0'; + signal s_sent : std_logic := '1'; + signal s_send : std_logic := '0'; + signal s_char_vec : std_logic_vector(7 downto 0) := (others => '0'); + signal s_baudrate_clk : std_logic := '0'; + +begin + -- Clock divider 0 gives the signal for when to send the string + clock_divider_0: entity work.clock_divider(clock_divider_rtl) + generic map (N => c_N_0) + port map ( + i_clk => i_clk_12mhz, + i_reset_n => i_reset_n, + i_divisor_vec => s_divisor_vec_0, + o_clk => s_send_clk + ); + -- Clock divider 1 produces a baudrate of 9600 Bd + clock_divider_1: entity work.clock_divider(clock_divider_rtl) + generic map (N => c_N_0) + port map ( + i_clk => i_clk_12mhz, + i_reset_n => i_reset_n, + i_divisor_vec => s_divisor_vec_1, + o_clk => s_baudrate_clk + ); + -- String sender component + string_send_0: entity work.string_sender(string_sender_rtl) + port map ( + i_clk => i_clk_12mhz, + i_send_clk => s_send_clk, + i_sent => s_sent, + i_reset_n => i_reset_n, + o_send => s_send, + o_char => s_char_vec + ); + -- UART transmitter component + uart_tx_0: entity work.uart_tx(uart_tx_rtl) + port map ( + i_clk_baudrate => s_baudrate_clk, + i_reset_n => i_reset_n, + i_tx_send => s_send, + i_tx_data_vec => s_char_vec, + o_tx_pin => o_tx_pin, + o_tx_sent => s_sent + ); + -- Couple send signal with LED + o_led <= s_send; +end; diff --git a/top_tb.vhdl b/top_tb.vhdl new file mode 100644 index 0000000..9c2d7c1 --- /dev/null +++ b/top_tb.vhdl @@ -0,0 +1,48 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity top_tb is +end top_tb; + +architecture top_tb_rtl of top_tb is + constant c_CLK_PERIOD : time := 83.33 ns; + + signal tb_clk_12mhz : std_logic := '0'; + signal tb_reset_n : std_logic := '1'; + signal tb_tx_pin : std_logic := '1'; + signal tb_led : std_logic := '0'; + signal tb_done : std_logic := '0'; + +begin + top_0: entity work.top(top_rtl) + port map( + i_clk_12mhz => tb_clk_12mhz, + i_reset_n => tb_reset_n, + o_tx_pin => tb_tx_pin, + o_led => tb_led + ); + -- Generate clock. + p_clock : process is + begin + if (tb_done = '0') then + tb_clk_12mhz <= '0'; + wait for c_CLK_PERIOD/2; + tb_clk_12mhz <= '1'; + wait for c_CLK_PERIOD/2; + elsif tb_done = '1' then + wait; + end if; + end process p_clock; + -- Process for stimuli. + p_stimuli : process is + begin + tb_reset_n <= '0'; + wait for 2*c_CLK_PERIOD; + tb_reset_n <= '1'; + wait for 1100 ms; + tb_done <= '1'; + assert false report "end of test" severity note; + wait; + end process p_stimuli; +end;