summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroharboe <oharboe>2008-05-01 08:23:39 +0000
committeroharboe <oharboe>2008-05-01 08:23:39 +0000
commit0d7bc56eab8ff2d28aa9c4721a56b022385e13d9 (patch)
treea3fc522428e8ac9df1f440b79a0a272cf9517893
parent30faee20f811215e6d53ca2434119aa5cd059feb (diff)
downloadzpu-0d7bc56eab8ff2d28aa9c4721a56b022385e13d9.zip
zpu-0d7bc56eab8ff2d28aa9c4721a56b022385e13d9.tar.gz
* zpu/hdl/zy1000 - ZPU implementation used on the zy1000 dev kit
-rw-r--r--.settings/org.eclipse.core.resources.prefs3
-rw-r--r--zpu/ChangeLog2
-rw-r--r--zpu/hdl/zy2000/timer.vhd137
-rw-r--r--zpu/hdl/zy2000/trace.vhd84
-rw-r--r--zpu/hdl/zy2000/txt_util.vhd587
-rw-r--r--zpu/hdl/zy2000/zpu_config.vhd20
-rw-r--r--zpu/hdl/zy2000/zpu_config_fast.vhd20
-rw-r--r--zpu/hdl/zy2000/zpu_core.vhd (renamed from zpu/hdl/zpu4/src/zpu_core_wip.vhd)1896
-rw-r--r--zpu/hdl/zy2000/zpupkg.vhd168
9 files changed, 1969 insertions, 948 deletions
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..3f4041d
--- /dev/null
+++ b/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Wed Apr 30 20:08:12 CEST 2008
+eclipse.preferences.version=1
+encoding//zpu/hdl/zpu4/src/zpu_core_small_wip.vhd=UTF-8
diff --git a/zpu/ChangeLog b/zpu/ChangeLog
index 249ff02..bb48431 100644
--- a/zpu/ChangeLog
+++ b/zpu/ChangeLog
@@ -1,3 +1,5 @@
+2008-05-01 Øyvind Harboe
+ * zpu/hdl/zy1000 - ZPU implementation used on the zy1000 dev kit
2008-04-17 Arnim Läuger
* zpu/hdl/example_ghdl/ghdl_import.sh, zpu/hdl/example_ghdl/ghdl_make.sh,
zpu/hdl/example_ghdl/ghdl_options.sh, zpu/hdl/example_ghdl/README: GHDL example
diff --git a/zpu/hdl/zy2000/timer.vhd b/zpu/hdl/zy2000/timer.vhd
new file mode 100644
index 0000000..bff82f2
--- /dev/null
+++ b/zpu/hdl/zy2000/timer.vhd
@@ -0,0 +1,137 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+entity timer is
+ port(
+ clk : in std_logic;
+ areset : in std_logic;
+ sample : in std_logic;
+ reset : in std_logic;
+ counter : out std_logic_vector(63 downto 0));
+end timer;
+
+
+architecture behave of timer is
+
+signal c : std_logic_vector(1 to 7);
+
+signal cnt : std_logic_vector(63 downto 0);
+signal cnt_smp : std_logic_vector(63 downto 0);
+
+begin
+
+ counter <= cnt_smp;
+
+ process(clk, areset) -- Carry generation
+ begin
+ if areset = '1' then
+ c <= "0000000";
+ elsif (clk'event and clk = '1') then
+ if reset = '1' then
+ c <= "0000000";
+ else
+ if cnt(7 downto 0) = "11111110" then
+ c(1) <= '1';
+ else
+ c(1) <= '0';
+ end if;
+ if cnt(15 downto 8) = "11111111" then
+ c(2) <= '1';
+ else
+ c(2) <= '0';
+ end if;
+ if cnt(23 downto 16) = "11111111" and c(2) = '1' then
+ c(3) <= '1';
+ else
+ c(3) <= '0';
+ end if;
+ if cnt(31 downto 24) = "11111111" and c(3) = '1' then
+ c(4) <= '1';
+ else
+ c(4) <= '0';
+ end if;
+ if cnt(39 downto 32) = "11111111" and c(4) = '1' then
+ c(5) <= '1';
+ else
+ c(5) <= '0';
+ end if;
+ if cnt(47 downto 40) = "11111111" and c(5) = '1' then
+ c(6) <= '1';
+ else
+ c(6) <= '0';
+ end if;
+ if cnt(55 downto 48) = "11111111" and c(6) = '1' then
+ c(7) <= '1';
+ else
+ c(7) <= '0';
+ end if;
+ end if;
+ end if;
+ end process;
+
+ process(clk, areset)
+ begin
+ if areset = '1' then
+ cnt <= (others=>'0');
+ elsif (clk'event and clk = '1') then
+ if reset = '1' then
+ cnt <= (others=>'0');
+ else
+ cnt(7 downto 0) <= cnt(7 downto 0) + '1';
+ if c(1) = '1' then
+ cnt(15 downto 8) <= cnt(15 downto 8) + '1';
+ else
+ cnt(15 downto 8) <= cnt(15 downto 8);
+ end if;
+ if c(2) = '1' and c(1) = '1' then
+ cnt(23 downto 16) <= cnt(23 downto 16) + '1';
+ else
+ cnt(23 downto 16) <= cnt(23 downto 16);
+ end if;
+ if c(3) = '1' and c(1) = '1' then
+ cnt(31 downto 24) <= cnt(31 downto 24) + '1';
+ else
+ cnt(31 downto 24) <= cnt(31 downto 24);
+ end if;
+ if c(4) = '1' and c(1) = '1' then
+ cnt(39 downto 32) <= cnt(39 downto 32) + '1';
+ else
+ cnt(39 downto 32) <= cnt(39 downto 32);
+ end if;
+ if c(5) = '1' and c(1) = '1' then
+ cnt(47 downto 40) <= cnt(47 downto 40) + '1';
+ else
+ cnt(47 downto 40) <= cnt(47 downto 40);
+ end if;
+ if c(6) = '1' and c(1) = '1' then
+ cnt(55 downto 48) <= cnt(55 downto 48) + '1';
+ else
+ cnt(55 downto 48) <= cnt(55 downto 48);
+ end if;
+ if c(7) = '1' and c(1) = '1' then
+ cnt(63 downto 56) <= cnt(63 downto 56) + '1';
+ else
+ cnt(63 downto 56) <= cnt(63 downto 56);
+ end if;
+ end if;
+ end if;
+ end process;
+
+ process(clk, areset)
+ begin
+ if areset = '1' then
+ cnt_smp <= (others=>'0');
+ elsif (clk'event and clk = '1') then
+ if reset = '1' then
+ cnt_smp <= (others=>'0');
+ elsif sample = '1' then
+ cnt_smp <= cnt;
+ else
+ cnt_smp <= cnt_smp;
+ end if;
+ end if;
+ end process;
+
+end behave;
+
diff --git a/zpu/hdl/zy2000/trace.vhd b/zpu/hdl/zy2000/trace.vhd
new file mode 100644
index 0000000..bc5279f
--- /dev/null
+++ b/zpu/hdl/zy2000/trace.vhd
@@ -0,0 +1,84 @@
+library ieee;
+use ieee.std_logic_1164.all;
+--use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+use std.textio.all;
+
+library work;
+use work.zpu_config.all;
+use work.zpupkg.all;
+use work.txt_util.all;
+
+
+entity trace is
+ generic (
+ log_file: string := "trace.txt"
+ );
+ port(
+ clk : in std_logic;
+ begin_inst : in std_logic;
+ pc : in std_logic_vector(maxAddrBitIncIO downto 0);
+ opcode : in std_logic_vector(7 downto 0);
+ sp : in std_logic_vector(maxAddrBitIncIO downto 2);
+ memA : in std_logic_vector(wordSize-1 downto 0);
+ memB : in std_logic_vector(wordSize-1 downto 0);
+ busy : in std_logic;
+ intSp : in std_logic_vector(stack_bits-1 downto 0)
+ );
+end trace;
+
+
+architecture behave of trace is
+
+
+file l_file : TEXT open write_mode is log_file;
+
+
+begin
+
+
+-- write data and control information to a file
+
+receive_data: process
+
+variable l: line;
+variable t : std_logic_vector(wordSize-1 downto 0);
+variable t2 : std_logic_vector(maxAddrBitIncIO downto 0);
+variable counter : std_logic_vector(63 downto 0);
+
+
+
+begin
+
+ t:= (others => '0');
+ t2:= (others => '0');
+
+counter := (others => '0');
+ -- print header for the logfile
+ print(l_file, "#pc,opcode,sp,top_of_stack ");
+ print(l_file, "#----------");
+ print(l_file, " ");
+
+ wait until clk = '1';
+ wait until clk = '0';
+
+ while true loop
+
+ counter := counter + 1;
+ if begin_inst = '1' then
+ t(maxAddrBitIncIO downto 2):=sp;
+ t2:=pc;
+ print(l_file, "0x" & hstr(t2) & " 0x" & hstr(opcode) & " 0x" & hstr(t) & " 0x" & hstr(memA) & " 0x" & hstr(memB) & " 0x" & hstr(intSp) & " 0x" & hstr(counter));
+ end if;
+
+ wait until clk = '0';
+
+ end loop;
+
+ end process receive_data;
+
+
+
+end behave;
+
diff --git a/zpu/hdl/zy2000/txt_util.vhd b/zpu/hdl/zy2000/txt_util.vhd
new file mode 100644
index 0000000..d3bf01a
--- /dev/null
+++ b/zpu/hdl/zy2000/txt_util.vhd
@@ -0,0 +1,587 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use std.textio.all;
+
+library work;
+
+package txt_util is
+
+ -- prints a message to the screen
+ procedure print(text: string);
+
+ -- prints the message when active
+ -- useful for debug switches
+ procedure print(active: boolean; text: string);
+
+ -- converts std_logic into a character
+ function chr(sl: std_logic) return character;
+
+ -- converts std_logic into a string (1 to 1)
+ function str(sl: std_logic) return string;
+
+ -- converts std_logic_vector into a string (binary base)
+ function str(slv: std_logic_vector) return string;
+
+ -- converts boolean into a string
+ function str(b: boolean) return string;
+
+ -- converts an integer into a single character
+ -- (can also be used for hex conversion and other bases)
+ function chr(int: integer) return character;
+
+ -- converts integer into string using specified base
+ function str(int: integer; base: integer) return string;
+
+ -- converts integer to string, using base 10
+ function str(int: integer) return string;
+
+ -- convert std_logic_vector into a string in hex format
+ function hstr(slv: std_logic_vector) return string;
+
+
+ -- functions to manipulate strings
+ -----------------------------------
+
+ -- convert a character to upper case
+ function to_upper(c: character) return character;
+
+ -- convert a character to lower case
+ function to_lower(c: character) return character;
+
+ -- convert a string to upper case
+ function to_upper(s: string) return string;
+
+ -- convert a string to lower case
+ function to_lower(s: string) return string;
+
+
+
+ -- functions to convert strings into other formats
+ --------------------------------------------------
+
+ -- converts a character into std_logic
+ function to_std_logic(c: character) return std_logic;
+
+ -- converts a string into std_logic_vector
+ function to_std_logic_vector(s: string) return std_logic_vector;
+
+
+
+ -- file I/O
+ -----------
+
+ -- read variable length string from input file
+ procedure str_read(file in_file: TEXT;
+ res_string: out string);
+
+ -- print string to a file and start new line
+ procedure print(file out_file: TEXT;
+ new_string: in string);
+
+ -- print character to a file and start new line
+ procedure print(file out_file: TEXT;
+ char: in character);
+
+end txt_util;
+
+
+
+
+package body txt_util is
+
+
+
+
+ -- prints text to the screen
+
+ procedure print(text: string) is
+ variable msg_line: line;
+ begin
+ write(msg_line, text);
+ writeline(output, msg_line);
+ end print;
+
+
+
+
+ -- prints text to the screen when active
+
+ procedure print(active: boolean; text: string) is
+ begin
+ if active then
+ print(text);
+ end if;
+ end print;
+
+
+ -- converts std_logic into a character
+
+ function chr(sl: std_logic) return character is
+ variable c: character;
+ begin
+ case sl is
+ when 'U' => c:= 'U';
+ when 'X' => c:= 'X';
+ when '0' => c:= '0';
+ when '1' => c:= '1';
+ when 'Z' => c:= 'Z';
+ when 'W' => c:= 'W';
+ when 'L' => c:= 'L';
+ when 'H' => c:= 'H';
+ when '-' => c:= '-';
+ end case;
+ return c;
+ end chr;
+
+
+
+ -- converts std_logic into a string (1 to 1)
+
+ function str(sl: std_logic) return string is
+ variable s: string(1 to 1);
+ begin
+ s(1) := chr(sl);
+ return s;
+ end str;
+
+
+
+ -- converts std_logic_vector into a string (binary base)
+ -- (this also takes care of the fact that the range of
+ -- a string is natural while a std_logic_vector may
+ -- have an integer range)
+
+ function str(slv: std_logic_vector) return string is
+ variable result : string (1 to slv'length);
+ variable r : integer;
+ begin
+ r := 1;
+ for i in slv'range loop
+ result(r) := chr(slv(i));
+ r := r + 1;
+ end loop;
+ return result;
+ end str;
+
+
+ function str(b: boolean) return string is
+
+ begin
+ if b then
+ return "true";
+ else
+ return "false";
+ end if;
+ end str;
+
+
+ -- converts an integer into a character
+ -- for 0 to 9 the obvious mapping is used, higher
+ -- values are mapped to the characters A-Z
+ -- (this is usefull for systems with base > 10)
+ -- (adapted from Steve Vogwell's posting in comp.lang.vhdl)
+
+ function chr(int: integer) return character is
+ variable c: character;
+ begin
+ case int is
+ when 0 => c := '0';
+ when 1 => c := '1';
+ when 2 => c := '2';
+ when 3 => c := '3';
+ when 4 => c := '4';
+ when 5 => c := '5';
+ when 6 => c := '6';
+ when 7 => c := '7';
+ when 8 => c := '8';
+ when 9 => c := '9';
+ when 10 => c := 'A';
+ when 11 => c := 'B';
+ when 12 => c := 'C';
+ when 13 => c := 'D';
+ when 14 => c := 'E';
+ when 15 => c := 'F';
+ when 16 => c := 'G';
+ when 17 => c := 'H';
+ when 18 => c := 'I';
+ when 19 => c := 'J';
+ when 20 => c := 'K';
+ when 21 => c := 'L';
+ when 22 => c := 'M';
+ when 23 => c := 'N';
+ when 24 => c := 'O';
+ when 25 => c := 'P';
+ when 26 => c := 'Q';
+ when 27 => c := 'R';
+ when 28 => c := 'S';
+ when 29 => c := 'T';
+ when 30 => c := 'U';
+ when 31 => c := 'V';
+ when 32 => c := 'W';
+ when 33 => c := 'X';
+ when 34 => c := 'Y';
+ when 35 => c := 'Z';
+ when others => c := '?';
+ end case;
+ return c;
+ end chr;
+
+
+
+ -- convert integer to string using specified base
+ -- (adapted from Steve Vogwell's posting in comp.lang.vhdl)
+
+ function str(int: integer; base: integer) return string is
+
+ variable temp: string(1 to 10);
+ variable num: integer;
+ variable abs_int: integer;
+ variable len: integer := 1;
+ variable power: integer := 1;
+
+ begin
+
+ -- bug fix for negative numbers
+ abs_int := abs(int);
+
+ num := abs_int;
+
+ while num >= base loop -- Determine how many
+ len := len + 1; -- characters required
+ num := num / base; -- to represent the
+ end loop ; -- number.
+
+ for i in len downto 1 loop -- Convert the number to
+ temp(i) := chr(abs_int/power mod base); -- a string starting
+ power := power * base; -- with the right hand
+ end loop ; -- side.
+
+ -- return result and add sign if required
+ if int < 0 then
+ return '-'& temp(1 to len);
+ else
+ return temp(1 to len);
+ end if;
+
+ end str;
+
+
+ -- convert integer to string, using base 10
+ function str(int: integer) return string is
+
+ begin
+
+ return str(int, 10) ;
+
+ end str;
+
+
+
+ -- converts a std_logic_vector into a hex string.
+ function hstr(slv: std_logic_vector) return string is
+ variable hexlen: integer;
+ variable longslv : std_logic_vector(67 downto 0) := (others => '0');
+ variable hex : string(1 to 16);
+ variable fourbit : std_logic_vector(3 downto 0);
+ begin
+ hexlen := (slv'left+1)/4;
+ if (slv'left+1) mod 4 /= 0 then
+ hexlen := hexlen + 1;
+ end if;
+ longslv(slv'left downto 0) := slv;
+ for i in (hexlen -1) downto 0 loop
+ fourbit := longslv(((i*4)+3) downto (i*4));
+ case fourbit is
+ when "0000" => hex(hexlen -I) := '0';
+ when "0001" => hex(hexlen -I) := '1';
+ when "0010" => hex(hexlen -I) := '2';
+ when "0011" => hex(hexlen -I) := '3';
+ when "0100" => hex(hexlen -I) := '4';
+ when "0101" => hex(hexlen -I) := '5';
+ when "0110" => hex(hexlen -I) := '6';
+ when "0111" => hex(hexlen -I) := '7';
+ when "1000" => hex(hexlen -I) := '8';
+ when "1001" => hex(hexlen -I) := '9';
+ when "1010" => hex(hexlen -I) := 'A';
+ when "1011" => hex(hexlen -I) := 'B';
+ when "1100" => hex(hexlen -I) := 'C';
+ when "1101" => hex(hexlen -I) := 'D';
+ when "1110" => hex(hexlen -I) := 'E';
+ when "1111" => hex(hexlen -I) := 'F';
+ when "ZZZZ" => hex(hexlen -I) := 'z';
+ when "UUUU" => hex(hexlen -I) := 'u';
+ when "XXXX" => hex(hexlen -I) := 'x';
+ when others => hex(hexlen -I) := '?';
+ end case;
+ end loop;
+ return hex(1 to hexlen);
+ end hstr;
+
+
+
+ -- functions to manipulate strings
+ -----------------------------------
+
+
+ -- convert a character to upper case
+
+ function to_upper(c: character) return character is
+
+ variable u: character;
+
+ begin
+
+ case c is
+ when 'a' => u := 'A';
+ when 'b' => u := 'B';
+ when 'c' => u := 'C';
+ when 'd' => u := 'D';
+ when 'e' => u := 'E';
+ when 'f' => u := 'F';
+ when 'g' => u := 'G';
+ when 'h' => u := 'H';
+ when 'i' => u := 'I';
+ when 'j' => u := 'J';
+ when 'k' => u := 'K';
+ when 'l' => u := 'L';
+ when 'm' => u := 'M';
+ when 'n' => u := 'N';
+ when 'o' => u := 'O';
+ when 'p' => u := 'P';
+ when 'q' => u := 'Q';
+ when 'r' => u := 'R';
+ when 's' => u := 'S';
+ when 't' => u := 'T';
+ when 'u' => u := 'U';
+ when 'v' => u := 'V';
+ when 'w' => u := 'W';
+ when 'x' => u := 'X';
+ when 'y' => u := 'Y';
+ when 'z' => u := 'Z';
+ when others => u := c;
+ end case;
+
+ return u;
+
+ end to_upper;
+
+
+ -- convert a character to lower case
+
+ function to_lower(c: character) return character is
+
+ variable l: character;
+
+ begin
+
+ case c is
+ when 'A' => l := 'a';
+ when 'B' => l := 'b';
+ when 'C' => l := 'c';
+ when 'D' => l := 'd';
+ when 'E' => l := 'e';
+ when 'F' => l := 'f';
+ when 'G' => l := 'g';
+ when 'H' => l := 'h';
+ when 'I' => l := 'i';
+ when 'J' => l := 'j';
+ when 'K' => l := 'k';
+ when 'L' => l := 'l';
+ when 'M' => l := 'm';
+ when 'N' => l := 'n';
+ when 'O' => l := 'o';
+ when 'P' => l := 'p';
+ when 'Q' => l := 'q';
+ when 'R' => l := 'r';
+ when 'S' => l := 's';
+ when 'T' => l := 't';
+ when 'U' => l := 'u';
+ when 'V' => l := 'v';
+ when 'W' => l := 'w';
+ when 'X' => l := 'x';
+ when 'Y' => l := 'y';
+ when 'Z' => l := 'z';
+ when others => l := c;
+ end case;
+
+ return l;
+
+ end to_lower;
+
+
+
+ -- convert a string to upper case
+
+ function to_upper(s: string) return string is
+
+ variable uppercase: string (s'range);
+
+ begin
+
+ for i in s'range loop
+ uppercase(i):= to_upper(s(i));
+ end loop;
+ return uppercase;
+
+ end to_upper;
+
+
+
+ -- convert a string to lower case
+
+ function to_lower(s: string) return string is
+
+ variable lowercase: string (s'range);
+
+ begin
+
+ for i in s'range loop
+ lowercase(i):= to_lower(s(i));
+ end loop;
+ return lowercase;
+
+ end to_lower;
+
+
+
+-- functions to convert strings into other types
+
+
+-- converts a character into a std_logic
+
+function to_std_logic(c: character) return std_logic is
+ variable sl: std_logic;
+ begin
+ case c is
+ when 'U' =>
+ sl := 'U';
+ when 'X' =>
+ sl := 'X';
+ when '0' =>
+ sl := '0';
+ when '1' =>
+ sl := '1';
+ when 'Z' =>
+ sl := 'Z';
+ when 'W' =>
+ sl := 'W';
+ when 'L' =>
+ sl := 'L';
+ when 'H' =>
+ sl := 'H';
+ when '-' =>
+ sl := '-';
+ when others =>
+ sl := 'X';
+ end case;
+ return sl;
+ end to_std_logic;
+
+
+-- converts a string into std_logic_vector
+
+function to_std_logic_vector(s: string) return std_logic_vector is
+ variable slv: std_logic_vector(s'high-s'low downto 0);
+ variable k: integer;
+begin
+ k := s'high-s'low;
+ for i in s'range loop
+ slv(k) := to_std_logic(s(i));
+ k := k - 1;
+ end loop;
+ return slv;
+end to_std_logic_vector;
+
+
+
+
+
+
+----------------
+-- file I/O --
+----------------
+
+
+
+-- read variable length string from input file
+
+procedure str_read(file in_file: TEXT;
+ res_string: out string) is
+
+ variable l: line;
+ variable c: character;
+ variable is_string: boolean;
+
+ begin
+
+ readline(in_file, l);
+ -- clear the contents of the result string
+ for i in res_string'range loop
+ res_string(i) := ' ';
+ end loop;
+ -- read all characters of the line, up to the length
+ -- of the results string
+ for i in res_string'range loop
+ read(l, c, is_string);
+ res_string(i) := c;
+ if not is_string then -- found end of line
+ exit;
+ end if;
+ end loop;
+
+end str_read;
+
+
+-- print string to a file
+procedure print(file out_file: TEXT;
+ new_string: in string) is
+
+ variable l: line;
+
+ begin
+
+ write(l, new_string);
+ writeline(out_file, l);
+
+end print;
+
+
+-- print character to a file and start new line
+procedure print(file out_file: TEXT;
+ char: in character) is
+
+ variable l: line;
+
+ begin
+
+ write(l, char);
+ writeline(out_file, l);
+
+end print;
+
+
+
+-- appends contents of a string to a file until line feed occurs
+-- (LF is considered to be the end of the string)
+
+procedure str_write(file out_file: TEXT;
+ new_string: in string) is
+ begin
+
+ for i in new_string'range loop
+ print(out_file, new_string(i));
+ if new_string(i) = LF then -- end of string
+ exit;
+ end if;
+ end loop;
+
+end str_write;
+
+
+
+
+end txt_util;
+
+
+
+
diff --git a/zpu/hdl/zy2000/zpu_config.vhd b/zpu/hdl/zy2000/zpu_config.vhd
new file mode 100644
index 0000000..61949c5
--- /dev/null
+++ b/zpu/hdl/zy2000/zpu_config.vhd
@@ -0,0 +1,20 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+package zpu_config is
+ -- generate trace output or not.
+ constant Generate_Trace : boolean := false;
+ constant wordPower : integer := 5;
+ -- during simulation, set this to '0' to get matching trace.txt
+ constant DontCareValue : std_logic := '0';
+ -- Clock frequency in MHz.
+ constant ZPU_Frequency : std_logic_vector(7 downto 0) := x"40";
+ -- This is the msb address bit. bytes=2^(maxAddrBitIncIO+1)
+ constant maxAddrBitIncIO : integer := 27;
+
+ -- start byte address of stack.
+ -- point to top of RAM - 2*words
+ constant spStart : std_logic_vector(maxAddrBitIncIO downto 0) := x"1fffff8";
+
+end zpu_config;
diff --git a/zpu/hdl/zy2000/zpu_config_fast.vhd b/zpu/hdl/zy2000/zpu_config_fast.vhd
new file mode 100644
index 0000000..61949c5
--- /dev/null
+++ b/zpu/hdl/zy2000/zpu_config_fast.vhd
@@ -0,0 +1,20 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+package zpu_config is
+ -- generate trace output or not.
+ constant Generate_Trace : boolean := false;
+ constant wordPower : integer := 5;
+ -- during simulation, set this to '0' to get matching trace.txt
+ constant DontCareValue : std_logic := '0';
+ -- Clock frequency in MHz.
+ constant ZPU_Frequency : std_logic_vector(7 downto 0) := x"40";
+ -- This is the msb address bit. bytes=2^(maxAddrBitIncIO+1)
+ constant maxAddrBitIncIO : integer := 27;
+
+ -- start byte address of stack.
+ -- point to top of RAM - 2*words
+ constant spStart : std_logic_vector(maxAddrBitIncIO downto 0) := x"1fffff8";
+
+end zpu_config;
diff --git a/zpu/hdl/zpu4/src/zpu_core_wip.vhd b/zpu/hdl/zy2000/zpu_core.vhd
index 882719d..2450f14 100644
--- a/zpu/hdl/zpu4/src/zpu_core_wip.vhd
+++ b/zpu/hdl/zy2000/zpu_core.vhd
@@ -1,948 +1,948 @@
-
--- Company: ZPU4 generic memory interface CPU
--- Engineer: Øyvind Harboe
-
-library IEEE;
-use IEEE.STD_LOGIC_1164.ALL;
-use IEEE.STD_LOGIC_UNSIGNED.ALL;
-use IEEE.STD_LOGIC_arith.ALL;
-
-library work;
-use work.zpu_config.all;
-use work.zpupkg.all;
-
-
-
-
-
-entity zpu_core is
- Port ( clk : in std_logic;
- areset : in std_logic;
- enable : in std_logic;
- mem_req : out std_logic;
- mem_we : out std_logic;
- mem_ack : in std_logic;
- mem_read : in std_logic_vector(wordSize-1 downto 0);
- mem_write : out std_logic_vector(wordSize-1 downto 0);
- out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
- mem_writeMask: out std_logic_vector(wordBytes-1 downto 0);
- interrupt : in std_logic;
- break : out std_logic;
- zpu_status : out std_logic_vector(63 downto 0));
-end zpu_core;
-
-architecture behave of zpu_core is
-
-type InsnType is
-(
-State_AddTop,
-State_Dup,
-State_DupStackB,
-State_Pop,
-State_Popdown,
-State_Add,
-State_Or,
-State_And,
-State_Store,
-State_AddSP,
-State_Shift,
-State_Nop,
-State_Im,
-State_LoadSP,
-State_StoreSP,
-State_Emulate,
-State_Load,
-State_PushPC,
-State_PushSP,
-State_PopPC,
-State_PopPCRel,
-State_Not,
-State_Flip,
-State_PopSP,
-State_Neqbranch,
-State_Eq,
-State_Loadb,
-State_Mult,
-State_Lessthan,
-State_Lessthanorequal,
-State_Ulessthanorequal,
-State_Ulessthan,
-State_Pushspadd,
-State_Call,
-State_Callpcrel,
-State_Sub,
-State_Break,
-State_Storeb,
-State_Interrupt,
-State_InsnFetch
-);
-
-type StateType is
-(
-State_Idle, -- using first state first on the list out of paranoia
-State_Load2,
-State_Popped,
-State_LoadSP2,
-State_LoadSP3,
-State_AddSP2,
-State_Fetch,
-State_Execute,
-State_Decode,
-State_Decode2,
-State_Resync,
-
-State_StoreSP2,
-State_Resync2,
-State_Resync3,
-State_Loadb2,
-State_Storeb2,
-State_Mult2,
-State_Mult3,
-State_Mult5,
-State_Mult6,
-State_Mult4,
-State_BinaryOpResult
-);
-
-
-signal pc : std_logic_vector(maxAddrBitIncIO downto 0);
-signal sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
-signal incSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
-signal incIncSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
-signal decSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
-signal stackA : std_logic_vector(wordSize-1 downto 0);
-signal binaryOpResult : std_logic_vector(wordSize-1 downto 0);
-signal multResult2 : std_logic_vector(wordSize-1 downto 0);
-signal multResult3 : std_logic_vector(wordSize-1 downto 0);
-signal multResult : std_logic_vector(wordSize-1 downto 0);
-signal multA : std_logic_vector(wordSize-1 downto 0);
-signal multB : std_logic_vector(wordSize-1 downto 0);
-signal stackB : std_logic_vector(wordSize-1 downto 0);
-signal idim_flag : std_logic;
-signal busy : std_logic;
-signal mem_readEnable : std_logic;
-signal mem_addr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
-signal mem_delayAddr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
-signal mem_delayReadEnable : std_logic;
-signal mem_busy : std_logic;
-signal decodeWord : std_logic_vector(wordSize-1 downto 0);
-
-
-signal state : StateType;
-signal insn : InsnType;
-type InsnArray is array(0 to wordBytes-1) of InsnType;
-signal decodedOpcode : InsnArray;
-
-type OpcodeArray is array(0 to wordBytes-1) of std_logic_vector(7 downto 0);
-
-signal opcode : OpcodeArray;
-
-
-
-
-signal begin_inst : std_logic;
-signal trace_opcode : std_logic_vector(7 downto 0);
-signal trace_pc : std_logic_vector(maxAddrBitIncIO downto 0);
-signal trace_sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
-signal trace_topOfStack : std_logic_vector(wordSize-1 downto 0);
-signal trace_topOfStackB : std_logic_vector(wordSize-1 downto 0);
-
-signal out_mem_req : std_logic;
-
-signal inInterrupt : std_logic;
-
--- state machine.
-
-begin
-
- zpu_status(maxAddrBitIncIO downto 0) <= trace_pc;
- zpu_status(31) <= '1';
- zpu_status(39 downto 32) <= trace_opcode;
- zpu_status(40) <= '1' when (state = State_Idle) else '0';
- zpu_status(62) <= '1';
-
- traceFileGenerate:
- if Generate_Trace generate
- trace_file: trace port map (
- clk => clk,
- begin_inst => begin_inst,
- pc => trace_pc,
- opcode => trace_opcode,
- sp => trace_sp,
- memA => trace_topOfStack,
- memB => trace_topOfStackB,
- busy => busy,
- intsp => (others => 'U')
- );
- end generate;
-
-
- -- the memory subsystem will tell us one cycle later whether or
- -- not it is busy
- out_mem_addr(maxAddrBitIncIO downto minAddrBit) <= mem_addr;
- out_mem_addr(minAddrBit-1 downto 0) <= (others => '0');
- mem_req <= out_mem_req;
-
- incSp <= sp + 1;
- incIncSp <= sp + 2;
- decSp <= sp - 1;
-
- mem_busy <= out_mem_req and not mem_ack; -- '1' when the memory is busy
-
- opcodeControl:
- process(clk, areset)
- variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0);
- variable spOffset : std_logic_vector(4 downto 0);
- variable tSpOffset : std_logic_vector(4 downto 0);
- variable nextPC : std_logic_vector(maxAddrBitIncIO downto 0);
- variable tNextState : InsnType;
- variable tDecodedOpcode : InsnArray;
- variable tMultResult : std_logic_vector(wordSize*2-1 downto 0);
- begin
- if areset = '1' then
- state <= State_Idle;
- break <= '0';
- sp <= spStart(maxAddrBitIncIO downto minAddrBit);
-
- pc <= (others => '0');
- idim_flag <= '0';
- begin_inst <= '0';
- mem_we <= '0';
- multA <= (others => '0');
- multB <= (others => '0');
- mem_writeMask <= (others => '1');
- out_mem_req <= '0';
- mem_addr <= (others => DontCareValue);
- mem_write <= (others => DontCareValue);
- inInterrupt <= '0';
- elsif (clk'event and clk = '1') then
- -- we must multiply unconditionally to get pipelined multiplication
- tMultResult := multA * multB;
- multResult3 <= multResult2;
- multResult2 <= multResult;
- multResult <= tMultResult(wordSize-1 downto 0);
-
-
- spOffset(4):=not opcode(conv_integer(pc(byteBits-1 downto 0)))(4);
- spOffset(3 downto 0):=opcode(conv_integer(pc(byteBits-1 downto 0)))(3 downto 0);
- nextPC := pc + 1;
-
- -- prepare trace snapshot
- trace_opcode <= opcode(conv_integer(pc(byteBits-1 downto 0)));
- trace_pc <= pc;
- trace_sp <= sp;
- trace_topOfStack <= stackA;
- trace_topOfStackB <= stackB;
- begin_inst <= '0';
-
- -- we terminate the requeset as soon as we get acknowledge
- if mem_ack = '1' then
- out_mem_req <= '0';
- mem_we <= '0';
- end if;
-
- if interrupt='0' then
- inInterrupt <= '0'; -- no longer in an interrupt
- end if;
-
- case state is
- when State_Idle =>
- if enable='1' then
- state <= State_Resync;
- end if;
- -- Initial state of ZPU, fetch top of stack + first instruction
- when State_Resync =>
- if mem_busy='0' then
- mem_addr <= sp;
- out_mem_req <= '1';
- state <= State_Resync2;
- end if;
- when State_Resync2 =>
- if mem_busy='0' then
- stackA <= mem_read;
- mem_addr <= incSp;
- out_mem_req <= '1';
- state <= State_Resync3;
- end if;
- when State_Resync3 =>
- if mem_busy='0' then
- stackB <= mem_read;
- mem_addr <= pc(maxAddrBitIncIO downto minAddrBit);
- out_mem_req <= '1';
- state <= State_Decode;
- end if;
- when State_Decode =>
- if mem_busy='0' then
- decodeWord <= mem_read;
- state <= State_Decode2;
- end if;
- when State_Decode2 =>
- -- decode 4 instructions in parallel
- for i in 0 to wordBytes-1 loop
- tOpcode := decodeWord((wordBytes-1-i+1)*8-1 downto (wordBytes-1-i)*8);
-
- tSpOffset(4):=not tOpcode(4);
- tSpOffset(3 downto 0):=tOpcode(3 downto 0);
-
- opcode(i) <= tOpcode;
- if (tOpcode(7 downto 7)=OpCode_Im) then
- tNextState:=State_Im;
- elsif (tOpcode(7 downto 5)=OpCode_StoreSP) then
- if tSpOffset = 0 then
- tNextState := State_Pop;
- elsif tSpOffset=1 then
- tNextState := State_PopDown;
- else
- tNextState :=State_StoreSP;
- end if;
- elsif (tOpcode(7 downto 5)=OpCode_LoadSP) then
- if tSpOffset = 0 then
- tNextState :=State_Dup;
- elsif tSpOffset = 1 then
- tNextState :=State_DupStackB;
- else
- tNextState :=State_LoadSP;
- end if;
- elsif (tOpcode(7 downto 5)=OpCode_Emulate) then
- tNextState :=State_Emulate;
- if tOpcode(5 downto 0)=OpCode_Neqbranch then
- tNextState :=State_Neqbranch;
- elsif tOpcode(5 downto 0)=OpCode_Eq then
- tNextState :=State_Eq;
- elsif tOpcode(5 downto 0)=OpCode_Lessthan then
- tNextState :=State_Lessthan;
- elsif tOpcode(5 downto 0)=OpCode_Lessthanorequal then
- --tNextState :=State_Lessthanorequal;
- elsif tOpcode(5 downto 0)=OpCode_Ulessthan then
- tNextState :=State_Ulessthan;
- elsif tOpcode(5 downto 0)=OpCode_Ulessthanorequal then
- --tNextState :=State_Ulessthanorequal;
- elsif tOpcode(5 downto 0)=OpCode_Loadb then
- tNextState :=State_Loadb;
- elsif tOpcode(5 downto 0)=OpCode_Mult then
- tNextState :=State_Mult;
- elsif tOpcode(5 downto 0)=OpCode_Storeb then
- tNextState :=State_Storeb;
- elsif tOpcode(5 downto 0)=OpCode_Pushspadd then
- tNextState :=State_Pushspadd;
- elsif tOpcode(5 downto 0)=OpCode_Callpcrel then
- tNextState :=State_Callpcrel;
- elsif tOpcode(5 downto 0)=OpCode_Call then
- --tNextState :=State_Call;
- elsif tOpcode(5 downto 0)=OpCode_Sub then
- tNextState :=State_Sub;
- elsif tOpcode(5 downto 0)=OpCode_PopPCRel then
- --tNextState :=State_PopPCRel;
- end if;
- elsif (tOpcode(7 downto 4)=OpCode_AddSP) then
- if tSpOffset = 0 then
- tNextState := State_Shift;
- elsif tSpOffset = 1 then
- tNextState := State_AddTop;
- else
- tNextState :=State_AddSP;
- end if;
- else
- case tOpcode(3 downto 0) is
- when OpCode_Nop =>
- tNextState :=State_Nop;
- when OpCode_PushSP =>
- tNextState :=State_PushSP;
- when OpCode_PopPC =>
- tNextState :=State_PopPC;
- when OpCode_Add =>
- tNextState :=State_Add;
- when OpCode_Or =>
- tNextState :=State_Or;
- when OpCode_And =>
- tNextState :=State_And;
- when OpCode_Load =>
- tNextState :=State_Load;
- when OpCode_Not =>
- tNextState :=State_Not;
- when OpCode_Flip =>
- tNextState :=State_Flip;
- when OpCode_Store =>
- tNextState :=State_Store;
- when OpCode_PopSP =>
- tNextState :=State_PopSP;
- when others =>
- tNextState := State_Break;
-
- end case;
- end if;
- tDecodedOpcode(i) := tNextState;
-
- end loop;
-
- insn <= tDecodedOpcode(conv_integer(pc(byteBits-1 downto 0)));
-
- -- once we wrap, we need to fetch
- tDecodedOpcode(0) := State_InsnFetch;
-
- decodedOpcode <= tDecodedOpcode;
- state <= State_Execute;
-
-
-
- -- Each instruction must:
- --
- -- 1. set idim_flag
- -- 2. increase pc if applicable
- -- 3. set next state if appliable
- -- 4. do it's operation
-
- when State_Execute =>
- insn <= decodedOpcode(conv_integer(nextPC(byteBits-1 downto 0)));
-
- case insn is
- when State_InsnFetch =>
- state <= State_Fetch;
- when State_Im =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '1';
- pc <= pc + 1;
-
- if idim_flag='1' then
- stackA(wordSize-1 downto 7) <= stackA(wordSize-8 downto 0);
- stackA(6 downto 0) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6 downto 0);
- else
- out_mem_req <= '1';
- mem_we <= '1';
- mem_addr <= incSp;
- mem_write <= stackB;
- stackB <= stackA;
- sp <= decSp;
- for i in wordSize-1 downto 7 loop
- stackA(i) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6);
- end loop;
- stackA(6 downto 0) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6 downto 0);
- end if;
- else
- insn <= insn;
- end if;
- when State_StoreSP =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_StoreSP2;
-
- out_mem_req <= '1';
- mem_we <= '1';
- mem_addr <= sp+spOffset;
- mem_write <= stackA;
- stackA <= stackB;
- sp <= incSp;
- else
- insn <= insn;
- end if;
-
-
- when State_LoadSP =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_LoadSP2;
-
- sp <= decSp;
- out_mem_req <= '1';
- mem_we <= '1';
- mem_addr <= incSp;
- mem_write <= stackB;
- else
- insn <= insn;
- end if;
- when State_Emulate =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- sp <= decSp;
- out_mem_req <= '1';
- mem_we <= '1';
- mem_addr <= incSp;
- mem_write <= stackB;
- stackA <= (others => DontCareValue);
- stackA(maxAddrBitIncIO downto 0) <= pc + 1;
- stackB <= stackA;
-
- -- The emulate address is:
- -- 98 7654 3210
- -- 0000 00aa aaa0 0000
- pc <= (others => '0');
- pc(9 downto 5) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(4 downto 0);
- state <= State_Fetch;
- else
- insn <= insn;
- end if;
- when State_Callpcrel =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- stackA <= (others => DontCareValue);
- stackA(maxAddrBitIncIO downto 0) <= pc + 1;
-
- pc <= pc + stackA(maxAddrBitIncIO downto 0);
- state <= State_Fetch;
- else
- insn <= insn;
- end if;
- when State_Call =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- stackA <= (others => DontCareValue);
- stackA(maxAddrBitIncIO downto 0) <= pc + 1;
- pc <= stackA(maxAddrBitIncIO downto 0);
- state <= State_Fetch;
- else
- insn <= insn;
- end if;
- when State_AddSP =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_AddSP2;
-
- out_mem_req <= '1';
- mem_addr <= sp+spOffset;
- else
- insn <= insn;
- end if;
- when State_PushSP =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- sp <= decSp;
- stackA <= (others => '0');
- stackA(maxAddrBitIncIO downto minAddrBit) <= sp;
- stackB <= stackA;
- out_mem_req <= '1';
- mem_we <= '1';
- mem_addr <= incSp;
- mem_write <= stackB;
- else
- insn <= insn;
- end if;
- when State_PopPC =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= stackA(maxAddrBitIncIO downto 0);
- sp <= incSp;
-
- out_mem_req <= '1';
- mem_we <= '1';
- mem_addr <= incSp;
- mem_write <= stackB;
- state <= State_Resync;
- else
- insn <= insn;
- end if;
- when State_PopPCRel =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= stackA(maxAddrBitIncIO downto 0) + pc;
- sp <= incSp;
-
- out_mem_req <= '1';
- mem_we <= '1';
- mem_addr <= incSp;
- mem_write <= stackB;
- state <= State_Resync;
- else
- insn <= insn;
- end if;
- when State_Add =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- stackA <= stackA + stackB;
-
- out_mem_req <= '1';
- mem_addr <= incIncSp;
- sp <= incSp;
- state <= State_Popped;
- else
- insn <= insn;
- end if;
- when State_Sub =>
- begin_inst <= '1';
- idim_flag <= '0';
- binaryOpResult <= stackB - stackA;
- state <= State_BinaryOpResult;
- when State_Pop =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- mem_addr <= incIncSp;
- out_mem_req <= '1';
- sp <= incSp;
- stackA <= stackB;
- state <= State_Popped;
- else
- insn <= insn;
- end if;
- when State_PopDown =>
- if mem_busy='0' then
- -- PopDown leaves top of stack unchanged
- begin_inst <= '1';
- idim_flag <= '0';
- mem_addr <= incIncSp;
- out_mem_req <= '1';
- sp <= incSp;
- state <= State_Popped;
- else
- insn <= insn;
- end if;
- when State_Or =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- stackA <= stackA or stackB;
- out_mem_req <= '1';
- mem_addr <= incIncSp;
- sp <= incSp;
- state <= State_Popped;
- else
- insn <= insn;
- end if;
- when State_And =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
-
- stackA <= stackA and stackB;
- out_mem_req <= '1';
- mem_addr <= incIncSp;
- sp <= incSp;
- state <= State_Popped;
- else
- insn <= insn;
- end if;
- when State_Eq =>
- begin_inst <= '1';
- idim_flag <= '0';
-
- binaryOpResult <= (others => '0');
- if (stackA=stackB) then
- binaryOpResult(0) <= '1';
- end if;
- state <= State_BinaryOpResult;
- when State_Ulessthan =>
- begin_inst <= '1';
- idim_flag <= '0';
-
- binaryOpResult <= (others => '0');
- if (stackA<stackB) then
- binaryOpResult(0) <= '1';
- end if;
- state <= State_BinaryOpResult;
- when State_Ulessthanorequal =>
- begin_inst <= '1';
- idim_flag <= '0';
-
- binaryOpResult <= (others => '0');
- if (stackA<=stackB) then
- binaryOpResult(0) <= '1';
- end if;
- state <= State_BinaryOpResult;
- when State_Lessthan =>
- begin_inst <= '1';
- idim_flag <= '0';
-
- binaryOpResult <= (others => '0');
- if (signed(stackA)<signed(stackB)) then
- binaryOpResult(0) <= '1';
- end if;
- state <= State_BinaryOpResult;
- when State_Lessthanorequal =>
- begin_inst <= '1';
- idim_flag <= '0';
-
- binaryOpResult <= (others => '0');
- if (signed(stackA)<=signed(stackB)) then
- binaryOpResult(0) <= '1';
- end if;
- state <= State_BinaryOpResult;
- when State_Load =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_Load2;
-
- mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
- out_mem_req <= '1';
- else
- insn <= insn;
- end if;
-
- when State_Dup =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- sp <= decSp;
- stackB <= stackA;
- mem_write <= stackB;
- mem_addr <= incSp;
- out_mem_req <= '1';
- mem_we <= '1';
- else
- insn <= insn;
- end if;
- when State_DupStackB =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- sp <= decSp;
- stackA <= stackB;
- stackB <= stackA;
- mem_write <= stackB;
- mem_addr <= incSp;
- out_mem_req <= '1';
- mem_we <= '1';
- else
- insn <= insn;
- end if;
- when State_Store =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
- mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
- mem_write <= stackB;
- out_mem_req <= '1';
- mem_we <= '1';
- sp <= incIncSp;
- state <= State_Resync;
- else
- insn <= insn;
- end if;
- when State_PopSP =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- mem_write <= stackB;
- mem_addr <= incSp;
- out_mem_req <= '1';
- mem_we <= '1';
- sp <= stackA(maxAddrBitIncIO downto minAddrBit);
- state <= State_Resync;
- else
- insn <= insn;
- end if;
- when State_Nop =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
- when State_Not =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- stackA <= not stackA;
- when State_Flip =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- for i in 0 to wordSize-1 loop
- stackA(i) <= stackA(wordSize-1-i);
- end loop;
- when State_AddTop =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- stackA <= stackA + stackB;
- when State_Shift =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- stackA(wordSize-1 downto 1) <= stackA(wordSize-2 downto 0);
- stackA(0) <= '0';
- when State_Pushspadd =>
- begin_inst <= '1';
- idim_flag <= '0';
- pc <= pc + 1;
-
- stackA <= (others => '0');
- stackA(maxAddrBitIncIO downto minAddrBit) <= stackA(maxAddrBitIncIO-minAddrBit downto 0)+sp;
- when State_Neqbranch =>
- -- branches are almost always taken as they form loops
- begin_inst <= '1';
- idim_flag <= '0';
- sp <= incIncSp;
- if (stackB/=0) then
- pc <= stackA(maxAddrBitIncIO downto 0) + pc;
- else
- pc <= pc + 1;
- end if;
- -- need to fetch stack again.
- state <= State_Resync;
- when State_Mult =>
- begin_inst <= '1';
- idim_flag <= '0';
-
- multA <= stackA;
- multB <= stackB;
- state <= State_Mult2;
- when State_Break =>
- report "Break instruction encountered" severity failure;
- break <= '1';
-
- when State_Loadb =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_Loadb2;
-
- mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
- out_mem_req <= '1';
- else
- insn <= insn;
- end if;
- when State_Storeb =>
- if mem_busy='0' then
- begin_inst <= '1';
- idim_flag <= '0';
- state <= State_Storeb2;
-
- mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
- out_mem_req <= '1';
- else
- insn <= insn;
- end if;
-
- when others =>
--- sp <= (others => DontCareValue);
- report "Illegal instruction" severity failure;
- break <= '1';
- end case;
-
-
- when State_StoreSP2 =>
- if mem_busy='0' then
- mem_addr <= incSp;
- out_mem_req <= '1';
- state <= State_Popped;
- end if;
- when State_LoadSP2 =>
- if mem_busy='0' then
- state <= State_LoadSP3;
- out_mem_req <= '1';
- mem_addr <= sp+spOffset+1;
- end if;
- when State_LoadSP3 =>
- if mem_busy='0' then
- pc <= pc + 1;
- state <= State_Execute;
- stackB <= stackA;
- stackA <= mem_read;
- end if;
- when State_AddSP2 =>
- if mem_busy='0' then
- pc <= pc + 1;
- state <= State_Execute;
- stackA <= stackA + mem_read;
- end if;
- when State_Load2 =>
- if mem_busy='0' then
- stackA <= mem_read;
- pc <= pc + 1;
- state <= State_Execute;
- end if;
- when State_Loadb2 =>
- if mem_busy='0' then
- stackA <= (others => '0');
- stackA(7 downto 0) <= mem_read(((wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8);
- pc <= pc + 1;
- state <= State_Execute;
- end if;
- when State_Storeb2 =>
- if mem_busy='0' then
- mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
- mem_write <= mem_read;
- mem_write(((wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8) <= stackB(7 downto 0) ;
- out_mem_req <= '1';
- mem_we <= '1';
- pc <= pc + 1;
- sp <= incIncSp;
- state <= State_Resync;
- end if;
- when State_Fetch =>
- if mem_busy='0' then
- if interrupt='1' and inInterrupt='0' and idim_flag='0' then
- -- We got an interrupt
- inInterrupt <= '1';
-
- sp <= decSp;
- out_mem_req <= '1';
- mem_we <= '1';
- mem_addr <= incSp;
- mem_write <= stackB;
- stackA <= (others => DontCareValue);
- stackA(maxAddrBitIncIO downto 0) <= pc;
- stackB <= stackA;
-
- pc <= conv_std_logic_vector(32, maxAddrBitIncIo+1); -- interrupt address
-
- report "ZPU jumped to interrupt!" severity note;
- else
- mem_addr <= pc(maxAddrBitIncIO downto minAddrBit);
- out_mem_req <= '1';
- state <= State_Decode;
- end if;
- end if;
- when State_Mult2 =>
- state <= State_Mult3;
- when State_Mult3 =>
- state <= State_Mult4;
- when State_Mult4 =>
- state <= State_Mult5;
- when State_Mult5 =>
- stackA <= multResult3;
- state <= State_Mult6;
- when State_Mult6 =>
- if mem_busy='0' then
- out_mem_req <= '1';
- mem_addr <= incIncSp;
- sp <= incSp;
- state <= State_Popped;
- end if;
- when State_BinaryOpResult =>
- if mem_busy='0' then
- -- NB!!!! we know that the memory isn't busy at this point!!!!
- out_mem_req <= '1';
- mem_addr <= incIncSp;
- sp <= incSp;
- stackA <= binaryOpResult;
- state <= State_Popped;
- end if;
- when State_Popped =>
- if mem_busy='0' then
- pc <= pc + 1;
- stackB <= mem_read;
- state <= State_Execute;
- end if;
- when others =>
--- sp <= (others => DontCareValue);
- report "Illegal state" severity failure;
- break <= '1';
- end case;
- end if;
- end process;
-
-
-
-end behave;
+
+-- Company: ZPU4 generic memory interface CPU
+-- Engineer: Øyvind Harboe
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+use IEEE.STD_LOGIC_arith.ALL;
+
+library work;
+use work.zpu_config.all;
+use work.zpupkg.all;
+
+
+
+
+
+entity zpu_core is
+ Port ( clk : in std_logic;
+ areset : in std_logic;
+ enable : in std_logic;
+ mem_req : out std_logic;
+ mem_we : out std_logic;
+ mem_ack : in std_logic;
+ mem_read : in std_logic_vector(wordSize-1 downto 0);
+ mem_write : out std_logic_vector(wordSize-1 downto 0);
+ out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
+ mem_writeMask: out std_logic_vector(wordBytes-1 downto 0);
+ interrupt : in std_logic;
+ break : out std_logic;
+ zpu_status : out std_logic_vector(63 downto 0));
+end zpu_core;
+
+architecture behave of zpu_core is
+
+type InsnType is
+(
+State_AddTop,
+State_Dup,
+State_DupStackB,
+State_Pop,
+State_Popdown,
+State_Add,
+State_Or,
+State_And,
+State_Store,
+State_AddSP,
+State_Shift,
+State_Nop,
+State_Im,
+State_LoadSP,
+State_StoreSP,
+State_Emulate,
+State_Load,
+State_PushPC,
+State_PushSP,
+State_PopPC,
+State_PopPCRel,
+State_Not,
+State_Flip,
+State_PopSP,
+State_Neqbranch,
+State_Eq,
+State_Loadb,
+State_Mult,
+State_Lessthan,
+State_Lessthanorequal,
+State_Ulessthanorequal,
+State_Ulessthan,
+State_Pushspadd,
+State_Call,
+State_Callpcrel,
+State_Sub,
+State_Break,
+State_Storeb,
+State_Interrupt,
+State_InsnFetch
+);
+
+type StateType is
+(
+State_Idle, -- using first state first on the list out of paranoia
+State_Load2,
+State_Popped,
+State_LoadSP2,
+State_LoadSP3,
+State_AddSP2,
+State_Fetch,
+State_Execute,
+State_Decode,
+State_Decode2,
+State_Resync,
+
+State_StoreSP2,
+State_Resync2,
+State_Resync3,
+State_Loadb2,
+State_Storeb2,
+State_Mult2,
+State_Mult3,
+State_Mult5,
+State_Mult6,
+State_Mult4,
+State_BinaryOpResult
+);
+
+
+signal pc : std_logic_vector(maxAddrBitIncIO downto 0);
+signal sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+signal incSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+signal incIncSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+signal decSp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+signal stackA : std_logic_vector(wordSize-1 downto 0);
+signal binaryOpResult : std_logic_vector(wordSize-1 downto 0);
+signal multResult2 : std_logic_vector(wordSize-1 downto 0);
+signal multResult3 : std_logic_vector(wordSize-1 downto 0);
+signal multResult : std_logic_vector(wordSize-1 downto 0);
+signal multA : std_logic_vector(wordSize-1 downto 0);
+signal multB : std_logic_vector(wordSize-1 downto 0);
+signal stackB : std_logic_vector(wordSize-1 downto 0);
+signal idim_flag : std_logic;
+signal busy : std_logic;
+signal mem_readEnable : std_logic;
+signal mem_addr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+signal mem_delayAddr : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+signal mem_delayReadEnable : std_logic;
+signal mem_busy : std_logic;
+signal decodeWord : std_logic_vector(wordSize-1 downto 0);
+
+
+signal state : StateType;
+signal insn : InsnType;
+type InsnArray is array(0 to wordBytes-1) of InsnType;
+signal decodedOpcode : InsnArray;
+
+type OpcodeArray is array(0 to wordBytes-1) of std_logic_vector(7 downto 0);
+
+signal opcode : OpcodeArray;
+
+
+
+
+signal begin_inst : std_logic;
+signal trace_opcode : std_logic_vector(7 downto 0);
+signal trace_pc : std_logic_vector(maxAddrBitIncIO downto 0);
+signal trace_sp : std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+signal trace_topOfStack : std_logic_vector(wordSize-1 downto 0);
+signal trace_topOfStackB : std_logic_vector(wordSize-1 downto 0);
+
+signal out_mem_req : std_logic;
+
+signal inInterrupt : std_logic;
+
+-- state machine.
+
+begin
+
+ zpu_status(maxAddrBitIncIO downto 0) <= trace_pc;
+ zpu_status(31) <= '1';
+ zpu_status(39 downto 32) <= trace_opcode;
+ zpu_status(40) <= '1' when (state = State_Idle) else '0';
+ zpu_status(62) <= '1';
+
+ traceFileGenerate:
+ if Generate_Trace generate
+ trace_file: trace port map (
+ clk => clk,
+ begin_inst => begin_inst,
+ pc => trace_pc,
+ opcode => trace_opcode,
+ sp => trace_sp,
+ memA => trace_topOfStack,
+ memB => trace_topOfStackB,
+ busy => busy,
+ intsp => (others => 'U')
+ );
+ end generate;
+
+
+ -- the memory subsystem will tell us one cycle later whether or
+ -- not it is busy
+ out_mem_addr(maxAddrBitIncIO downto minAddrBit) <= mem_addr;
+ out_mem_addr(minAddrBit-1 downto 0) <= (others => '0');
+ mem_req <= out_mem_req;
+
+ incSp <= sp + 1;
+ incIncSp <= sp + 2;
+ decSp <= sp - 1;
+
+ mem_busy <= out_mem_req and not mem_ack; -- '1' when the memory is busy
+
+ opcodeControl:
+ process(clk, areset)
+ variable tOpcode : std_logic_vector(OpCode_Size-1 downto 0);
+ variable spOffset : std_logic_vector(4 downto 0);
+ variable tSpOffset : std_logic_vector(4 downto 0);
+ variable nextPC : std_logic_vector(maxAddrBitIncIO downto 0);
+ variable tNextState : InsnType;
+ variable tDecodedOpcode : InsnArray;
+ variable tMultResult : std_logic_vector(wordSize*2-1 downto 0);
+ begin
+ if areset = '1' then
+ state <= State_Idle;
+ break <= '0';
+ sp <= spStart(maxAddrBitIncIO downto minAddrBit);
+
+ pc <= (others => '0');
+ idim_flag <= '0';
+ begin_inst <= '0';
+ mem_we <= '0';
+ multA <= (others => '0');
+ multB <= (others => '0');
+ mem_writeMask <= (others => '1');
+ out_mem_req <= '0';
+ mem_addr <= (others => DontCareValue);
+ mem_write <= (others => DontCareValue);
+ inInterrupt <= '0';
+ elsif (clk'event and clk = '1') then
+ -- we must multiply unconditionally to get pipelined multiplication
+ tMultResult := multA * multB;
+ multResult3 <= multResult2;
+ multResult2 <= multResult;
+ multResult <= tMultResult(wordSize-1 downto 0);
+
+
+ spOffset(4):=not opcode(conv_integer(pc(byteBits-1 downto 0)))(4);
+ spOffset(3 downto 0):=opcode(conv_integer(pc(byteBits-1 downto 0)))(3 downto 0);
+ nextPC := pc + 1;
+
+ -- prepare trace snapshot
+ trace_opcode <= opcode(conv_integer(pc(byteBits-1 downto 0)));
+ trace_pc <= pc;
+ trace_sp <= sp;
+ trace_topOfStack <= stackA;
+ trace_topOfStackB <= stackB;
+ begin_inst <= '0';
+
+ -- we terminate the requeset as soon as we get acknowledge
+ if mem_ack = '1' then
+ out_mem_req <= '0';
+ mem_we <= '0';
+ end if;
+
+ if interrupt='0' then
+ inInterrupt <= '0'; -- no longer in an interrupt
+ end if;
+
+ case state is
+ when State_Idle =>
+ if enable='1' then
+ state <= State_Resync;
+ end if;
+ -- Initial state of ZPU, fetch top of stack + first instruction
+ when State_Resync =>
+ if mem_busy='0' then
+ mem_addr <= sp;
+ out_mem_req <= '1';
+ state <= State_Resync2;
+ end if;
+ when State_Resync2 =>
+ if mem_busy='0' then
+ stackA <= mem_read;
+ mem_addr <= incSp;
+ out_mem_req <= '1';
+ state <= State_Resync3;
+ end if;
+ when State_Resync3 =>
+ if mem_busy='0' then
+ stackB <= mem_read;
+ mem_addr <= pc(maxAddrBitIncIO downto minAddrBit);
+ out_mem_req <= '1';
+ state <= State_Decode;
+ end if;
+ when State_Decode =>
+ if mem_busy='0' then
+ decodeWord <= mem_read;
+ state <= State_Decode2;
+ end if;
+ when State_Decode2 =>
+ -- decode 4 instructions in parallel
+ for i in 0 to wordBytes-1 loop
+ tOpcode := decodeWord((wordBytes-1-i+1)*8-1 downto (wordBytes-1-i)*8);
+
+ tSpOffset(4):=not tOpcode(4);
+ tSpOffset(3 downto 0):=tOpcode(3 downto 0);
+
+ opcode(i) <= tOpcode;
+ if (tOpcode(7 downto 7)=OpCode_Im) then
+ tNextState:=State_Im;
+ elsif (tOpcode(7 downto 5)=OpCode_StoreSP) then
+ if tSpOffset = 0 then
+ tNextState := State_Pop;
+ elsif tSpOffset=1 then
+ tNextState := State_PopDown;
+ else
+ tNextState :=State_StoreSP;
+ end if;
+ elsif (tOpcode(7 downto 5)=OpCode_LoadSP) then
+ if tSpOffset = 0 then
+ tNextState :=State_Dup;
+ elsif tSpOffset = 1 then
+ tNextState :=State_DupStackB;
+ else
+ tNextState :=State_LoadSP;
+ end if;
+ elsif (tOpcode(7 downto 5)=OpCode_Emulate) then
+ tNextState :=State_Emulate;
+ if tOpcode(5 downto 0)=OpCode_Neqbranch then
+ tNextState :=State_Neqbranch;
+ elsif tOpcode(5 downto 0)=OpCode_Eq then
+ tNextState :=State_Eq;
+ elsif tOpcode(5 downto 0)=OpCode_Lessthan then
+ tNextState :=State_Lessthan;
+ elsif tOpcode(5 downto 0)=OpCode_Lessthanorequal then
+ --tNextState :=State_Lessthanorequal;
+ elsif tOpcode(5 downto 0)=OpCode_Ulessthan then
+ tNextState :=State_Ulessthan;
+ elsif tOpcode(5 downto 0)=OpCode_Ulessthanorequal then
+ --tNextState :=State_Ulessthanorequal;
+ elsif tOpcode(5 downto 0)=OpCode_Loadb then
+ tNextState :=State_Loadb;
+ elsif tOpcode(5 downto 0)=OpCode_Mult then
+ tNextState :=State_Mult;
+ elsif tOpcode(5 downto 0)=OpCode_Storeb then
+ tNextState :=State_Storeb;
+ elsif tOpcode(5 downto 0)=OpCode_Pushspadd then
+ tNextState :=State_Pushspadd;
+ elsif tOpcode(5 downto 0)=OpCode_Callpcrel then
+ tNextState :=State_Callpcrel;
+ elsif tOpcode(5 downto 0)=OpCode_Call then
+ --tNextState :=State_Call;
+ elsif tOpcode(5 downto 0)=OpCode_Sub then
+ tNextState :=State_Sub;
+ elsif tOpcode(5 downto 0)=OpCode_PopPCRel then
+ --tNextState :=State_PopPCRel;
+ end if;
+ elsif (tOpcode(7 downto 4)=OpCode_AddSP) then
+ if tSpOffset = 0 then
+ tNextState := State_Shift;
+ elsif tSpOffset = 1 then
+ tNextState := State_AddTop;
+ else
+ tNextState :=State_AddSP;
+ end if;
+ else
+ case tOpcode(3 downto 0) is
+ when OpCode_Nop =>
+ tNextState :=State_Nop;
+ when OpCode_PushSP =>
+ tNextState :=State_PushSP;
+ when OpCode_PopPC =>
+ tNextState :=State_PopPC;
+ when OpCode_Add =>
+ tNextState :=State_Add;
+ when OpCode_Or =>
+ tNextState :=State_Or;
+ when OpCode_And =>
+ tNextState :=State_And;
+ when OpCode_Load =>
+ tNextState :=State_Load;
+ when OpCode_Not =>
+ tNextState :=State_Not;
+ when OpCode_Flip =>
+ tNextState :=State_Flip;
+ when OpCode_Store =>
+ tNextState :=State_Store;
+ when OpCode_PopSP =>
+ tNextState :=State_PopSP;
+ when others =>
+ tNextState := State_Break;
+
+ end case;
+ end if;
+ tDecodedOpcode(i) := tNextState;
+
+ end loop;
+
+ insn <= tDecodedOpcode(conv_integer(pc(byteBits-1 downto 0)));
+
+ -- once we wrap, we need to fetch
+ tDecodedOpcode(0) := State_InsnFetch;
+
+ decodedOpcode <= tDecodedOpcode;
+ state <= State_Execute;
+
+
+
+ -- Each instruction must:
+ --
+ -- 1. set idim_flag
+ -- 2. increase pc if applicable
+ -- 3. set next state if appliable
+ -- 4. do it's operation
+
+ when State_Execute =>
+ insn <= decodedOpcode(conv_integer(nextPC(byteBits-1 downto 0)));
+
+ case insn is
+ when State_InsnFetch =>
+ state <= State_Fetch;
+ when State_Im =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '1';
+ pc <= pc + 1;
+
+ if idim_flag='1' then
+ stackA(wordSize-1 downto 7) <= stackA(wordSize-8 downto 0);
+ stackA(6 downto 0) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6 downto 0);
+ else
+ out_mem_req <= '1';
+ mem_we <= '1';
+ mem_addr <= incSp;
+ mem_write <= stackB;
+ stackB <= stackA;
+ sp <= decSp;
+ for i in wordSize-1 downto 7 loop
+ stackA(i) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6);
+ end loop;
+ stackA(6 downto 0) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(6 downto 0);
+ end if;
+ else
+ insn <= insn;
+ end if;
+ when State_StoreSP =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_StoreSP2;
+
+ out_mem_req <= '1';
+ mem_we <= '1';
+ mem_addr <= sp+spOffset;
+ mem_write <= stackA;
+ stackA <= stackB;
+ sp <= incSp;
+ else
+ insn <= insn;
+ end if;
+
+
+ when State_LoadSP =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_LoadSP2;
+
+ sp <= decSp;
+ out_mem_req <= '1';
+ mem_we <= '1';
+ mem_addr <= incSp;
+ mem_write <= stackB;
+ else
+ insn <= insn;
+ end if;
+ when State_Emulate =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ sp <= decSp;
+ out_mem_req <= '1';
+ mem_we <= '1';
+ mem_addr <= incSp;
+ mem_write <= stackB;
+ stackA <= (others => DontCareValue);
+ stackA(maxAddrBitIncIO downto 0) <= pc + 1;
+ stackB <= stackA;
+
+ -- The emulate address is:
+ -- 98 7654 3210
+ -- 0000 00aa aaa0 0000
+ pc <= (others => '0');
+ pc(9 downto 5) <= opcode(conv_integer(pc(byteBits-1 downto 0)))(4 downto 0);
+ state <= State_Fetch;
+ else
+ insn <= insn;
+ end if;
+ when State_Callpcrel =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ stackA <= (others => DontCareValue);
+ stackA(maxAddrBitIncIO downto 0) <= pc + 1;
+
+ pc <= pc + stackA(maxAddrBitIncIO downto 0);
+ state <= State_Fetch;
+ else
+ insn <= insn;
+ end if;
+ when State_Call =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ stackA <= (others => DontCareValue);
+ stackA(maxAddrBitIncIO downto 0) <= pc + 1;
+ pc <= stackA(maxAddrBitIncIO downto 0);
+ state <= State_Fetch;
+ else
+ insn <= insn;
+ end if;
+ when State_AddSP =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_AddSP2;
+
+ out_mem_req <= '1';
+ mem_addr <= sp+spOffset;
+ else
+ insn <= insn;
+ end if;
+ when State_PushSP =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ sp <= decSp;
+ stackA <= (others => '0');
+ stackA(maxAddrBitIncIO downto minAddrBit) <= sp;
+ stackB <= stackA;
+ out_mem_req <= '1';
+ mem_we <= '1';
+ mem_addr <= incSp;
+ mem_write <= stackB;
+ else
+ insn <= insn;
+ end if;
+ when State_PopPC =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= stackA(maxAddrBitIncIO downto 0);
+ sp <= incSp;
+
+ out_mem_req <= '1';
+ mem_we <= '1';
+ mem_addr <= incSp;
+ mem_write <= stackB;
+ state <= State_Resync;
+ else
+ insn <= insn;
+ end if;
+ when State_PopPCRel =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= stackA(maxAddrBitIncIO downto 0) + pc;
+ sp <= incSp;
+
+ out_mem_req <= '1';
+ mem_we <= '1';
+ mem_addr <= incSp;
+ mem_write <= stackB;
+ state <= State_Resync;
+ else
+ insn <= insn;
+ end if;
+ when State_Add =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ stackA <= stackA + stackB;
+
+ out_mem_req <= '1';
+ mem_addr <= incIncSp;
+ sp <= incSp;
+ state <= State_Popped;
+ else
+ insn <= insn;
+ end if;
+ when State_Sub =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ binaryOpResult <= stackB - stackA;
+ state <= State_BinaryOpResult;
+ when State_Pop =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ mem_addr <= incIncSp;
+ out_mem_req <= '1';
+ sp <= incSp;
+ stackA <= stackB;
+ state <= State_Popped;
+ else
+ insn <= insn;
+ end if;
+ when State_PopDown =>
+ if mem_busy='0' then
+ -- PopDown leaves top of stack unchanged
+ begin_inst <= '1';
+ idim_flag <= '0';
+ mem_addr <= incIncSp;
+ out_mem_req <= '1';
+ sp <= incSp;
+ state <= State_Popped;
+ else
+ insn <= insn;
+ end if;
+ when State_Or =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ stackA <= stackA or stackB;
+ out_mem_req <= '1';
+ mem_addr <= incIncSp;
+ sp <= incSp;
+ state <= State_Popped;
+ else
+ insn <= insn;
+ end if;
+ when State_And =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ stackA <= stackA and stackB;
+ out_mem_req <= '1';
+ mem_addr <= incIncSp;
+ sp <= incSp;
+ state <= State_Popped;
+ else
+ insn <= insn;
+ end if;
+ when State_Eq =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ binaryOpResult <= (others => '0');
+ if (stackA=stackB) then
+ binaryOpResult(0) <= '1';
+ end if;
+ state <= State_BinaryOpResult;
+ when State_Ulessthan =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ binaryOpResult <= (others => '0');
+ if (stackA<stackB) then
+ binaryOpResult(0) <= '1';
+ end if;
+ state <= State_BinaryOpResult;
+ when State_Ulessthanorequal =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ binaryOpResult <= (others => '0');
+ if (stackA<=stackB) then
+ binaryOpResult(0) <= '1';
+ end if;
+ state <= State_BinaryOpResult;
+ when State_Lessthan =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ binaryOpResult <= (others => '0');
+ if (signed(stackA)<signed(stackB)) then
+ binaryOpResult(0) <= '1';
+ end if;
+ state <= State_BinaryOpResult;
+ when State_Lessthanorequal =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ binaryOpResult <= (others => '0');
+ if (signed(stackA)<=signed(stackB)) then
+ binaryOpResult(0) <= '1';
+ end if;
+ state <= State_BinaryOpResult;
+ when State_Load =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_Load2;
+
+ mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
+ out_mem_req <= '1';
+ else
+ insn <= insn;
+ end if;
+
+ when State_Dup =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ sp <= decSp;
+ stackB <= stackA;
+ mem_write <= stackB;
+ mem_addr <= incSp;
+ out_mem_req <= '1';
+ mem_we <= '1';
+ else
+ insn <= insn;
+ end if;
+ when State_DupStackB =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ sp <= decSp;
+ stackA <= stackB;
+ stackB <= stackA;
+ mem_write <= stackB;
+ mem_addr <= incSp;
+ out_mem_req <= '1';
+ mem_we <= '1';
+ else
+ insn <= insn;
+ end if;
+ when State_Store =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+ mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
+ mem_write <= stackB;
+ out_mem_req <= '1';
+ mem_we <= '1';
+ sp <= incIncSp;
+ state <= State_Resync;
+ else
+ insn <= insn;
+ end if;
+ when State_PopSP =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ mem_write <= stackB;
+ mem_addr <= incSp;
+ out_mem_req <= '1';
+ mem_we <= '1';
+ sp <= stackA(maxAddrBitIncIO downto minAddrBit);
+ state <= State_Resync;
+ else
+ insn <= insn;
+ end if;
+ when State_Nop =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+ when State_Not =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ stackA <= not stackA;
+ when State_Flip =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ for i in 0 to wordSize-1 loop
+ stackA(i) <= stackA(wordSize-1-i);
+ end loop;
+ when State_AddTop =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ stackA <= stackA + stackB;
+ when State_Shift =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ stackA(wordSize-1 downto 1) <= stackA(wordSize-2 downto 0);
+ stackA(0) <= '0';
+ when State_Pushspadd =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+ pc <= pc + 1;
+
+ stackA <= (others => '0');
+ stackA(maxAddrBitIncIO downto minAddrBit) <= stackA(maxAddrBitIncIO-minAddrBit downto 0)+sp;
+ when State_Neqbranch =>
+ -- branches are almost always taken as they form loops
+ begin_inst <= '1';
+ idim_flag <= '0';
+ sp <= incIncSp;
+ if (stackB/=0) then
+ pc <= stackA(maxAddrBitIncIO downto 0) + pc;
+ else
+ pc <= pc + 1;
+ end if;
+ -- need to fetch stack again.
+ state <= State_Resync;
+ when State_Mult =>
+ begin_inst <= '1';
+ idim_flag <= '0';
+
+ multA <= stackA;
+ multB <= stackB;
+ state <= State_Mult2;
+ when State_Break =>
+ report "Break instruction encountered" severity failure;
+ break <= '1';
+
+ when State_Loadb =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_Loadb2;
+
+ mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
+ out_mem_req <= '1';
+ else
+ insn <= insn;
+ end if;
+ when State_Storeb =>
+ if mem_busy='0' then
+ begin_inst <= '1';
+ idim_flag <= '0';
+ state <= State_Storeb2;
+
+ mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
+ out_mem_req <= '1';
+ else
+ insn <= insn;
+ end if;
+
+ when others =>
+-- sp <= (others => DontCareValue);
+ report "Illegal instruction" severity failure;
+ break <= '1';
+ end case;
+
+
+ when State_StoreSP2 =>
+ if mem_busy='0' then
+ mem_addr <= incSp;
+ out_mem_req <= '1';
+ state <= State_Popped;
+ end if;
+ when State_LoadSP2 =>
+ if mem_busy='0' then
+ state <= State_LoadSP3;
+ out_mem_req <= '1';
+ mem_addr <= sp+spOffset+1;
+ end if;
+ when State_LoadSP3 =>
+ if mem_busy='0' then
+ pc <= pc + 1;
+ state <= State_Execute;
+ stackB <= stackA;
+ stackA <= mem_read;
+ end if;
+ when State_AddSP2 =>
+ if mem_busy='0' then
+ pc <= pc + 1;
+ state <= State_Execute;
+ stackA <= stackA + mem_read;
+ end if;
+ when State_Load2 =>
+ if mem_busy='0' then
+ stackA <= mem_read;
+ pc <= pc + 1;
+ state <= State_Execute;
+ end if;
+ when State_Loadb2 =>
+ if mem_busy='0' then
+ stackA <= (others => '0');
+ stackA(7 downto 0) <= mem_read(((wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8);
+ pc <= pc + 1;
+ state <= State_Execute;
+ end if;
+ when State_Storeb2 =>
+ if mem_busy='0' then
+ mem_addr <= stackA(maxAddrBitIncIO downto minAddrBit);
+ mem_write <= mem_read;
+ mem_write(((wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8+7) downto (wordBytes-1-conv_integer(stackA(byteBits-1 downto 0)))*8) <= stackB(7 downto 0) ;
+ out_mem_req <= '1';
+ mem_we <= '1';
+ pc <= pc + 1;
+ sp <= incIncSp;
+ state <= State_Resync;
+ end if;
+ when State_Fetch =>
+ if mem_busy='0' then
+ if interrupt='1' and inInterrupt='0' and idim_flag='0' then
+ -- We got an interrupt
+ inInterrupt <= '1';
+
+ sp <= decSp;
+ out_mem_req <= '1';
+ mem_we <= '1';
+ mem_addr <= incSp;
+ mem_write <= stackB;
+ stackA <= (others => DontCareValue);
+ stackA(maxAddrBitIncIO downto 0) <= pc;
+ stackB <= stackA;
+
+ pc <= conv_std_logic_vector(32, maxAddrBitIncIo+1); -- interrupt address
+
+ report "ZPU jumped to interrupt!" severity note;
+ else
+ mem_addr <= pc(maxAddrBitIncIO downto minAddrBit);
+ out_mem_req <= '1';
+ state <= State_Decode;
+ end if;
+ end if;
+ when State_Mult2 =>
+ state <= State_Mult3;
+ when State_Mult3 =>
+ state <= State_Mult4;
+ when State_Mult4 =>
+ state <= State_Mult5;
+ when State_Mult5 =>
+ stackA <= multResult3;
+ state <= State_Mult6;
+ when State_Mult6 =>
+ if mem_busy='0' then
+ out_mem_req <= '1';
+ mem_addr <= incIncSp;
+ sp <= incSp;
+ state <= State_Popped;
+ end if;
+ when State_BinaryOpResult =>
+ if mem_busy='0' then
+ -- NB!!!! we know that the memory isn't busy at this point!!!!
+ out_mem_req <= '1';
+ mem_addr <= incIncSp;
+ sp <= incSp;
+ stackA <= binaryOpResult;
+ state <= State_Popped;
+ end if;
+ when State_Popped =>
+ if mem_busy='0' then
+ pc <= pc + 1;
+ stackB <= mem_read;
+ state <= State_Execute;
+ end if;
+ when others =>
+-- sp <= (others => DontCareValue);
+ report "Illegal state" severity failure;
+ break <= '1';
+ end case;
+ end if;
+ end process;
+
+
+
+end behave;
diff --git a/zpu/hdl/zy2000/zpupkg.vhd b/zpu/hdl/zy2000/zpupkg.vhd
new file mode 100644
index 0000000..1a01563
--- /dev/null
+++ b/zpu/hdl/zy2000/zpupkg.vhd
@@ -0,0 +1,168 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use IEEE.STD_LOGIC_ARITH.all;
+
+library work;
+use work.zpu_config.all;
+
+package zpupkg is
+
+ -- This bit is set for read/writes to IO
+ -- FIX!!! eventually this should be set to wordSize-1 so as to
+ -- to make the address of IO independent of amount of memory
+ -- reserved for CPU. Requires trivial tweaks in toolchain/runtime
+ -- libraries.
+
+ constant byteBits : integer := wordPower-3; -- # of bits in a word that addresses bytes
+ constant maxAddrBit : integer := maxAddrBitIncIO-1;
+ constant ioBit : integer := maxAddrBit+1;
+ constant wordSize : integer := 2**wordPower;
+ constant wordBytes : integer := wordSize/8;
+ constant minAddrBit : integer := byteBits;
+ -- configurable internal stack size. Probably going to be 16 after toolchain is done
+ constant stack_bits : integer := 5;
+ constant stack_size : integer := 2**stack_bits;
+
+ component dualport_ram is
+ port (clk : in std_logic;
+ memAWriteEnable : in std_logic;
+ memAAddr : in std_logic_vector(maxAddrBit downto minAddrBit);
+ memAWrite : in std_logic_vector(wordSize-1 downto 0);
+ memARead : out std_logic_vector(wordSize-1 downto 0);
+ memBWriteEnable : in std_logic;
+ memBAddr : in std_logic_vector(maxAddrBit downto minAddrBit);
+ memBWrite : in std_logic_vector(wordSize-1 downto 0);
+ memBRead : out std_logic_vector(wordSize-1 downto 0));
+ end component;
+
+ component dram is
+ port (clk : in std_logic;
+ areset : in std_logic;
+ mem_writeEnable : in std_logic;
+ mem_readEnable : in std_logic;
+ mem_addr : in std_logic_vector(maxAddrBit downto 0);
+ mem_write : in std_logic_vector(wordSize-1 downto 0);
+ mem_read : out std_logic_vector(wordSize-1 downto 0);
+ mem_busy : out std_logic;
+ mem_writeMask : in std_logic_vector(wordBytes-1 downto 0));
+ end component;
+
+
+ component trace is
+ port(
+ clk : in std_logic;
+ begin_inst : in std_logic;
+ pc : in std_logic_vector(maxAddrBitIncIO downto 0);
+ opcode : in std_logic_vector(7 downto 0);
+ sp : in std_logic_vector(maxAddrBitIncIO downto minAddrBit);
+ memA : in std_logic_vector(wordSize-1 downto 0);
+ memB : in std_logic_vector(wordSize-1 downto 0);
+ busy : in std_logic;
+ intSp : in std_logic_vector(stack_bits-1 downto 0)
+ );
+ end component;
+
+ component zpu_core is
+ port ( clk : in std_logic;
+ areset : in std_logic;
+ enable : in std_logic;
+ mem_req : out std_logic;
+ mem_we : out std_logic;
+ mem_ack : in std_logic;
+ mem_read : in std_logic_vector(wordSize-1 downto 0);
+ mem_write : out std_logic_vector(wordSize-1 downto 0);
+ out_mem_addr : out std_logic_vector(maxAddrBitIncIO downto 0);
+ mem_writeMask: out std_logic_vector(wordBytes-1 downto 0);
+ interrupt : in std_logic;
+ break : out std_logic;
+ zpu_status : out std_logic_vector(63 downto 0));
+ end component;
+
+
+
+ component timer is
+ port(
+ clk : in std_logic;
+ areset : in std_logic;
+ sample : in std_logic;
+ reset : in std_logic;
+ counter : out std_logic_vector(63 downto 0));
+ end component;
+
+ component zpuio is
+ port ( areset : in std_logic;
+ cpu_clk : in std_logic;
+ clk_status : in std_logic_vector(2 downto 0);
+ cpu_din : in std_logic_vector(15 downto 0);
+ cpu_a : in std_logic_vector(20 downto 0);
+ cpu_we : in std_logic_vector(1 downto 0);
+ cpu_re : in std_logic;
+ cpu_dout : inout std_logic_vector(15 downto 0));
+ end component;
+
+
+
+
+ -- opcode decode constants
+ constant OpCode_Im : std_logic_vector(7 downto 7) := "1";
+ constant OpCode_StoreSP : std_logic_vector(7 downto 5) := "010";
+ constant OpCode_LoadSP : std_logic_vector(7 downto 5) := "011";
+ constant OpCode_Emulate : std_logic_vector(7 downto 5) := "001";
+ constant OpCode_AddSP : std_logic_vector(7 downto 4) := "0001";
+ constant OpCode_Short : std_logic_vector(7 downto 4) := "0000";
+
+ constant OpCode_Break : std_logic_vector(3 downto 0) := "0000";
+ constant OpCode_Shiftleft: std_logic_vector(3 downto 0) := "0001";
+ constant OpCode_PushSP : std_logic_vector(3 downto 0) := "0010";
+ constant OpCode_PushInt : std_logic_vector(3 downto 0) := "0011";
+
+ constant OpCode_PopPC : std_logic_vector(3 downto 0) := "0100";
+ constant OpCode_Add : std_logic_vector(3 downto 0) := "0101";
+ constant OpCode_And : std_logic_vector(3 downto 0) := "0110";
+ constant OpCode_Or : std_logic_vector(3 downto 0) := "0111";
+
+ constant OpCode_Load : std_logic_vector(3 downto 0) := "1000";
+ constant OpCode_Not : std_logic_vector(3 downto 0) := "1001";
+ constant OpCode_Flip : std_logic_vector(3 downto 0) := "1010";
+ constant OpCode_Nop : std_logic_vector(3 downto 0) := "1011";
+
+ constant OpCode_Store : std_logic_vector(3 downto 0) := "1100";
+ constant OpCode_PopSP : std_logic_vector(3 downto 0) := "1101";
+ constant OpCode_Compare : std_logic_vector(3 downto 0) := "1110";
+ constant OpCode_PopInt : std_logic_vector(3 downto 0) := "1111";
+
+ constant OpCode_Lessthan : std_logic_vector(5 downto 0) := conv_std_logic_vector(36, 6);
+ constant OpCode_Lessthanorequal : std_logic_vector(5 downto 0) := conv_std_logic_vector(37, 6);
+ constant OpCode_Ulessthan : std_logic_vector(5 downto 0) := conv_std_logic_vector(38, 6);
+ constant OpCode_Ulessthanorequal : std_logic_vector(5 downto 0) := conv_std_logic_vector(39, 6);
+
+ constant OpCode_Swap : std_logic_vector(5 downto 0) := conv_std_logic_vector(40, 6);
+ constant OpCode_Mult : std_logic_vector(5 downto 0) := conv_std_logic_vector(41, 6);
+
+ constant OpCode_Lshiftright : std_logic_vector(5 downto 0) := conv_std_logic_vector(42, 6);
+ constant OpCode_Ashiftleft : std_logic_vector(5 downto 0) := conv_std_logic_vector(43, 6);
+ constant OpCode_Ashiftright : std_logic_vector(5 downto 0) := conv_std_logic_vector(44, 6);
+ constant OpCode_Call : std_logic_vector(5 downto 0) := conv_std_logic_vector(45, 6);
+
+ constant OpCode_Eq : std_logic_vector(5 downto 0) := conv_std_logic_vector(46, 6);
+ constant OpCode_Neq : std_logic_vector(5 downto 0) := conv_std_logic_vector(47, 6);
+
+ constant OpCode_Sub : std_logic_vector(5 downto 0) := conv_std_logic_vector(49, 6);
+ constant OpCode_Loadb : std_logic_vector(5 downto 0) := conv_std_logic_vector(51, 6);
+ constant OpCode_Storeb : std_logic_vector(5 downto 0) := conv_std_logic_vector(52, 6);
+
+ constant OpCode_Eqbranch : std_logic_vector(5 downto 0) := conv_std_logic_vector(55, 6);
+ constant OpCode_Neqbranch : std_logic_vector(5 downto 0) := conv_std_logic_vector(56, 6);
+ constant OpCode_Poppcrel : std_logic_vector(5 downto 0) := conv_std_logic_vector(57, 6);
+
+ constant OpCode_Pushspadd : std_logic_vector(5 downto 0) := conv_std_logic_vector(61, 6);
+ constant OpCode_Mult16x16 : std_logic_vector(5 downto 0) := conv_std_logic_vector(62, 6);
+ constant OpCode_Callpcrel : std_logic_vector(5 downto 0) := conv_std_logic_vector(63, 6);
+
+
+
+ constant OpCode_Size : integer := 8;
+
+
+
+end zpupkg;
OpenPOWER on IntegriCloud