URL
https://opencores.org/ocsvn/tinycpu/tinycpu/trunk
Subversion Repositories tinycpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 4 to Rev 5
- ↔ Reverse comparison
Rev 4 → Rev 5
/tinycpu/trunk/testbench/registerfile_tb.vhd
11,24 → 11,30
|
component registerfile |
port( |
Write:in std_logic_vector(7 downto 0); --what should be put into the write register |
SelRead1:in std_logic_vector(2 downto 0); --select which register to read |
SelRead2: in std_logic_vector(2 downto 0); --select second register to read |
SelWrite:in std_logic_vector(2 downto 0); --select which register to write |
UseWrite:in std_logic; --if the register should actually be written to |
Write1:in std_logic_vector(7 downto 0); --what should be put into the write register |
Write2: in std_logic_vector(7 downto 0); |
SelRead1:in std_logic_vector(3 downto 0); --select which register to read |
SelRead2: in std_logic_vector(3 downto 0); --select second register to read |
SelWrite1:in std_logic_vector(3 downto 0); --select which register to write |
SelWrite2:in std_logic_vector(3 downto 0); |
UseWrite1:in std_logic; --if the register should actually be written to |
UseWrite2: in std_logic; |
Clock:in std_logic; |
Read1:out std_logic_vector(7 downto 0); --register to be read output |
Read2:out std_logic_vector(7 downto 0) --register to be read on second output |
); |
); |
end component; |
|
|
--Inputs |
signal Write : std_logic_vector(7 downto 0) := (others => '0'); |
signal SelRead1: std_logic_vector(2 downto 0) := (others => '0'); |
signal SelRead2: std_logic_vector(2 downto 0) := (others => '0'); |
signal SelWrite: std_logic_vector(2 downto 0) := (others => '0'); |
signal UseWrite: std_logic := '0'; |
signal Write1 : std_logic_vector(7 downto 0) := (others => '0'); |
signal Write2 : std_logic_vector(7 downto 0) := (others => '0'); |
signal SelRead1: std_logic_vector(3 downto 0) := (others => '0'); |
signal SelRead2: std_logic_vector(3 downto 0) := (others => '0'); |
signal SelWrite1: std_logic_vector(3 downto 0) := (others => '0'); |
signal SelWrite2: std_logic_vector(3 downto 0) := (others => '0'); |
signal UseWrite1: std_logic := '0'; |
signal UseWrite2: std_logic := '0'; |
|
--Outputs |
signal Read1 : std_logic_vector(7 downto 0); |
41,11 → 47,14
|
-- Instantiate the Unit Under Test (UUT) |
uut: registerfile PORT MAP ( |
Write => Write, |
Write1 => Write1, |
Write2 => Write2, |
SelRead1 => SelRead1, |
SelRead2 => SelRead2, |
SelWrite => SelWrite, |
UseWrite => UseWrite, |
SelWrite1 => SelWrite1, |
SelWrite2 => SelWrite2, |
UseWrite1 => UseWrite1, |
UseWrite2 => UseWrite2, |
Clock => Clock, |
Read1 => Read1, |
Read2 => Read2 |
71,51 → 80,66
wait for clock_period*10; |
|
-- case 1 |
SelWrite <= "000"; |
Write <= "11110000"; |
UseWrite <= '1'; |
SelWrite1 <= "0000"; |
Write1 <= "11110000"; |
UseWrite1 <= '1'; |
wait for 10 ns; |
SelRead1 <= "000"; |
UseWrite <= '0'; |
SelRead1 <= "0000"; |
UseWrite1 <= '0'; |
wait for 10 ns; |
assert (Read1="11110000") report "Storage error case 1" severity error; |
if (Read1/="11110000") then |
err_cnt:=err_cnt+1; |
end if; |
|
-- case 2 |
SelWrite <= "100"; |
Write <= "11110001"; |
UseWrite <= '1'; |
SelWrite1 <= "1000"; |
Write1 <= "11110001"; |
UseWrite1 <= '1'; |
wait for 10 ns; |
SelRead1 <= "100"; |
UseWrite <= '0'; |
SelRead1 <= "1000"; |
UseWrite1 <= '0'; |
wait for 10 ns; |
assert (Read1="11110001") report "Storage selector error case 2" severity error; |
if (Read1/="11110001") then |
err_cnt:=err_cnt+1; |
end if; |
|
-- case 3 |
SelRead1 <= "000"; |
UseWrite <= '0'; |
SelRead1 <= "0000"; |
UseWrite1 <= '0'; |
wait for 10 ns; |
assert (Read1="11110000") report "Storage selector(remembering) error case 3" severity error; |
if (Read1/="11110000") then |
err_cnt:=err_cnt+1; |
end if; |
|
--case 4 |
SelWrite1 <= x"0"; |
SelWrite2 <= x"1"; |
Write1 <= x"12"; |
Write2 <= x"34"; |
UseWrite1 <= '1'; |
UseWrite2 <= '1'; |
wait for 10 ns; |
UseWrite1 <= '0'; |
UseWrite2 <= '0'; |
SelRead1 <= x"0"; |
SelRead2 <= x"1"; |
wait for 10 ns; |
assert (Read1=x"12" and Read2=x"34") report "simultaneous write and read error case 4" severity error; |
|
SelWrite1 <= x"0"; |
SelWrite2 <= x"0"; |
Write1 <= x"ff"; |
Write2 <= x"00"; |
UseWrite1 <= '1'; |
UseWrite2 <= '1'; |
wait for 10 ns; |
SelRead1 <= x"0"; |
UseWrite1 <= '0'; |
UseWrite2 <= '0'; |
wait for 10 ns; |
assert (Read1=x"ff") report "dual-write error handling error case 5" severity error; |
|
|
|
-- summary of testbench |
if (err_cnt=0) then |
assert false |
report "Testbench of registerfile completed successfully!" |
severity note; |
else |
assert true |
report "Something wrong, try again" |
severity error; |
end if; |
|
assert false |
report "Testbench of registerfile completed successfully!" |
severity note; |
|
wait; |
|
-- insert stimulus here |
/tinycpu/trunk/src/registerfile.vhd
5,11 → 5,14
|
entity registerfile is |
port( |
Write:in std_logic_vector(7 downto 0); --what should be put into the write register |
SelRead1:in std_logic_vector(2 downto 0); --select which register to read |
SelRead2: in std_logic_vector(2 downto 0); --select second register to read |
SelWrite:in std_logic_vector(2 downto 0); --select which register to write |
UseWrite:in std_logic; --if the register should actually be written to |
Write1:in std_logic_vector(7 downto 0); --what should be put into the write register |
Write2: in std_logic_vector(7 downto 0); |
SelRead1:in std_logic_vector(3 downto 0); --select which register to read |
SelRead2: in std_logic_vector(3 downto 0); --select second register to read |
SelWrite1:in std_logic_vector(3 downto 0); --select which register to write |
SelWrite2:in std_logic_vector(3 downto 0); |
UseWrite1:in std_logic; --if the register should actually be written to |
UseWrite2: in std_logic; |
Clock:in std_logic; |
Read1:out std_logic_vector(7 downto 0); --register to be read output |
Read2:out std_logic_vector(7 downto 0) --register to be read on second output |
17,16 → 20,21
end registerfile; |
|
architecture Behavioral of registerfile is |
type registerstype is array(0 to 7) of std_logic_vector(7 downto 0); |
type registerstype is array(0 to 15) of std_logic_vector(7 downto 0); |
signal registers: registerstype; |
begin |
writereg: process(Write, SelWrite, UseWrite, Clock) |
writereg: process(Write1, Write2, SelWrite1, SelWrite2, UseWrite1, UseWrite2, Clock) |
begin |
if(UseWrite='1') then |
if(UseWrite1='1') then |
if(rising_edge(clock)) then |
registers(conv_integer(SelWrite)) <= Write; |
registers(conv_integer(SelWrite1)) <= Write1; |
end if; |
end if; |
if(UseWrite2='1') then |
if(rising_edge(clock) and conv_integer(SelWrite1)/=conv_integer(SelWrite2)) then |
registers(conv_integer(SelWrite2)) <= Write2; |
end if; |
end if; |
end process; |
Read1 <= registers(conv_integer(SelRead1)); |
Read2 <= registers(conv_integer(SelRead2)); |
/tinycpu/trunk/docs/design.md.txt
7,7 → 7,8
5. 1 instruction per clock cycle |
|
Register list: |
r0-r6 general purpose registers |
r0-r5 general purpose registers |
sp stack pointer (represented as r6) |
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 |
21,7 → 22,7
|
second byte: |
first 1 bit: second portion of condition (if not immediate) (1 for only if false) |
next 1 bit: unused |
next 1 bit: use extra segment |
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 |
|
35,6 → 36,7
2. move [reg], immediate |
3. push and move reg, immediate (or call immediate) |
4. push immediate |
5. jmp immediate |
|
groups: (limited to 2 registers and no immediates. each group has 8 opcodes) |
group 1: |
42,8 → 44,11
move(load) reg,[reg] |
out reg1,reg2 (output to port reg1 value reg2) |
in reg1,reg2 (input from port reg2 and store in reg1) |
pop reg |
push reg |
move segmentreg,reg |
move reg,segmentreg |
|
|
group 2: |
and reg1,reg2 (reg1=reg1 and reg2) |
or reg, reg |
61,17 → 66,39
is less than or equal to reg,reg |
is equal to reg,reg |
is not equal to reg,reg |
equals 0 reg |
not equals 0 reg |
|
group 4: |
push segmentreg |
pop segmentreg |
push and move reg, reg (or call reg) |
exchange reg,reg |
exchange reg,seg |
clear TR |
Set TR |
|
group 5: |
increment reg |
decrement reg |
far jmp reg1, reg2 (CS=reg1 and IP=reg2) |
far call reg1,reg2 |
far jmp [reg] (first byte is CS, second byte is IP) |
push extended segmentreg, reg (equivalent to push seg; push reg) |
pop extended segmentreg, reg (equivalent to pop reg; pop seg) |
reset processor (will completely reset the processor to starting state, but not RAM or anything else) |
|
|
|
3 register instructions: |
1. add reg1, reg2, reg3 (reg1=reg2+reg3) |
2. sub reg1, reg2, reg3 |
|
|
opcodes used: 12 of 16. 4 more opcodes available. Decide what to do with the room later. |
|
|
|
0 -nop (doesn't do a thing) |
1 -move immediate (only uses first byte) |
2 -move |
97,3 → 124,16
move |
add |
sub |
|
limitations that shouldn't be passed with instructions |
* Doing 2 memory references |
* pushing a memory reference (equates to 2 memory references) |
|
Note it is possible however to read and write 16bits at one time to the memory to consecutive addresses. |
|
|
segments: |
DS is used in all "normal" memory references |
SS is used in all push and pop instructions |
ES is used when the ExtraSegment bit is set for either push/pop or normal memory references |
CS is only used for fetching instructions |