------------------------------------------------------------------------- -- Project: JCPU, a portable 8-bit RISC CPU written in VHDL -- This file: cpu_embedded using cpu_core and rom -- -- Copyright (C) 2007 J. Ahrensfeld -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . -- -- For questions and ideas, please contact the author at jens@jayfield.org -- -------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.ALL; library work; use work.mips_types.all; entity mips_embedded is Port ( rst : in STD_LOGIC; clk : in STD_LOGIC; halt : in STD_LOGIC; int : in unsigned(5 downto 0); rxd : in STD_LOGIC; txd : out STD_LOGIC; dout : out word_t ); end mips_embedded; architecture rtl of mips_embedded is COMPONENT mips_top Port ( rst : in STD_LOGIC; clk : in STD_LOGIC; int : in unsigned(5 downto 0); mem_rdy : in STD_LOGIC; mem_re : out STD_LOGIC; mem_en : out STD_LOGIC; mem_we : out unsigned(3 downto 0); mem_din : in word_t; mem_dout : out word_t; mem_addr : out word_t ); END COMPONENT; signal mem_din : word_t; signal mem_dout : word_t; signal mem_addr : word_t; signal mem_re : std_logic; signal mem_en : std_logic; signal mem_we : unsigned(3 downto 0); signal mem_rdy : std_logic; subtype tick_usec_t is natural range 0 to 99; signal tick_usec : tick_usec_t; signal cnt_usec : word_t; signal cnt_sec : word_t; signal cnt_usec_preset : word_t; signal cnt_sec_preset : word_t; signal cnt_usec_en : std_logic; signal cnt_usec_we : std_logic; signal cnt_sec_en : std_logic; signal cnt_sec_we : std_logic; COMPONENT uart_tx Port ( data_in : in std_logic_vector(7 downto 0); write_buffer : in std_logic; reset_buffer : in std_logic; en_16_x_baud : in std_logic; serial_out : out std_logic; buffer_full : out std_logic; buffer_half_full : out std_logic; clk : in std_logic ); END COMPONENT; COMPONENT uart_rx Port ( serial_in : in std_logic; data_out : out std_logic_vector(7 downto 0); read_buffer : in std_logic; reset_buffer : in std_logic; en_16_x_baud : in std_logic; buffer_data_present : out std_logic; buffer_full : out std_logic; buffer_half_full : out std_logic; clk : in std_logic ); END COMPONENT; signal baud_count : unsigned(7 downto 0); signal en_16_x_baud : std_logic; signal reg_we_uart_tx : std_logic; signal tx_full : std_logic; signal tx_half_full : std_logic; signal reg_uart_tx : unsigned(7 downto 0); signal reg_re_uart_rx : std_logic; signal reg_uart_rx : std_logic_vector(7 downto 0); signal rx_data_present : std_logic; signal rx_full : std_logic; signal rx_half_full : std_logic; signal uart_status_port : unsigned(7 downto 0); signal reg_uart_ctrl : unsigned(7 downto 0); signal reg_uart_baud : unsigned(7 downto 0); begin registers_write: process(clk) begin if rising_edge(clk) then reg_we_uart_tx <= '0'; cnt_usec_we <= '0'; cnt_sec_we <= '0'; if rst = '1' then dout <= (others => '0'); reg_uart_baud <= to_unsigned(53, 8); reg_uart_ctrl <= to_unsigned(0, 8); elsif mem_en = '1' then case mem_addr(5 downto 2) is when "0000" => if mem_we(0) = '1' then dout(7 downto 0) <= mem_dout(7 downto 0); end if; if mem_we(1) = '1' then dout(15 downto 8) <= mem_dout(15 downto 8); end if; if mem_we(2) = '1' then dout(23 downto 16) <= mem_dout(23 downto 16); end if; if mem_we(3) = '1' then dout(31 downto 24) <= mem_dout(31 downto 24); end if; when "0001" => if mem_we(0) = '1' then reg_we_uart_tx <= '1'; reg_uart_tx <= mem_dout(7 downto 0); end if; when "0010" => if mem_we(0) = '1' then reg_uart_ctrl <= mem_dout(7 downto 0); end if; if mem_we(1) = '1' then reg_uart_baud <= mem_dout(15 downto 8); end if; when "0100" => if mem_we(3) = '1' then cnt_usec_we <= '1'; cnt_usec_preset <= mem_dout; end if; when "0101" => if mem_we(3) = '1' then cnt_sec_we <= '1'; cnt_sec_preset <= mem_dout; end if; when others => null; end case; end if; end if; end process; registers_read: process(clk) begin if rising_edge(clk) then reg_re_uart_rx <= '0'; if mem_en = '1' then mem_din <= (others => '0'); case mem_addr(5 downto 2) is when "0000" => null; when "0001" => reg_re_uart_rx <= '1'; mem_din(7 downto 0) <= unsigned(reg_uart_rx); when "0010" => mem_din(7 downto 0) <= uart_status_port; mem_din(15 downto 8) <= reg_uart_baud; when "0100" => mem_din <= cnt_usec; when "0101" => mem_din <= cnt_sec; when others => null; end case; end if; end if; end process; mem_rdy <= not halt; inst_mips_top: mips_top PORT MAP ( rst => rst, clk => clk, int => int, mem_rdy => mem_rdy, mem_en => mem_en, mem_we => mem_we, mem_din => mem_din, mem_dout => mem_dout, mem_addr => mem_addr ); inst_uart_tx: uart_tx port map ( data_in => std_logic_vector(reg_uart_tx), write_buffer => reg_we_uart_tx, reset_buffer => rst, en_16_x_baud => en_16_x_baud, serial_out => txd, buffer_full => tx_full, buffer_half_full => tx_half_full, clk => clk ); inst_uart_rx: uart_rx port map ( serial_in => rxd, data_out => reg_uart_rx, read_buffer => reg_re_uart_rx, reset_buffer => rst, en_16_x_baud => en_16_x_baud, buffer_data_present => rx_data_present, buffer_full => rx_full, buffer_half_full => rx_half_full, clk => clk ); uart_status_port <= (7 downto 5 => '0') & rx_data_present & rx_full & rx_half_full & tx_full & tx_half_full; tick_usec_timer: process(clk) begin if clk'event and clk='1' then cnt_usec_en <= '0'; if rst = '1' then tick_usec <= 0; cnt_usec_en <= '0'; elsif tick_usec = tick_usec_t'high then tick_usec <= 0; cnt_usec_en <= '1'; else tick_usec <= tick_usec + 1; end if; end if; end process; cnt_usec_timer: process(clk) begin if clk'event and clk='1' then cnt_sec_en <= '0'; if rst = '1' then cnt_usec <= (others => '0'); cnt_sec_en <= '0'; elsif cnt_usec_we = '1' then cnt_usec <= cnt_usec_preset; elsif cnt_usec_en = '1' then if cnt_usec = to_unsigned(1E6 - 1, word_t'length) then cnt_usec <= (others => '0'); cnt_sec_en <= '1'; else cnt_usec <= cnt_usec + 1; end if; end if; end if; end process; cnt_sec_timer: process(clk) begin if clk'event and clk='1' then if rst = '1' then cnt_sec <= (others => '0'); elsif cnt_sec_we = '1' then cnt_sec <= cnt_sec_preset; elsif cnt_sec_en = '1' then cnt_sec <= cnt_sec + 1; end if; end if; end process; baud_timer: process(clk) begin if clk'event and clk='1' then if rst = '1' then baud_count <= (others => '0'); elsif baud_count = reg_uart_baud then baud_count <= (others => '0'); en_16_x_baud <= '1'; else baud_count <= baud_count + 1; en_16_x_baud <= '0'; end if; end if; end process; end rtl;