Files
vhdl/lib/CPUs/J1/src/core/j1.vhd
T
jens 026c442fce Initial revision
Committed on the Free edition of March Hare Software CVSNT Server.
Upgrade to CVS Suite for more features and support:
http://march-hare.com/cvsnt/


git-svn-id: http://moon:8086/svn/vhdl/trunk@939 cc03376c-175c-47c8-b038-4cd826a8556b
2013-02-07 14:50:03 +00:00

283 lines
6.4 KiB
VHDL

LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.numeric_std.ALL;
entity j1 is
Generic
(
R_STACK_SIZE : natural := 32;
D_STACK_SIZE : natural := 32
);
Port
(
sys_clk_i : in std_logic;
sys_rst_i : in std_logic;
io_din : in unsigned(15 downto 0);
io_rd : out std_logic;
io_wr : out std_logic;
io_addr : out unsigned(15 downto 0);
io_dout : out unsigned(15 downto 0);
inst_din : in unsigned(15 downto 0);
inst_addr : out unsigned(12 downto 0);
data_addr : out unsigned(12 downto 0);
data_we : out std_logic;
data_en : out std_logic;
data_din : in unsigned(15 downto 0);
data_dout : out unsigned(15 downto 0)
);
end j1;
architecture behave of j1 is
signal insn : unsigned(15 downto 0);
signal immediate : unsigned(15 downto 0);
signal ramrd : unsigned(15 downto 0);
signal dsp : unsigned(4 downto 0); -- Data stack pointer (register)
signal dsp2 : unsigned(4 downto 0); -- register
signal st0 : unsigned(15 downto 0); -- Return stack pointer (register)
signal st02 : unsigned(15 downto 0); -- register
signal dstkW2 : std_logic; -- D stack write
signal pc : unsigned(12 downto 0); -- register
signal pc2 : unsigned(12 downto 0); -- register
signal rsp : unsigned(4 downto 0); -- register
signal rsp2 : unsigned(4 downto 0); -- register
signal rstkW2 : std_logic; -- register
signal rstkD2 : unsigned(15 downto 0); -- register
signal ramWE2 : std_logic; -- RAM write enable
signal pc_plus_1 : unsigned(15 downto 0);
type stack_t is array (integer range <>) of unsigned(15 downto 0);
signal dstack : stack_t(0 to D_STACK_SIZE-1); -- register
signal rstack : stack_t(0 to R_STACK_SIZE-1); -- register
signal st1 : unsigned(15 downto 0);
signal rst0 : unsigned(15 downto 0);
signal st0sel : unsigned(3 downto 0);
signal is_alu : BOOLEAN;
signal is_lit : BOOLEAN;
signal dd : unsigned(1 downto 0); -- D stack delta
signal rd : unsigned(1 downto 0); -- R stack delta
signal stack_ram_en : std_logic; -- helper for RAM R/W
signal stack_ram_we : std_logic; -- helper for RAM R/W
begin
-- LINE 25:
pc_plus_1 <= ("000" & pc) + 1;
-- LINE 37:
st1 <= dstack(to_integer(dsp));
rst0 <= rstack(to_integer(rsp));
immediate <= '1' & insn(14 downto 0);
-- LINE 112:
is_alu <= (insn(15 downto 13) = "011");
is_lit <= (insn(15) = '1');
-- LINE 115:
io_rd <= '1' when (is_alu and (insn(11 downto 8) = X"C")) else '0';
io_wr <= ramWE2;
io_addr <= st0;
io_dout <= st1;
ramWE2 <= '1' when (is_alu and (insn(5) = '1')) else '0';
dstkW2 <= '1' when (is_lit or (is_alu and insn(7) = '1')) else '0';
dd <= insn(1 downto 0);
rd <= insn(3 downto 2);
-- LINE 27:
-- The D and R stacks
proc_d_and_r_stack:
process(sys_clk_i)
begin
if rising_edge(sys_clk_i) then
if dstkW2 = '1' then
dstack(to_integer(dsp2)) <= st0;
end if;
if rstkW2 = '1' then
rstack(to_integer(rsp2)) <= rstkD2;
end if;
end if;
end process;
-- LINE 40:
-- st0sel is the ALU operation. For branch and call the operation
-- is T, for 0branch it is N. For ALU ops it is loaded from the instruction
-- field.
proc_aluop_sel:
process(insn)
begin
case insn(14 downto 13) is
when "00" => st0sel <= "0000";
when "10" => st0sel <= "0000";
when "01" => st0sel <= "0001";
when "11" => st0sel <= insn(11 downto 8);
when others => st0sel <= "XXXX";
end case;
end process;
-- LINE 55:
-- define RAMS outside this module
insn <= inst_din;
inst_addr <= pc2(12 downto 0);
data_en <= not (st02(15) or st02(14));
data_we <= ramWE2 and not (st02(15) or st02(14));
ramrd <= data_din;
data_dout <= st1;
data_addr <= st02(13 downto 1);
-- LINE 85:
-- Compute the new value of T.
proc_alu:
process(insn, immediate, st0sel, st0, st1, rst0, rsp, dsp)
begin
if insn(15) = '1' then
st02 <= immediate;
else
case st0sel is
when "0000" => st02 <= st0;
when "0001" => st02 <= st1;
when "0010" => st02 <= st0 + st1;
when "0011" => st02 <= st0 and st1;
when "0100" => st02 <= st0 or st1;
when "0101" => st02 <= st0 xor st1;
when "0110" => st02 <= not st0;
when "0111" =>
if st1 = st0 then
st02 <= X"FFFF";
else
st02 <= X"0000";
end if;
when "1000" =>
if signed(st1) < signed(st0) then
st02 <= X"FFFF";
else
st02 <= X"0000";
end if;
when "1001" => st02 <= st1 srl to_integer(st0(3 downto 0));
when "1010" => st02 <= st0 - 1;
when "1011" => st02 <= rst0;
when "1100" =>
if st0(15) = '1' or st0(14) = '1' then -- LINE 104: ????
st02 <= io_din;
else
st02 <= ramrd;
end if;
when "1101" => st02 <= st1 sll to_integer(st0(3 downto 0));
when "1110" => st02 <= "000" & rsp & "000" & dsp; -- LINE 106: ????
when "1111" =>
if st1 < st0 then
st02 <= X"FFFF";
else
st02 <= X"0000";
end if;
when others => st02 <= "XXXXXXXXXXXXXXXX";
end case;
end if;
end process;
-- LINE 126:
proc_stack_ctrl:
process(is_lit, is_alu, pc2, dd, rd, insn, st0, pc_plus_1, rsp, dsp)
begin
if is_lit then -- literal
dsp2 <= dsp + 1;
rsp2 <= rsp;
rstkW2 <= '0';
rstkD2 <= "000" & pc2;
elsif is_alu then
dsp2 <= dsp + (dd(1) & dd(1) & dd(1) & dd);
rsp2 <= rsp + (rd(1) & rd(1) & rd(1) & rd);
rstkW2 <= insn(6);
rstkD2 <= st0;
else -- jump/call
-- predicated jump is like DROP
if insn(15 downto 13) = "001" then
dsp2 <= dsp - 1;
else
dsp2 <= dsp; -- *default
end if;
if insn(15 downto 13) = "010" then -- call
rsp2 <= rsp + 1;
rstkW2 <= '1';
rstkD2 <= pc_plus_1(14 downto 0) & '0';
else
rsp2 <= rsp; -- *default
rstkW2 <= '0'; -- *default
rstkD2 <= "000" & pc2; -- *default
end if;
end if;
end process;
-- LINE 157:
proc_pc:
process(sys_rst_i, is_alu, insn, pc, st0, rst0, pc_plus_1)
begin
if sys_rst_i = '1' then
pc2 <= pc;
else
if ((insn(15 downto 13) = "000")
or ((insn(15 downto 13) = "001")
and (st0 = X"0000"))
or (insn(15 downto 13) = "010")) then
pc2 <= insn(12 downto 0);
elsif is_alu and (insn(12) = '1') then -- return
pc2 <= rst0(13 downto 1); -- LINE 167: ????
else
pc2 <= pc_plus_1(12 downto 0); -- LINE 169: truncation ????
end if;
end if;
end process;
-- LINE 172:
proc_next:
process(sys_clk_i)
begin
if rising_edge(sys_clk_i) then
if sys_rst_i = '1' then
pc <= (others => '0');
dsp <= (others => '0');
st0 <= (others => '0');
rsp <= (others => '0');
else
dsp <= dsp2;
pc <= pc2;
st0 <= st02;
rsp <= rsp2;
end if;
end if;
end process;
end behave;