/*********************************************************/
// MODULE:			ByteRAM
//
// FILE NAME:		ByteRAM.v
// VERSION:			1.0
// DATE:				Feb 10, 2003
//                Modified Oct 28, 2003 by Larry Merkle 
//                  to correct timing error
// AUTHOR:			Larry Merkle, based on ram.v by Allen Bast 
//
// DESCRIPTION:	This module defines a RAM module for use
//                in the CS232 Winter 2002-2003 Term Project.
//
/*********************************************************/

module ByteRam(
		WriteData, 
      MemData,
		Address,
		MemWrite,
      CLK);

/*********************************************************/

// Definitions
						
//SZ of lower 'a' memory is 1KB starting at 0x0000
`define RAM_A_LOWER 16'h0000
`define RAM_A_UPPER 16'h03FF
parameter RAM_A_SZ = `RAM_A_UPPER - `RAM_A_LOWER + 1;

//SZ of mid 'b' memory is 2KB starting at 0x0400
`define RAM_B_LOWER 16'h0400
`define RAM_B_UPPER 16'h0BFF
parameter RAM_B_SZ = `RAM_B_UPPER - `RAM_B_LOWER + 1;

//SZ of upper 'c' memory is 1KB starting at 0xFC00
`define RAM_C_LOWER 16'hFC00
`define RAM_C_UPPER 16'hFFFF
parameter RAM_C_SZ = `RAM_C_UPPER - `RAM_C_LOWER + 1;

// Actual depth of RAM (number of bytes)
parameter RAM_DEPTH = RAM_A_SZ + RAM_B_SZ + RAM_C_SZ;	

/*********************************************************/

// INPUTS

input [15:0] 	Address; // RAM address
input [15:0]	WriteData;	// RAM data in
input				MemWrite;	// Write strobe
input          CLK;

/*********************************************************/

// OUTPUTS
output [15:0]	MemData;	// RAM data out

/*********************************************************/

// SIGNAL DECLARATIONS

wire [15:0] Address;
wire  [15:0]	MSB;
wire  [15:0]	LSB;
wire [15:0]	WriteData;
//reg  [15:0]	MemData;
wire			MemWrite;

/*********************************************************/

// The RAM

reg  [7:0]	mem [RAM_DEPTH-1:0];

/*********************************************************/

assign MSB = RealAddress( Address );
assign LSB = RealAddress( Address + 1 );

//
assign MemData = { mem[ MSB ], mem[ LSB ] };
//

always @ ( posedge CLK ) begin

//   MemData <= { mem[ MSB ], mem[ LSB ] };

   if ( MemWrite ) begin
   	mem[ MSB ] <= WriteData[ 15:8 ];
   	mem[ LSB ] <= WriteData[  7:0 ];
   end

end

// Initialization of RAM for simulation

initial begin

// If your program and procedures are written in binary, use these two lines:
//$readmemb("main_prog_bin.txt", mem, `RAM_A_LOWER, `RAM_A_UPPER-1);
//$readmemb("procedures_bin.txt", mem, `RAM_B_LOWER, `RAM_B_UPPER-1);

// If your program and procedures are written in hex, use these two lines:
$readmemh("main_prog_hex.txt", mem, `RAM_A_LOWER, `RAM_A_UPPER-1);
$readmemh("procedures_hex.txt", mem, `RAM_B_LOWER, `RAM_B_UPPER-1);

end


function [15:0] RealAddress;
   input [15:0] VirtualAddress;
   begin
   if( ( VirtualAddress >= `RAM_A_LOWER ) && ( VirtualAddress <= `RAM_A_UPPER ) )
		RealAddress = VirtualAddress - `RAM_A_LOWER;
	else if( ( VirtualAddress >= `RAM_B_LOWER ) && ( VirtualAddress <= `RAM_B_UPPER ) )
		RealAddress = VirtualAddress - `RAM_B_LOWER + RAM_A_SZ;
	else if( ( VirtualAddress >= `RAM_C_LOWER ) && ( VirtualAddress <= `RAM_C_UPPER ) )
		RealAddress = VirtualAddress - `RAM_C_LOWER + RAM_A_SZ + RAM_B_SZ;
	else
		RealAddress = 16'bX;
   end
endfunction

/*********************************************************/

endmodule		// Ram
