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