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

Subversion Repositories the_wizardry_project

[/] [the_wizardry_project/] [trunk/] [Wizardry/] [VHDL/] [Wizardry Top Level/] [Address Generation/] [JOP/] [stack.vhd] - Rev 22

Compare with Previous | Blame | View Log

--
--
--  This file is a part of JOP, the Java Optimized Processor
--
--  Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
--
--  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/>.
--
 
 
--
--	stack.vhd
--
--	Stack/Alu for JOP3
--
--	resources on ACEX1K30-3
--
--
--	2001-06-30	first version (adapted from alu.vhd)
--	2001-07-18	components add, sub in own file for Xilinx
--	2001-10-28	ldjpc, stjpc
--	2001-10-31	init cp and vp with 0
--	2001-12-04	cp removed
--	2001-12-06	sp is 0 after reset, must be set in sw
--	2001-12-07	removed imm. values
--	2002-03-24	barrel shifter
--	2003-02-12	added mux for 8 and 16 bit unsigned bytecode operand
--	2004-10-07	new alu selection with sel_sub, sel_amux and ena_a
--	2006-01-12	new ar for local memory addressing, sp and vp MSB fix at '1'
--	2007-08-31	change stack addressing without wrapping, generate sp_ov on max_stack-8
--	2007-09-01	use ram_width from jop_config instead of parameter
--	2007-11-21	use 33 bit for the comparison (compare bug for diff > 2^31 corrected)
--
 
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.jop_config.all;
 
entity stack is
 
generic (
	width		: integer := 32;	-- one data word
	jpc_width	: integer := 10		-- address bits of java byte code pc
);
port (
	clk, reset	: in std_logic;
 
	din			: in std_logic_vector(width-1 downto 0);
	dir			: in std_logic_vector(ram_width-1 downto 0);
	opd			: in std_logic_vector(15 downto 0);		-- index for vp load opd
	jpc			: in std_logic_vector(jpc_width downto 0);	-- jpc read
 
	sel_sub		: in std_logic;							-- 0..add, 1..sub
	sel_amux	: in std_logic;							-- 0..sum, 1..lmux
	ena_a		: in std_logic;							-- 1..store new value
	sel_bmux	: in std_logic;							-- 0..a, 1..mem
	sel_log		: in std_logic_vector(1 downto 0);		-- pop/st, and, or, xor
	sel_shf		: in std_logic_vector(1 downto 0);		-- sr, sl, sra, (sr)
	sel_lmux	: in std_logic_vector(2 downto 0);		-- log, shift, mem, din, reg
	sel_imux	: in std_logic_vector(1 downto 0);		-- java opds
	sel_rmux	: in std_logic_vector(1 downto 0);		-- sp, vp, jpc
	sel_smux	: in std_logic_vector(1 downto 0);		-- sp, a, sp-1, sp+1
 
	sel_mmux	: in std_logic;							-- 0..a, 1..b
	sel_rda		: in std_logic_vector(2 downto 0);		-- 
	sel_wra		: in std_logic_vector(2 downto 0);		-- 
 
	wr_ena		: in std_logic;
 
	ena_b		: in std_logic;
	ena_vp		: in std_logic;
	ena_ar		: in std_logic;
 
	sp_ov		: out std_logic;
 
	zf			: out std_logic;
	nf			: out std_logic;
	eq			: out std_logic;
	lt			: out std_logic;
	aout		: out std_logic_vector(width-1 downto 0);
	bout		: out std_logic_vector(width-1 downto 0)
);
end stack;
 
architecture rtl of stack is
 
component shift is
generic (width : integer);
port (
	din			: in std_logic_vector(width-1 downto 0);
	off			: in std_logic_vector(4 downto 0);
	shtyp		: in std_logic_vector(1 downto 0);
	dout		: out std_logic_vector(width-1 downto 0)
);
end component shift;
 
--
--	ram component (use technology specific vhdl-file (aram/xram))
--
--	registered  and delayed wraddress, wren
--	registered din
--	registered rdaddress
--	unregistered dout
--
--		=> read during write on same address
--
component ram is
generic (width : integer; addr_width : integer);
port (
	data		: in std_logic_vector(width-1 downto 0);
	wraddress	: in std_logic_vector(ram_width-1 downto 0);
	rdaddress	: in std_logic_vector(ram_width-1 downto 0);
	wren		: in std_logic;
	clock		: in std_logic;
        reset           : in std_logic;
 
	q			: out std_logic_vector(width-1 downto 0)
);
end component;
 
	signal a, b			: std_logic_vector(width-1 downto 0);
	signal ram_dout		: std_logic_vector(width-1 downto 0);
 
	signal sp, spp, spm	: std_logic_vector(ram_width-1 downto 0);
	signal vp0, vp1, vp2, vp3
						: std_logic_vector(ram_width-1 downto 0);
	signal ar			: std_logic_vector(ram_width-1 downto 0);
 
	signal sum			: std_logic_vector(32 downto 0);
	signal sout			: std_logic_vector(width-1 downto 0);
	signal log			: std_logic_vector(width-1 downto 0);
	signal immval		: std_logic_vector(width-1 downto 0);
	signal opddly		: std_logic_vector(15 downto 0);
 
	signal amux		: std_logic_vector(width-1 downto 0);
	signal lmux		: std_logic_vector(width-1 downto 0);
	signal imux		: std_logic_vector(width-1 downto 0);
	signal mmux		: std_logic_vector(width-1 downto 0);
 
	signal rmux		: std_logic_vector(jpc_width downto 0);
	signal smux		: std_logic_vector(ram_width-1 downto 0);
	signal vpadd	: std_logic_vector(ram_width-1 downto 0);
	signal wraddr	: std_logic_vector(ram_width-1 downto 0);
	signal rdaddr	: std_logic_vector(ram_width-1 downto 0);
	signal ci : std_logic_vector(width-1 downto 0);
begin
 
	cmp_shf: shift generic map (width) port map (b, a(4 downto 0), sel_shf, sout);
 
	cmp_ram: ram generic map(width, ram_width)
			port map(mmux, wraddr, rdaddr, wr_ena, clk, reset, ram_dout);
 
 
-- a version that 'could' be better in Spartan
--process(a, b, sel_sub)
--begin
--
--	if sel_sub='0' then
--		temp <= a;
--		ci <= X"00000000";
--	else
--		temp <= not a;
--		ci <= X"00000001";
--	end if;
--	sum <= std_logic_vector(signed(b) + signed(temp)+ signed(ci));
--
--end process;
 
 
-- this add/sub, the sum/lmux mux and the enable should fit into
-- a single LE.
-- But it doesn't! A synthesizer problem in Quartus.
--
process(a, b, sel_sub)
begin
 
	-- subtract with 33 bits to get the correct carry
	if sel_sub='1' then
		sum <= std_logic_vector(signed(b(31) & b) - signed(a(31) & a));
	else
		sum <= std_logic_vector(signed(b(31) & b) + signed(a(31) & a));
	end if;
 
end process;
 
	lt <= sum(32);		-- default is subtract
 
-- shift version from Flavius?
 
--
--	mux for stack register, alu
--
process(ram_dout, opddly, immval, sout, din, lmux, rmux, sp, vp0, jpc, sum, log, a, b,
		sel_log, sel_shf, sel_rmux, sel_lmux, sel_imux, sel_mmux, sel_amux)
 
begin
 
	case sel_log is
		when "00" =>
			log <= b;
		when "01" =>
			log <= a and b;
		when "10" =>
			log <= a or b;
		when "11" =>
			log <= a xor b;
		when others =>
			null;
	end case;
 
	case sel_rmux is
		when "00" =>
--			rmux <= "00" & sp;
			rmux <= std_logic_vector(to_signed(to_integer(unsigned(sp)), jpc_width+1));
		when "01" =>
--			rmux <= "00" & vp0;
			rmux <= std_logic_vector(to_signed(to_integer(unsigned(vp0)), jpc_width+1));
		when others =>
			rmux <= jpc;
	end case;
 
--
--	this is worse than the shift component
--
--	case sel_shf is
--		when "00" =>
--			sout <= std_logic_vector(shift_right(unsigned(b),to_integer(unsigned(a(4 downto 0)))));
--		when "01" =>
--			sout <= std_logic_vector(shift_left(signed(b),to_integer(unsigned(a(4 downto 0)))));
--		when "10" =>
--			sout <= std_logic_vector(shift_right(signed(b),to_integer(unsigned(a(4 downto 0)))));
--		when "11" =>
--			sout <= std_logic_vector(shift_right(unsigned(b),to_integer(unsigned(a(4 downto 0)))));
--		when others =>
--			null;
--	end case;
 
	case sel_lmux(2 downto 0) is
		when "000" =>
			lmux <= log;
		when "001" =>
			lmux <= sout;
		when "010" =>
			lmux <= ram_dout;
		when "011" =>
			lmux <= immval;
		when "100" =>
			lmux <= din;
		when others =>
			lmux <= std_logic_vector(to_signed(to_integer(unsigned(rmux)), width));
	end case;
 
	case sel_imux is
		when "00" =>
			imux <= "000000000000000000000000" & opddly(7 downto 0);
		when "01" =>
			imux <= std_logic_vector(to_signed(to_integer(signed(opddly(7 downto 0))), width));
		when "10" =>
			imux <= "0000000000000000" & opddly;
		when others =>
			imux <= std_logic_vector(to_signed(to_integer(signed(opddly)), width));
	end case;
 
	if sel_mmux='0' then
		mmux <= a;
	else
		mmux <= b;
	end if;
 
	if sel_amux='0' then
		amux <= sum(31 downto 0);
	else
		amux <= lmux;
	end if;
 
--	if (a = (a'range => '0'))  then		-- Xilinx ISE has problems
	if (a=std_logic_vector(to_unsigned(0, width))) then
		zf <= '1';
	else
		zf <= '0';
	end if;
	nf <= a(width-1);
	if (a=b) then
		eq <= '1';
	else
		eq <= '0';
	end if;
 
end process;
 
process(clk, reset) begin
 
	if (reset='1') then
		a <= (others => '0');
		b <= (others => '0');
	elsif rising_edge(clk) then
 
		if ena_a='1' then
			a <= amux;
		end if;
 
		if ena_b = '1' then
			if sel_bmux = '0' then
				b <= a;
			else
				b <= ram_dout;
			end if;
		end if;
 
	end if;
end process;
 
	aout <= a;
	bout <= b;
 
--
--	stack pointer and vp register
--
process(a, sp, spm, spp, sel_smux)
 
begin
 
	case sel_smux is
		when "00" =>
			smux <= sp;
		when "01" =>
			smux <= spm;
		when "10" =>
			smux <= spp;
		when "11" =>
			smux <= a(ram_width-1 downto 0);
		when others =>
			null;
	end case;
 
end process;
 
 
--
--	address mux for ram
--
process(sp, spp, vp0, vp1, vp2, vp3, vpadd, ar, dir, sel_rda, sel_wra)
 
begin
 
 
	case sel_rda is
		when "000" =>
			rdaddr <= vp0;
		when "001" =>
			rdaddr <= vp1;
		when "010" =>
			rdaddr <= vp2;
		when "011" =>
			rdaddr <= vp3;
		when "100" =>
			rdaddr <= vpadd;
		when "101" =>
			rdaddr <= ar;
		when "110" =>
			rdaddr <= sp;
		when others =>
			rdaddr <= dir;
	end case;
 
	case sel_wra is
		when "000" =>
			wraddr <= vp0;
		when "001" =>
			wraddr <= vp1;
		when "010" =>
			wraddr <= vp2;
		when "011" =>
			wraddr <= vp3;
		when "100" =>
			wraddr <= vpadd;
		when "101" =>
			wraddr <= ar;
		when "110" =>
			wraddr <= spp;
		when others =>
			wraddr <= dir;
	end case;
 
end process;
 
process(clk, reset)
 
begin
	if (reset='1') then
		-- a reasonable start value for the stack addressing
		-- will be overwritten by the first microcode instructions
		sp <= std_logic_vector(to_unsigned(128, ram_width));		
		spp <= std_logic_vector(to_unsigned(129, ram_width));
		spm <= std_logic_vector(to_unsigned(127, ram_width));
		sp_ov <= '0';
		vp0 <= std_logic_vector(to_unsigned(0, ram_width));
		vp1 <= std_logic_vector(to_unsigned(0, ram_width));
		vp2 <= std_logic_vector(to_unsigned(0, ram_width));
		vp3 <= std_logic_vector(to_unsigned(0, ram_width));
		ar <= (others => '0');
		vpadd <= std_logic_vector(to_unsigned(0, ram_width));
		immval <= std_logic_vector(to_unsigned(0, width));
		opddly <= std_logic_vector(to_unsigned(0, 16));
	elsif rising_edge(clk) then
		spp <= std_logic_vector(unsigned(smux) + 1);
		spm <= std_logic_vector(unsigned(smux) - 1);
		sp <= smux;
		-- Value depends on code in JVMHelp.exception() and how much
		-- usefull information can be printed out
		-- -8 was ok with just a plain print...
		-- -10 (or -12) should be ok for a stack trace?
		if sp=std_logic_vector(to_unsigned(2**ram_width-1-16, ram_width)) then
			sp_ov <= '1';
		end if;
		if (ena_vp = '1') then
			vp0 <= a(ram_width-1 downto 0);
			vp1 <= std_logic_vector(unsigned(a(ram_width-1 downto 0)) + 1);
			vp2 <= std_logic_vector(unsigned(a(ram_width-1 downto 0)) + 2);
			vp3 <= std_logic_vector(unsigned(a(ram_width-1 downto 0)) + 3);
		end if;
		if ena_ar = '1' then
			ar <= a(ram_width-1 downto 0);
		end if;
		vpadd <= std_logic_vector(unsigned(vp0(ram_width-1 downto 0)) + unsigned(opd(6 downto 0)));
		opddly <= opd;
		immval <= imux;
	end if;
end process;
 
end rtl;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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