OpenCores
URL https://opencores.org/ocsvn/zx_ula/zx_ula/trunk

Subversion Repositories zx_ula

[/] [zx_ula/] [branches/] [xilinx/] [spectrum_16k_with_rom_game_for_ols/] [ram.v] - Rev 27

Compare with Previous | Blame | View Log

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:        Dept. Architecture and Computing Technology. University of Seville
// Engineer:       Miguel Angel Rodriguez Jodar. rodriguj@atc.us.es
// Revision:       Joseba Epalza Ramos <jepalza@gmail.com> 
//                 
// Create Date:    20-December-2012 
// Design Name:    ZX Spectrum
// Module Name:    Ram16K
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description:    Spectrum 16k OLS (Open Logic Sniffer) Dangerous Prototypes, "http://dangerousprototypes.com"
//
// Dependencies: 
//
// Revision: 
// Revision 2.00 - File Created
// Additional Comments: GPL License policies apply to the contents of this file.
//
//////////////////////////////////////////////////////////////////////////////////
 
/*
This module generates a high level on "isfalling" when "a" changes from high to low.
*/
module getfedge (
	input clk,
	input a,
	output isfalling
	);
 
	reg sh = 1'b1;
	assign isfalling = sh & ~a;
	always @(posedge clk)
		sh <= a;
endmodule
 
 
/*
This module implements a shared RAM controller. 
 
Notes from <jepalza>:
 OLS (Open Logic Sniffer) from Dangerous Prototypes, hasn't any SRAM connected in board.
 We need to create it into Spartan. At this point, only has enought logic to implement
 16k rom and 8k ram, in order to run basic Spectrum 16k!!
 but it's unusable with only 8k of ram. For this reason, it's best implement 8k rom and 16k ram
 with any of 8k rom games or demos, in the first 0x0000-0x1fff space. 
 
As the ZX Spectrum needs two independent memory banks, and bus cycles may happen to both at the same
time, it's necessary to emulate those two banks with one chip.
 
I tried a simple round-robin multiplexing, but didn't work as expected. This module is a bit more complicated
as it implements a first-come-first-serve approach, with fixed priority scheme when several petitions happen
at the same time.
 
This may be my first 100% synchronous implementation for a FPGA (that is, only one clock and all the ff's are
activated at the same edge)
 
*/
module ram_controller (
	input clk,
	input [15:0] a1,
	input cs1_n,
	input oe1_n,
	input we1_n,
	input [7:0] din1,
	output [7:0] dout1
	);
 
	// SRAM into OLS (16k max with 8k ROM, or 8k max with 16k ROM)
	reg [7:0] mem [0:16383]; //[0:7900] //7900: test with spectrum rom
 
	// Permanently enable SRAM and set it to use only LSB
	assign sramce = 0;
	assign sramoe = 0;
 
	reg rsramwe = 1;
	assign sramwe = rsramwe;
 
	// set when there has been a high to low transition in the corresponding signal
	wire bank1read, bank1write;
	getfedge detectbank1read (clk, cs1_n | oe1_n, bank1read);
	getfedge detectbank1write (clk, cs1_n | we1_n, bank1write);
 
	reg [15:0] ra1;
	reg [7:0] rdin1;
 
	reg [7:0] rdout1;
	assign dout1 = rdout1;
 
	// ff's to store pending memory requests
	reg pendingreadb1 = 0;
	reg pendingwriteb1 = 0;
 
	// ff's to store current memory requests
	reg reqreadb1 = 0;
	reg reqwriteb1 = 0;
 
	reg state = 1;
	always @(posedge clk) begin
		// get requests from the two banks
		if (bank1read) begin
			ra1 <= a1;
			pendingreadb1 <= 1;
			pendingwriteb1 <= 0;
		end
		else if (bank1write) begin
			ra1 <= a1;
			rdin1 <= din1;
			pendingwriteb1 <= 1;
			pendingreadb1 <= 0;
		end
 
		// reads from bank1 have the higher priority, then writes to bank1,
		// the reads from bank2, then writes from bank2.
		// Reads and writes to bank2 are mutually exclusive, though, as only the CPU
		// performs those operations. So they are with respect to bank1.
		case (state)
			0 : begin
					if (reqreadb1 || reqwriteb1) begin
						if (reqwriteb1) begin       // if this is a write operation...
							pendingwriteb1 <= 0;     // accept it, and mark pending operation as cleared
							mem[ra1[13:0]] <= rdin1; // put data into virtual SRAM
							rsramwe <= 0;		       // pulse /WE in SRAM to begin write
						end
						else begin
							pendingreadb1 <= 0;  // else, this is a read operation...
							rsramwe <= 1;        // we can read from the SRAM data bus itself. Deassert /WE to enable data output bus
						end
						state <= 1;             // if either request has been accepted, proceed to next phase.
					end
				  end
			1 : begin
					if (reqreadb1) begin		     // for read requests, read the SRAM data bus and store into the corresponding data output register
						rdout1 <= mem[ra1[13:0]]; // get data from SRAM OLS
					end
					if (reqwriteb1) begin	// for write requests, deassert /WE, as writting has already been happened.
						rsramwe <= 1;
					end
					reqreadb1 <= pendingreadb1;	// current request has finished, so update current requests with pending requests to serve  the next one
					reqwriteb1 <= pendingwriteb1;					
					if (pendingreadb1 || pendingwriteb1)
						state <= 0;
				 end
		endcase
	end
 
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.