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.vhdl184
1 files changed, 184 insertions, 0 deletions
diff --git a/works/life/computer-organization-experiment/cpu.vhdl b/works/life/computer-organization-experiment/cpu.vhdl
new file mode 100644
index 0000000..fb4b45f
--- /dev/null
+++ b/works/life/computer-organization-experiment/cpu.vhdl
@@ -0,0 +1,184 @@
+library ieee;
+
+subtype word of std_logic_vector(31 downto 0);
+constant clock_time : time := 10 ns;
+
+entity register is
+ port (
+ CLK: in std_logic; -- Rising edge -> Read; Falling edge -> Write.
+ W: in word; -- The data to write.
+ ENABLE: in std_logic; -- If 1 then at falling edge of clock, W will be written.
+ ZERO: in std_logic; -- If 1 then at rising edge of clock, 0 will be output to R.
+ R: out word; -- The data to read.
+ )
+end entity;
+
+architecture Behavioral of register is
+ signal V: word;
+begin
+ process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if ZERO = '1' then
+ R <= (others => '0');
+ else
+ R <= V;
+ end if;
+ end if;
+ if falling_edge(CLK) and ENABLE = '1' then
+ V <= W;
+ end if;
+ end process;
+end architecture;
+
+entity register_file is
+ port (
+ CLK: in std_logic;
+ ENABLE: in std_logic;
+ ZERO1, ZERO2: in std_logic;
+ R1, R2, W: in std_logic_vector(4 downto 0);
+ WD: in std_logic_vector(31 downto 0);
+ RD1, RD2: out std_logic_vector(31 downto 0);
+ )
+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 => '0');
+begin
+ process (CLK)
+ begin
+ if rising_edge(CLK) then
+ if ZERO1 = '1' then
+ RD1 <= (others => '0');
+ else
+ RD1 <= reg_file(to_integer(R1));
+ end if;
+ if ZERO2 = '1' then
+ RD2 <= (others => '0');
+ else
+ RD2 <= reg_file(to_integer(R2));
+ end if;
+ end if;
+ if falling_edge(CLK) and ENABLE = '1' then
+ reg_file(to_integer(W)) <= WD;
+ end if;
+ end;
+end architecture;
+
+entity alu is
+ port (
+ A, B: in std_logic_vector(31 downto 0);
+ ALUC: in std_logic_vector(3 downto 0);
+ S: out std_logic_vector(31 downto 0);
+ Z: out std_logic);
+end entity;
+
+architecture Behavioral of alu is
+begin
+ S <= A + B when ALUC(2 downto 0) ?= B"000"
+ else A - B when ALUC(2 downto 0) ?= B"010"
+ else A and B when ALUC(2 downto 0) ?= B"100"
+ else A or B when ALUC(2 downto 0) ?= B"101"
+ else A xor B when ALUC(2 downto 0) ?= B"110"
+ else std_logic_vector(signed(A) sll 16) and H"FFFF0000" when ALUC(2 downto 0) ?= B"110"
+ 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 ?= H"00000000";
+end architecture;
+
+entity clock is
+ port(CLK: out std_logic)
+end entity;
+
+architecture Behavioral of clock is
+begin
+ CLK <= not CLK after clock_time;
+end architecture;
+
+type memory_type = array (0 to 1023) of std_logic_vector(31 downto 0);
+
+entity cpu is
+ port (memory: in memory_type)
+end entity;
+
+architecture Behavioral of cpu is
+ signal pc: std_logic_vector(31 downto 0);
+ signal pc_to_write: std_logic_vector(31 downto 0);
+
+ signal CLK: in std_logic;
+ signal WRITE_REG: in std_logic;
+ signal R1, R2, W: in std_logic_vector(4 downto 0);
+ signal WD: in std_logic_vector(31 downto 0);
+ signal RD1, RD2: out std_logic_vector(31 downto 0);
+
+ signal A, B: in std_logic_vector(31 downto 0);
+ signal ALUC: in std_logic_vector(3 downto 0);
+ signal S: out std_logic_vector(31 downto 0);
+ signal Z: out std_logic);
+begin
+ pc_reg: register
+ port map (
+ CLK => CLK,
+ ENABLE => '1',
+ ZERO => '0',
+ W => pc_to_write,
+ R => pc
+ );
+ reg: register_file
+ port map(
+ CLK => CLK,
+ ENABLE => WRITE_REG,
+ R1 => R1,
+ R2 => R2,
+ W => W,
+ WD => WD,
+ RD1 => RD1,
+ RD2 => RD2
+ );
+ alu: alu
+ port map(
+ A => A,
+ B => B,
+ ALUC => ALUC,
+ S => S,
+ Z => Z
+ );
+ logic: process is
+ variable ins: std_logic_vector(31 downto 0);
+ begin
+ ins <= memory(to_integer(pc));
+ pc_to_write <= pc + H"00000001";
+
+ if 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);
+ A <= RD1;
+ B <= RD2;
+ W <= ins(15 downto 11);
+ WRITE_REG <= '1';
+ WD <= S;
+ else if ins(3) = '0' then
+ R1 <= ins(20 downto 16);
+ ALUC(3 downto 2) <= ins(1 downto 0);
+ ALUC(1 downto 0) <= B"11";
+ A <= RD1;
+ B(31 downto 5) <= (others => '0');
+ B(4 downto 0) <= ins(10 downto 6);
+ W <= ins(15 downto 11);
+ WRITE_REG <= '1';
+ WD <= S;
+ else
+ R1 <= ins(25 downto 16)
+ WRITE_REG <= '0';
+ pc_to_write <= RD1;
+ end if;
+ else
+ -- TODO: Implement this.
+ end if;
+
+ end process;
+end architecture;