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

Subversion Repositories tinycpu

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 15 to Rev 16
    Reverse comparison

Rev 15 → Rev 16

/tinycpu/trunk/testbench/carryover_tb.vhd
0,0 → 1,110
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
use work.tinycpu.all;
 
ENTITY carryover_tb IS
END carryover_tb;
ARCHITECTURE behavior OF carryover_tb IS
-- Component Declaration for the Unit Under Test (UUT)
component carryover is
port(
EnableCarry: in std_logic;
DataIn: in std_logic_vector(7 downto 0);
SegmentIn: in std_logic_vector(7 downto 0);
Addend: in std_logic_vector(7 downto 0); --How much to increase DataIn by (as a signed number). Believe it or not, that's the actual word for what we need.
DataOut: out std_logic_vector(7 downto 0);
SegmentOut: out std_logic_vector(7 downto 0)
-- Debug: out std_logic_vector(8 downto 0)
);
end component;
 
--Inputs
signal EnableCarry: std_logic := '0';
signal DataIn: std_logic_vector(7 downto 0) := "00000000";
signal Addend: std_logic_vector(7 downto 0) := "00000000";
signal SegmentIn: std_logic_vector(7 downto 0) := "00000000";
--Outputs
signal DataOut: std_logic_vector(7 downto 0);
signal SegmentOut: std_logic_vector(7 downto 0);
-- signal Debug: std_logic_vector(8 downto 0);
 
signal Clock: std_logic;
constant clock_period : time := 10 ns;
BEGIN
 
-- Instantiate the Unit Under Test (UUT)
uut: carryover PORT MAP (
EnableCarry => EnableCarry,
DataIn => DataIn,
Addend => Addend,
SegmentIn => SegmentIn,
DataOut => DataOut,
SegmentOut => SegmentOut
-- Debug => Debug
);
 
-- Clock process definitions
clock_process :process
begin
Clock <= '0';
wait for clock_period/2;
Clock <= '1';
wait for clock_period/2;
end process;
 
-- Stimulus process
stim_proc: process
variable err_cnt: integer :=0;
begin
-- hold reset state for 20 ns.
wait for 20 ns;
 
--wait for clock_period*10;
EnableCarry <= '1';
-- case 1
DataIn <= x"10";
Addend <= x"02";
SegmentIn <= x"00";
wait for 10 ns;
assert (SegmentOut=x"00" and DataOut = x"12") report "Addition Carryover when not appropriate" severity error;
--case 2
DataIn <= x"10";
Addend <= x"FE"; -- -2
SegmentIn <= x"00";
wait for 10 ns;
assert (SegmentOut=x"00" and DataOut = x"0E") report "Subtraction Carryover when not appropriate" severity error;
DataIn <= x"10";
Addend <= x"EE"; -- -18 (-0x12)
SegmentIn <= x"00";
wait for 10 ns;
assert (SegmentOut=x"FF" and DataOut = x"FE") report "Subtraction Carryover Error" severity error;
DataIn <= x"FE";
Addend <= x"04";
SegmentIn <= x"00";
wait for 10 ns;
assert (SegmentOut=x"01" and DataOut = x"02") report "Addition Carryover Error" severity error;
 
 
-- summary of testbench
assert false
report "Testbench of carryover completed successfully!"
severity note;
 
wait;
 
-- insert stimulus here
 
wait;
end process;
 
 
END;
/tinycpu/trunk/src/carryover.vhd
0,0 → 1,36
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.tinycpu.all;
 
entity carryover is
port(
EnableCarry: in std_logic; --When disabled, SegmentIn goes to SegmentOut
DataIn: in std_logic_vector(7 downto 0);
SegmentIn: in std_logic_vector(7 downto 0);
Addend: in std_logic_vector(7 downto 0); --How much to increase DataIn by (as a signed number). Believe it or not, that's the actual word for what we need.
DataOut: out std_logic_vector(7 downto 0);
SegmentOut: out std_logic_vector(7 downto 0)
-- Debug: out std_logic_vector(8 downto 0)
);
end carryover;
 
architecture Behavioral of carryover is
signal temp: std_logic_vector(8 downto 0);
begin
--treat as unsigned because it doesn't actually matter for addition and just make carry and borrow correct
process(DataIn, SegmentIn,Addend, EnableCarry)
begin
temp <= std_logic_vector(unsigned('0' & DataIn) + unsigned( Addend));
-- if ('1' and ((not Addend(7)) and DataIn(7) and temp(8)))='1' then
if (EnableCarry and ((not Addend(7)) and DataIn(7) and not temp(8)))='1' then
SegmentOut <= std_logic_vector(unsigned(SegmentIn)+1);
elsif (EnableCarry and (Addend(7) and not DataIn(7) and temp(8)))='1' then
SegmentOut <= std_logic_vector(unsigned(SegmentIn)-1);
else
SegmentOut <= SegmentIn;
end if;
end process;
--Debug <= Temp;
DataOut <= temp(7 downto 0);
end Behavioral;
/tinycpu/trunk/docs/design.md.txt
6,6 → 6,16
4. use a small amount of "rich" instructions to do powerful things
5. 1 instruction per clock cycle
 
Relative moves:
In order to provide uesfulness to the segment-carryover feature, there are a few options for moving a "relative" amount to a register, including IP and SP
A relative move differs in most of the opcodes in that the relative factor is treated as a signed value.
so for instance, a
mov r0,50
mov_relative r0, -10
 
in the ned, r0 will end up being 40. Although this feature won't see much use in general registers, IP and SP are special because of the option of using the
segment-carryover feature. This means that SP and IP, while being 8-bit registers, can function very similar to a 16-bit register, enabling full usage of the available address space.
 
Register list:
r0-r5 general purpose registers
sp stack pointer (represented as r6)
23,7 → 33,7
second byte:
first 1 bit: second portion of condition (if not immediate) (1 for only if false)
next 1 bit: use extra segment
next 3 bits: other register
next 3 bits: other register. If not 3rd register, top bit specifies which register bank, others unused
last 3 bits: extra opcode information or third register. such as for ADD it could be target=source+third_register
 
...or second byte is immediate value
36,8 → 46,9
2. move [reg], immediate
3. push and move reg, immediate (or call immediate)
4. push immediate
5. jmp immediate
5. mov (relative) immediate
 
 
groups: (limited to 2 registers and no immediates. each group has 8 opcodes)
group 1:
move(store) [reg],reg
89,12 → 100,15
reset processor (will completely reset the processor to starting state, but not RAM or anything else)
 
group 6:
set register bank 0
set register bank 1
set default register bank to 0 (can be condensed to 1 opcode)
set default register bank to 1
push extended reg, reg
pop extended reg,reg
enable carryover seg
disable CS carryover seg
mov relative reg, reg
exchange reg, reg
 
 
3 register instructions:
1. add reg1, reg2, reg3 (reg1=reg2+reg3)
2. sub reg1, reg2, reg3
143,7 → 157,12
ES is used when the ExtraSegment bit is set for either push/pop or normal memory references
CS is only used for fetching instructions
 
Segment carryover:
In order to overcome the limitations of only having a 256 byte segment, there is a workaround option to "pretend" that IP is a 16 bit register.
When CS carryover is enabled, when IP rollover from 255 to 0 or whatever, CS will be incremented. This makes it so that if you start at address 0:0.
you can continue as far as needed into the address space without having to do ugly far jumps at each of the borders.
 
 
States needed:
0. reset
1. decode current instruction (All without memory capable within 1 clock cycle)

powered by: WebSVN 2.1.0

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