------------------------------------------------------------------------- -- 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;