-- IMPORTANT NOTES: -- 1. The Altera UP1 board has a 25MHz (VGA) clock generated on pin 91 (FLEX10K) -- 2. The FLEX push buttons are active low on pins 28 and 29. -- 3. The FLEX SW1 switches are connected on pins 33,34,35,36,38,39,40,41 -- 4. The FLEX 7-segment displays are on pins (6,7,8,9,11,12,13,14) and (17,18,19,20,21,23,24,25) -- in segment order (a,b,c,d,e,f,g,decimal point) -- 5. The FLEX 7-segment displays are "memory mapped" to address 0x0D and the FLEX switches are -- mapped to address 0x0C LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; LIBRARY lpm; USE lpm.lpm_components.all; LIBRARY altera; USE altera.altera_primitives_components.all; LIBRARY altera_mf; USE altera_mf.altera_mf_components.all; ENTITY protocomputer IS GENERIC (DATA_WIDTH : integer := 12; ADDRESS_WIDTH : integer := 8; OPERATIONS : integer := 16); PORT ( Clock, Reset : IN std_logic; -- DIP switch on the Altera UP1 board FLEXSWITCHES : IN std_logic_vector(7 downto 0); -- Simple diagnostics oHALT, oFETCH, oEXE, oSTATUS, oWREN, ClockMain : OUT std_logic; -- 7-segment displays on the Altera UP1 board SEG1, SEG2 : OUT std_logic_vector(7 downto 0); -- TEST I/O: -- oS1_RESET, oS1_SET, oS0_RESET, oS0_SET : OUT std_logic; -- oMAR_IN_EN : OUT std_logic; -- oMBR_IN_EN, oMBR_OUT_EN, oMBR_BUS_SELECT : OUT std_logic; -- oSP_IN_EN, oSP_OUT_EN, oSP_DEC, oSP_INC : OUT std_logic; -- oPC_IN_EN, oPC_OUT_EN, oPC_INC : OUT std_logic; -- oIR_IN_EN, oIR_OUT_EN : OUT std_logic; -- oAC_IN_EN, oAC_OUT_EN : OUT std_logic; -- oALU_OP : OUT std_logic_vector(6 downto 0); -- oPHI : OUT std_logic_vector(1 downto 0); -- oINST : OUT std_logic_vector(15 downto 0); -- BUS_VAL, MBR_VAL, MEM_VAL : OUT std_logic_vector(DATA_WIDTH-1 downto 0); AC_VAL, IR_VAL : OUT std_logic_vector(DATA_WIDTH-1 downto 0); -- ALU_VAL : OUT std_logic_vector(DATA_WIDTH-1 downto 0); -- MAR_VAL, SP_VAL, PC_VAL : OUT std_logic_vector(ADDRESS_WIDTH-1 downto 0) ); ---- END OF TEST I/O END protocomputer; ARCHITECTURE LogicFunc OF protocomputer IS COMPONENT MEMORY GENERIC (DATA_WIDTH : integer; ADDRESS_WIDTH : integer); PORT (WREN, Clock : IN std_ulogic; Q : OUT std_logic_vector(DATA_WIDTH-1 downto 0); DATA : IN std_logic_vector(DATA_WIDTH-1 downto 0); ADDRESS : IN std_logic_vector(ADDRESS_WIDTH-1 downto 0) ); END COMPONENT; COMPONENT MAPPEDSEGMENTS GENERIC (DATA_WIDTH : integer; ADDRESS_WIDTH : integer); PORT (ADDRESS, MAGIC_ADDRESS : IN std_logic_vector(ADDRESS_WIDTH-1 downto 0); DATA : IN std_logic_vector(DATA_WIDTH-1 downto 0); WREN, Clock : IN std_logic; OUT1, OUT2 : OUT std_logic_vector(7 downto 0)); END COMPONENT; COMPONENT MAPPEDBUTTONS GENERIC (DATA_WIDTH : integer := 16; ADDRESS_WIDTH : integer := 8); PORT (ADDRESS, MAGIC_ADDRESS : IN std_logic_vector(ADDRESS_WIDTH-1 downto 0); DATA : IN std_logic_vector(DATA_WIDTH-1 downto 0); BUTTONS : IN std_logic_vector(7 downto 0); Clock : IN std_logic; Q : OUT std_logic_vector(DATA_WIDTH-1 downto 0)); END COMPONENT; SIGNAL the_bus : std_logic_vector(DATA_WIDTH-1 downto 0); SIGNAL bus_to_mar : std_logic_vector(ADDRESS_WIDTH-1 downto 0); SIGNAL intMAR : std_logic_vector(ADDRESS_WIDTH-1 downto 0); SIGNAL intMEM, intMEM0 : std_logic_vector(DATA_WIDTH-1 downto 0); SIGNAL intMBRdirect : std_logic_vector(DATA_WIDTH-1 downto 0); SIGNAL CLKmain, CLKmem, intCLK, intCLK0 : std_logic; BEGIN -------------------------------------------------------------------------------------- -- Clock generation: Takes the clock input and halves it for the main clock -- NOTE: This will generate both the logic clock (CLKmain) and memory clock (CLKmem) clk: srff PORT MAP(PRN => '1', CLRN => '1', CLK => Clock, S => '1', R => '1', Q => intCLK0); clk2: srff PORT MAP(PRN => '1', CLRN => '1', CLK => intCLK0, S=> '1', R => '1', Q => intCLK); clk3: global PORT MAP(A_IN => intCLK, A_OUT => CLKmain); clk4: global PORT MAP(A_IN => Clock, A_OUT => CLKmem); ClockMain <= CLKmain; --- IMPORTANT NOTE: use CLKmain as your system clock... this is required for the memory --------------------------------------------------------------------------------------- -- START OF BUS COMPONENTS ------------------------------------------------------------- -- PUT YOUR COMPONENTS HERE. -- THE MEMORY SUBSYSTEM IS PROVIDED BELOW. -------------------------------------------------------------------------------------- u4: MEMORY GENERIC MAP(DATA_WIDTH => DATA_WIDTH, ADDRESS_WIDTH => ADDRESS_WIDTH) PORT MAP(WREN => WREN, Clock => CLKmem, Q => intMEM0, DATA => intMBRdirect, ADDRESS => intMAR); --MEM_VAL <= intMEM; -- memory mapped 7-segment displays and input buttons... u4b: MAPPEDSEGMENTS GENERIC MAP(DATA_WIDTH => DATA_WIDTH, ADDRESS_WIDTH => ADDRESS_WIDTH) PORT MAP(ADDRESS => intMAR, MAGIC_ADDRESS => CONV_STD_LOGIC_VECTOR(x"0D", ADDRESS_WIDTH), DATA => intMBRdirect, WREN => WREN, Clock => CLKmem, OUT1 => SEG1, OUT2 => SEG2); u4c: MAPPEDBUTTONS GENERIC MAP(DATA_WIDTH => DATA_WIDTH, ADDRESS_WIDTH => ADDRESS_WIDTH) PORT MAP(ADDRESS => intMAR, MAGIC_ADDRESS => CONV_STD_LOGIC_VECTOR(x"0C", ADDRESS_WIDTH), BUTTONS => FLEXSWITCHES, DATA => intMEM0, Clock => CLKmem, Q => intMEM); -------------------------------------------------------------------------------------- -- END OF BUS COMPONENTS ------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- FETCH/EXE CONTROL ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- PHASE COUNTER ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- DECODER and STATUS BIT ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- FETCH and INSTRUCTION CONTROL LOGIC -- FETCH (steals some phases from HALT to make the other INST indices work out nicely) -- ADD 0000 -- READ 0001 -- WRITE 0010 -- NEG 0011 -- AND 0100 -- OR 0101 -- RSHIFT 1001 -- LSHIFT 1010 -- HALT 1011 -- JNZ 0110 -- JSR 0111 -- RET 1000 -- JMP 1100 (OPTIONAL) -- YOU CAN ADD ADDITIONAL INSTRUCTIONS FOR EXTRA CREDIT ------------------------------------------------------------------------------------------- END LogicFunc; ------------------------------------------------------------------------------------------- -- MAIN MEMORY (must have the file main_memory.mif in the project working directory) ---------------IMPORTANT NOTE ABOVE!!!!!!!!!!!!!!! LIBRARY ieee; USE ieee.std_logic_1164.all; LIBRARY altera; USE altera.altera_primitives_components.all; LIBRARY lpm; USE lpm.lpm_components.all; ENTITY MEMORY IS GENERIC (DATA_WIDTH : integer := 16; ADDRESS_WIDTH : integer := 8); PORT (WREN, Clock : IN std_ulogic; Q : OUT std_logic_vector(DATA_WIDTH-1 downto 0); DATA : IN std_logic_vector(DATA_WIDTH-1 downto 0); ADDRESS : IN std_logic_vector(ADDRESS_WIDTH-1 downto 0) ); END MEMORY; ARCHITECTURE LogicFunc OF MEMORY IS COMPONENT LPM_RAM_DQ generic (LPM_WIDTH : natural; -- MUST be greater than 0 LPM_WIDTHAD : natural; -- MUST be greater than 0 LPM_NUMWORDS : natural := 0; LPM_INDATA : string := "REGISTERED"; LPM_ADDRESS_CONTROL: string := "REGISTERED"; LPM_OUTDATA : string := "REGISTERED"; LPM_FILE : string := "UNUSED"; LPM_TYPE : string := L_RAM_DQ; USE_EAB : string := "ON"; INTENDED_DEVICE_FAMILY : string := "UNUSED"; LPM_HINT : string := "UNUSED"); port (DATA : in std_logic_vector(LPM_WIDTH-1 downto 0); ADDRESS : in std_logic_vector(LPM_WIDTHAD-1 downto 0); INCLOCK : in std_logic := '0'; OUTCLOCK : in std_logic := '0'; WE : in std_logic; Q : out std_logic_vector(LPM_WIDTH-1 downto 0)); end component; COMPONENT LPM_DECODE generic (LPM_WIDTH : natural; -- MUST be greater than 0 LPM_DECODES : natural; -- MUST be greater than 0 LPM_PIPELINE : natural := 0; LPM_TYPE : string := L_DECODE; LPM_HINT : string := "UNUSED"); port (DATA : in std_logic_vector(LPM_WIDTH-1 downto 0); CLOCK : in std_logic := '0'; CLKEN : in std_logic := '1'; ACLR : in std_logic := '0'; ENABLE : in std_logic := '1'; EQ : out std_logic_vector(LPM_DECODES-1 downto 0)); end component; COMPONENT LPM_FF generic (LPM_WIDTH : natural; -- MUST be greater than 0 LPM_AVALUE : string := "UNUSED"; LPM_SVALUE : string := "UNUSED"; LPM_PVALUE : string := "UNUSED"; LPM_FFTYPE: string := "DFF"; LPM_TYPE: string := L_FF; LPM_HINT : string := "UNUSED"); port (DATA : in std_logic_vector(LPM_WIDTH-1 downto 0); CLOCK : in std_logic; ENABLE : in std_logic := '1'; SLOAD : in std_logic := '0'; SCLR : in std_logic := '0'; SSET : in std_logic := '0'; ALOAD : in std_logic := '0'; ACLR : in std_logic := '0'; ASET : in std_logic := '0'; Q : out std_logic_vector(LPM_WIDTH-1 downto 0)); end component; COMPONENT LPM_MUX generic (LPM_WIDTH : natural; -- MUST be greater than 0 LPM_SIZE : natural; -- MUST be greater than 0 LPM_WIDTHS : natural; -- MUST be greater than 0 LPM_PIPELINE : natural := 0; LPM_TYPE : string := L_MUX; LPM_HINT : string := "UNUSED"); port (DATA : in std_logic_2D(LPM_SIZE-1 downto 0, LPM_WIDTH-1 downto 0); ACLR : in std_logic := '0'; CLOCK : in std_logic := '0'; CLKEN : in std_logic := '1'; SEL : in std_logic_vector(LPM_WIDTHS-1 downto 0); RESULT : out std_logic_vector(LPM_WIDTH-1 downto 0)); end component; BEGIN u4: LPM_RAM_DQ GENERIC MAP(LPM_WIDTH => DATA_WIDTH, LPM_WIDTHAD => ADDRESS_WIDTH, LPM_FILE => "main_memory.mif") PORT MAP(WE => WREN, DATA => DATA, ADDRESS => ADDRESS, INCLOCK => Clock, OUTCLOCK => Clock, Q => Q); END LogicFunc; ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- Memory mapped 7-segment displays (2). Intercepts MAR/MBR values to the MAGIC_ADDRESS -- address and converts MBR into 7-segment display driver signals. LIBRARY ieee; USE ieee.std_logic_1164.all; LIBRARY lpm; USE lpm.lpm_components.all; ENTITY MAPPEDSEGMENTS IS GENERIC (DATA_WIDTH : integer := 16; ADDRESS_WIDTH : integer := 8); PORT (ADDRESS, MAGIC_ADDRESS : IN std_logic_vector(ADDRESS_WIDTH-1 downto 0); DATA : IN std_logic_vector(DATA_WIDTH-1 downto 0); WREN, Clock : IN std_logic; OUT1, OUT2 : OUT std_logic_vector(7 downto 0)); END MAPPEDSEGMENTS; ARCHITECTURE LogicFunc OF MAPPEDSEGMENTS IS component LPM_COMPARE generic (LPM_WIDTH : natural; -- MUST be greater than 0 LPM_REPRESENTATION : string := "UNSIGNED"; LPM_PIPELINE : natural := 0; LPM_TYPE: string := L_COMPARE; LPM_HINT : string := "UNUSED"); port (DATAA : in std_logic_vector(LPM_WIDTH-1 downto 0); DATAB : in std_logic_vector(LPM_WIDTH-1 downto 0); ACLR : in std_logic := '0'; CLOCK : in std_logic := '0'; CLKEN : in std_logic := '1'; AGB : out std_logic; AGEB : out std_logic; AEB : out std_logic; ANEB : out std_logic; ALB : out std_logic; ALEB : out std_logic); end component; COMPONENT REG GENERIC (BIT_WIDTH : integer); PORT (INE, OUTE, Clock : IN std_ulogic; Q, Qdirect : OUT std_logic_vector(BIT_WIDTH-1 downto 0); DATA : IN std_logic_vector(BIT_WIDTH-1 downto 0) ); END COMPONENT; SIGNAL intGOTCHA, intAEB : std_logic; SIGNAL intQ : std_logic_vector(DATA_WIDTH-1 downto 0); SIGNAL nOUT1, nOUT2 : std_logic_vector(7 downto 0); BEGIN u0: lpm_compare GENERIC MAP(LPM_WIDTH => ADDRESS_WIDTH) PORT MAP(aeb => intAEB, dataa => ADDRESS, datab => MAGIC_ADDRESS); intGOTCHA <= WREN and intAEB; -- capture the snooped value... u1: REG GENERIC MAP(BIT_WIDTH => DATA_WIDTH) PORT MAP(INE => intGOTCHA, OUTE => '0', Clock => Clock, Qdirect => intQ, DATA => DATA); -- MOMENTARY BEHAVIORAL INTERLUDE: to convert a dataword into 7-segment driver signals... -- Assumes DATA_WIDTH >= 8 (displays lower 8 bits) PROCESS (intQ) BEGIN CASE intQ(3 downto 0) IS WHEN x"0" => nOUT2 <= "11111100"; WHEN x"1" => nOUT2 <= "00001100"; WHEN x"2" => nOUT2 <= "11011010"; WHEN x"3" => nOUT2 <= "11110010"; WHEN x"4" => nOUT2 <= "01100110"; WHEN x"5" => nOUT2 <= "10110110"; WHEN x"6" => nOUT2 <= "10111110"; WHEN x"7" => nOUT2 <= "11100000"; WHEN x"8" => nOUT2 <= "11111110"; WHEN x"9" => nOUT2 <= "11110110"; WHEN x"A" => nOUT2 <= "11101110"; WHEN x"B" => nOUT2 <= "00111110"; WHEN x"C" => nOUT2 <= "10011100"; WHEN x"D" => nOUT2 <= "01111000"; WHEN x"E" => nOUT2 <= "10011110"; WHEN x"F" => nOUT2 <= "10001110"; WHEN OTHERS => nOUT2 <= "00000000"; END CASE; CASE intQ(7 downto 4) IS WHEN x"0" => nOUT1 <= "11111100"; WHEN x"1" => nOUT1 <= "00001100"; WHEN x"2" => nOUT1 <= "11011010"; WHEN x"3" => nOUT1 <= "11110010"; WHEN x"4" => nOUT1 <= "01100110"; WHEN x"5" => nOUT1 <= "10110110"; WHEN x"6" => nOUT1 <= "10111110"; WHEN x"7" => nOUT1 <= "11100000"; WHEN x"8" => nOUT1 <= "11111110"; WHEN x"9" => nOUT1 <= "11110110"; WHEN x"A" => nOUT1 <= "11101110"; WHEN x"B" => nOUT1 <= "00111110"; WHEN x"C" => nOUT1 <= "10011100"; WHEN x"D" => nOUT1 <= "01111000"; WHEN x"E" => nOUT1 <= "10011110"; WHEN x"F" => nOUT1 <= "10001110"; WHEN OTHERS => nOUT1 <= "00000000"; END CASE; END PROCESS; OUT1 <= not nOUT1; OUT2 <= not nOUT2; END LogicFunc; ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- Memory mapped buttons. This component intercepts the memory bus and snoops MAR to -- detect the magic button address (MAGIC_BUTTONS) LIBRARY ieee; USE ieee.std_logic_1164.all; LIBRARY lpm; USE lpm.lpm_components.all; LIBRARY altera; USE altera.altera_primitives_components.all; ENTITY MAPPEDBUTTONS IS GENERIC (DATA_WIDTH : integer := 16; ADDRESS_WIDTH : integer := 8); PORT (ADDRESS, MAGIC_ADDRESS : IN std_logic_vector(ADDRESS_WIDTH-1 downto 0); DATA : IN std_logic_vector(DATA_WIDTH-1 downto 0); BUTTONS : IN std_logic_vector(7 downto 0); Clock : IN std_logic; Q : OUT std_logic_vector(DATA_WIDTH-1 downto 0)); END MAPPEDBUTTONS; ARCHITECTURE LogicFunc OF MAPPEDBUTTONS IS component LPM_COMPARE generic (LPM_WIDTH : natural; -- MUST be greater than 0 LPM_REPRESENTATION : string := "UNSIGNED"; LPM_PIPELINE : natural := 0; LPM_TYPE: string := L_COMPARE; LPM_HINT : string := "UNUSED"); port (DATAA : in std_logic_vector(LPM_WIDTH-1 downto 0); DATAB : in std_logic_vector(LPM_WIDTH-1 downto 0); ACLR : in std_logic := '0'; CLOCK : in std_logic := '0'; CLKEN : in std_logic := '1'; AGB : out std_logic; AGEB : out std_logic; AEB : out std_logic; ANEB : out std_logic; ALB : out std_logic; ALEB : out std_logic); end component; SIGNAL intANEB, intAEB : std_logic; BEGIN u0: lpm_compare GENERIC MAP(LPM_WIDTH => ADDRESS_WIDTH) PORT MAP(aneb => intANEB, aeb => intAEB, dataa => ADDRESS, datab => MAGIC_ADDRESS); tri_array1: for i in (DATA_WIDTH-1) downto 0 generate u1: tri PORT MAP(A_IN => DATA(i), OE => intANEB, A_OUT => Q(i)); end generate; tri_array2: for i in 7 downto 0 generate u2: tri PORT MAP(A_IN => BUTTONS(i), OE => intAEB, A_OUT => Q(i)); end generate; -- sign extend value with BUTTONS(7) tri_array3: for i in (DATA_WIDTH-1) downto 8 generate u2: tri PORT MAP(A_IN => BUTTONS(7), OE => intAEB, A_OUT => Q(i)); end generate; END LogicFunc; ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -- A simple 3-state bus register LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; LIBRARY altera; USE altera.altera_primitives_components.all; ENTITY REG IS GENERIC (BIT_WIDTH : integer := 16); PORT (INE, OUTE, Clock : IN std_ulogic := '0'; Q, Qdirect : OUT std_logic_vector(BIT_WIDTH-1 downto 0) := CONV_STD_LOGIC_VECTOR(0, BIT_WIDTH); DATA : IN std_logic_vector(BIT_WIDTH-1 downto 0) := CONV_STD_LOGIC_VECTOR(0, BIT_WIDTH) ); END REG; ARCHITECTURE LogicFunc OF REG IS SIGNAL intQ : std_logic_vector(BIT_WIDTH-1 downto 0) := CONV_STD_LOGIC_VECTOR(0, BIT_WIDTH); BEGIN dff_array: for i in BIT_WIDTH-1 downto 0 generate d: dffe PORT MAP(PRN => '1', CLRN => '1', ENA => INE, CLK => Clock, D => DATA(i), Q => intQ(i)); t: tri PORT MAP(A_IN => intQ(i), OE => OUTE, A_OUT => Q(i)); end generate; Qdirect <= intQ; END LogicFunc; -------------------------------------------------------------------------------------------