-- pipe1.vhdl VHDL '93 version using entities from WORK library -- basic five stage pipeline of just Instruction Register -- The 411 course pipeline has the same 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 -- an instruction memory entity and behavioral architecture -- -- a top level entity, pipe1, test bench -- the architecture, schematic layout of the top level entity -- the signals for interconnecting the entities -- a clock generator process -- the entities connected with signals (port maps) -- a print process that shows the registers in the pipeline each clock -- The add32 comes from the WORK library, compiled separately. library IEEE; use IEEE.std_logic_1164.all; package util_pkg is function to_integer(sig : std_logic_vector) return integer; end package util_pkg; package body util_pkg is -- converts std_logic_vector to integer function to_integer(sig : std_logic_vector) return integer is variable num : integer := 0; -- descending sig as integer begin for i in sig'range loop if sig(i)='1' then num := num*2+1; else -- use anything other than '1' as '0' num := num*2; end if; end loop; -- i return num; end function to_integer; end package body 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 entity 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 architecture behavior; -- of register_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 entity 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) := (x"00000001", x"00000002", x"00000003", x"00000004", x"00000005", x"00000006", x"00000007"); 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 architecture behavior; -- of instruction_memory entity pipe1 is -- test bench end entity 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 entities -- signals used in top level architecture (the interconnections) signal zero_32 : std_logic_vector(31 downto 0) := x"00000000"; -- 32 bit zero signal zero : std_logic := '0'; -- one bit zero signal four_32 : std_logic_vector(31 downto 0) := x"00000004"; -- 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 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: entity WORK.register_32 port map (clk, clear, IF_PC_next, IF_PC); PC_incr: entity WORK.add32 port map (IF_PC, four_32, zero, IF_PC_next, open); inst_mem:entity WORK.instruction_memory port map (IF_PC, inst); -- ID, Instruction Decode and register stack pipeline stage ID_IR_reg: entity WORK.register_32 port map (clk, clear, inst, ID_IR); -- EX, Execute pipeline stage EX_IR_reg: entity WORK.register_32 port map (clk, clear, ID_IR, EX_IR); -- MEM Data Memory pipeline stage MEM_IR_reg: entity WORK.register_32 port map (clk, clear, EX_IR, MEM_IR); -- WB, Write Back pipeline stage WB_IR_reg: entity WORK.register_32 port map (clk, clear, MEM_IR, WB_IR); printout: process(clk) -- 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 architecture schematic;