[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [oc] Open Core Forth Processor
----- Original Message -----
From: j-p.martin@l...
To: cores@o...
Date: Mon, 28 Oct 2002 03:21:13 -0100
Subject: Re: [oc] Open Core Forth Processor
>
>
>
>
> ----- Original Message -----
> From: "Don Golding" <dgolding@a... >
> To: <cores@o... >
> Date: Thu, 24 Feb 2000 09:39:23 -0000
> Subject: [oc] Open Core Forth Processor
>
> > -- Don Golding
> >
> > -- Angelus Research Corp.
> >
> > -- dgolding@a...
> >
> > -- Version 3
> >
> > -- Forth Processor Design
> >
> > --
> >
> > -- This code represents my current thoughts on designing a
> Forth
> > Processor in VHDL.
> >
> > -- Please review it and email me with your input on either
> Forth
> > design issues or
> >
> > -- VHDL design issues.
> >
> > --
> >
> > -- The goal is to build a generic Forth processor that can be
> > included in VHDL designs.
> >
> > -- If it could fit into a Xilinx 4005 or 4010 it would be
> ideal!
> >
> > -- Forth is really a virtual microprocessor implemented on
> other
> > various processors
> >
> > -- from 68HC11 to VAX machines and supercomputers. You will
> > currently find Forth used
> >
> > -- as the driver for PCI hardware in high end Macintosh's and
> Sun
> > Workstations.
> >
> > --
> >
> > -- This is an attempt to create a real Forth Processor on an
> FPGA
> > or ASIC using VHDL.
> >
> > -- Previous real Forth Microprocessors include: Harris
> RTX2000,
> > SHABOOM, F21,etc.
> >
> > -- The current attempts F21, etc. are trying to make 500mips
> > screamers.
> >
> > -- There are also people like Dr. Ting using the Schematic
> editor
> > to create Forth
> >
> > -- processors. I wonder how a Schematic designed Forth
> processor
> > will compare to a VHDL
> >
> > -- based design in speed and the number of gates used.
> >
> >
> >
> > -- I think a straight forward simple design will have
> considerable
> > applications
> >
> > -- when you need a processor included in your FPGA/ASIC
> design.
> >
> > -- FPGA operate at 200mhz, I don't know how fast this design
> will
> > be, but it's speed
> >
> > -- should be limited to the external RAM speed when memory
> access
> > is required.
> >
> > -- Internal register to register operations should be
> 50-200mhz
> > range.
> >
> > --
> >
> > -- The preliminary specifications are:
> >
> > --
> >
> > -- 16 bit data bus (to save space, could be 8 bit but it would
> take
> > more statements)
> >
> > -- 16 bit address bus
> >
> > -- by editing the code in the Entity declariations, you
> implement
> > 32, 64, ? designs
> >
> > --
> >
> > -- Return Stack levels=16
> >
> > -- Data Stack levels=16 (could be smaller, 4 items could be
> ok)
> >
> > -- Output port A is 8 lines
> >
> > -- Output port B is 8 lines
> >
> > -- Motorola SPI compatible port (SPI_In,SPI_Out,SPI_Ck,SS/)
> >
> > --
> >
> > -- By editing the code in the Entity declariations, you can
> add
> > serial ports, parallel
> >
> > -- ports, adc's or just about anything you can imagine.
> >
> > --
> >
> >
> >
> > library IEEE;
> >
> > use IEEE.std_logic_1164.all;
> >
> >
> >
> > entity Proc is
> >
> > port (
> >
> > DataBus: inout STD_LOGIC_VECTOR (15 downto 0);
> >
> > OutPortA: out STD_LOGIC_VECTOR (7 downto 0);
> >
> > OutPortB: out STD_LOGIC_VECTOR (7 downto 0);
> >
> > OutputA: out STD_LOGIC_LOGIC;
> >
> > OutputB: out STD_LOGIC_LOGIC;
> >
> > AddressBus: out STD_LOGIC_VECTOR (15 downto 0);
> >
> > Reset: in STD_LOGIC;
> >
> > SPI_In: in STD_LOGIC;
> >
> > SPI_Out: out STD_LOGIC;
> >
> > SS: in STD_LOGIC;
> >
> > SPI_Ck: in STD_LOGIC;
> >
> > clock: in STD_LOGIC;
> >
> > rd: out STD_LOGIC;
> >
> > );
> >
> > end Proc;
> >
> >
> >
> > architecture Proc_arch of Proc is
> >
> >
> >
> > --define op codes, only 25 so far...
> >
> > type op_code is(abort, depth, dup, pick, over, swap, >r,
> r>,
> > r@, drop,
> >
> > rot, equal, zero_equal, greater, greater_than,
> >
> > less_than, store, +store, fetch, plus, minus, times
> >
> > divide, branch, Obranch );
> >
> >
> >
> > -- check these for correct sizes
> >
> > type data_word is array(15 downto 0) of STD_ULOGIC; --16 bit
> wide
> >
> > type Return_stack is array (15 downto 0) of data_word; --16
> bits
> > wide, 16 deep
> >
> > type Data_stack is array (15 downto 0) of data_word; --16
> bits
> > wide, 16 deep
> >
> > type memory_size is range (15 downto 0); --64K max?
> >
> >
> >
> > constant stack_depth: integer:=16; --16 items max
> >
> >
> >
> > variable rp of stack_depth; -- return stack pointer
> >
> > variable dp of stack_depth; -- data stack pointer
> >
> > variable mp of memory_size; -- memory pointer
> >
> > variable temp1 of data_word; -- reg:Temp1 internal
> >
> > variable error of data_word; -- reg:Error code
> >
> > variable sucessful of bit; -- Flag:operation sucessful
> >
> >
> >
> > constant dstack_start:integer:=0;
> >
> > constant write:bit:=0;
> >
> > constant read:bit:=1;
> >
> > constant dstack_overflow:integer:=1; --Errorcodes are defined
> here
> >
> > constant dstack_underflow:integer:=2;
> >
> > constant rstack_overflow:integer:=3;
> >
> > constant rstack_underflow:integer:=4;
> >
> > constant invalid_instruction:integer:=5;
> >
> >
> >
> > --Forth stack manipulation primitives
> >
> > --I think we should implement a circular que here.
> >
> > --data_stack(dp) points to next available location, can use
> as
> > temp variable
> >
> > --before using push_dp_stack or pop_dp_stack procedures.
> >
> > --each stack are really 16 registers! Stack operations should
> be
> > real fast!
> >
> >
> >
> > procedure reset_proc is
> >
> >
> >
> > begin
> >
> >
> >
> > dp <= '0';
> >
> > rp <= '0';
> >
> > mp <= '0';
> >
> >
> >
> > end reset_proc;
> >
> >
> >
> > procedure push_dp_stack is
> >
> > -- dp points the the next stack element not the current one
> after
> > operation is completed.
> >
> >
> >
> > begin
> >
> >
> >
> > if dp = stack_depth then
> >
> > error<=dstack_overflow;
> >
> > reset_proc;
> >
> > else dp <= dp+1;
> >
> > end if
> >
> > end push_dp_stack;
> >
> >
> >
> > procedure pop_dp_stack is
> >
> > -- dp points the the next stack element not the current one
> after
> > operation is completed.
> >
> > begin
> >
> >
> >
> > if dp = dstack_start then
> >
> > error<=dstack_underflow;
> >
> > reset_proc;
> >
> > else dp <= dp-1;
> >
> > end if
> >
> > end pop_dp_stack;
> >
> >
> >
> > procedure push_rp_stack is
> >
> > -- dp points the the next stack element not the current one
> after
> > operation is completed.
> >
> >
> >
> > begin
> >
> >
> >
> > if rp = 16 then
> >
> > error<=rstack_overflow;
> >
> > reset_proc;
> >
> > else rp <= rp+1;
> >
> > end if
> >
> > end push_rp_stack;
> >
> >
> >
> > procedure pop_rp_stack is
> >
> > -- dp points the the next stack element not the current one
> after
> > operation is completed.
> >
> >
> >
> > begin
> >
> >
> >
> > if rp = 0 then
> >
> > error<=rstack_underflow;
> >
> > reset_proc;
> >
> > else rp <= rp-1;
> >
> > end if
> >
> > end pop_rp_stack;
> >
> >
> >
> > procedure proc_code(sucessful) is --is the parameter list ok?
> >
> >
> >
> > begin
> >
> >
> >
> > sucessful<=true;
> >
> > case data_bus is
> >
> >
> >
> > when abort => --reset processor
> >
> >
> >
> > reset_proc;
> >
> >
> >
> > when depth => --put the depth of the stack on the top
> >
> >
> >
> > data_stack(dp) <= dp;
> >
> > up_data_stack;
> >
> >
> >
> > when dup => --duplicate the top item on data stack
> >
> >
> >
> > data_stack(dp)<=data_stack(dp+1);
> >
> > up_data_stack;
> >
> >
> >
> > when pick => --get on data stack pointed to by TOS
> >
> >
> >
> > data_stack(dp)<=data_stack(data_stack(dp+1);
> >
> > up_data_stack;
> >
> >
> >
> > when over => --duplicate the second number on data stack
> >
> >
> >
> > data_stack(dp) <= data_stack(data_stack(dp+2);
> >
> > up_data_stack;
> >
> >
> >
> > when swap => --swap top two numbers on data stack
> >
> >
> >
> > return_stack(rp) <= data_stack(dp+1);
> >
> > data_stack(dp+1) <= data_stack(dp+2);
> >
> > data_stack(dp+2) <= return_stack(rp);
> >
> >
> >
> > when >r => --move top of data stack to return stack
> >
> >
> >
> > return_stack(rp) <= data_stack(dp+1);
> >
> > pop_data_stack;
> >
> > push_return_stack;
> >
> >
> >
> > when r> => --move top of return stack to data stack
> >
> >
> >
> > data_stack(dp+1) <= return_stack(rp+1);
> >
> > pop_return_stack;
> >
> > push_data_stack;
> >
> >
> >
> > when r@ => --move top of return stack to data stack
> >
> >
> >
> > data_stack(dp) <= return_stack(rp+1);
> >
> > push_data_stack;
> >
> >
> >
> > when drop => --drop top number from data stack
> >
> >
> >
> > pop_dp_stack;
> >
> >
> >
> > when rot => --rotate 3rd numbr to 1st on data stack
> >
> >
> >
> > return_stack(rp) <= data_stack(dp+1);
> >
> > data_stack(dp+1) <= data_stack(dp+3);
> >
> >
> >
> > when equal => -- if tos and second are equal then true
> >
> >
> >
> > if data_stack(dp+1)=data_stack(dp+2) then
> >
> > pop_data_stack;
> >
> > data_stack(dp+1)<='1';
> >
> > end if;
> >
> >
> >
> > when zero_equal => -- if tos=0 then tos=true
> >
> >
> >
> > if data_stack(dp+1)='0' then
> >
> > data_stack(dp+1)<='1';
> >
> > end if;
> >
> >
> >
> >
> >
> > when greater_than => -- if tos is greater then the sec
> then
> > tos=true
> >
> >
> >
> > if data_stack(dp+1)>data_stack(dp+2) then
> >
> > pop_data_stack;
> >
> > data_stack(dp+1)<='1';
> >
> > end if;
> >
> >
> >
> > when less_than => -- if tos is less than the second item
> then
> > tos=true
> >
> >
> >
> > if data_stack(dp+1)<data_stack(dp+2) then
> >
> > pop_data_stack;
> >
> > data_stack(dp+1)<='1';
> >
> > end if;
> >
> >
> >
> > when store => -- store 16 bit value to memory
> >
> >
> >
> > rd<=write;
> >
> > addressBus <= data_stack(dp+1);
> >
> > dataBus <= data_stack(dp+2)
> >
> > rd<=read; -- probably need a delay here
> >
> > pop_data_stack;
> >
> > pop_data_stack;
> >
> >
> >
> > when +store => -- increment 16 bit value in memory
> >
> >
> >
> > rd<=read;
> >
> > addressBus <= data_stack(dp+1);
> >
> > data_bus <= data_bus+data_stack(dp+1);
> >
> > rd<=write;
> >
> > pop_data_stack;
> >
> > pop_data_stack;
> >
> > rd<=read; -- probably need a delay here
> >
> >
> >
> > when fetch => -- get 16 bit value from memory
> >
> > rd<=read;
> >
> > data_stack(dp) <= dataBus;
> >
> > push_data_stack;
> >
> >
> >
> > when plus => --add two 16 bit numbers
> >
> > data_stack(dp+1) <= data_stack(dp+2) + data_stack(dp+1);
> >
> > pop_data_stack;
> >
> >
> >
> > when minus => --subtract two 16 bit numbers
> >
> > data_stack(dp+2) <= data_stack(dp+1) - data_stack(dp+2);
> >
> > pop_data_stack;
> >
> >
> >
> > when times => --multiply two 16 bit numbers
> >
> > data_stack(dp+2) <= data_stack(dp+1) * data_stack(dp+2);
> >
> > pop_data_stack;
> >
> >
> >
> > when divide => --divide two 16 bit numbers
> >
> > data_stack(dp+2) <= data_stack(dp+1) / data_stack(dp+2);
> >
> > pop_data_stack;
> >
> >
> >
> > when branch => --branch unconditionally
> >
> > mp=mp+1;
> >
> > rd<=read;
> >
> > mp=DataBus;
> >
> >
> >
> > when Obranch => --branch if tos = 0
> >
> > if data_stack(dp+1)='0' then
> >
> > mp=mp+1;
> >
> > rd<=read;
> >
> > mp=DataBus;
> >
> > end if;
> >
> >
> >
> > when others => -- not an opcode
> >
> > sucessful<=false;
> >
> > end case;
> >
> > end proc_code;
> >
> >
> >
> > synch: process(clock)
> >
> >
> >
> > begin
> >
> > if clock'event and clock='1' then
> >
> > clock<= not clock; -- need a delay here?
> >
> > end if;
> >
> > end process;
> >
> >
> >
> > code: process(clock,reset,mp,rp)
> >
> > begin
> >
> >
> >
> > if reset ='0' then
> >
> > reset_proc;
> >
> >
> >
> > else --get and process instruction
> >
> >
> >
> > rd<=read; --set read/write line to read
> >
> > addressBus<=mp; --output address
> >
> >
> >
> > proc_code;
> >
> >
> >
> > --Forth's inner interpreter(next)
> >
> > if sucessful=true then -- it was a valid instruction
> >
> > mp <= mp+1;
> >
> > sucessful<=false;
> >
> > else -- it wasn't a valid instruction
> >
> > error<=invalid_instruction;
> >
> > reset_proc;
> >
> > --
> >
> > end if;
> >
> >
> >
> > end if;
> >
> >
> >
> > end process;
> >
> > end Proc_arch;
> >
> >
> >
> >
> >
> >
> >
> >
> >
>
--
To unsubscribe from cores mailing list please visit http://www.opencores.org/mailinglists.shtml