diff options
Diffstat (limited to 'works/life/computer-organization-experiment/cpu.vhdl')
-rw-r--r-- | works/life/computer-organization-experiment/cpu.vhdl | 476 |
1 files changed, 0 insertions, 476 deletions
diff --git a/works/life/computer-organization-experiment/cpu.vhdl b/works/life/computer-organization-experiment/cpu.vhdl deleted file mode 100644 index 7ca6d9e..0000000 --- a/works/life/computer-organization-experiment/cpu.vhdl +++ /dev/null @@ -1,476 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; - -package cru is - subtype word is std_logic_vector(31 downto 0); - constant clock_time : time := 10 ns; -end package; - -library ieee; -use ieee.std_logic_1164.all; -use work.cru.all; - -entity generic_clock is - generic(delay, interval: time); - port(CLK: out std_logic); -end entity; - -architecture Behavioral of generic_clock is - signal V : std_logic := '1'; -begin - l: process is - begin - CLK <= '0'; - wait for delay; - loop - CLK <= V; - V <= not V; - wait for interval; - end loop; - end process; -end architecture; - -library ieee; -use ieee.std_logic_1164.all; -use work.cru.all; - -entity reg is - port ( - CLK: in std_logic; -- Rising edge -> Read; Falling edge -> Write. - WRITE: in std_logic; -- If 1 then at falling edge of clock, W will be written. - W_DATA: in word; -- The data to write. - R_DATA: out word -- The data to read. - ); -end entity; - -architecture Behavioral of reg is - signal V: word := X"00000000"; -begin - process(CLK) - begin - if rising_edge(CLK) then - R_DATA <= V; - end if; - if falling_edge(CLK) and WRITE = '1' then - V <= W_DATA; - end if; - end process; -end architecture; - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; -use work.cru.all; - -entity register_file is - port ( - CLK: in std_logic; - WRITE: 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 word; - signal reg_file: reg_file_type := (others => X"00000000"); -begin - process (CLK) - begin - if rising_edge(CLK) then - RD1 <= reg_file(to_integer(unsigned(R1))); - RD2 <= reg_file(to_integer(unsigned(R2))); - end if; - if falling_edge(CLK) and WRITE = '1' then - reg_file(to_integer(unsigned(W))) <= WD; - end if; - 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 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 X"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"1011" - else std_logic_vector(signed(A) sra to_integer(unsigned(B))) when ALUC ?= B"1111"; - Z <= S ?= X"00000000" after 10 ps; -end architecture; - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; -use work.cru.all; - -entity ram is - port( - CLK: in std_logic; - R_DATA: out word; - W_DATA: in word; - ADDR: in word; - READ: in std_logic; - WRITE: in std_logic - ); -end entity; - -architecture Behavioral of ram is - type memory_type is array (0 to 16#30#) of word; - signal memory: memory_type := ( -/* - X"3c010000", - X"34240080", - X"20050004", - X"0c000018", - X"ac820000", - X"8c890000", - X"01244022", - X"20050003", - X"20a5ffff", - X"34a8ffff", - X"39085555", - X"2009ffff", - X"312affff", - X"01493025", - X"01494026", - X"01463824", - X"10a00001", - X"08000008", - X"2005ffff", - X"000543c0", - X"00084400", - X"00084403", - X"000843c2", - X"08000017", - X"00004020", - X"8c890000", - X"20840004", - X"01094020", - X"20a5ffff", - X"14a0fffb", - X"00081000", - X"03e00008", - X"000000A3", - X"00000027", - X"00000079", - X"00000115", -*/ - X"3C010000", - X"3421004C", - X"8C240000", - X"20210004", - X"8C250000", - X"20210004", - X"0C000009", - X"AC230000", - X"08000008", - X"20020010", - X"00001820", - X"30A60001", - X"10060001", - X"00641820", - X"00042040", - X"00052842", - X"2042FFFF", - X"1440FFF9", - X"03e00008", - X"0000C9AE", - X"0000F6E5", - others => (others => '0') - ); -begin - l: process(CLK) is - begin - if rising_edge(CLK) and READ = '1' then - r_data <= memory(to_integer(unsigned(ADDR)) / 4); - end if; - if falling_edge(CLK) and WRITE = '1' then - memory(to_integer(unsigned(ADDR)) / 4) <= w_data; - end if; - 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 cpu is -end entity; - -architecture Behavioral of cpu is - signal pc_clk: std_logic := '0'; - signal reg_clk: std_logic := '0'; - signal mem_clk: std_logic := '0'; - - signal pc: word := X"00000000"; - signal pc_to_write: word; - - signal ins: word; - - signal mem_addr: word; - signal mem_r_data: word; - signal mem_w_data: word; - 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) := X"00000000"; - signal RD1: std_logic_vector(31 downto 0) := X"00000000"; - signal RD2: std_logic_vector(31 downto 0) := X"00000000"; - - signal A: std_logic_vector(31 downto 0) := X"00000000"; - signal B: std_logic_vector(31 downto 0) := X"00000000"; - signal ALUC: std_logic_vector(3 downto 0) := B"0000"; - signal S: std_logic_vector(31 downto 0); - signal Z: std_logic; -begin - pc_clock: entity work.generic_clock - generic map (delay => 1 ps, interval => clock_time) - port map (CLK => pc_clk); - - mem_clock: entity work.generic_clock - generic map (delay => 1 ns, interval => clock_time / 2) - port map (CLK => mem_clk); - - reg_clock: entity work.generic_clock - generic map (delay => 2 ns, interval => clock_time) - port map (CLK => reg_clk); - - pc_reg: entity work.reg - port map ( - CLK => pc_clk, - WRITE => '1', - R_DATA => pc, - W_DATA => pc_to_write - ); - - reg_file: entity work.register_file - port map( - CLK => reg_clk, - WRITE => WRITE_REG, - R1 => R1, - R2 => R2, - W => W, - WD => WD, - RD1 => RD1, - RD2 => RD2 - ); - - alu: entity work.alu - port map( - A => A, - B => B, - ALUC => ALUC, - S => S, - Z => Z - ); - - ram: entity work.ram - port map ( - CLK => mem_clk, - r_data => mem_r_data, - w_data => mem_w_data, - addr => mem_addr, - READ => mem_read, - WRITE => mem_write - ); - - logic: process is - begin - wait until rising_edge(pc_clk); - - wait for 100 ps; - - mem_read <= '1'; - mem_addr <= pc; - pc_to_write <= pc + 4; - - wait for 1 ns; - - ins <= mem_r_data; - - wait for 100 ps; - - if ins(31 downto 27) = B"00001" then -- j / jal, not read reg - R1 <= (others => '0'); - R2 <= (others => '0'); - elsif ins(31 downto 26) = B"000000" then - if ins(5) = '1' then - R1 <= ins(25 downto 21); - R2 <= ins(20 downto 16); - elsif ins(3) = '0' then - R1 <= ins(20 downto 16); - R2 <= (others => '0'); - else - R1 <= ins(25 downto 21); - R2 <= (others => '0'); - end if; - else - if ins(31) = '1' then - R1 <= ins(25 downto 21); - R2 <= ins(20 downto 16); - elsif ins(29 downto 26) = B"1111" then - R1 <= (others => '0'); - R2 <= (others => '0'); - elsif ins(29) = '1' then - R1 <= ins(25 downto 21); - R2 <= (others => '0'); - else - R1 <= ins(25 downto 21); - R2 <= ins(20 downto 16); - end if; - end if; - - wait for 1 ns; - - if ins(31 downto 27) = B"00001" then -- j / jal, not read reg - - ALUC <= B"0011"; - A <= (25 downto 0 => ins(25 downto 0), others => '0'); - B <= X"00000002"; - elsif ins(31 downto 26) = B"000000" then - if ins(5) = '1' then - ALUC <= ins(3 downto 0); - A <= RD1; - B <= RD2; - elsif ins(3) = '0' then - 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'); - else - ALUC <= (others => '0'); - A <= (others => '0'); - B <= (others => '0'); - end if; - else - if ins(31) = '1' then - ALUC <= B"0000"; - A <= RD1; - B <= (15 downto 0 => ins(15 downto 0), others => '0' ); - elsif ins(29 downto 26) = B"1111" then - ALUC <= (others => '0'); - A <= (others => '0'); - B <= (others => '0'); - elsif ins(29) = '1' then - ALUC <= ins(29 downto 26); - A <= RD1; - B(15 downto 0) <= ins(15 downto 0); - if ins(15) = '0' then - B(31 downto 16) <= X"0000"; - else - B(31 downto 16) <= X"FFFF"; - end if; - else - ALUC <= B"0010"; - A <= RD1; - B <= RD2; - end if; - end if; - - wait for 100 ps; - - if ins(31 downto 27) = B"00001" then -- j / jal, not read reg - if ins(26) = '1' then -- jal - W <= B"11111"; - WD <= pc + 4; - WRITE_REG <= '1'; - else - WRITE_REG <= '0'; - end if; - pc_to_write <= S; - elsif ins(31 downto 26) = B"000000" then - if ins(5) = '1' then - WRITE_REG <= '1'; - W <= ins(15 downto 11); - WD <= S; - elsif ins(3) = '0' then - WRITE_REG <= '1'; - W <= ins(15 downto 11); - WD <= S; - else - WRITE_REG <= '0'; - pc_to_write <= RD1; - end if; - else - if ins(31) = '1' then - if ins(29) = '1' then - R2 <= ins(20 downto 16); - mem_write <= '1'; - mem_addr <= S; - mem_w_data <= RD2; - - wait until falling_edge(mem_clk); - - wait for 100 ps; - - mem_write <= '0'; - - else - W <= ins(20 downto 16); - mem_read <= '1'; - mem_addr <= S; - - wait until rising_edge(mem_clk); - - wait for 100 ps; - - WD <= mem_r_data; - WRITE_REG <= '1'; - end if; - elsif ins(29 downto 26) = B"1111" then - WRITE_REG <= '1'; - W <= ins(20 downto 16); - WD(31 downto 16) <= ins(15 downto 0); - elsif ins(29) = '1' then - WRITE_REG <= '1'; - W <= ins(20 downto 16); - WD <= S; - else - WRITE_REG <= '0'; - if Z = '1' xor ins(26) = '1' then - pc_to_write <= pc_to_write + to_integer(signed(ins(15 downto 0)) * 4); - end if; - end if; - end if; - 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 cpu_test_bench is -end entity; - -architecture Behavioral of cpu_test_bench is - signal CLK: std_logic; -begin - cpu : entity work.cpu; -end architecture; |