URL
https://opencores.org/ocsvn/tinycpu/tinycpu/trunk
Subversion Repositories tinycpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 3 to Rev 4
- ↔ Reverse comparison
Rev 3 → Rev 4
/tinycpu/trunk/testbench/memory_tb.vhd
0,0 → 1,146
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.numeric_std.ALL; |
|
ENTITY memory_tb IS |
END memory_tb; |
|
ARCHITECTURE behavior OF memory_tb IS |
|
-- Component Declaration for the Unit Under Test (UUT) |
|
component memory |
port( |
Address: in std_logic_vector(15 downto 0); --memory address |
Write: in std_logic; --write or read |
UseTopBits: in std_logic; --if 1, top 8 bits of data is ignored and not written to memory |
Clock: in std_logic; |
DataIn: in std_logic_vector(15 downto 0); |
DataOut: out std_logic_vector(15 downto 0); |
Reset: in std_logic |
); |
end component; |
|
|
--Inputs |
signal Address: std_logic_vector(15 downto 0) := (others => '0'); |
signal Write: std_logic := '0'; |
signal UseTopBits: std_logic := '0'; |
signal DataIn: std_logic_vector(15 downto 0) := (others => '0'); |
signal Reset: std_logic := '0'; |
|
--Outputs |
signal DataOut: std_logic_vector(15 downto 0); |
|
signal Clock: std_logic; |
constant clock_period : time := 10 ns; |
|
BEGIN |
|
-- Instantiate the Unit Under Test (UUT) |
uut: memory PORT MAP ( |
Address => Address, |
Write => Write, |
UseTopBits => UseTopBits, |
Clock => Clock, |
DataIn => DataIn, |
DataOut => DataOut, |
Reset => Reset |
); |
|
-- 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 100 ns. |
Reset <= '1'; |
wait for 100 ns; |
|
wait for clock_period*10; |
|
--case 1 |
Reset <= '0'; |
Write <= '0'; |
wait for 10 ns; |
Address <= "0000000000001000"; |
DataIn <= "1000000000001000"; |
Write <= '1'; |
UseTopBits <= '1'; |
wait for 10 ns; |
Write <= '0'; |
wait for 10 ns; |
assert (DataOut="1000000000001000") report "Storage error case 1" severity error; |
|
--case 2 |
Address <= "0000000000001100"; |
DataIn <= "1000000000001100"; |
Write <= '1'; |
UseTopBits <= '1'; |
wait for 10 ns; |
Write <= '0'; |
wait for 10 ns; |
assert (DataOut="1000000000001100") report "memory selection error case 2" severity error; |
|
-- case 3 |
Address <= "0000000000001000"; |
wait for 10 ns; |
assert (DataOut="1000000000001000") report "memory retention error case 3" severity error; |
|
--case 4 |
Address <= x"0000"; |
Write <= '1'; |
DataIn <= x"FFCC"; |
wait for 10 ns; |
UseTopBits <= '0'; |
DataIn <= x"F0C0"; |
wait for 10 ns; |
UseTopBits <='1'; |
Write <= '0'; |
wait for 10 ns; |
assert (DataOut=x"FFC0") report "ignore top bits error case 4" severity error; |
|
--case 5 |
Address <= x"FFFF"; |
Write <= '0'; |
wait for 10 ns; |
assert (DataOut=x"FFC0") report "memory out of range error case 5" severity error; |
|
--case 6 (fetch and store practical) |
Address <= x"0012"; |
wait for 10 ns; |
Address <= x"0000"; |
wait for 5 ns; |
assert(DataOut=x"FFC0") report "practical fail 1" severity error; |
Address <= x"00FF"; |
Write <= '1'; |
DataIn <= x"1234"; |
wait for 5 ns; |
Write <= '0'; |
wait for 10 ns; |
assert(DataOut=x"1234") report "practical fail 2" severity error; |
|
|
|
assert false |
report "Testbench of memory completed successfully!" |
severity note; |
|
wait; |
|
-- insert stimulus here |
|
wait; |
end process; |
|
|
END; |
/tinycpu/trunk/src/memory.vhd
0,0 → 1,59
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
use ieee.std_logic_arith.all; |
use IEEE.NUMERIC_STD.ALL; |
use ieee.std_logic_unsigned.all; |
|
entity memory is |
port( |
Address: in std_logic_vector(15 downto 0); --memory address |
Write: in std_logic; --write or read |
UseTopBits: in std_logic; --if 1, top 8 bits of data is ignored and not written to memory |
Clock: in std_logic; |
DataIn: in std_logic_vector(15 downto 0); |
DataOut: out std_logic_vector(15 downto 0); |
Reset: in std_logic |
); |
end memory; |
|
architecture Behavioral of memory is |
constant SIZE : integer := 4096; |
type memorytype is array(0 to (size-1)) of std_logic_vector(7 downto 0); |
signal mem: memorytype; |
|
begin |
|
writemem: process(Reset,Write, Address, UseTopBits, Clock) |
variable addr: integer; |
begin |
addr := conv_integer(Address); |
if(addr>size-1) then |
addr:=0; |
end if; |
if(Reset ='1' and rising_edge(Clock)) then |
mem <= (others => "00000000"); |
elsif(Write='1' and Reset='0') then |
if(rising_edge(clock)) then |
mem(conv_integer(addr)) <= DataIn(7 downto 0); |
if(UseTopBits='1') then |
mem(conv_integer(addr)+1) <= DataIn(15 downto 8); |
end if; |
end if; |
end if; |
end process; |
readmem: process(Reset,Address,Write,Clock) |
variable addr: integer; |
begin |
addr := conv_integer(Address); |
if(addr>size-1) then |
addr:=0; |
end if; |
if(Reset='1') then |
DataOut <= (others => '0'); |
elsif(Write='0') then |
DataOut <= mem(conv_integer(addr)+1) & mem(conv_integer(addr)); |
else |
DataOut <= (others => '0'); |
end if; |
end process; |
end Behavioral; |
/tinycpu/trunk/docs/design.md.txt
7,8 → 7,8
5. 1 instruction per clock cycle |
|
Register list: |
r0-r2 general purpose registers |
ip instruction pointer register (represented as r3) |
r0-r6 general purpose registers |
ip instruction pointer register (represented as r7) |
cs, ds, es, ss segment registers (code segment, data segment, extra segment, stack segment) |
tr truth register for conditionals |
|
16,15 → 16,14
|
first byte: |
first 4 bits: actual instruction |
next 2 bits: (target) register |
last 2 bits: conditional |
next 3 bits: (target) register |
last 1 bit: conditional |
|
second byte: |
first 1 bit: use segment registers |
next 1 bit: exchange target and source register |
next 2 bits: other register |
next 1 bit: dereference first register for memory (respecting the "exchange" bit) |
next 3 bits: extra opcode information(optional) or last two bits is third register (such as for ADD it could be target=source+third_register) |
second byte: |
first 1 bit: second portion of condition (if not immediate) (1 for only if false) |
next 1 bit: unused |
next 3 bits: other register |
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 |
|
31,6 → 30,48
For opcodes requiring 3 registers but without room, the target opcode is assume to be the second operation. Such as for AND, target=source AND target |
|
short list of instructions: (not final, still planning) |
immediates: |
1. move reg, immediate |
2. move [reg], immediate |
3. push and move reg, immediate (or call immediate) |
4. push immediate |
|
groups: (limited to 2 registers and no immediates. each group has 8 opcodes) |
group 1: |
move(store) [reg],reg |
move(load) reg,[reg] |
out reg1,reg2 (output to port reg1 value reg2) |
in reg1,reg2 (input from port reg2 and store in reg1) |
|
|
group 2: |
and reg1,reg2 (reg1=reg1 and reg2) |
or reg, reg |
xor reg,reg |
not reg1,reg2 (reg1=not reg2) |
left shift reg,reg |
right shift reg,reg |
rotate right reg,reg |
rotate left reg,reg |
|
group 3: compares |
is greater than reg1,reg2 (TR=reg1>reg2) |
is greater or equal to reg,reg |
is less than reg,reg |
is less than or equal to reg,reg |
is equal to reg,reg |
is not equal to reg,reg |
|
|
|
|
3 register instructions: |
1. add reg1, reg2, reg3 (reg1=reg2+reg3) |
2. sub reg1, reg2, reg3 |
|
|
|
|
0 -nop (doesn't do a thing) |
1 -move immediate (only uses first byte) |
2 -move |
47,10 → 88,9
|
|
conditionals |
00 -- always |
01 -- if true |
10 -- if false |
11 -- reserved/not used |
0 -- always |
1 -- only if true |
for only if false, there should basically be another compare or if applicable an always afterwards |
|
push |
pop |