/*********************************************************/
// MODULE:			ByteRAM  
//
// FILE NAME:		ByteRAM.v
// VERSION:			1.4
// DATE:				Created Feb 10, 2003
//                Modified Oct 28, 2003 by Larry Merkle 
//                  to correct timing error
//                Modified Nov 8, 2003 by Larry Merkle
//                  - removed RAM_C
//                  - changed independent design parameters
//                  from LOWER and UPPER to LOWER and SZ
//                Modified Nov 11, 2003 by Larry Merkle
//                  - corrected upper limits in $readmemb 
//                    directives
//                  - corrected virtual address calculation
//                    for addresses in second block
//                  - added ValidAddress output
//                  - changed default SZ values to 0x0020
//                Modified Nov 12, 2003 by Larry Merkle
//                  - added Reset signal
//                  - replaced "initial" block with
//                    "always @ ( posedge Reset ) " block
//                    to allow initialization within
//                    synthesized module
//                Modified Nov 15, 2003 by Larry Merkle
//                  - (finally and really this time) corrected
//                    upper limits in $readmemb directives
// 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,
      Reset,
      Valid,
      CLK);

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

// Definitions
						
`define RAM_A_LOWER 16'h0000
`define RAM_A_SZ 16'h0080
parameter RAM_A_UPPER = `RAM_A_SZ - 1;

`define RAM_B_LOWER 16'hFEE0
`define RAM_B_SZ 16'h0020
parameter RAM_B_UPPER = `RAM_B_LOWER + `RAM_B_SZ - 1;

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

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

// INPUTS

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

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

// OUTPUTS
output [15:0]	MemData;	// RAM data out
output         Valid; // Asserted when MSB and LSB actually exist

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

// SIGNAL DECLARATIONS

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

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

// The RAM

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

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

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

//
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

always @ ( posedge Reset ) begin

// If your program and procedures are written in binary, use these two lines:
//$readmemb("main_prog_bin.txt", mem, 0, `RAM_A_SZ - 1);
//$readmemb("procedures_bin.txt", mem, `RAM_A_SZ, `RAM_A_SZ + `RAM_B_SZ - 1);

// If your program and procedures are written in hex, use these two lines:
$readmemh("main_prog_hex.txt", mem, 0, `RAM_A_SZ - 1);
//$readmemh("procedures_hex.txt", mem, `RAM_A_SZ, `RAM_A_SZ + `RAM_B_SZ - 1);

end


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

function ValidAddress;
   input [15:0] VirtualAddress;
   begin
   if( ( VirtualAddress >= `RAM_A_LOWER ) && ( VirtualAddress + 1 < `RAM_A_LOWER + `RAM_A_SZ ) )
      ValidAddress = 1;
	else if( ( VirtualAddress >= `RAM_B_LOWER ) && ( VirtualAddress + 1 < `RAM_B_LOWER + `RAM_B_SZ ) )
      ValidAddress = 1;
	else
      ValidAddress = 0;
   end
endfunction

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

endmodule		// Ram
