OpenCores
URL https://opencores.org/ocsvn/potato/potato/trunk

Subversion Repositories potato

[/] [potato/] [trunk/] [soc/] [pp_soc_uart.vhd] - Diff between revs 7 and 66

Only display areas with differences | Details | Blame | View Log

Rev 7 Rev 66
-- The Potato Processor - A simple processor for FPGAs
-- The Potato Processor - A simple processor for FPGAs
-- (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>
-- (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>
-- Report bugs and issues on <https://github.com/skordal/potato/issues>
-- Report bugs and issues on <https://github.com/skordal/potato/issues>
 
 
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
 
 
--! @brief Simple UART module.
--! @brief Simple UART module.
--! The following registers are defined:
--! The following registers are defined:
--! 0 - Transmit data register (write-only)
--! 0 - Transmit data register (write-only)
--! 1 - Receive data register (read-only)
--! 1 - Receive data register (read-only)
--! 2 - Status register; (read-only)
--! 2 - Status register; (read-only)
--!     - Bit 0: data in receive buffer
--!     - Bit 0: no data in receive buffer
--!     - Bit 1: no data in transmit buffer
--!     - Bit 1: no data in transmit buffer
--!     - Bit 2: receive buffer full
--!     - Bit 2: receive buffer full
--!     - Bit 3: transmit buffer full
--!     - Bit 3: transmit buffer full
--! 3 - Control register, currently unused.
--! 3 - Control register, currently unused.
entity pp_soc_uart is
entity pp_soc_uart is
        generic(
        generic(
                FIFO_DEPTH : natural := 64;        --! Depth of the input and output FIFOs.
                FIFO_DEPTH : natural := 64;        --! Depth of the input and output FIFOs.
                SAMPLE_CLK_DIVISOR : natural := 54 --! Divisor used to obtain the sample clock, f_clk / (16 * baudrate).
                SAMPLE_CLK_DIVISOR : natural := 54 --! Divisor used to obtain the sample clock, f_clk / (16 * baudrate).
        );
        );
        port(
        port(
                clk : in std_logic;
                clk : in std_logic;
                reset : in std_logic;
                reset : in std_logic;
 
 
                -- UART ports:
                -- UART ports:
                txd : out std_logic;
                txd : out std_logic;
                rxd : in  std_logic;
                rxd : in  std_logic;
 
 
                -- Interrupt signals:
                -- Interrupt signals:
                irq_send_buffer_empty : out std_logic;
                irq_send_buffer_empty : out std_logic;
                irq_data_received     : out std_logic;
                irq_data_received     : out std_logic;
 
 
                -- Wishbone ports:
                -- Wishbone ports:
                wb_adr_in  : in  std_logic_vector(1 downto 0);
                wb_adr_in  : in  std_logic_vector(1 downto 0);
                wb_dat_in  : in  std_logic_vector(7 downto 0);
                wb_dat_in  : in  std_logic_vector(7 downto 0);
                wb_dat_out : out std_logic_vector(7 downto 0);
                wb_dat_out : out std_logic_vector(7 downto 0);
                wb_we_in   : in  std_logic;
                wb_we_in   : in  std_logic;
                wb_cyc_in  : in  std_logic;
                wb_cyc_in  : in  std_logic;
                wb_stb_in  : in  std_logic;
                wb_stb_in  : in  std_logic;
                wb_ack_out : out std_logic
                wb_ack_out : out std_logic
        );
        );
end entity pp_soc_uart;
end entity pp_soc_uart;
 
 
architecture behaviour of pp_soc_uart is
architecture behaviour of pp_soc_uart is
 
 
        subtype bitnumber is natural range 0 to 7;
        subtype bitnumber is natural range 0 to 7;
 
 
        -- UART sample clock signals:
        -- UART sample clock signals:
        signal sample_clk : std_logic;
        signal sample_clk : std_logic;
 
 
        subtype sample_clk_counter_type is natural range 0 to SAMPLE_CLK_DIVISOR - 1;
        subtype sample_clk_counter_type is natural range 0 to SAMPLE_CLK_DIVISOR - 1;
        signal sample_clk_counter : sample_clk_counter_type := 0;
        signal sample_clk_counter : sample_clk_counter_type := 0;
 
 
        -- UART receive process signals:
        -- UART receive process signals:
        type rx_state_type is (IDLE, RECEIVE, STOPBIT);
        type rx_state_type is (IDLE, RECEIVE, STOPBIT);
        signal rx_state : rx_state_type;
        signal rx_state : rx_state_type;
        signal rx_byte : std_logic_vector(7 downto 0);
        signal rx_byte : std_logic_vector(7 downto 0);
        signal rx_current_bit : bitnumber;
        signal rx_current_bit : bitnumber;
 
 
        subtype rx_sample_counter_type is natural range 0 to 15;
        subtype rx_sample_counter_type is natural range 0 to 15;
        signal rx_sample_counter : rx_sample_counter_type;
        signal rx_sample_counter : rx_sample_counter_type;
        signal rx_sample_value   : rx_sample_counter_type;
        signal rx_sample_value   : rx_sample_counter_type;
 
 
        -- UART transmit process signals:
        -- UART transmit process signals:
        type tx_state_type is (IDLE, TRANSMIT, STOPBIT);
        type tx_state_type is (IDLE, TRANSMIT, STOPBIT);
        signal tx_state : tx_state_type;
        signal tx_state : tx_state_type;
        signal tx_byte : std_logic_vector(7 downto 0);
        signal tx_byte : std_logic_vector(7 downto 0);
        signal tx_current_bit : bitnumber;
        signal tx_current_bit : bitnumber;
 
 
        -- UART transmit clock:
        -- UART transmit clock:
        subtype uart_tx_counter_type is natural range 0 to 15;
        subtype uart_tx_counter_type is natural range 0 to 15;
        signal uart_tx_counter : uart_tx_counter_type := 0;
        signal uart_tx_counter : uart_tx_counter_type := 0;
        signal uart_tx_clk : std_logic;
        signal uart_tx_clk : std_logic;
 
 
        -- Buffer signals:
        -- Buffer signals:
        signal send_buffer_full, send_buffer_empty   : std_logic;
        signal send_buffer_full, send_buffer_empty   : std_logic;
        signal recv_buffer_full, recv_buffer_empty   : std_logic;
        signal recv_buffer_full, recv_buffer_empty   : std_logic;
        signal send_buffer_input, send_buffer_output : std_logic_vector(7 downto 0);
        signal send_buffer_input, send_buffer_output : std_logic_vector(7 downto 0);
        signal recv_buffer_input, recv_buffer_output : std_logic_vector(7 downto 0);
        signal recv_buffer_input, recv_buffer_output : std_logic_vector(7 downto 0);
        signal send_buffer_push, send_buffer_pop     : std_logic := '0';
        signal send_buffer_push, send_buffer_pop     : std_logic := '0';
        signal recv_buffer_push, recv_buffer_pop     : std_logic := '0';
        signal recv_buffer_push, recv_buffer_pop     : std_logic := '0';
 
 
        -- Wishbone signals:
        -- Wishbone signals:
        type wb_state_type is (IDLE, WRITE_ACK, READ_ACK);
        type wb_state_type is (IDLE, WRITE_ACK, READ_ACK);
        signal wb_state : wb_state_type;
        signal wb_state : wb_state_type;
 
 
        signal wb_ack : std_logic; --! Wishbone acknowledge signal
        signal wb_ack : std_logic; --! Wishbone acknowledge signal
 
 
begin
begin
 
 
        irq_send_buffer_empty <= send_buffer_empty;
        irq_send_buffer_empty <= send_buffer_empty;
        irq_data_received <= not recv_buffer_empty;
        irq_data_received <= not recv_buffer_empty;
 
 
        ---------- UART receive ----------
        ---------- UART receive ----------
 
 
        recv_buffer_input <= rx_byte;
        recv_buffer_input <= rx_byte;
 
 
        uart_receive: process(clk)
        uart_receive: process(clk)
        begin
        begin
                if rising_edge(clk) then
                if rising_edge(clk) then
                        if reset = '1' then
                        if reset = '1' then
                                rx_state <= IDLE;
                                rx_state <= IDLE;
                        else
                        else
                                case rx_state is
                                case rx_state is
                                        when IDLE =>
                                        when IDLE =>
                                                if sample_clk = '1' and rxd = '0' then
                                                if sample_clk = '1' and rxd = '0' then
                                                        rx_sample_value <= rx_sample_counter;
                                                        rx_sample_value <= rx_sample_counter;
                                                        rx_current_bit <= 0;
                                                        rx_current_bit <= 0;
                                                        rx_state <= RECEIVE;
                                                        rx_state <= RECEIVE;
                                                end if;
                                                end if;
                                        when RECEIVE =>
                                        when RECEIVE =>
                                                if sample_clk = '1' and rx_sample_counter = rx_sample_value then
                                                if sample_clk = '1' and rx_sample_counter = rx_sample_value then
                                                        if rx_current_bit /= 7 then
                                                        if rx_current_bit /= 7 then
                                                                rx_byte(rx_current_bit) <= rxd;
                                                                rx_byte(rx_current_bit) <= rxd;
                                                                rx_current_bit <= rx_current_bit + 1;
                                                                rx_current_bit <= rx_current_bit + 1;
                                                        else
                                                        else
                                                                rx_byte(rx_current_bit) <= rxd;
                                                                rx_byte(rx_current_bit) <= rxd;
                                                                rx_state <= STOPBIT;
                                                                rx_state <= STOPBIT;
 
 
                                                                if recv_buffer_full = '0' then
                                                                if recv_buffer_full = '0' then
                                                                        recv_buffer_push <= '1';
                                                                        recv_buffer_push <= '1';
                                                                end if;
                                                                end if;
                                                        end if;
                                                        end if;
                                                end if;
                                                end if;
                                        when STOPBIT =>
                                        when STOPBIT =>
                                                recv_buffer_push <= '0';
                                                recv_buffer_push <= '0';
 
 
                                                if sample_clk = '1' and rx_sample_counter = rx_sample_value then
                                                if sample_clk = '1' and rx_sample_counter = rx_sample_value then
                                                        rx_state <= IDLE;
                                                        rx_state <= IDLE;
                                                end if;
                                                end if;
                                end case;
                                end case;
                        end if;
                        end if;
                end if;
                end if;
        end process uart_receive;
        end process uart_receive;
 
 
        sample_counter: process(clk)
        sample_counter: process(clk)
        begin
        begin
                if rising_edge(clk) then
                if rising_edge(clk) then
                        if reset = '1' then
                        if reset = '1' then
                                rx_sample_counter <= 0;
                                rx_sample_counter <= 0;
                        elsif sample_clk = '1' then
                        elsif sample_clk = '1' then
                                if rx_sample_counter = 15 then
                                if rx_sample_counter = 15 then
                                        rx_sample_counter <= 0;
                                        rx_sample_counter <= 0;
                                else
                                else
                                        rx_sample_counter <= rx_sample_counter + 1;
                                        rx_sample_counter <= rx_sample_counter + 1;
                                end if;
                                end if;
                        end if;
                        end if;
                end if;
                end if;
        end process sample_counter;
        end process sample_counter;
 
 
        ---------- UART transmit ----------
        ---------- UART transmit ----------
 
 
        tx_byte <= send_buffer_output;
        tx_byte <= send_buffer_output;
 
 
        uart_transmit: process(clk)
        uart_transmit: process(clk)
        begin
        begin
                if rising_edge(clk) then
                if rising_edge(clk) then
                        if reset = '1' then
                        if reset = '1' then
                                txd <= '1';
                                txd <= '1';
                                tx_state <= IDLE;
                                tx_state <= IDLE;
                                send_buffer_pop <= '0';
                                send_buffer_pop <= '0';
                                tx_current_bit <= 0;
                                tx_current_bit <= 0;
                        else
                        else
                                case tx_state is
                                case tx_state is
                                        when IDLE =>
                                        when IDLE =>
                                                if send_buffer_empty = '0' and uart_tx_clk = '1' then
                                                if send_buffer_empty = '0' and uart_tx_clk = '1' then
                                                        txd <= '0';
                                                        txd <= '0';
                                                        send_buffer_pop <= '1';
                                                        send_buffer_pop <= '1';
                                                        tx_current_bit <= 0;
                                                        tx_current_bit <= 0;
                                                        tx_state <= TRANSMIT;
                                                        tx_state <= TRANSMIT;
                                                elsif uart_tx_clk = '1' then
                                                elsif uart_tx_clk = '1' then
                                                        txd <= '1';
                                                        txd <= '1';
                                                end if;
                                                end if;
                                        when TRANSMIT =>
                                        when TRANSMIT =>
                                                if send_buffer_pop = '1' then
                                                if send_buffer_pop = '1' then
                                                        send_buffer_pop <= '0';
                                                        send_buffer_pop <= '0';
                                                elsif uart_tx_clk = '1' and tx_current_bit = 7 then
                                                elsif uart_tx_clk = '1' and tx_current_bit = 7 then
                                                        txd <= tx_byte(tx_current_bit);
                                                        txd <= tx_byte(tx_current_bit);
                                                        tx_state <= STOPBIT;
                                                        tx_state <= STOPBIT;
                                                elsif uart_tx_clk = '1' then
                                                elsif uart_tx_clk = '1' then
                                                        txd <= tx_byte(tx_current_bit);
                                                        txd <= tx_byte(tx_current_bit);
                                                        tx_current_bit <= tx_current_bit + 1;
                                                        tx_current_bit <= tx_current_bit + 1;
                                                end if;
                                                end if;
                                        when STOPBIT =>
                                        when STOPBIT =>
                                                if uart_tx_clk = '1' then
                                                if uart_tx_clk = '1' then
                                                        txd <= '1';
                                                        txd <= '1';
                                                        tx_state <= IDLE;
                                                        tx_state <= IDLE;
                                                end if;
                                                end if;
                                end case;
                                end case;
                        end if;
                        end if;
                end if;
                end if;
        end process uart_transmit;
        end process uart_transmit;
 
 
        uart_tx_clock_generator: process(clk)
        uart_tx_clock_generator: process(clk)
        begin
        begin
                if rising_edge(clk) then
                if rising_edge(clk) then
                        if reset = '1' then
                        if reset = '1' then
                                uart_tx_counter <= 0;
                                uart_tx_counter <= 0;
                                uart_tx_clk <= '0';
                                uart_tx_clk <= '0';
                        else
                        else
                                if sample_clk = '1' then
                                if sample_clk = '1' then
                                        if uart_tx_counter = 15 then
                                        if uart_tx_counter = 15 then
                                                uart_tx_counter <= 0;
                                                uart_tx_counter <= 0;
                                                uart_tx_clk <= '1';
                                                uart_tx_clk <= '1';
                                        else
                                        else
                                                uart_tx_counter <= uart_tx_counter + 1;
                                                uart_tx_counter <= uart_tx_counter + 1;
                                                uart_tx_clk <= '0';
                                                uart_tx_clk <= '0';
                                        end if;
                                        end if;
                                else
                                else
                                        uart_tx_clk <= '0';
                                        uart_tx_clk <= '0';
                                end if;
                                end if;
                        end if;
                        end if;
                end if;
                end if;
        end process uart_tx_clock_generator;
        end process uart_tx_clock_generator;
 
 
        ---------- Sample clock generator ----------
        ---------- Sample clock generator ----------
 
 
        sample_clock_generator: process(clk)
        sample_clock_generator: process(clk)
        begin
        begin
                if rising_edge(clk) then
                if rising_edge(clk) then
                        if reset = '1' then
                        if reset = '1' then
                                sample_clk_counter <= 0;
                                sample_clk_counter <= 0;
                                sample_clk <= '0';
                                sample_clk <= '0';
                        else
                        else
                                if sample_clk_counter = SAMPLE_CLK_DIVISOR - 1 then
                                if sample_clk_counter = SAMPLE_CLK_DIVISOR - 1 then
                                        sample_clk_counter <= 0;
                                        sample_clk_counter <= 0;
                                        sample_clk <= '1';
                                        sample_clk <= '1';
                                else
                                else
                                        sample_clk_counter <= sample_clk_counter + 1;
                                        sample_clk_counter <= sample_clk_counter + 1;
                                        sample_clk <= '0';
                                        sample_clk <= '0';
                                end if;
                                end if;
                        end if;
                        end if;
                end if;
                end if;
        end process sample_clock_generator;
        end process sample_clock_generator;
 
 
        ---------- Data Buffers ----------
        ---------- Data Buffers ----------
 
 
        send_buffer: entity work.pp_fifo
        send_buffer: entity work.pp_fifo
                generic map(
                generic map(
                        DEPTH => FIFO_DEPTH,
                        DEPTH => FIFO_DEPTH,
                        WIDTH => 8
                        WIDTH => 8
                ) port map(
                ) port map(
                        clk => clk,
                        clk => clk,
                        reset => reset,
                        reset => reset,
                        full => send_buffer_full,
                        full => send_buffer_full,
                        empty => send_buffer_empty,
                        empty => send_buffer_empty,
                        data_in => send_buffer_input,
                        data_in => send_buffer_input,
                        data_out => send_buffer_output,
                        data_out => send_buffer_output,
                        push => send_buffer_push,
                        push => send_buffer_push,
                        pop => send_buffer_pop
                        pop => send_buffer_pop
                );
                );
 
 
        recv_buffer: entity work.pp_fifo
        recv_buffer: entity work.pp_fifo
                generic map(
                generic map(
                        DEPTH => FIFO_DEPTH,
                        DEPTH => FIFO_DEPTH,
                        WIDTH => 8
                        WIDTH => 8
                ) port map(
                ) port map(
                        clk => clk,
                        clk => clk,
                        reset => reset,
                        reset => reset,
                        full => recv_buffer_full,
                        full => recv_buffer_full,
                        empty => recv_buffer_empty,
                        empty => recv_buffer_empty,
                        data_in => recv_buffer_input,
                        data_in => recv_buffer_input,
                        data_out => recv_buffer_output,
                        data_out => recv_buffer_output,
                        push => recv_buffer_push,
                        push => recv_buffer_push,
                        pop => recv_buffer_pop
                        pop => recv_buffer_pop
                );
                );
 
 
        ---------- Wishbone Interface ---------- 
        ---------- Wishbone Interface ---------- 
 
 
        wb_ack_out <= wb_ack and wb_cyc_in and wb_stb_in;
        wb_ack_out <= wb_ack and wb_cyc_in and wb_stb_in;
 
 
        wishbone: process(clk)
        wishbone: process(clk)
        begin
        begin
                if rising_edge(clk) then
                if rising_edge(clk) then
                        if reset = '1' then
                        if reset = '1' then
                                wb_ack <= '0';
                                wb_ack <= '0';
                                wb_state <= IDLE;
                                wb_state <= IDLE;
                                send_buffer_push <= '0';
                                send_buffer_push <= '0';
                        else
                        else
                                case wb_state is
                                case wb_state is
                                        when IDLE =>
                                        when IDLE =>
                                                if wb_cyc_in = '1' and wb_stb_in = '1' then
                                                if wb_cyc_in = '1' and wb_stb_in = '1' then
                                                        if wb_we_in = '1' then -- Write to register
                                                        if wb_we_in = '1' then -- Write to register
                                                                if wb_adr_in = b"00" then
                                                                if wb_adr_in = b"00" then
                                                                        send_buffer_input <= wb_dat_in;
                                                                        send_buffer_input <= wb_dat_in;
                                                                        send_buffer_push <= '1';
                                                                        send_buffer_push <= '1';
                                                                        wb_ack <= '1';
                                                                        wb_ack <= '1';
                                                                        wb_state <= WRITE_ACK;
                                                                        wb_state <= WRITE_ACK;
                                                                else -- Invalid write, just ack and ignore
                                                                else -- Invalid write, just ack and ignore
                                                                        wb_ack <= '1';
                                                                        wb_ack <= '1';
                                                                        wb_state <= WRITE_ACK;
                                                                        wb_state <= WRITE_ACK;
                                                                end if;
                                                                end if;
                                                        else -- Read from register
                                                        else -- Read from register
                                                                if wb_adr_in = b"01" then
                                                                if wb_adr_in = b"01" then
                                                                        recv_buffer_pop <= '1';
                                                                        recv_buffer_pop <= '1';
                                                                        wb_state <= READ_ACK;
                                                                        wb_state <= READ_ACK;
                                                                elsif wb_adr_in = b"10" then
                                                                elsif wb_adr_in = b"10" then
                                                                        wb_dat_out <= x"0" & send_buffer_full & recv_buffer_full & send_buffer_empty & not recv_buffer_empty;
                                                                        wb_dat_out <= x"0" & send_buffer_full & recv_buffer_full & send_buffer_empty & recv_buffer_empty;
                                                                        wb_ack <= '1';
                                                                        wb_ack <= '1';
                                                                        wb_state <= READ_ACK;
                                                                        wb_state <= READ_ACK;
                                                                else
                                                                else
                                                                        wb_dat_out <= (others => '0');
                                                                        wb_dat_out <= (others => '0');
                                                                        wb_ack <= '1';
                                                                        wb_ack <= '1';
                                                                        wb_state <= READ_ACK;
                                                                        wb_state <= READ_ACK;
                                                                end if;
                                                                end if;
                                                        end if;
                                                        end if;
                                                end if;
                                                end if;
                                        when WRITE_ACK =>
                                        when WRITE_ACK =>
                                                send_buffer_push <= '0';
                                                send_buffer_push <= '0';
 
 
                                                if wb_stb_in = '0' then
                                                if wb_stb_in = '0' then
                                                        wb_ack <= '0';
                                                        wb_ack <= '0';
                                                        wb_state <= IDLE;
                                                        wb_state <= IDLE;
                                                end if;
                                                end if;
                                        when READ_ACK =>
                                        when READ_ACK =>
                                                if recv_buffer_pop = '1' then
                                                if recv_buffer_pop = '1' then
                                                        wb_ack <= '1';
                                                        wb_ack <= '1';
                                                        recv_buffer_pop <= '0';
                                                        recv_buffer_pop <= '0';
                                                        wb_dat_out <= recv_buffer_output;
                                                        wb_dat_out <= recv_buffer_output;
                                                end if;
                                                end if;
 
 
                                                if wb_stb_in = '0' then
                                                if wb_stb_in = '0' then
                                                        wb_ack <= '0';
                                                        wb_ack <= '0';
                                                        wb_state <= IDLE;
                                                        wb_state <= IDLE;
                                                end if;
                                                end if;
                                end case;
                                end case;
                        end if;
                        end if;
                end if;
                end if;
        end process wishbone;
        end process wishbone;
 
 
end architecture behaviour;
end architecture behaviour;
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.