1 |
27 |
mcleod_ide |
`timescale 1ns / 1ps
|
2 |
|
|
//////////////////////////////////////////////////////////////////////////////////
|
3 |
|
|
// Company: Dept. Architecture and Computing Technology. University of Seville
|
4 |
|
|
// Engineer: Miguel Angel Rodriguez Jodar. rodriguj@atc.us.es
|
5 |
|
|
// Revision: Joseba Epalza Ramos <jepalza@gmail.com>
|
6 |
|
|
//
|
7 |
|
|
// Create Date: 20-December-2012
|
8 |
|
|
// Design Name: ZX Spectrum
|
9 |
|
|
// Module Name: Ram16K
|
10 |
|
|
// Project Name:
|
11 |
|
|
// Target Devices:
|
12 |
|
|
// Tool versions:
|
13 |
|
|
// Description: Spectrum 16k OLS (Open Logic Sniffer) Dangerous Prototypes, "http://dangerousprototypes.com"
|
14 |
|
|
//
|
15 |
|
|
// Dependencies:
|
16 |
|
|
//
|
17 |
|
|
// Revision:
|
18 |
|
|
// Revision 2.00 - File Created
|
19 |
|
|
// Additional Comments: GPL License policies apply to the contents of this file.
|
20 |
|
|
//
|
21 |
|
|
//////////////////////////////////////////////////////////////////////////////////
|
22 |
|
|
|
23 |
|
|
/*
|
24 |
|
|
This module generates a high level on "isfalling" when "a" changes from high to low.
|
25 |
|
|
*/
|
26 |
|
|
module getfedge (
|
27 |
|
|
input clk,
|
28 |
|
|
input a,
|
29 |
|
|
output isfalling
|
30 |
|
|
);
|
31 |
|
|
|
32 |
|
|
reg sh = 1'b1;
|
33 |
|
|
assign isfalling = sh & ~a;
|
34 |
|
|
always @(posedge clk)
|
35 |
|
|
sh <= a;
|
36 |
|
|
endmodule
|
37 |
|
|
|
38 |
|
|
|
39 |
|
|
/*
|
40 |
|
|
This module implements a shared RAM controller.
|
41 |
|
|
|
42 |
|
|
Notes from <jepalza>:
|
43 |
|
|
OLS (Open Logic Sniffer) from Dangerous Prototypes, hasn't any SRAM connected in board.
|
44 |
|
|
We need to create it into Spartan. At this point, only has enought logic to implement
|
45 |
|
|
16k rom and 8k ram, in order to run basic Spectrum 16k!!
|
46 |
|
|
but it's unusable with only 8k of ram. For this reason, it's best implement 8k rom and 16k ram
|
47 |
|
|
with any of 8k rom games or demos, in the first 0x0000-0x1fff space.
|
48 |
|
|
|
49 |
|
|
As the ZX Spectrum needs two independent memory banks, and bus cycles may happen to both at the same
|
50 |
|
|
time, it's necessary to emulate those two banks with one chip.
|
51 |
|
|
|
52 |
|
|
I tried a simple round-robin multiplexing, but didn't work as expected. This module is a bit more complicated
|
53 |
|
|
as it implements a first-come-first-serve approach, with fixed priority scheme when several petitions happen
|
54 |
|
|
at the same time.
|
55 |
|
|
|
56 |
|
|
This may be my first 100% synchronous implementation for a FPGA (that is, only one clock and all the ff's are
|
57 |
|
|
activated at the same edge)
|
58 |
|
|
|
59 |
|
|
*/
|
60 |
|
|
module ram_controller (
|
61 |
|
|
input clk,
|
62 |
|
|
input [15:0] a1,
|
63 |
|
|
input cs1_n,
|
64 |
|
|
input oe1_n,
|
65 |
|
|
input we1_n,
|
66 |
|
|
input [7:0] din1,
|
67 |
|
|
output [7:0] dout1
|
68 |
|
|
);
|
69 |
|
|
|
70 |
|
|
// SRAM into OLS (16k max with 8k ROM, or 8k max with 16k ROM)
|
71 |
|
|
reg [7:0] mem [0:16383]; //[0:7900] //7900: test with spectrum rom
|
72 |
|
|
|
73 |
|
|
// Permanently enable SRAM and set it to use only LSB
|
74 |
|
|
assign sramce = 0;
|
75 |
|
|
assign sramoe = 0;
|
76 |
|
|
|
77 |
|
|
reg rsramwe = 1;
|
78 |
|
|
assign sramwe = rsramwe;
|
79 |
|
|
|
80 |
|
|
// set when there has been a high to low transition in the corresponding signal
|
81 |
|
|
wire bank1read, bank1write;
|
82 |
|
|
getfedge detectbank1read (clk, cs1_n | oe1_n, bank1read);
|
83 |
|
|
getfedge detectbank1write (clk, cs1_n | we1_n, bank1write);
|
84 |
|
|
|
85 |
|
|
reg [15:0] ra1;
|
86 |
|
|
reg [7:0] rdin1;
|
87 |
|
|
|
88 |
|
|
reg [7:0] rdout1;
|
89 |
|
|
assign dout1 = rdout1;
|
90 |
|
|
|
91 |
|
|
// ff's to store pending memory requests
|
92 |
|
|
reg pendingreadb1 = 0;
|
93 |
|
|
reg pendingwriteb1 = 0;
|
94 |
|
|
|
95 |
|
|
// ff's to store current memory requests
|
96 |
|
|
reg reqreadb1 = 0;
|
97 |
|
|
reg reqwriteb1 = 0;
|
98 |
|
|
|
99 |
|
|
reg state = 1;
|
100 |
|
|
always @(posedge clk) begin
|
101 |
|
|
// get requests from the two banks
|
102 |
|
|
if (bank1read) begin
|
103 |
|
|
ra1 <= a1;
|
104 |
|
|
pendingreadb1 <= 1;
|
105 |
|
|
pendingwriteb1 <= 0;
|
106 |
|
|
end
|
107 |
|
|
else if (bank1write) begin
|
108 |
|
|
ra1 <= a1;
|
109 |
|
|
rdin1 <= din1;
|
110 |
|
|
pendingwriteb1 <= 1;
|
111 |
|
|
pendingreadb1 <= 0;
|
112 |
|
|
end
|
113 |
|
|
|
114 |
|
|
// reads from bank1 have the higher priority, then writes to bank1,
|
115 |
|
|
// the reads from bank2, then writes from bank2.
|
116 |
|
|
// Reads and writes to bank2 are mutually exclusive, though, as only the CPU
|
117 |
|
|
// performs those operations. So they are with respect to bank1.
|
118 |
|
|
case (state)
|
119 |
|
|
|
120 |
|
|
if (reqreadb1 || reqwriteb1) begin
|
121 |
|
|
if (reqwriteb1) begin // if this is a write operation...
|
122 |
|
|
pendingwriteb1 <= 0; // accept it, and mark pending operation as cleared
|
123 |
|
|
mem[ra1[13:0]] <= rdin1; // put data into virtual SRAM
|
124 |
|
|
rsramwe <= 0; // pulse /WE in SRAM to begin write
|
125 |
|
|
end
|
126 |
|
|
else begin
|
127 |
|
|
pendingreadb1 <= 0; // else, this is a read operation...
|
128 |
|
|
rsramwe <= 1; // we can read from the SRAM data bus itself. Deassert /WE to enable data output bus
|
129 |
|
|
end
|
130 |
|
|
state <= 1; // if either request has been accepted, proceed to next phase.
|
131 |
|
|
end
|
132 |
|
|
end
|
133 |
|
|
1 : begin
|
134 |
|
|
if (reqreadb1) begin // for read requests, read the SRAM data bus and store into the corresponding data output register
|
135 |
|
|
rdout1 <= mem[ra1[13:0]]; // get data from SRAM OLS
|
136 |
|
|
end
|
137 |
|
|
if (reqwriteb1) begin // for write requests, deassert /WE, as writting has already been happened.
|
138 |
|
|
rsramwe <= 1;
|
139 |
|
|
end
|
140 |
|
|
reqreadb1 <= pendingreadb1; // current request has finished, so update current requests with pending requests to serve the next one
|
141 |
|
|
reqwriteb1 <= pendingwriteb1;
|
142 |
|
|
if (pendingreadb1 || pendingwriteb1)
|
143 |
|
|
state <= 0;
|
144 |
|
|
end
|
145 |
|
|
endcase
|
146 |
|
|
end
|
147 |
|
|
|
148 |
|
|
|
149 |
|
|
endmodule
|