URL
https://opencores.org/ocsvn/tinycpu/tinycpu/trunk
Subversion Repositories tinycpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/tinycpu
- from Rev 15 to Rev 16
- ↔ Reverse comparison
Rev 15 → Rev 16
/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; |
/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; |
/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) |