aboutsummaryrefslogtreecommitdiff
path: root/works/life/computer-organization-experiment/cpu.vhdl
diff options
context:
space:
mode:
Diffstat (limited to 'works/life/computer-organization-experiment/cpu.vhdl')
-rw-r--r--works/life/computer-organization-experiment/cpu.vhdl212
1 files changed, 146 insertions, 66 deletions
diff --git a/works/life/computer-organization-experiment/cpu.vhdl b/works/life/computer-organization-experiment/cpu.vhdl
index f1a7d65..aca35cf 100644
--- a/works/life/computer-organization-experiment/cpu.vhdl
+++ b/works/life/computer-organization-experiment/cpu.vhdl
@@ -4,6 +4,7 @@ use ieee.std_logic_1164.all;
package cru is
subtype word is std_logic_vector(31 downto 0);
constant clock_time : time := 10 ns;
+ constant ram_clock_time: time := 2.5 ns;
end package;
library ieee;
@@ -35,13 +36,36 @@ end architecture;
library ieee;
use ieee.std_logic_1164.all;
+use work.cru.all;
+
+entity reg_file_clock is
+ port(CLK: out std_logic);
+end entity;
+
+architecture Behavioral of reg_file_clock is
+ signal V: std_logic := '1';
+begin
+ l: process is
+ begin
+ CLK <= V;
+ wait for 1 ns;
+ loop
+ V <= not V;
+ wait for 1 ps;
+ CLK <= V;
+ wait for clock_time;
+ end loop;
+ end process;
+end architecture;
+
+library ieee;
+use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
use work.cru.all;
entity register_file is
port (
- CLK: in std_logic;
ENABLE: in std_logic;
R1, R2, W: in std_logic_vector(4 downto 0);
WD: in std_logic_vector(31 downto 0);
@@ -52,7 +76,10 @@ end entity;
architecture Behavioral of register_file is
type reg_file_type is array (0 to 31) of std_logic_vector(31 downto 0);
signal reg_file: reg_file_type := (others => (others => '0'));
+ signal CLK : std_logic;
begin
+ clock: entity work.reg_file_clock
+ port map (CLK);
process (CLK)
begin
if rising_edge(CLK) then
@@ -91,13 +118,11 @@ begin
else std_logic_vector(signed(A) sll to_integer(unsigned(B))) when ALUC ?= B"0011"
else std_logic_vector(signed(A) srl to_integer(unsigned(B))) when ALUC ?= B"0111"
else std_logic_vector(signed(A) sra to_integer(unsigned(B))) when ALUC ?= B"1111";
- Z <= S ?= X"00000000";
+ Z <= S ?= X"00000000" after 10 ps;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
-use ieee.numeric_std.all;
-use ieee.std_logic_unsigned.all;
use work.cru.all;
entity clock is
@@ -113,16 +138,41 @@ end architecture;
library ieee;
use ieee.std_logic_1164.all;
+use work.cru.all;
+
+entity ram_clock is
+ port(CLK: out std_logic);
+end entity;
+
+architecture Behavioral of ram_clock is
+ signal V: std_logic := '0';
+begin
+ l: process is
+ begin
+ CLK <= V;
+ wait for 500 ps;
+ loop
+ V <= not V;
+ wait for 1 ps;
+ CLK <= V;
+ wait for ram_clock_time;
+ end loop;
+ end process;
+end architecture;
+
+library ieee;
+use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-use ieee.std_logic_unsigned.all;
use work.cru.all;
entity ram is
- port(CLK: in std_logic;
- R: out word;
- W: in word;
- ADDR: in word;
- ENABLE: in std_logic
+ port(
+ R_DATA: out word;
+ W_DATA: in word;
+ R_ADDR: in word;
+ W_ADDR: in word;
+ READ: in std_logic;
+ WRITE: in std_logic
);
end entity;
@@ -130,7 +180,7 @@ architecture Behavioral of ram is
type memory_type is array (0 to 16#30#) of word;
signal memory: memory_type := (
X"3c010000",
- X"34240020",
+ X"34240080",
X"20050004",
X"0c000018",
X"ac820000",
@@ -168,14 +218,17 @@ architecture Behavioral of ram is
others => (others => '0')
);
signal V: std_logic := '0';
+ signal CLK: std_logic;
begin
+ clock: entity work.ram_clock
+ port map (CLK);
b: process(CLK) is
begin
- if rising_edge(CLK) then
- R <= memory(to_integer(unsigned(ADDR)) / 4);
+ if rising_edge(CLK) and READ = '1' then
+ R_DATA <= memory(to_integer(unsigned(R_ADDR)) / 4);
end if;
- if falling_edge(CLK) and ENABLE = '1' then
- memory(to_integer(unsigned(ADDR)) / 4) <= W;
+ if falling_edge(CLK) and WRITE = '1' then
+ memory(to_integer(unsigned(W_ADDR)) / 4) <= W_DATA;
end if;
end process;
end architecture;
@@ -198,17 +251,18 @@ architecture Behavioral of cpu is
signal ins: word;
- signal enable_mem: std_logic;
- signal write_mem: std_logic := '0';
- signal addr: word := X"00000000";
- signal mem_w: word;
- signal mem_r: word;
+ signal mem_r_addr: word := X"00000000";
+ signal mem_w_addr: word := X"00000000";
+ signal mem_r_data: word;
+ signal mem_w_data: word := X"00000000";
+ signal mem_read: std_logic := '0';
+ signal mem_write: std_logic := '0';
signal WRITE_REG: std_logic := '0';
signal R1: std_logic_vector(4 downto 0) := B"00000";
signal R2: std_logic_vector(4 downto 0) := B"00000";
signal W: std_logic_vector(4 downto 0) := B"00000";
- signal WD: std_logic_vector(31 downto 0);
+ signal WD: std_logic_vector(31 downto 0) := X"00000000";
signal RD1: std_logic_vector(31 downto 0) := X"00000000";
signal RD2: std_logic_vector(31 downto 0) := X"00000000";
@@ -227,7 +281,6 @@ begin
);
reg: entity work.register_file
port map(
- CLK => CLK,
ENABLE => WRITE_REG,
R1 => R1,
R2 => R2,
@@ -247,84 +300,112 @@ begin
ram: entity work.ram
port map (
- CLK => CLK,
- R => mem_r,
- W => mem_w,
- ADDR => addr,
- ENABLE => write_mem
+ R_DATA => mem_r_data,
+ W_DATA => mem_w_data,
+ R_ADDR => mem_r_addr,
+ W_ADDR => mem_w_addr,
+ READ => mem_read,
+ WRITE => mem_write
);
logic: process is
begin
wait until rising_edge(CLK);
- wait for 100 ps;
- addr <= pc;
+ wait for 250 ps;
+
+ mem_read <= '1';
+ mem_r_addr <= pc;
pc_to_write <= pc + 4;
- wait for 1 ns;
- ins <= mem_r;
+ wait for 500 ps;
+
+ ins <= mem_r_data;
+
+ mem_write <= '0';
WRITE_REG <= '0';
+
+ wait for 100 ps;
- if ins(31 downto 27) = B"00001" then -- j / jal
+ if ins(31 downto 27) = B"00001" then -- j / jal, not read reg
if ins(26) = '1' then -- jal
W <= B"11111";
- WD <= pc;
+ WD <= pc + 4;
WRITE_REG <= '1';
end if;
- pc_to_write <= (25 downto 0 => ins(25 downto 0), others => '0');
+
+ ALUC <= B"0011";
+ A <= (25 downto 0 => ins(25 downto 0), others => '0');
+ B <= X"00000002";
+ wait for 100 ps;
+ pc_to_write <= S;
elsif ins(31 downto 26) = B"000000" then
if ins(5) = '1' then
R1 <= ins(25 downto 21);
R2 <= ins(20 downto 16);
- ALUC <= ins(3 downto 0);
- wait for 100 ps;
+ wait for 500 ps;
+ ALUC <= ins(3 downto 0);
A <= RD1;
B <= RD2;
+
+ wait for 100 ps;
+
W <= ins(15 downto 11);
WRITE_REG <= '1';
WD <= S;
elsif ins(3) = '0' then
R1 <= ins(20 downto 16);
+
+ wait for 500 ps;
+
ALUC(3 downto 2) <= ins(1 downto 0);
ALUC(1 downto 0) <= B"11";
+ A <= RD1;
+ B <= (4 downto 0 => ins(10 downto 6), others => '0');
wait for 100 ps;
- A <= RD1;
- B <= (4 downto 0 => ins(10 downto 6), others => '0');
W <= ins(15 downto 11);
WRITE_REG <= '1';
WD <= S;
else
R1 <= ins(25 downto 21);
- WRITE_REG <= '0';
- wait for 100 ps;
+ wait for 500 ps;
pc_to_write <= RD1;
end if;
else
if ins(31) = '1' then
- enable_mem <= '1';
R1 <= ins(25 downto 21);
- ALUC <= B"0000";
+ R2 <= ins(20 downto 16);
- wait for 100 ps;
+ wait for 500 ps;
+ ALUC <= B"0000";
A <= RD1;
B <= (15 downto 0 => ins(15 downto 0), others => '0' );
+
+ wait for 100 ps;
+
if ins(29) = '1' then
- W <= ins(20 downto 16);
- write_mem <= '0';
- else
R2 <= ins(20 downto 16);
- write_mem <= '1';
+ mem_write <= '1';
+ mem_w_addr <= S;
+ mem_w_data <= RD2;
+
+ else
+ W <= ins(20 downto 16);
+ mem_read <= '1';
+ mem_r_addr <= S;
+
+ wait for ram_clock_time * 2;
- wait for 100 ps;
+ WD <= mem_r_data;
+ WRITE_REG <= '1';
end if;
elsif ins(29 downto 26) = B"1111" then
WRITE_REG <= '1';
@@ -332,43 +413,42 @@ begin
WD(31 downto 16) <= ins(15 downto 0);
elsif ins(29) = '1' then
R1 <= ins(25 downto 21);
- ALUC <= ins(29 downto 26);
- wait for 100 ps;
+ wait for 500 ps;
+ ALUC <= ins(29 downto 26);
A <= RD1;
B(15 downto 0) <= ins(15 downto 0);
- B(31 downto 16) <= X"0000";
+ if ins(15) = '0' then
+ B(31 downto 16) <= X"0000";
+ else
+ B(31 downto 16) <= X"FFFF";
+ end if;
+
+ wait for 100 ps;
+
W <= ins(20 downto 16);
WRITE_REG <= '1';
WD <= S;
else
R1 <= ins(25 downto 21);
R2 <= ins(20 downto 16);
- ALUC <= B"0010";
- wait for 100 ps;
+ wait for 500 ps;
+ ALUC <= B"0010";
A <= RD1;
B <= RD2;
- if Z = '1' then
- pc_to_write <= pc_to_write + to_integer(unsigned(ins(15 downto 0)) * 4);
+
+ wait for 100 ps;
+
+ if Z = '1' xor ins(26) = '1' then
+ pc_to_write <= pc_to_write + to_integer(signed(ins(15 downto 0)) * 4);
end if;
WRITE_REG <= '0';
end if;
end if;
- if enable_mem then
- if write_mem then
- WRITE_REG <= '0';
- mem_w <= RD2;
- else
- WRITE_REG <= '1';
- WD <= mem_r;
- end if;
- else
- write_mem <= '0';
- end if;
end process;
end architecture;