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
283 lines
6.4 KiB
VHDL
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;
|