-- pipe1.vhd VHDL '87 version for vdt, ivc -- basic five stage pipeline of just Instruction Register -- The 411 course pipeline has five stages -- IF Instruction Fetch includes PC and instruction memory -- ID Instruction Decode and registers -- EX Execution including the ALU Arithmetic Logic Unit -- MEM data Memory -- WB Write Back into registers -- -- This self contained VHDL file defines: -- a package declaration and body that defines a function -- a 32 bit register entity with clock and clear inputs -- a 32 bit adder entity and behavioral architecture -- an instruction memory entity and behavioral architecture -- -- a top level entity, pipe1, test bench -- the architecture, schematic layout of the top level entity -- component interfaces used in schematic -- the signals for interconnecting the components -- a clock generator process -- the components connected with signals (port maps) -- a print process that shows the registers in the pipeline each clock -- -- the configuration that maps entities to components library IEEE; use IEEE.std_logic_1164.all; package util_pkg is function to_integer(sig : std_logic_vector) return integer; end util_pkg; package body util_pkg is function to_integer(sig : std_logic_vector) return integer is variable num : integer := 0; -- sig as integer begin for i in sig'range loop if sig(i)='1' then num := num*2+1; else num := num*2; end if; end loop; -- i return num; end to_integer; end util_pkg; library IEEE; use IEEE.std_logic_1164.all; entity register_32 is port (clk : in std_logic; clear : in std_logic; input : in std_logic_vector (31 downto 0); output : out std_logic_vector (31 downto 0) ); end register_32; architecture behavior of register_32 is begin -- behavior reg_32: process(clk, clear) begin if clear='1' then output <= (others=>'0'); elsif clk='1' then output <= input after 250 ps; end if; end process reg_32; end behavior; -- of register_32 library IEEE; use IEEE.std_logic_1164.all; entity add_32 is port (a : in std_logic_vector (31 downto 0); b : in std_logic_vector (31 downto 0); cin : in std_logic; sum : out std_logic_vector (31 downto 0); cout : out std_logic); end add_32; architecture behavior of add_32 is begin -- behavior adder: process variable carry : std_logic; -- internal variable isum : std_logic_vector(31 downto 0); -- internal begin carry := cin; for i in 0 to 31 loop isum(i) := a(i) xor b(i) xor carry; carry := (a(i) and b(i)) or (a(i) and carry) or (b(i) and carry); end loop; sum <= isum; cout <= carry; wait for 1 ns; -- signals updated after process ends end process adder; end behavior; -- of add_32 library IEEE; use IEEE.std_logic_1164.all; use WORK.util_pkg.all; entity instruction_memory is port (addr : in std_logic_vector (31 downto 0); inst : out std_logic_vector (31 downto 0)); end instruction_memory; architecture behavior of instruction_memory is begin -- behavior inst_mem: process(addr) subtype word is std_logic_vector(31 downto 0); type mem_array is array(natural range <>) of word; variable memory: mem_array(0 to 6) := ("00000000000000000000000000000001", "00000000000000000000000000000010", "00000000000000000000000000000011", "00000000000000000000000000000100", "00000000000000000000000000000101", "00000000000000000000000000000110", "00000000000000000000000000000111"); variable word_addr : natural; -- byte addr/4 begin word_addr := to_integer(addr)/4; inst <= memory(word_addr) after 250 ps; end process inst_mem; end behavior; -- of instruction_memory entity pipe1 is -- test bench end pipe1; library STD; use STD.textio.all; library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_textio.all; use WORK.util_pkg.all; architecture schematic of pipe1 is -- top level connection of components -- selection of architectures for components -- is in pipe1_config, below. -- components used in top level architecture (just the interface) component register_32 -- port copied from Entity declaration port (clk : in std_logic; clear : in std_logic; input : in std_logic_vector (31 downto 0); output : out std_logic_vector (31 downto 0) ); end component; component add_32 port (a : in std_logic_vector (31 downto 0); b : in std_logic_vector (31 downto 0); cin : in std_logic; sum : out std_logic_vector (31 downto 0); cout : out std_logic); end component; component instruction_memory port (addr : in std_logic_vector (31 downto 0); inst : out std_logic_vector (31 downto 0)); end component; -- signals used in top level architecture (the interconnections) signal zero_32 : std_logic_vector(31 downto 0) := (others=>'0'); -- 32 zeros signal zero : std_logic := '0'; -- one bit zero signal four_32 : std_logic_vector(31 downto 0) := "00000000000000000000000000000100"; -- four signal clear : std_logic := '1'; -- one shot clear signal clk : std_logic := '0'; -- master clock signal counter : integer := 0; -- master clock counter, raising edge signal nc1 : std_logic; -- a No Connection for unused output signal IF_PC_next : std_logic_vector(31 downto 0); -- next value of PC signal IF_PC : std_logic_vector(31 downto 0); -- Program Counter signal inst : std_logic_vector(31 downto 0); -- instruction fetched signal ID_IR : std_logic_vector(31 downto 0); -- ID Instruction Register signal EX_IR : std_logic_vector(31 downto 0); -- EX Instruction Register signal MEM_IR : std_logic_vector(31 downto 0); -- MEM Instruction Register signal WB_IR : std_logic_vector(31 downto 0); -- WB Instruction Register begin -- schematic of pipe1, top level architecture and test bench clock_gen: process(clk) -- clock generator and one shot clear signal begin if clear='1' then -- happens only once clear <= '0' after 200 ps; end if; clk <= not clk after 5 ns; -- 10 ns period end process clock_gen; -- IF, Instruction Fetch pipeline stage PC_reg: register_32 port map (clk, clear, IF_PC_next, IF_PC); PC_incr: add_32 port map (IF_PC, four_32, zero, IF_PC_next, nc1); inst_mem: instruction_memory port map (IF_PC, inst); -- ID, Instruction Decode and register stack pipeline stage ID_IR_reg: register_32 port map (clk, clear, inst, ID_IR); -- EX, Execute pipeline stage EX_IR_reg: register_32 port map (clk, clear, ID_IR, EX_IR); -- MEM Data Memory pipeline stage MEM_IR_reg: register_32 port map (clk, clear, EX_IR, MEM_IR); -- WB, Write Back pipeline stage WB_IR_reg: register_32 port map (clk, clear, MEM_IR, WB_IR); printout: process(clk) -- used to show state of registers in pipeline variable my_line : LINE; -- not part of working circuit begin if clk='1' then write(my_line, string'("at clock ")); write(my_line, counter); write(my_line, string'(" PC=")); write(my_line, IF_PC); writeline(output, my_line); write(my_line, string'("IF stage inst=")); write(my_line, inst); writeline(output, my_line); write(my_line, string'("IF_PC_next =")); write(my_line, IF_PC_next); writeline(output, my_line); write(my_line, string'("ID stage IR=")); write(my_line, ID_IR); writeline(output, my_line); write(my_line, string'("EX stage IR=")); write(my_line, EX_IR); writeline(output, my_line); write(my_line, string'("MEM stage IR=")); write(my_line, MEM_IR); writeline(output, my_line); write(my_line, string'("WB stage IR=")); write(my_line, WB_IR); writeline(output, my_line); writeline(output, my_line); -- blank line counter <= counter+1; end if; end process printout; end schematic; configuration pipe1_config of pipe1 is for schematic for all : register_32 use entity WORK.register_32; end for; for inst_mem : instruction_memory use entity WORK.instruction_memory; end for; for all : add_32 use entity WORK.add_32(behavior); end for; end for; end pipe1_config;