`timescale 1ns / 1ps

// A simple register file wrapper

// University of California San Diego
// CSE141L Spring 2010
// Written by Matt DeVuyst
// April 7, 2010

module register_file_wrap
  (
   // Inputs
   clock,                       // Clock to control when write happen.
   write_enable,                // Enable writing to a register.
   read_reg0,                   // The number of a register to read from.
   read_reg1,                   // The number of a register to read from.
   write_reg,                   // The number of a register to write to.
   data_in,                     // Data to write to a given register.

   // Outputs
   data_out0,                   // Data read from a given register.
   data_out1                    // Data read from a given register.
   );

   parameter NUM_REGS = 8;      // Number of registers.
   parameter NUM_REGS_LOG = 3;  // Log_base_2 (number_of_registers).
   parameter DATA_WIDTH = 16;   // The width of each register.

   // Inputs
   input                    clock;
   input                    write_enable;
   input [NUM_REGS_LOG-1:0] read_reg0;
   input [NUM_REGS_LOG-1:0] read_reg1;
   input [NUM_REGS_LOG-1:0] write_reg;
   input [DATA_WIDTH-1:0]   data_in;

   // Outputs
   output [DATA_WIDTH-1:0]  data_out0;
   output [DATA_WIDTH-1:0]  data_out1;

   // Registers
   reg                      write_enable_reg;
   reg   [NUM_REGS_LOG-1:0] read_reg0_reg;
   reg   [NUM_REGS_LOG-1:0] read_reg1_reg;
   reg   [NUM_REGS_LOG-1:0] write_reg_reg;
   reg   [DATA_WIDTH-1:0]   data_in_reg;
   reg   [DATA_WIDTH-1:0]   data_out0_reg;
   reg   [DATA_WIDTH-1:0]   data_out1_reg;

   // Internal wires
   wire  [DATA_WIDTH-1:0]   data_out0_wire;
   wire  [DATA_WIDTH-1:0]   data_out1_wire;

   assign data_out0 = data_out0_reg;
   assign data_out1 = data_out1_reg;

   register_file rf
     (
      // Inputs
      .clock        (clock),
      .write_enable (write_enable_reg),
      .read_reg0    (read_reg0_reg),
      .read_reg1    (read_reg1_reg),
      .write_reg    (write_reg_reg),
      .data_in      (data_in_reg),
      // Outputs
      .data_out0    (data_out0_wire),
      .data_out1    (data_out1_wire)
      );

   always @(posedge clock)
     begin
        write_enable_reg <= write_enable;
        read_reg0_reg    <= read_reg0;
        read_reg1_reg    <= read_reg1;
        write_reg_reg    <= write_reg;
        data_in_reg      <= data_in;
        data_out0_reg    <= data_out0_wire;
        data_out1_reg    <= data_out1_wire;
     end

endmodule // register_file_wrap
