diff options
| author | crupest <crupest@outlook.com> | 2021-12-26 23:59:28 +0800 | 
|---|---|---|
| committer | crupest <crupest@outlook.com> | 2021-12-26 23:59:28 +0800 | 
| commit | d122ab74ce2e7c3bf1e126e8b08d6b36d1cf0a83 (patch) | |
| tree | fc5987a3b8c67062a4479ab64980023ad6ab10c9 /works/life | |
| parent | 825afbb7774d5a507f198429b8999c6aae3f8592 (diff) | |
| download | crupest-d122ab74ce2e7c3bf1e126e8b08d6b36d1cf0a83.tar.gz crupest-d122ab74ce2e7c3bf1e126e8b08d6b36d1cf0a83.tar.bz2 crupest-d122ab74ce2e7c3bf1e126e8b08d6b36d1cf0a83.zip  | |
import(life): ...
Diffstat (limited to 'works/life')
| -rw-r--r-- | works/life/computer-organization-experiment/cpu.vhdl | 352 | ||||
| -rw-r--r-- | works/life/computer-organization-experiment/out.ghw | bin | 4661248 -> 34000 bytes | |||
| -rw-r--r-- | works/life/computer-organization-experiment/out.vcd | 184 | 
3 files changed, 165 insertions, 371 deletions
diff --git a/works/life/computer-organization-experiment/cpu.vhdl b/works/life/computer-organization-experiment/cpu.vhdl index aca35cf..5a7c558 100644 --- a/works/life/computer-organization-experiment/cpu.vhdl +++ b/works/life/computer-organization-experiment/cpu.vhdl @@ -4,33 +4,29 @@ 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;  use ieee.std_logic_1164.all;  use work.cru.all; -entity reg is -    port ( -        CLK: in std_logic; -- Rising edge -> Read; Falling edge -> Write. -        ENABLE: in std_logic; -- If 1 then at falling edge of clock, W will be written. -        W: in word; -- The data to write. -        R: out word -- The data to read. -    ); +entity generic_clock is +    generic(delay, interval: time); +    port(CLK: out std_logic);  end entity; -architecture Behavioral of reg is -    signal V: word := (others => '0'); +architecture Behavioral of generic_clock is +    signal V : std_logic := '1';  begin -    process(CLK) +    l: process is      begin -        if rising_edge(CLK) then -            R <= V; -        end if; -        if falling_edge(CLK) and ENABLE = '1' then -            V <= W; -        end if; +        CLK <= '0'; +        wait for delay; +        loop +            CLK <= V; +            V <= not V; +            wait for interval; +        end loop;      end process;  end architecture; @@ -38,35 +34,38 @@ library ieee;  use ieee.std_logic_1164.all;  use work.cru.all; -entity reg_file_clock is -    port(CLK: out std_logic); +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_file_clock is -    signal V: std_logic := '1'; +architecture Behavioral of reg is +    signal V: word := X"00000000";  begin -    l: process is +    process(CLK)      begin -        CLK <= V; -        wait for 1 ns; -        loop -            V <= not V; -            wait for 1 ps; -            CLK <= V; -            wait for clock_time; -        end loop; +        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 ieee.std_logic_unsigned.all;  use work.cru.all;  entity register_file is      port ( -        ENABLE: in std_logic; +        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) @@ -74,19 +73,16 @@ entity register_file is  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; +    type reg_file_type is array (0 to 31) of word; +    signal reg_file: reg_file_type := (others => X"00000000");  begin -    clock: entity work.reg_file_clock -        port map (CLK);      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 ENABLE = '1' then +        if falling_edge(CLK) and WRITE = '1' then              reg_file(to_integer(unsigned(W))) <= WD;          end if;      end process; @@ -123,54 +119,15 @@ end architecture;  library ieee;  use ieee.std_logic_1164.all; -use work.cru.all; - -entity clock is -    port(CLK: out std_logic); -end entity; - -architecture Behavioral of clock is -    signal V: std_logic := '0'; -begin -    V <= not V after clock_time; -    CLK <= V; -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 work.cru.all;  entity ram is      port( +        CLK: in std_logic;          R_DATA: out word;          W_DATA: in word; -        R_ADDR: in word; -        W_ADDR: in word; +        ADDR: in word;          READ: in std_logic;          WRITE: in std_logic      ); @@ -217,18 +174,14 @@ architecture Behavioral of ram is                  X"00000115",                  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  +    l: process(CLK) is       begin          if rising_edge(CLK) and READ = '1' then -            R_DATA <= memory(to_integer(unsigned(R_ADDR)) / 4); +            r_data <= memory(to_integer(unsigned(ADDR)) / 4);          end if;          if falling_edge(CLK) and WRITE = '1' then -            memory(to_integer(unsigned(W_ADDR)) / 4) <= W_DATA; +            memory(to_integer(unsigned(ADDR)) / 4) <= w_data;          end if;      end process;  end architecture; @@ -240,21 +193,21 @@ use ieee.std_logic_unsigned.all;  use work.cru.all;  entity cpu is -    port ( -        CLK: in std_logic -    );  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_r_addr: word := X"00000000"; -    signal mem_w_addr: word := X"00000000"; +    signal mem_addr: word;      signal mem_r_data: word; -    signal mem_w_data: word := X"00000000"; +    signal mem_w_data: word;      signal mem_read: std_logic := '0';      signal mem_write: std_logic := '0'; @@ -272,16 +225,30 @@ architecture Behavioral of cpu is      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 => CLK, -            ENABLE => '1', -            W => pc_to_write, -            R => pc +            CLK => pc_clk, +            WRITE => '1', +            R_DATA => pc, +            W_DATA => pc_to_write          ); -    reg: entity work.register_file +     +    reg_file: entity work.register_file          port map( -            ENABLE => WRITE_REG, +            CLK => reg_clk, +            WRITE => WRITE_REG,              R1 => R1,              R2 => R2,              W => W, @@ -289,6 +256,7 @@ begin              RD1 => RD1,              RD2 => RD2          ); +      alu: entity work.alu          port map(              A => A, @@ -300,109 +268,153 @@ begin      ram: entity work.ram          port map ( -            R_DATA => mem_r_data, -            W_DATA => mem_w_data, -            R_ADDR => mem_r_addr, -            W_ADDR => mem_w_addr, +            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(CLK); +        wait until rising_edge(pc_clk); -        wait for 250 ps; +        wait for 100 ps;          mem_read <= '1'; -        mem_r_addr <= pc; +        mem_addr <= pc;          pc_to_write <= pc + 4; -        wait for 500 ps; +        wait for 1 ns;          ins <= mem_r_data; -        mem_write <= '0'; - -        WRITE_REG <= '0'; -                  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'; +            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"; -            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); - -                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'); +            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; +        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 -                R1 <= ins(25 downto 21); - -                wait for 500 ps; - +                WRITE_REG <= '0';                  pc_to_write <= RD1;              end if;          else              if ins(31) = '1' then -                R1 <= ins(25 downto 21); -                R2 <= ins(20 downto 16); - -                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                      R2 <= ins(20 downto 16);                      mem_write <= '1'; -                    mem_w_addr <= S; +                    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_r_addr <= S; +                    mem_addr <= S; -                    wait for ram_clock_time * 2; +                    wait until rising_edge(mem_clk); +                     +                    wait for 100 ps;                      WD <= mem_r_data;                      WRITE_REG <= '1'; @@ -412,43 +424,16 @@ begin                  W <= ins(20 downto 16);                  WD(31 downto 16) <= ins(15 downto 0);              elsif ins(29) = '1' then -                R1 <= ins(25 downto 21); - -                wait for 500 ps; - -                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; - -                wait for 100 ps; - -                W <= ins(20 downto 16);                  WRITE_REG <= '1'; +                W <= ins(20 downto 16);                  WD <= S;              else -                R1 <= ins(25 downto 21); -                R2 <= ins(20 downto 16); -                 -                wait for 500 ps; -                 -                ALUC <= B"0010"; -                A <= RD1; -                B <= RD2; - -                wait for 100 ps; - +                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; -                WRITE_REG <= '0';              end if;          end if; -      end process;  end architecture; @@ -464,12 +449,5 @@ end entity;  architecture Behavioral of cpu_test_bench is      signal CLK: std_logic;  begin -    clock: entity work.clock -        port map ( -            CLK -        ); -    cpu : entity work.cpu -        port map ( -            CLK -        ); +    cpu : entity work.cpu;  end architecture; diff --git a/works/life/computer-organization-experiment/out.ghw b/works/life/computer-organization-experiment/out.ghw Binary files differindex 81d1df7..23af3af 100644 --- a/works/life/computer-organization-experiment/out.ghw +++ b/works/life/computer-organization-experiment/out.ghw diff --git a/works/life/computer-organization-experiment/out.vcd b/works/life/computer-organization-experiment/out.vcd deleted file mode 100644 index a47fb22..0000000 --- a/works/life/computer-organization-experiment/out.vcd +++ /dev/null @@ -1,184 +0,0 @@ -$date -  Sun Dec 26 07:20:30 2021 -$end -$version -  GHDL v0 -$end -$timescale -  1 fs -$end -$scope module standard $end -$upscope $end -$scope module textio $end -$upscope $end -$scope module std_logic_1164 $end -$upscope $end -$scope module numeric_std $end -$upscope $end -$scope module std_logic_arith $end -$upscope $end -$scope module std_logic_unsigned $end -$upscope $end -$scope module cru $end -$upscope $end -$scope module cpu_test_bench $end -$var reg 1 ! clk $end -$scope module clock $end -$var reg 1 " clk $end -$var reg 1 # v $end -$upscope $end -$scope module cpu $end -$var reg 1 $ clk $end -$var reg 32 % pc[31:0] $end -$var reg 32 & pc_to_write[31:0] $end -$var reg 32 ' ins[31:0] $end -$var reg 32 ( mem_r_addr[31:0] $end -$var reg 32 ) mem_w_addr[31:0] $end -$var reg 32 * mem_r_data[31:0] $end -$var reg 32 + mem_w_data[31:0] $end -$var reg 1 , mem_read $end -$var reg 1 - mem_write $end -$var reg 1 . write_reg $end -$var reg 5 / r1[4:0] $end -$var reg 5 0 r2[4:0] $end -$var reg 5 1 w[4:0] $end -$var reg 32 2 wd[31:0] $end -$var reg 32 3 rd1[31:0] $end -$var reg 32 4 rd2[31:0] $end -$var reg 32 5 a[31:0] $end -$var reg 32 6 b[31:0] $end -$var reg 4 7 aluc[3:0] $end -$var reg 32 8 s[31:0] $end -$var reg 1 9 z $end -$scope module pc_reg $end -$var reg 1 : clk $end -$var reg 1 ; enable $end -$var reg 32 < w[31:0] $end -$var reg 32 = r[31:0] $end -$var reg 32 > v[31:0] $end -$upscope $end -$scope module reg $end -$var reg 1 ? clk $end -$var reg 1 @ enable $end -$var reg 5 A r1[4:0] $end -$var reg 5 B r2[4:0] $end -$var reg 5 C w[4:0] $end -$var reg 32 D wd[31:0] $end -$var reg 32 E rd1[31:0] $end -$var reg 32 F rd2[31:0] $end -$comment reg_file is not handled $end -$upscope $end -$scope module alu $end -$var reg 32 G a[31:0] $end -$var reg 32 H b[31:0] $end -$var reg 4 I aluc[3:0] $end -$var reg 32 J s[31:0] $end -$var reg 1 K z $end -$upscope $end -$scope module ram $end -$var reg 32 L r_data[31:0] $end -$var reg 32 M w_data[31:0] $end -$var reg 32 N r_addr[31:0] $end -$var reg 32 O w_addr[31:0] $end -$var reg 1 P read $end -$var reg 1 Q write $end -$comment memory is not handled $end -$var reg 1 R v $end -$var reg 1 S clk $end -$scope module clock $end -$var reg 1 T clk $end -$var reg 1 U v $end -$upscope $end -$upscope $end -$upscope $end -$upscope $end -$enddefinitions $end -#0 -0! -0" -0# -0$ -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU % -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU & -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU ' -b00000000000000000000000000000000 ( -b00000000000000000000000000000000 ) -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU * -b00000000000000000000000000000000 + -0, -0- -0. -b00000 / -b00000 0 -b00000 1 -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU 2 -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU 3 -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU 4 -b00000000000000000000000000000000 5 -b00000000000000000000000000000000 6 -b0000 7 -b00000000000000000000000000000000 8 -19 -0: -1; -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU < -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU = -b00000000000000000000000000000000 > -0? -0@ -b00000 A -b00000 B -b00000 C -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU D -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU E -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU F -b00000000000000000000000000000000 G -b00000000000000000000000000000000 H -b0000 I -b00000000000000000000000000000000 J -1K -bUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU L -b00000000000000000000000000000000 M -b00000000000000000000000000000000 N -b00000000000000000000000000000000 O -0P -0Q -0R -0S -0T -0U -#200000 -#2700000 -1U -#5200000 -1S -1T -0U -#7700000 -0S -0T -1U -#10000000 -1! -1" -1# -1$ -b00000000000000000000000000000000 % -b00000000000000000000000000000000 3 -b00000000000000000000000000000000 4 -1: -b00000000000000000000000000000000 = -1? -b00000000000000000000000000000000 E -b00000000000000000000000000000000 F -#10100000 -b00000000000000000000000000000100 & -1, -b00000000000000000000000000000100 < -1P -#10200000 -b00111100000000010000000000000000 * -b00111100000000010000000000000000 L -1S -1T -0U  | 
