git-svn-id: http://moon:8086/svn/vhdl/trunk@1414 cc03376c-175c-47c8-b038-4cd826a8556b
409 lines
11 KiB
VHDL
409 lines
11 KiB
VHDL
-------------------------------------------------------------------------
|
|
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
|
-- This file: system test using Xilinx ML-402
|
|
|
|
-- Copyright (C) 2007 J. Ahrensfeld
|
|
|
|
-- This library is free software; you can redistribute it and/or
|
|
-- modify it under the terms of the GNU Lesser General Public
|
|
-- License as published by the Free Software Foundation; either
|
|
-- version 2.1 of the License, or (at your option) any later version.
|
|
|
|
-- This library 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
|
|
-- Lesser General Public License for more details.
|
|
|
|
-- You should have received a copy of the GNU Lesser General Public
|
|
-- License along with this library; if not, write to the Free Software
|
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
-- 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;
|
|
use std.textio.all; -- Imports the standard textio package.
|
|
|
|
Library UNISIM;
|
|
use UNISIM.vcomponents.all;
|
|
|
|
library work;
|
|
use work.cpu_pkg.all;
|
|
|
|
ENTITY systest IS
|
|
PORT
|
|
(
|
|
sys_rst_n_in : in std_logic;
|
|
sys_clk_in : in std_logic;
|
|
sys_btn : in std_logic_vector(4 downto 0);
|
|
sys_dip : in std_logic_vector(7 downto 0);
|
|
sys_led : out std_logic_vector(8 downto 0);
|
|
sys_rx : in std_logic;
|
|
sys_tx : out std_logic;
|
|
sys_lcd_d : inout std_logic_vector(3 downto 0);
|
|
sys_lcd_e : out std_logic;
|
|
sys_lcd_rs : out std_logic;
|
|
sys_lcd_rw : out std_logic
|
|
);
|
|
END systest;
|
|
|
|
|
|
ARCHITECTURE behavior OF systest IS
|
|
|
|
COMPONENT embedded_cpu
|
|
Port (
|
|
rst : in STD_LOGIC;
|
|
clk : in STD_LOGIC;
|
|
ce : in STD_LOGIC;
|
|
int_in : in STD_LOGIC;
|
|
int_ack : out STD_LOGIC;
|
|
xmem_we : out STD_LOGIC;
|
|
xmem_re : out STD_LOGIC;
|
|
xmem_din : in unsigned (DMEM_WIDTH-1 downto 0);
|
|
xmem_dout : out unsigned (DMEM_WIDTH-1 downto 0);
|
|
xmem_addr : out unsigned (DMEM_WIDTH-1 downto 0)
|
|
);
|
|
END COMPONENT;
|
|
|
|
--
|
|
-- declaration of UART transmitter with integral 16 byte FIFO buffer
|
|
--
|
|
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;
|
|
--
|
|
-- declaration of UART Receiver with integral 16 byte FIFO buffer
|
|
--
|
|
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 rst : std_logic;
|
|
signal clk, clk0 : std_logic;
|
|
signal ce : std_logic;
|
|
signal int_req, int_in, int_ack, int_en : std_logic;
|
|
|
|
signal cpu_din : data_t;
|
|
signal cpu_dout : data_t;
|
|
signal cpu_addr : unsigned (DMEM_WIDTH-1 downto 0);
|
|
signal cpu_we, reg_sel : std_logic;
|
|
signal cpu_re : std_logic;
|
|
signal led_reg_we, lcd_reg_we, ctrl_reg_we : std_logic;
|
|
signal rom_dout, reg_dout, ctrl_reg : data_t;
|
|
signal led_reg : data_t;
|
|
signal lcd_reg_out, lcd_reg_in: data_t;
|
|
--
|
|
-- Signals for connection of peripherals
|
|
--
|
|
signal uart_status_port : data_t;
|
|
--
|
|
-- Signals to form an timer generating an interrupt every microsecond
|
|
--
|
|
constant timer_reload : integer := 99999;
|
|
signal timer_count : integer range 0 to 99999 :=0;
|
|
signal timer_pulse, timer_en : std_logic;
|
|
--
|
|
-- Signals for UART connections
|
|
--
|
|
signal baud_count : integer range 0 to 255 :=0;
|
|
signal en_16_x_baud : std_logic;
|
|
signal write_to_uart : std_logic;
|
|
signal tx_full : std_logic;
|
|
signal tx_half_full : std_logic;
|
|
signal read_from_uart : std_logic;
|
|
signal rx_data : std_logic_vector(7 downto 0);
|
|
signal rx_data_present : std_logic;
|
|
signal rx_full : std_logic;
|
|
signal rx_half_full : std_logic;
|
|
|
|
signal rom_addr : unsigned(5 downto 0);
|
|
signal reg_addr : unsigned(5 downto 0);
|
|
|
|
constant rom_data : string(1 to 64) :=
|
|
(
|
|
"J-CPU V1.0 " &
|
|
' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' &
|
|
' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' &
|
|
' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' &
|
|
' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' ' & ' '
|
|
|
|
);
|
|
constant lcd_e : integer := 7;
|
|
constant lcd_rs : integer := 6;
|
|
constant lcd_rw : integer := 5;
|
|
|
|
BEGIN
|
|
|
|
int_in <= sys_btn(4) or sys_dip(7) or timer_pulse or ctrl_reg(7) or rx_data_present;
|
|
clk0 <= sys_clk_in;
|
|
ce <= not rst;
|
|
int_en <= ctrl_reg(0);
|
|
timer_en <= ctrl_reg(1);
|
|
sys_led(8) <= int_in;
|
|
sys_led (7 downto 0) <= std_logic_vector(led_reg(7 downto 0));
|
|
uart_status_port <= "000" & rx_data_present & rx_full & rx_half_full & tx_full & tx_half_full ;
|
|
sys_lcd_d <= std_logic_vector(lcd_reg_out(3 downto 0)) when lcd_reg_out(lcd_rw) = '0' else (others => 'Z');
|
|
sys_lcd_e <= lcd_reg_out(lcd_e);
|
|
sys_lcd_rw <= lcd_reg_out(lcd_rw);
|
|
sys_lcd_rs <= lcd_reg_out(lcd_rs);
|
|
rom_addr <= cpu_addr(5 downto 0);
|
|
reg_addr <= cpu_addr(5 downto 0);
|
|
|
|
BUFG_inst : BUFG
|
|
port map (
|
|
O => clk, -- Clock buffer output
|
|
I => clk0 -- Clock buffer input
|
|
);
|
|
|
|
clock_halbe:
|
|
process(sys_rst_n_in, sys_clk_in)
|
|
variable reset_latency : integer range 0 to 999 := 999;
|
|
begin
|
|
if sys_rst_n_in = '0' then
|
|
-- clk0 <= '0';
|
|
rst <= '1';
|
|
reset_latency := 999;
|
|
elsif rising_edge(sys_clk_in) then
|
|
rst <= '1';
|
|
-- clk0 <= not clk0;
|
|
if reset_latency /= 0 then
|
|
reset_latency := reset_latency - 1;
|
|
else
|
|
rst <= '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
timer:
|
|
process(rst, clk, timer_count, timer_en)
|
|
begin
|
|
if rst = '1' then
|
|
timer_count <= timer_reload;
|
|
timer_pulse <= '0';
|
|
elsif rising_edge(clk) then
|
|
timer_pulse <= '0';
|
|
if timer_count /= 0 then
|
|
if timer_en = '1' then
|
|
timer_count <= timer_count - 1;
|
|
end if;
|
|
else
|
|
timer_pulse <= '1';
|
|
timer_count <= timer_reload;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
reg_mux:
|
|
process(clk, reg_addr, reg_sel, cpu_we, cpu_re, sys_btn, sys_dip, lcd_reg_in, led_reg, uart_status_port)
|
|
variable data : data_t;
|
|
begin
|
|
led_reg_we <= '0';
|
|
lcd_reg_we <= '0';
|
|
ctrl_reg_we <= '0';
|
|
write_to_uart <= '0';
|
|
read_from_uart <= '0';
|
|
data := (others => '-');
|
|
|
|
if reg_sel = '1' then
|
|
case reg_addr(2 downto 0) is
|
|
|
|
when "000" => -- C0
|
|
data := "0000" & unsigned(sys_btn(3 downto 0));
|
|
when "001" => -- C1
|
|
data := led_reg;
|
|
led_reg_we <= cpu_we;
|
|
when "010" => -- C2
|
|
data := unsigned(rx_data);
|
|
write_to_uart <= cpu_we;
|
|
read_from_uart <= cpu_re;
|
|
when "011" => -- C3
|
|
data := lcd_reg_in;
|
|
lcd_reg_we <= cpu_we;
|
|
when "100" => -- C4
|
|
data := ctrl_reg;
|
|
ctrl_reg_we <= cpu_we;
|
|
when "101" => -- C5
|
|
data := unsigned(sys_dip);
|
|
when "110" => -- C6
|
|
data := uart_status_port;
|
|
when others => null;
|
|
end case;
|
|
|
|
end if;
|
|
|
|
if rising_edge(clk) then
|
|
reg_dout <= data;
|
|
end if;
|
|
|
|
end process;
|
|
|
|
din_mux:
|
|
process(clk, cpu_addr, cpu_we, rom_dout, reg_dout)
|
|
variable data : data_t;
|
|
begin
|
|
reg_sel <= '0';
|
|
|
|
case cpu_addr(7 downto 6) is
|
|
when "00" | "01" => -- 00 .. 7F
|
|
data := X"AA";
|
|
when "10" => -- 80 .. BF
|
|
data := rom_dout;
|
|
when "11" => -- C0 .. FF
|
|
data := reg_dout;
|
|
reg_sel <= '1';
|
|
|
|
when others =>
|
|
data := (others => '-');
|
|
end case;
|
|
|
|
cpu_din <= data;
|
|
|
|
end process;
|
|
|
|
ctrl_reg_write:
|
|
process(rst, clk, ctrl_reg_we, cpu_dout)
|
|
begin
|
|
if (rst = '1') then
|
|
ctrl_reg <= (others => '0');
|
|
elsif rising_edge(clk) then
|
|
if ctrl_reg_we = '1' then
|
|
ctrl_reg <= cpu_dout;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
led_reg_write:
|
|
process(rst, clk, led_reg_we, cpu_dout)
|
|
begin
|
|
if (rst = '1') then
|
|
led_reg <= (others => '0');
|
|
elsif rising_edge(clk) then
|
|
if led_reg_we = '1' then
|
|
led_reg <= cpu_dout;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
proc_lcd_reg_write:
|
|
process(rst, clk, lcd_reg_we, cpu_dout)
|
|
begin
|
|
if (rst = '1') then
|
|
lcd_reg_out <= (others => '0');
|
|
elsif rising_edge(clk) then
|
|
if lcd_reg_we = '1' then
|
|
lcd_reg_out <= cpu_dout;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
proc_lcd_reg_sample:
|
|
process(rst, clk, sys_lcd_d, lcd_reg_out)
|
|
begin
|
|
if (rst = '1') then
|
|
lcd_reg_in <= (others => '0');
|
|
elsif rising_edge(clk) then
|
|
if lcd_reg_out(lcd_rw) = '1' then
|
|
lcd_reg_in <= unsigned("0000" & sys_lcd_d);
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
int_register:
|
|
process(rst, clk, int_in, int_ack)
|
|
begin
|
|
if (rst = '1') then
|
|
int_req <= '0';
|
|
elsif rising_edge(clk) then
|
|
if int_ack = '1' then
|
|
int_req <= '0';
|
|
elsif int_en = '1' and int_in = '1' then
|
|
int_req <= '1';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
|
|
the_embedded_cpu: embedded_cpu
|
|
PORT MAP(
|
|
rst => rst,
|
|
clk => clk,
|
|
ce => ce,
|
|
int_in => int_req,
|
|
int_ack => int_ack,
|
|
xmem_we => cpu_we,
|
|
xmem_re => cpu_re,
|
|
xmem_din => cpu_din,
|
|
xmem_dout => cpu_dout,
|
|
xmem_addr => cpu_addr
|
|
);
|
|
|
|
transmit: uart_tx
|
|
port map ( data_in => std_logic_vector(cpu_dout),
|
|
write_buffer => write_to_uart,
|
|
reset_buffer => rst,
|
|
en_16_x_baud => en_16_x_baud,
|
|
serial_out => sys_tx,
|
|
buffer_full => tx_full,
|
|
buffer_half_full => tx_half_full,
|
|
clk => clk );
|
|
|
|
receive: uart_rx
|
|
port map ( serial_in => sys_rx,
|
|
data_out => rx_data,
|
|
read_buffer => read_from_uart,
|
|
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 );
|
|
--
|
|
-- Set baud rate to 38400 for the UART communications
|
|
-- Requires en_16_x_baud to be 614400Hz which is a single cycle pulse every 163 cycles at 100MHz
|
|
--
|
|
-- NOTE : If the highest value for baud_count exceeds 127 you will need to adjust
|
|
-- the range of integers in the signal declaration for baud_count.
|
|
--
|
|
|
|
baud_timer: process(clk)
|
|
begin
|
|
if clk'event and clk='1' then
|
|
if baud_count=162 then
|
|
baud_count <= 0;
|
|
en_16_x_baud <= '1';
|
|
else
|
|
baud_count <= baud_count + 1;
|
|
en_16_x_baud <= '0';
|
|
end if;
|
|
end if;
|
|
end process baud_timer;
|
|
|
|
ROM_RD:
|
|
process(rst, clk, rom_addr)
|
|
begin
|
|
if rising_edge(clk) then
|
|
rom_dout <= to_unsigned(character'pos(rom_data(to_integer(rom_addr)+1)), data_t'length);
|
|
end if;
|
|
end process;
|
|
|
|
END;
|