diff options
Diffstat (limited to 'PIC/uart.vhd')
| -rw-r--r-- | PIC/uart.vhd | 195 |
1 files changed, 0 insertions, 195 deletions
diff --git a/PIC/uart.vhd b/PIC/uart.vhd deleted file mode 100644 index a0fad93..0000000 --- a/PIC/uart.vhd +++ /dev/null @@ -1,195 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - --- TX: fire and forget (8E1) --- RX: FIFO-backed (8E1), consumer reads via rd_en/rx_data/rx_empty - -entity uart is - generic ( - CLK_FREQ : positive := 50_000_000; - BAUD_RATE : positive := 115_200; - CLKS_PER_BIT : positive := CLK_FREQ / BAUD_RATE - ); - port ( - clk : in std_logic; - -- TX - tx_should_send : in std_logic; - byte_in : in std_logic_vector(7 downto 0); - tx_done : out std_logic; - baud_tick : out std_logic; - uart_tx : out std_logic; - -- RX - uart_rx : in std_logic; - rd_en : in std_logic; - rx_data : out std_logic_vector(7 downto 0); - rx_empty : out std_logic; - rx_full : out std_logic - ); -end entity uart; - -architecture rtl of uart is - - signal baud_counter : std_logic_vector(15 downto 0) - := (others => '0'); - signal baud_tick_i : std_logic := '0'; - - signal tx_out : std_logic := '1'; - signal current_byte : std_logic_vector(7 downto 0) := (others => '0'); - signal tx_byte_latch : std_logic_vector(7 downto 0) := (others => '0'); - - -- RX input synchronizer (2FF, idle state is '1') - signal uart_rx_meta : std_logic := '1'; - signal uart_rx_sync : std_logic := '1'; - - -- RX FIFO wiring - signal fifo_wr_en : std_logic := '0'; - signal fifo_din : std_logic_vector(7 downto 0) - := (others => '0'); - signal fifo_full : std_logic := '0'; - -begin - - uart_tx <= tx_out; - baud_tick <= baud_tick_i; - - rx_fifo : entity work.fifo - generic map (DEPTH => 64, ADDR_BITS => 6, WIDTH => 8) - port map ( - clk => clk, - wr_en => fifo_wr_en, - rd_en => rd_en, - din => fifo_din, - dout => rx_data, - full => fifo_full, - empty => rx_empty - ); - - rx_full <= fifo_full; - - uart_rx_synchronizer : process(clk) - begin - if rising_edge(clk) then - uart_rx_meta <= uart_rx; - uart_rx_sync <= uart_rx_meta; - end if; - end process uart_rx_synchronizer; - - uart_baud_timer : process(clk) - begin - if rising_edge(clk) then - if unsigned(baud_counter) = CLKS_PER_BIT - 1 then - baud_counter <= (others => '0'); - baud_tick_i <= '1'; - else - baud_counter <= std_logic_vector(unsigned(baud_counter) + 1); - baud_tick_i <= '0'; - end if; - end if; - end process uart_baud_timer; - - uart_transmit_byte : process(clk) - type t_state is (idle, start, data, parity, stop); - variable state : t_state := idle; - variable bit_index : unsigned(2 downto 0); - variable parity_value : std_logic; - begin - if rising_edge(clk) then - tx_done <= '0'; - if baud_tick_i = '1' then - case state is - when idle => - if tx_should_send = '1' then - tx_out <= '0'; -- start bit immediately - tx_byte_latch <= byte_in; -- latch byte now - parity_value := '0'; - bit_index := (others => '0'); - state := data; - end if; - when start => - null; -- unused, kept for completeness - when data => - tx_out <= tx_byte_latch(to_integer(bit_index)); - parity_value := parity_value xor tx_byte_latch(to_integer(bit_index)); - if bit_index = 7 then - state := parity; - else - state := data; - end if; - bit_index := bit_index + 1; - when parity => - tx_out <= parity_value; - state := stop; - when stop => - tx_out <= '1'; - tx_done <= '1'; - state := idle; - end case; - end if; - end if; - end process uart_transmit_byte; - - uart_receive_byte : process(clk) - type rx_state_t is (idle, start, data, parity, stop); - variable state : rx_state_t := idle; - variable bit_index : unsigned(2 downto 0); - variable rx_byte : std_logic_vector(7 downto 0); - variable parity_val : std_logic; - variable rx_counter : unsigned(15 downto 0); - begin - if rising_edge(clk) then - fifo_wr_en <= '0'; - case state is - when idle => - if uart_rx_sync = '0' then - rx_counter := to_unsigned(CLKS_PER_BIT / 2, 16); - state := start; - end if; - when start => - if rx_counter = 0 then - if uart_rx_sync = '0' then - rx_counter := to_unsigned(CLKS_PER_BIT - 1, 16); - bit_index := (others => '0'); - parity_val := '0'; - state := data; - else - state := idle; - end if; - else - rx_counter := rx_counter - 1; - end if; - when data => - if rx_counter = 0 then - rx_byte(to_integer(bit_index)) := uart_rx_sync; - parity_val := parity_val xor uart_rx_sync; - rx_counter := to_unsigned(CLKS_PER_BIT - 1, 16); - if bit_index = 7 then - state := parity; - else - bit_index := bit_index + 1; - end if; - else - rx_counter := rx_counter - 1; - end if; - when parity => - if rx_counter = 0 then - rx_counter := to_unsigned(CLKS_PER_BIT - 1, 16); - state := stop; - else - rx_counter := rx_counter - 1; - end if; - when stop => - if rx_counter = 0 then - if uart_rx_sync = '1' and fifo_full = '0' then - fifo_din <= rx_byte; - fifo_wr_en <= '1'; - end if; - state := idle; - else - rx_counter := rx_counter - 1; - end if; - end case; - end if; - end process uart_receive_byte; - -end architecture rtl; |
