Single-Cycle 16-bit MIPS in VHDL

This project presents a **16-bit single-cycle MIPS processor**, entirely written in VHDL. It aims to illustrate the internal functioning of a RISC-style architecture, enabling learners to visualize instruction flow from fetch to write-back. Every component — instruction memory, register file, ALU, control unit, and testbench — has been designed to be concise and pedagogically clear.

Objective

The goal of this project is to design and simulate a compact 16-bit processor that implements a subset of the MIPS instruction set architecture. The processor demonstrates fundamental stages of instruction execution — **Fetch, Decode, Execute, Memory Access,** and **Write-Back** — in a single clock cycle.

It serves as a foundation for students and developers to understand RISC principles, control logic, and data movement within a CPU at the register-transfer level.

Key Features

  • 16-bit datapath with modular component design
  • Instruction memory (ROM) and data memory (RAM) modeled in VHDL
  • Register file with 8 registers and synchronous write mechanism
  • ALU supporting arithmetic and logical operations with a zero flag
  • Control and ALU-Control units for instruction decoding and operation selection
  • Comprehensive testbench with clock, reset, and stimulus generation

Use Cases

  • Educational visualization of CPU operation and instruction flow
  • Practical demonstration in Digital Logic or Computer Architecture courses
  • FPGA deployment for real-time hardware observation
  • Research base for micro-architecture extensions like pipelining

Future Enhancements

  • Extend to a 32-bit pipeline with hazard detection and forwarding logic
  • Implement memory hierarchy with cache and memory-mapped I/O
  • Add interrupt and exception handling mechanisms
  • Integrate UVM-based testbench for automated verification

Architecture Overview

Datapath

The datapath connects key hardware blocks: Program Counter → Instruction Memory → Register File & Control → ALU → Data Memory → Write-Back. Each instruction passes through these stages sequentially in a single clock cycle.

Control Unit

Decodes opcodes and generates control signals such as regDst, ALUSrc, memRead, memWrite, and regWrite. It determines how data flows between the modules.

ALU & ALU-Control

The ALU performs core arithmetic and logic operations such as ADD, SUB, AND, OR, and SLTU. The ALU-Control block interprets ALUOp and Funct fields to select the operation dynamically.

Memory System

The design uses simple on-chip ROM and RAM modeled as VHDL arrays. ROM stores the instruction set, while RAM enables data reads and writes during execution.

Instruction Flow

Each instruction begins with fetching from ROM using the program counter. It is then decoded by the control unit, which signals the ALU and memory modules. Results are written back to the register file in a single clock cycle.

The testbench demonstrates instruction sequencing with observable signals like mem_read_data, alu_result, and pc_current.

Educational Impact

This 16-bit MIPS model is ideal for teaching because of its simplicity and modular structure. Students can trace the logic flow, add custom instructions, or expand it to a pipelined version. Its architecture balances clarity with completeness, making it a perfect learning scaffold.

Source Code (VHDL Modules)

ALU

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_SIGNED.ALL;

entity ALU_VHDL is
  port(
    a, b        : in  std_logic_vector(15 downto 0);
    alu_control : in  std_logic_vector(2 downto 0);
    alu_result  : out std_logic_vector(15 downto 0);
    zero        : out std_logic
  );
end ALU_VHDL;

architecture Behavioral of ALU_VHDL is
  signal result : std_logic_vector(15 downto 0);
begin
  process(alu_control, a, b)
  begin
    case alu_control is
      when "000" => result <= a + b;
      when "001" => result <= a - b;
      when "010" => result <= a and b;
      when "011" => result <= a or  b;
      when "100" => result <= (x"0001" when a < b else x"0000");
      when others => result <= (others => '0');
    end case;
  end process;

  zero       <= '1' when result = x"0000" else '0';
  alu_result <= result;
end Behavioral;

Control Unit

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity control_unit_VHDL is
  port(
    opcode       : in  std_logic_vector(2 downto 0);
    reset        : in  std_logic;
    reg_dst,
    mem_to_reg,
    alu_op       : out std_logic_vector(1 downto 0);
    jump, branch, mem_read, mem_write,
    alu_src, reg_write, sign_or_zero : out std_logic
  );
end control_unit_VHDL;

architecture Behavioral of control_unit_VHDL is
begin
  process(reset, opcode)
  begin
    if reset = '1' then
      reg_dst <= "00"; mem_to_reg <= "00"; alu_op <= "00";
      jump <= '0'; branch <= '0'; mem_read <= '0';
      mem_write <= '0'; alu_src <= '0'; reg_write <= '0';
      sign_or_zero <= '1';
    else
      case opcode is
        when "000" => alu_op <= "00"; reg_write <= '1';  -- ADD
        when "001" => alu_op <= "01"; reg_write <= '1';  -- SUB
        when "010" => alu_op <= "10"; reg_write <= '1';  -- SLTU
        when "011" => branch  <= '1';                    -- BEQ
        when others => null;
      end case;
    end if;
  end process;
end Behavioral;

Register File

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity register_file_VHDL is
  port(
    clk, rst       : in  std_logic;
    reg_write_en   : in  std_logic;
    reg_write_dest : in  std_logic_vector(2 downto 0);
    reg_write_data : in  std_logic_vector(15 downto 0);
    reg_read_addr_1, reg_read_addr_2 : in  std_logic_vector(2 downto 0);
    reg_read_data_1, reg_read_data_2 : out std_logic_vector(15 downto 0)
  );
end register_file_VHDL;