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 17 to Rev 18
- ↔ Reverse comparison
Rev 17 → Rev 18
/trunk/testbench/memory_tb.vhd
11,13 → 11,12
|
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 |
Address: in std_logic_vector(15 downto 0); --memory address (in bytes) |
WriteWord: in std_logic; --if set, will write a full 16-bit word instead of a byte. Address must be aligned to 16-bit address. (bottom bit must be 0) |
WriteEnable: in std_logic; |
Clock: in std_logic; |
DataIn: in std_logic_vector(15 downto 0); |
DataOut: out std_logic_vector(15 downto 0); |
Reset: in std_logic |
DataOut: out std_logic_vector(15 downto 0) |
); |
end component; |
|
24,10 → 23,9
|
--Inputs |
signal Address: std_logic_vector(15 downto 0) := (others => '0'); |
signal Write: std_logic := '0'; |
signal UseTopBits: std_logic := '0'; |
signal WriteWord: std_logic := '0'; |
signal WriteEnable: 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); |
40,12 → 38,11
-- Instantiate the Unit Under Test (UUT) |
uut: memory PORT MAP ( |
Address => Address, |
Write => Write, |
UseTopBits => UseTopBits, |
WriteWord => WriteWord, |
WriteEnable => WriteEnable, |
Clock => Clock, |
DataIn => DataIn, |
DataOut => DataOut, |
Reset => Reset |
DataOut => DataOut |
); |
|
-- Clock process definitions |
62,75 → 59,61
stim_proc: process |
variable err_cnt: integer :=0; |
begin |
-- hold reset state for 100 ns. |
Reset <= '1'; |
wait for 100 ns; |
wait for 50 ns; |
|
wait for clock_period*10; |
|
--case 1 |
Reset <= '0'; |
Write <= '0'; |
Address <= x"0000"; |
WriteWord <= '1'; |
WriteEnable <='1'; |
DataIn <= x"1234"; |
wait for 10 ns; |
Address <= "0000000000001000"; |
DataIn <= "1000000000001000"; |
Write <= '1'; |
UseTopBits <= '1'; |
WriteWord <= '0'; |
WriteEnable <= '0'; |
wait for 10 ns; |
Write <= '0'; |
assert (DataOut = x"1234") report "Basic storage failure" severity error; |
|
Address <= x"0022"; |
WriteWord <= '1'; |
WriteEnable <= '1'; |
DataIn <= x"5215"; |
wait for 10 ns; |
assert (DataOut="1000000000001000") report "Storage error case 1" severity error; |
|
--case 2 |
Address <= "0000000000001100"; |
DataIn <= "1000000000001100"; |
Write <= '1'; |
UseTopBits <= '1'; |
assert (DataOut = x"1234") report "no-change block ram failure" severity error; |
WriteWord <= '0'; |
WriteEnable <= '0'; |
Address <= x"0000"; |
wait for 10 ns; |
Write <= '0'; |
assert( DataOut = x"1234") report "Memory retention failure" severity error; |
Address <= x"0022"; |
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; |
assert( DataOut = x"5215") report "memory timing is too slow" severity error; |
|
--case 4 |
Address <= x"0000"; |
Write <= '1'; |
DataIn <= x"FFCC"; |
Address <= x"0010"; |
WriteWord <= '1'; |
WriteEnable <= '1'; |
DataIn <= x"1234"; |
wait for 10 ns; |
UseTopBits <= '0'; |
DataIn <= x"F0C0"; |
WriteWord <= '0'; |
WriteEnable <= '0'; |
Address <= x"0011"; |
wait for 10 ns; |
UseTopBits <='1'; |
Write <= '0'; |
assert (DataOut = x"0012") report "unaligned 8-bit memory read is wrong" severity error; |
WriteWord <='0'; |
WriteEnable <= '1'; |
DataIn <= x"0056"; |
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"; |
WriteEnable <= '0'; |
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'; |
assert (DataOut = x"0056") report "unaligned 8 bit memory write and then read is wrong" severity error; |
Address <= x"0010"; |
wait for 10 ns; |
assert(DataOut=x"1234") report "practical fail 2" severity error; |
assert (DataOut = x"5634") report "aligned memory read after unaligned write is wrong" severity error; |
WriteEnable <= '1'; |
DataIn <= x"0078"; |
wait for 10 ns; |
WriteEnable <= '0'; |
wait for 10 ns; |
assert (DataOut = x"5678") report "aligned 8-bit memory write is wrong" severity error; |
|
|
|
assert false |
report "Testbench of memory completed successfully!" |
severity note; |
/trunk/testbench/fetch_tb.vhd
60,7 → 60,7
variable err_cnt: integer :=0; |
begin |
-- hold reset state for 20 ns. |
wait for 20 ns; |
wait for 10 ns; |
|
--wait for clock_period*10; |
Enable<= '1'; |
/trunk/src/memory.vhd
1,63 → 1,109
--RAM module |
--4096*8 bit file |
--simultaneous write/read support |
--16 bit or 8 bit data bus |
--16 bit address bus |
--On Reset, will load a "default" RAM image |
--Memory management component |
--By having this separate, it should be fairly easy to add RAMs or ROMs later |
--This basically lets the CPU not have to worry about how memory "Really" works |
--currently just one RAM. 1024 byte blockram.vhd mapped as 0 - 1023 |
|
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 |
Address: in std_logic_vector(15 downto 0); --memory address (in bytes) |
WriteWord: in std_logic; --if set, will write a full 16-bit word instead of a byte. Address must be aligned to 16-bit address. (bottom bit must be 0) |
WriteEnable: in std_logic; |
Clock: in std_logic; |
DataIn: in std_logic_vector(15 downto 0); |
DataOut: out std_logic_vector(15 downto 0); |
Reset: in std_logic |
DataOut: out std_logic_vector(15 downto 0) |
-- Reset: in std_logic |
|
--RAM/ROM interface (RAMA is built in to here |
--RAMBDataIn: out std_logic_vector(15 downto 0); |
--RAMBDataOut: in std_logic_vector(15 downto 0); |
--RAMBAddress: out std_logic_vector(15 downto 0); |
--RAMBWriteEnable: out std_logic_vector(1 downto 0); |
); |
end memory; |
|
architecture Behavioral of memory is |
constant BUSSIZE : integer := 8; |
type memorytype is array(0 to integer((2**BUSSIZE))) of std_logic_vector(7 downto 0); |
signal mem: memorytype; |
|
component blockram |
port( |
Address: in std_logic_vector(7 downto 0); --memory address |
WriteEnable: in std_logic_vector(1 downto 0); --write or read |
Enable: in std_logic; |
Clock: in std_logic; |
DataIn: in std_logic_vector(15 downto 0); |
DataOut: out std_logic_vector(15 downto 0) |
); |
end component; |
|
constant R1START: integer := 0; |
constant R1END: integer := 1023; |
signal addr: std_logic_vector(15 downto 0) := (others => '0'); |
signal R1addr: std_logic_vector(7 downto 0); |
signal we: std_logic_vector(1 downto 0); |
signal datawrite: std_logic_vector(15 downto 0); |
signal dataread: std_logic_vector(15 downto 0); |
--signal en: std_logic; |
signal R1we: std_logic_vector(1 downto 0); |
signal R1en: std_logic; |
signal R1in: std_logic_vector(15 downto 0); |
signal R1out: std_logic_vector(15 downto 0); |
begin |
|
writemem: process(Reset,Write, Address, UseTopBits, Clock) |
variable addr: integer range 0 to (2**BUSSIZE)-1 := 0; |
R1: blockram port map (R1addr, R1we, R1en, Clock, R1in, R1out); |
addrwe: process(Address, WriteWord, WriteEnable, DataIn) |
begin |
addr := conv_integer(Address(BUSSIZE-1 downto 0)); |
if(rising_edge(Clock)) then |
if(Reset ='1') then |
--mem <= (others => "00000000"); |
elsif( Write='1') then |
mem(addr) <= DataIn(7 downto 0); |
if(UseTopBits='1') then |
mem(addr+1) <= DataIn(15 downto 8); |
addr <= Address(15 downto 1) & '0'; |
if WriteEnable='1' then |
if WriteWord='1' then |
we <= "11"; |
datawrite <= DataIn; |
else |
if Address(0)='0' then |
we <= "01"; |
datawrite <= x"00" & DataIn(7 downto 0); --not really necessary |
else |
we <= "10"; |
datawrite <= DataIn(7 downto 0) & x"00"; |
end if; |
end if; |
else |
we <= "00"; |
end if; |
end process; |
readmem: process(Reset,Address,Write,Clock) |
variable addr: integer range 0 to (2**BUSSIZE)-1 := 0; |
variable addr2: integer range 0 to (2**BUSSIZE)-1 := 0; -- for second part |
|
assignram: process (we, datawrite, addr, r1out) |
variable tmp: integer; |
variable found: boolean := false; |
begin |
addr := conv_integer(Address(BUSSIZE-1 downto 0)); |
addr2 := conv_integer(Address(BUSSIZE-1 downto 0)); |
if(Reset='1') then |
DataOut <= (others => '0'); |
elsif(Write='0') then |
DataOut <= mem(addr+1) & mem(addr); |
else |
DataOut <= (others => '0'); |
tmp := to_integer(unsigned(addr)); |
if tmp >= R1START and tmp <= R1END then |
--map all to R1 |
found := true; |
R1en <= '1'; |
R1we <= we; |
R1in <= datawrite; |
dataread <= R1out; |
R1addr <= addr(8 downto 1); |
else |
R1en <= '0'; |
R1we <= "00"; |
R1in <= x"0000"; |
R1addr <= x"00"; |
dataread <= x"0000"; |
end if; |
end process; |
|
readdata: process(Address, dataread) |
begin |
if Address(0) = '0' then |
DataOut <= dataread; |
else |
DataOut <= x"00" & dataread(15 downto 8); |
end if; |
end process; |
|
end Behavioral; |