333 lines
7.7 KiB
VHDL
333 lines
7.7 KiB
VHDL
-------------------------------------------------------------------------
|
|
-- 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 <http://www.gnu.org/licenses/>.
|
|
--
|
|
-- 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;
|