From: Jan Michel Date: Tue, 1 Jul 2014 09:57:19 +0000 (+0200) Subject: added uart X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=b6e056698ff47c98cddb4528ef5d3e802f8164b6;p=trbnet.git added uart --- diff --git a/special/uart_rec.vhd b/special/uart_rec.vhd new file mode 100644 index 0000000..5edbaf0 --- /dev/null +++ b/special/uart_rec.vhd @@ -0,0 +1,157 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + + +entity uart_rec is +-- generic( +-- CLK_DIV : integer +-- ); + port( + CLK_DIV : in integer; + CLK : in std_logic; + RST : in std_logic; + RX : in std_logic; + + DATA_OUT : out std_logic_vector(7 downto 0); + DATA_WAITING : out std_logic; + DEBUG : out std_logic_vector(3 downto 0) + ); +end entity; + + + +architecture uart_rec_arch of uart_rec is + +signal clk_div_counter: unsigned(15 downto 0) := x"0000"; +signal symbol_pulse : std_logic := '0'; +signal symbol_counter: unsigned(3 downto 0) := x"0"; + +type state_type is (idle,receiving,update_parallel_output); +signal state: state_type := idle; + +-- MSB is the stopbit, LSB is the start bit, both are never changed +signal rx_shift_register: std_logic_vector(9 downto 0); +signal symbol : std_logic := '1'; +signal data_waiting_sig: std_logic := '0'; +signal current_data_out: std_logic_vector(7 downto 0) := "00000000"; +signal symbol_start_pulse : std_logic := '0'; -- just debug +signal rst_clk_div_counter : std_logic; + + +begin +---------------------------- +-- debug +---------------------------- + +DEBUG(0) <= symbol_start_pulse; +DEBUG(1) <= symbol_pulse; +DEBUG(2) <= data_waiting_sig; +DEBUG(3) <= '0'; + +---------------------------- +-- Inputs +---------------------------- + sync_input : process begin + wait until rising_edge(CLK); + symbol <= RX; + end process; + +---------------------------- +-- Outputs +---------------------------- + sync_output : process begin + wait until rising_edge(CLK); + DATA_WAITING <= data_waiting_sig; + DATA_OUT <= current_data_out; + end process; + +---------------------------- +-- Generate Serial Clock +---------------------------- + clock_division : process begin + wait until rising_edge(CLK); + -- scaling down the main clock to the desired baudrate + if clk_div_counter = CLK_DIV-1 then + clk_div_counter <= x"0000"; + else + clk_div_counter <= clk_div_counter + 1; + end if; + -- generates symbol_pulse, a signal that has 1 clock cycle pulses, one symbol duration period apart + -- in contrast to the transceiver module, the symbol pulse is generated in the middle of the + -- symbol period + -- if clk_div_counter = '0' & CLK_DIV(15 downto 1) then -- CLK_DIV/2 by >> (right shifting) + if clk_div_counter = CLK_DIV/2 then + symbol_pulse <= '1'; + else + symbol_pulse <= '0'; + end if; + + if clk_div_counter = x"0000" then + symbol_start_pulse <= '1'; + else + symbol_start_pulse <= '0'; + end if; + if (RST or rst_clk_div_counter) = '1' then + clk_div_counter <= x"0000"; + end if; + + end process; + +---------------------------- +-- State Machine of the Receiver +---------------------------- + state_machine : process begin + wait until rising_edge(CLK); + data_waiting_sig <= '0'; + rst_clk_div_counter <= '0'; + + -- state machine rules: + case state is + when idle => + + if symbol = '0' then -- the start bit comes! + state <= receiving; + -- restart the divcounter + -- clk_div_counter <= x"0000"; + rst_clk_div_counter<= '1'; + symbol_counter <= x"0"; + + end if; + + when receiving => + if symbol_pulse = '1' then + if symbol_counter <= 9 then -- reception process + rx_shift_register(to_integer(symbol_counter)) <= symbol; + symbol_counter <= symbol_counter + 1; + end if; + if symbol_counter = 9 then + state <= update_parallel_output; + end if; + + + end if; + when update_parallel_output => + state <= idle; + -- check start and stop bit consistency + -- (checking the start bit again seems a little obsolete) + -- only if bit was received correctly output the data! + if rx_shift_register(0) = '0' and rx_shift_register(9) = '1' then + current_data_out <= rx_shift_register(8 downto 1); + data_waiting_sig <= '1'; + end if; + + end case; + + -- reset clock divider counters when reset signal is on + if RST = '1' then + symbol_counter <= x"0"; + data_waiting_sig <= '0'; + state <= idle; + end if; + + end process; + + +end architecture; \ No newline at end of file diff --git a/special/uart_trans.vhd b/special/uart_trans.vhd new file mode 100644 index 0000000..c062f81 --- /dev/null +++ b/special/uart_trans.vhd @@ -0,0 +1,147 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + + +entity uart_trans is +-- generic( +-- CLK_DIV : integer +-- ); + port( + CLK_DIV : in integer; + CLK : in std_logic; + RST : in std_logic; + + DATA_IN : in std_logic_vector(7 downto 0); + SEND : in std_logic; + READY : out std_logic; + + TX : out std_logic; + DEBUG : out std_logic_vector(3 downto 0) + + ); +end entity; + + + +architecture uart_trans_arch of uart_trans is + + + +signal clk_div_counter: unsigned(15 downto 0) := x"0000"; +signal symbol_start_pulse : std_logic := '0'; +signal symbol_counter: unsigned(3 downto 0) := x"0"; + +type state_type is (idle,transmitting); +signal state: state_type := idle; + +-- MSB is the stopbit, LSB is the start bit, both are never changed +signal tx_shift_register: std_logic_vector(9 downto 0) := "1000000000"; +signal symbol: std_logic := '1'; +signal ready_sig: std_logic := '1'; +signal rst_clk_div_counter : std_logic; + + +begin +---------------------------- +-- debug +---------------------------- + +DEBUG(0) <= symbol_start_pulse; +DEBUG(1) <= '0'; +DEBUG(2) <= ready_sig; +DEBUG(3) <= '0'; + +---------------------------- +-- Inputs +---------------------------- +-- sync_input : process begin +-- wait until rising_edge(CLK); +-- synced_send <= SEND; +-- end process; +-- hard wired stuff + +---------------------------- +-- Outputs +---------------------------- + sync_output : process begin + wait until rising_edge(CLK); + TX <= symbol; + end process; + + READY <= ready_sig and not SEND; + +---------------------------- +-- Generate Serial Clock +---------------------------- + clock_division : process begin + wait until rising_edge(CLK); + -- scaling down the main clock to the desired baudrate + if clk_div_counter = CLK_DIV-1 then + clk_div_counter <= x"0000"; + else + clk_div_counter <= clk_div_counter + 1; + end if; + + + if clk_div_counter = x"0000" then + symbol_start_pulse <= '1'; + else + symbol_start_pulse <= '0'; + end if; + if (RST or rst_clk_div_counter) = '1' then + clk_div_counter <= x"0000"; + end if; + + end process; + +---------------------------- +-- State Machine of the Transmitter +---------------------------- + + state_machine : process begin + wait until rising_edge(CLK); + -- state machine rules: + rst_clk_div_counter <= '0'; + + case state is + when idle => + if SEND = '1' then + state <= transmitting; + symbol_counter <= x"0"; + -- capture the byte at the parallel input + tx_shift_register(8 downto 1) <= DATA_IN; + ready_sig <= '0'; + end if; + + when transmitting => + if symbol_start_pulse = '1' then + if symbol_counter <= 9 then -- transmission process + symbol <= tx_shift_register(to_integer(symbol_counter)); + symbol_counter <= symbol_counter + 1; + end if; + + end if; + if symbol_counter = 10 then -- pulse #10 (1 start, 8 data, 1 stop) has been sent + --, time to go to idle mode again + -- pull the tx line high again, actually obsolete, because stop bit is 1 + symbol <= '1'; + ready_sig <= '1'; + state <= idle; + end if; + + end case; + + -- reset clock divider counters when reset signal is on + if RST = '1' then + state <= idle; + ready_sig <= '1'; + end if; + + end process; + + + +end architecture; +