diff options
Diffstat (limited to 'works/life/computer-organization-experiment/cpu.vhdl')
-rw-r--r-- | works/life/computer-organization-experiment/cpu.vhdl | 184 |
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; |