Last active
February 19, 2017 12:01
-
-
Save stone3311/12b6d7cf1cd614d184e47efcb038ed73 to your computer and use it in GitHub Desktop.
A simple 4-bit processor, written in VHDL, moved to https://github.com/stone3311/f4001
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| library ieee; | |
| use ieee.std_logic_1164.all; | |
| use ieee.numeric_std.all; | |
| ENTITY alu IS | |
| PORT ( | |
| opcode : IN std_logic_vector (7 DOWNTO 0); | |
| in_0, in_1 : IN std_logic_vector (3 DOWNTO 0); | |
| output : OUT std_logic_vector (3 DOWNTO 0); | |
| equal_zero : OUT std_logic; | |
| nequal_zero: OUT std_logic; | |
| clk: IN std_logic | |
| ); | |
| END alu; | |
| ARCHITECTURE Behaviour OF alu IS | |
| -- SIGNAL mirror: std_logic_vector (3 DOWNTO 0) := "1111"; | |
| BEGIN | |
| PROCESS(clk) | |
| BEGIN | |
| IF (rising_edge(clk)) THEN | |
| IF opcode(7 DOWNTO 4) = "0001" THEN -- alu | |
| CASE opcode(3 DOWNTO 0) IS | |
| WHEN "0000" => output <= std_logic_vector(unsigned(in_0) + unsigned(in_1)); | |
| WHEN "0001" => output <= std_logic_vector(unsigned(in_0) - unsigned(in_1)); | |
| WHEN "0010" => output <= std_logic_vector(unsigned(in_0) and unsigned(in_1)); | |
| WHEN "0011" => output <= std_logic_vector(unsigned(in_0) or unsigned(in_1)); | |
| WHEN "0100" => output <= std_logic_vector(rotate_left(unsigned(in_0), to_integer(unsigned(in_1)))); | |
| WHEN "0101" => output <= std_logic_vector(rotate_right(unsigned(in_0), to_integer(unsigned(in_1)))); | |
| WHEN "0110" => output <= std_logic_vector(unsigned(in_0(1 DOWNTO 0)) * unsigned(in_1(1 DOWNTO 0))); | |
| WHEN "0111" => output <= std_logic_vector(unsigned(in_0) / unsigned(in_1)); | |
| -- WHEN "1000" => output(1 DOWNTO 0) <= in_0 (3 DOWNTO 2); output(3 DOWNTO 2) <= in_0 (1 DOWNTO 0); | |
| WHEN others => output <= (others => '0'); | |
| END CASE; | |
| ELSIF opcode(7 DOWNTO 4) = "0111" THEN -- cmp | |
| equal_zero <= '0'; | |
| nequal_zero <= '0'; | |
| IF in_0 = "0000" THEN | |
| equal_zero <= '1'; | |
| ELSE | |
| nequal_zero <= '1'; | |
| END IF; | |
| END IF; | |
| END IF; | |
| END PROCESS; | |
| END Behaviour; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| library ieee; | |
| use ieee.std_logic_1164.all; | |
| use ieee.numeric_std.all; | |
| ENTITY clockdivider IS | |
| PORT ( | |
| clk_in : IN std_logic; | |
| clk_out: OUT std_logic; | |
| clk_ena: IN std_logic := '1' | |
| ); | |
| END clockdivider; | |
| ARCHITECTURE Behaviour OF clockdivider IS | |
| BEGIN | |
| PROCESS (clk_in) | |
| VARIABLE divider : std_logic_vector (23 DOWNTO 0) := (others => '0'); | |
| VARIABLE state : std_logic := '0'; | |
| BEGIN | |
| IF rising_edge(clk_in) THEN | |
| divider := std_logic_vector(unsigned(divider) + 1); | |
| IF unsigned(divider) = 50000 THEN | |
| divider := (others => '0'); | |
| state := not state; | |
| IF clk_ena = '1' THEN | |
| clk_out <= state; | |
| END IF; | |
| END IF; | |
| END IF; | |
| END PROCESS; | |
| END Behaviour; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| library ieee; | |
| use ieee.std_logic_1164.all; | |
| ENTITY f4001 IS | |
| PORT( | |
| input_0, input_1 : IN std_logic; | |
| output_0, output_1: OUT std_logic; | |
| global_clk : IN std_logic | |
| ); | |
| END f4001; | |
| ARCHITECTURE Behaviour OF f4001 IS | |
| SIGNAL opcode_bus : std_logic_vector (7 DOWNTO 0) := (others => '1'); | |
| SIGNAL romaddr_bus: std_logic_vector (7 DOWNTO 0) := (others => '0'); | |
| SIGNAL reg_a, reg_d, reg_hi, reg_lo : std_logic_vector (3 DOWNTO 0); | |
| SIGNAL regmemdata : std_logic_vector (3 DOWNTO 0); | |
| SIGNAL regaludata : std_logic_vector (3 DOWNTO 0); | |
| SIGNAL alu_eqz, alu_nqz : std_logic; | |
| SIGNAL peripherals_out: std_logic_vector (1 DOWNTO 0); | |
| SIGNAL peripherals_in : std_logic_vector (1 DOWNTO 0); | |
| SIGNAL clock_enable: std_logic := '1'; | |
| SIGNAL clock : std_logic; | |
| -- NOTE: Used for the "In-System Sources and Probes Editor" in Quartus II | |
| SIGNAL probesignal : std_logic_vector (7 DOWNTO 0); | |
| COMPONENT probes | |
| PORT ( | |
| probe : in std_logic_vector(7 downto 0) := (others => '0') -- probes.probe | |
| ); | |
| END COMPONENT; | |
| COMPONENT clockdivider | |
| PORT ( | |
| clk_in : IN std_logic; | |
| clk_out: OUT std_logic; | |
| clk_ena: IN std_logic := '1' | |
| ); | |
| END COMPONENT; | |
| COMPONENT rom | |
| PORT( | |
| address: IN std_logic_vector (7 DOWNTO 0); | |
| opcode: OUT std_logic_vector (7 DOWNTO 0) := (others => '1'); | |
| clk: IN std_logic | |
| ); | |
| END COMPONENT; | |
| COMPONENT pc | |
| PORT( | |
| opcode : IN std_logic_vector (7 DOWNTO 0); | |
| address: OUT std_logic_vector (7 DOWNTO 0) := (others => '0'); | |
| addr_hi: IN std_logic_vector (3 DOWNTO 0); | |
| addr_lo: IN std_logic_vector (3 DOWNTO 0); | |
| equal_zero : IN std_logic; | |
| nequal_zero: IN std_logic; | |
| clk_ena: OUT std_logic := '1'; | |
| clk: IN std_logic | |
| ); | |
| END COMPONENT; | |
| COMPONENT registers | |
| PORT( | |
| opcode : IN std_logic_vector (7 DOWNTO 0); | |
| memdata : IN std_logic_vector (3 DOWNTO 0); | |
| aludata : IN std_logic_vector (3 DOWNTO 0); | |
| a, d, hi, lo : OUT std_logic_vector (3 DOWNTO 0); | |
| clk: IN std_logic | |
| ); | |
| END COMPONENT; | |
| COMPONENT alu | |
| PORT ( | |
| opcode : IN std_logic_vector (7 DOWNTO 0); | |
| in_0, in_1 : IN std_logic_vector (3 DOWNTO 0); | |
| output : OUT std_logic_vector (3 DOWNTO 0); | |
| equal_zero : OUT std_logic; | |
| nequal_zero: OUT std_logic; | |
| clk: IN std_logic | |
| ); | |
| END COMPONENT; | |
| COMPONENT memory | |
| PORT( | |
| opcode : IN std_logic_vector (7 DOWNTO 0); | |
| addr_hi : IN std_logic_vector (3 DOWNTO 0); | |
| addr_lo : IN std_logic_vector (3 DOWNTO 0); | |
| periph_out: OUT std_logic_vector (1 DOWNTO 0); | |
| periph_in : IN std_logic_vector (1 DOWNTO 0); | |
| data : OUT std_logic_vector (3 DOWNTO 0); | |
| a,d,hi,lo : IN std_logic_vector (3 DOWNTO 0); | |
| clk: IN std_logic | |
| ); | |
| END COMPONENT; | |
| BEGIN | |
| mydiv : clockdivider PORT MAP (global_clk, clock, clock_enable); | |
| myrom : rom PORT MAP (romaddr_bus, opcode_bus, clock); | |
| mypc : pc PORT MAP (opcode_bus, romaddr_bus, reg_hi, reg_lo, alu_eqz, alu_nqz, clock_enable, clock); | |
| myregs: registers PORT MAP (opcode_bus, regmemdata, regaludata, reg_a, reg_d, reg_hi, reg_lo, clock); | |
| myalu : alu PORT MAP (opcode_bus, reg_a, reg_d, regaludata, alu_eqz, alu_nqz, clock); | |
| mymem : memory PORT MAP (opcode_bus, reg_hi, reg_lo, peripherals_out, peripherals_in, regmemdata, reg_a, reg_d, reg_hi, reg_lo, clock); | |
| probesignal(3 DOWNTO 0) <= reg_a; | |
| probesignal(7 DOWNTO 4) <= regaludata; | |
| myprobe: probes PORT MAP (opcode_bus); | |
| output_0 <= peripherals_out(0); | |
| output_1 <= peripherals_out(1); | |
| peripherals_in(0) <= input_0; | |
| peripherals_in(1) <= input_1; | |
| END Behaviour; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| library ieee; | |
| use ieee.std_logic_1164.all; | |
| use ieee.numeric_std.all; | |
| ENTITY memory IS | |
| PORT( | |
| opcode : IN std_logic_vector (7 DOWNTO 0); | |
| addr_hi : IN std_logic_vector (3 DOWNTO 0); | |
| addr_lo : IN std_logic_vector (3 DOWNTO 0); | |
| periph_out: OUT std_logic_vector (1 DOWNTO 0); | |
| periph_in : IN std_logic_vector (1 DOWNTO 0); | |
| data : OUT std_logic_vector (3 DOWNTO 0); | |
| a,d,hi,lo : IN std_logic_vector (3 DOWNTO 0); | |
| clk: IN std_logic | |
| ); | |
| END memory; | |
| ARCHITECTURE Behaviour OF memory IS | |
| PROCEDURE read_register (signal reg: in std_logic_vector(1 DOWNTO 0); signal rvalue: out std_logic_vector (3 DOWNTO 0)) IS | |
| BEGIN | |
| CASE reg IS | |
| WHEN "00" => rvalue <= a; | |
| WHEN "01" => rvalue <= d; | |
| WHEN "10" => rvalue <= hi; | |
| WHEN "11" => rvalue <= lo; | |
| END CASE; | |
| END read_register; | |
| CONSTANT memsize: natural := 1; -- Size of the SRAM in bytes, beginning at address 1 | |
| TYPE sram4 IS ARRAY (1 TO memsize) OF std_logic_vector (3 DOWNTO 0); | |
| SIGNAL mem : sram4; | |
| SIGNAL addr: std_logic_vector (7 DOWNTO 0); | |
| SIGNAL ioreg: std_logic_vector (3 DOWNTO 0); | |
| BEGIN | |
| PROCESS (clk) | |
| VARIABLE sp : std_logic_vector (7 DOWNTO 0) := std_logic_vector(to_unsigned(memsize, 8)); | |
| BEGIN | |
| IF rising_edge(clk) THEN | |
| IF opcode(7 DOWNTO 4) = "0011" THEN -- push | |
| read_register(opcode(1 DOWNTO 0), mem(to_integer(unsigned(sp)))); | |
| sp := std_logic_vector( unsigned(sp) - 1 ); | |
| ELSIF opcode(7 DOWNTO 4) = "0100" THEN -- pop | |
| data <= mem(to_integer(unsigned(sp))); | |
| sp := std_logic_vector( unsigned(sp) + 1 ); | |
| ELSIF opcode(7 DOWNTO 4) = "0101" THEN -- sto | |
| addr(7 DOWNTO 4) <= addr_hi; | |
| addr(3 DOWNTO 0) <= addr_lo; | |
| IF addr = "00000000" THEN | |
| read_register(opcode(1 DOWNTO 0), ioreg); | |
| periph_out <= ioreg(1 DOWNTO 0); | |
| ELSE | |
| read_register(opcode(1 DOWNTO 0), mem(to_integer(unsigned(addr)))); | |
| END IF; | |
| ELSIF opcode(7 DOWNTO 4) = "0110" THEN -- lod | |
| addr(7 DOWNTO 4) <= addr_hi; | |
| addr(3 DOWNTO 0) <= addr_lo; | |
| IF addr = "00000000" THEN | |
| ioreg(3 DOWNTO 2) <= periph_in; | |
| data <= ioreg; | |
| ELSE | |
| data <= mem(to_integer(unsigned(addr))); | |
| END IF; | |
| END IF; | |
| END IF; | |
| END PROCESS; | |
| END Behaviour; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| library ieee; | |
| use ieee.std_logic_1164.all; | |
| use ieee.numeric_std.all; | |
| ENTITY pc IS | |
| PORT( | |
| opcode : IN std_logic_vector (7 DOWNTO 0); | |
| address: OUT std_logic_vector (7 DOWNTO 0) := (others => '0'); | |
| addr_hi: IN std_logic_vector (3 DOWNTO 0); | |
| addr_lo: IN std_logic_vector (3 DOWNTO 0); | |
| equal_zero : IN std_logic; | |
| nequal_zero: IN std_logic; | |
| clk_ena: OUT std_logic := '1'; | |
| clk: IN std_logic | |
| ); | |
| END pc; | |
| ARCHITECTURE Behaviour OF pc IS | |
| BEGIN | |
| PROCESS (clk) | |
| VARIABLE current_address : std_logic_vector (7 DOWNTO 0) := "00000000"; | |
| BEGIN | |
| IF rising_edge(clk) THEN | |
| IF opcode(7 DOWNTO 4) = "1010" THEN -- jmp | |
| current_address(7 DOWNTO 4) := addr_hi; | |
| current_address(3 DOWNTO 0) := addr_lo; | |
| ELSIF opcode(7 DOWNTO 4) = "1000" AND equal_zero = '1' THEN -- jiz | |
| current_address(7 DOWNTO 4) := addr_hi; | |
| current_address(3 DOWNTO 0) := addr_lo; | |
| ELSIF opcode(7 DOWNTO 4) = "1001" AND nequal_zero = '1' THEN -- jnz | |
| current_address(7 DOWNTO 4) := addr_hi; | |
| current_address(3 DOWNTO 0) := addr_lo; | |
| ELSIF opcode(7 DOWNTO 4) = "1110" THEN -- hlt | |
| clk_ena <= '0'; | |
| ELSE | |
| current_address := std_logic_vector( unsigned(current_address) + 1 ); | |
| END IF; | |
| address <= current_address; | |
| END IF; | |
| END PROCESS; | |
| END Behaviour; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| library ieee; | |
| use ieee.std_logic_1164.all; | |
| ENTITY registers IS | |
| PORT( | |
| opcode : IN std_logic_vector (7 DOWNTO 0); | |
| memdata : IN std_logic_vector (3 DOWNTO 0); | |
| aludata : IN std_logic_vector (3 DOWNTO 0); | |
| a, d, hi, lo : OUT std_logic_vector (3 DOWNTO 0); | |
| clk: IN std_logic | |
| ); | |
| END registers; | |
| ARCHITECTURE Behaviour OF registers IS | |
| SHARED VARIABLE register_a : std_logic_vector (3 DOWNTO 0) := (others => '0'); | |
| SHARED VARIABLE register_d : std_logic_vector (3 DOWNTO 0) := (others => '0'); | |
| SHARED VARIABLE register_hi : std_logic_vector (3 DOWNTO 0) := (others => '0'); | |
| SHARED VARIABLE register_lo : std_logic_vector (3 DOWNTO 0) := (others => '0'); | |
| PROCEDURE write_register (signal reg: in std_logic_vector(1 DOWNTO 0); signal nvalue: in std_logic_vector (3 DOWNTO 0)) IS | |
| BEGIN | |
| CASE reg IS | |
| WHEN "00" => register_a := nvalue; | |
| WHEN "01" => register_d := nvalue; | |
| WHEN "10" => register_hi := nvalue; | |
| WHEN "11" => register_lo := nvalue; | |
| END CASE; | |
| END write_register; | |
| PROCEDURE read_register (signal reg: in std_logic_vector(1 DOWNTO 0); signal rvalue: out std_logic_vector (3 DOWNTO 0)) IS | |
| BEGIN | |
| CASE reg IS | |
| WHEN "00" => rvalue <= register_a; | |
| WHEN "01" => rvalue <= register_d; | |
| WHEN "10" => rvalue <= register_hi; | |
| WHEN "11" => rvalue <= register_lo; | |
| END CASE; | |
| END read_register; | |
| SIGNAL temp : std_logic_vector (3 DOWNTO 0) := (others => '0'); | |
| BEGIN | |
| a <= register_a; | |
| d <= register_d; | |
| hi <= register_hi; | |
| lo <= register_lo; | |
| PROCESS (clk) | |
| BEGIN | |
| IF rising_edge(clk) THEN | |
| IF opcode(7 DOWNTO 4) = "0000" THEN -- lda | |
| register_a := opcode(3 DOWNTO 0); | |
| ELSIF opcode(7 DOWNTO 4) = "1011" THEN -- ldd | |
| register_d := opcode(3 DOWNTO 0); | |
| ELSIF opcode(7 DOWNTO 4) = "1100" THEN -- ldh | |
| register_hi := opcode(3 DOWNTO 0); | |
| ELSIF opcode(7 DOWNTO 4) = "1101" THEN -- ldl | |
| register_lo := opcode(3 DOWNTO 0); | |
| ELSIF opcode(7 DOWNTO 4) = "0010" THEN -- mov | |
| read_register(opcode(1 DOWNTO 0), temp); | |
| write_register(opcode(3 DOWNTO 2), temp); | |
| ELSIF opcode(7 DOWNTO 4) = "0001" THEN -- alu | |
| register_a := aludata; | |
| ELSIF opcode(7 DOWNTO 4) = "0100" THEN -- push | |
| write_register(opcode(1 DOWNTO 0), memdata); | |
| ELSIF opcode(7 DOWNTO 4) = "0110" THEN -- lod | |
| write_register(opcode(1 DOWNTO 0), memdata); | |
| END IF; | |
| END IF; | |
| end PROCESS; | |
| END Behaviour; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 00 C0 B1 D0 10 50 D3 A0 | |
| A0 A0 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 | |
| 00 00 00 00 00 00 00 00 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| library ieee; | |
| use ieee.std_logic_1164.all; | |
| ENTITY rom IS | |
| PORT( | |
| address: IN std_logic_vector (7 DOWNTO 0); | |
| opcode: OUT std_logic_vector (7 DOWNTO 0) := (others => '1'); | |
| clk: IN std_logic | |
| ); | |
| END rom; | |
| ARCHITECTURE Behaviour OF rom IS | |
| SIGNAL myufm_addr, myufm_dataout : std_logic_vector (7 DOWNTO 0); | |
| SIGNAL myufm_nread, myufm_nbusy, myufm_data_valid : std_logic; | |
| COMPONENT ufm_parallel | |
| PORT ( | |
| ufm_addr_addr : in std_logic_vector(7 downto 0) := (others => '0'); -- ufm_addr.addr | |
| ufm_data_valid_data_valid : out std_logic; -- ufm_data_valid.data_valid | |
| ufm_dataout_dataout : out std_logic_vector(7 downto 0); -- ufm_dataout.dataout | |
| ufm_nbusy_nbusy : out std_logic; -- ufm_nbusy.nbusy | |
| ufm_nread_nread : in std_logic := '0' -- ufm_nread.nread | |
| ); | |
| END COMPONENT; | |
| SHARED VARIABLE nextopcode: std_logic_vector (7 DOWNTO 0) := (others => '1'); | |
| BEGIN | |
| ufm: ufm_parallel PORT MAP(myufm_addr, myufm_data_valid, myufm_dataout, myufm_nbusy, myufm_nread); | |
| PROCESS(clk) | |
| BEGIN | |
| IF rising_edge(clk) THEN | |
| opcode <= nextopcode; | |
| myufm_addr <= address; | |
| myufm_nread <= '0'; | |
| END IF; | |
| END PROCESS; | |
| PROCESS(myufm_data_valid) | |
| BEGIN | |
| IF rising_edge(myufm_data_valid) THEN | |
| nextopcode := myufm_dataout; | |
| END IF; | |
| END PROCESS; | |
| END Behaviour; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment