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 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

powered by: WebSVN 2.1.0

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