forked from raplin/OpenNX4
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexternal_memory_controller.v
259 lines (227 loc) · 6.85 KB
/
external_memory_controller.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// OpenNX4 - Open source firmware for Barco NX4 tiles
// Company: Bohemian Bits
// Engineer: Richard Aplin (Twitter: @DrTune)
// Copyright (C) 2017 Richard Aplin
// Released under the Attribution-NonCommercial 2.0 Generic (CC BY-NC 2.0)
// You may not use this code or a derived work for commercial purposes unless you have a commercial license, contact [email protected]
//////////////////////////////////////////////////////////////////////////////////
// Note this file is incomplete at present and not used
// Create Date: 23:22:20 10/29/2017
// Design Name:
// Module Name: external_memory_controller
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
// SRAM is http://www.cypress.com/file/42801/download
// 256x16, 10ns. Currently we just use a 40mhz clock but we could use both edges (or fire up a PLL)
// In this case it's wired with an 8 bit data bus
// Flash is http://www.cypress.com/file/217501/download
// 2mbit/8 'access time as fast as 70ns'
// require unlock sequence to write
// max address to output delay is 70ns, CE delay is also 70ns, OE is 30ns
module external_memory_controller(
//external device IOs
output reg [19:0] ext_address_bus,
inout [7:0] ext_data_bus,
output reg mem_we, //active low
output reg sram_oe, //active low
output reg sram_bhe, //active low
output reg sram_ble, //active low
output reg flash_ce, //active low
output reg flash_oe, //active low
input flash_ry_by,
input CLK_40,
//internal interface
output reg [7:0] sram_read_data,
input [7:0] sram_write_data,
input [17:0] sram_write_address,
input [17:0] sram_read_address,
output reg sram_read_idle,
input sram_read_req,
input sram_write_req,
output reg sram_write_idle,
output reg [7:0] flash_read_data,
input flash_read_req,
input [7:0] flash_write_data,
input [19:0] flash_write_address,
input [19:0] flash_read_address,
output reg flash_read_idle,
input flash_write_req,
output reg flash_write_idle,
input reset
);
//this is clocked on both edges of the 40mhz (25ns) clock for the sram (10ns) but the flash is 70ns or so
parameter STATE_IDLE =0;
parameter STATE_SRAM_READ =1;
parameter STATE_SRAM_WRITE =2;
parameter STATE_FLASH_READ_SETUP =3;
parameter STATE_FLASH_READ =4;
parameter STATE_FLASH_WRITE_SETUP=5;
parameter STATE_FLASH_WRITE =6;
parameter FLASH_ACCESS_TIME_CYCLES=3; //3 25ns cycles = 75ns
reg [3:0]state;
reg ext_data_is_output=0;
reg [7:0] ext_data_out;
reg [2:0] delay_cycles;
assign ext_data_bus = ext_data_is_output ? ext_data_out : 8'bz;
integer next_state;
always @(posedge CLK_40 or posedge reset)
begin
if (reset) begin
ext_address_bus<=0;
mem_we<=1;
sram_bhe<=1;
sram_ble<=0;
flash_ce<=1;
flash_oe<=1;
flash_read_data<=0;
flash_read_idle<=1;
sram_read_data<=0;
sram_read_idle<=1;
sram_oe<=1;
state<=STATE_IDLE;
flash_write_idle<=1;
sram_write_idle<=1;
end
else
begin
//client de-asserts read_req when they've consumed the data from the last read
//when a client requests an operation we immediately go non-idle on that; the rising edge of idle will be when the operation has been scheduled and done
//note that we don't necessarily sample the address (or data if writing) immediately on deasserting idle - it depends if another operation is running
//we could always latch these if it'd be useful but it's just more gates
//basically the client should also keep asserting their _req and addr/data until the operation is done although in practice once we're out of STATE_IDLE it's been latched.
if (sram_read_req && sram_read_idle) sram_read_idle<=0;
if (sram_write_req && sram_write_idle) sram_write_idle<=0;
if (flash_read_req && flash_read_idle) flash_read_idle<=0;
if (flash_write_req && flash_write_idle) flash_write_idle<=0;
if (delay_cycles>0)begin
delay_cycles<=delay_cycles-1;
end
else
begin
next_state=state;
if (state!=STATE_IDLE)
begin
case (state)
STATE_SRAM_READ:
begin
sram_read_data<=ext_data_bus;
sram_read_idle<=1;
sram_oe<=1;
next_state=STATE_IDLE;
end
STATE_FLASH_READ:
begin
flash_read_data<=ext_data_bus;
flash_read_idle<=1;
flash_oe<=1;
next_state=STATE_IDLE;
end
STATE_SRAM_WRITE:
begin
mem_we<=1;
sram_write_idle<=1;
next_state=STATE_IDLE;
end
STATE_FLASH_WRITE:
begin //todo this should probably stall until any previous write has finished
mem_we<=1;
flash_write_idle<=1;
next_state=STATE_IDLE;
end
default: begin
end
endcase
end
if (next_state==STATE_IDLE)
begin
//first priority is sram reads
if (sram_read_req)
begin
next_state=STATE_SRAM_READ;
flash_oe<=1;
flash_ce<=1;
sram_oe<=0;
mem_we<=1;
sram_ble<=sram_write_address[0];
sram_bhe<=~sram_write_address[0];
ext_data_is_output<=0;
ext_address_bus<=sram_read_address[17:1]; //samples address here
end
else
sram_read_idle<=1;
if (next_state==STATE_IDLE)
begin
if (sram_write_req)
begin
next_state=STATE_SRAM_WRITE;
flash_oe<=1;
flash_ce<=1;
mem_we<=0;
sram_oe<=1;
ext_data_out<=sram_write_data;
ext_data_is_output<=1;
sram_ble<=sram_write_address[0];
sram_bhe<=~sram_write_address[0];
ext_address_bus<=sram_write_address[17:1];
end
else
sram_write_idle<=1;
end
if (next_state==STATE_IDLE)
begin
if (flash_read_req)
begin
next_state=STATE_FLASH_READ;
flash_oe<=0;
flash_ce<=0;
sram_oe<=1;
mem_we<=1;
ext_data_is_output<=0;
ext_address_bus<=flash_read_address[19:0];
delay_cycles<=FLASH_ACCESS_TIME_CYCLES;
end
else
flash_read_idle<=1;
end
if (next_state==STATE_IDLE)
begin
if (flash_write_req)
begin
next_state=STATE_FLASH_WRITE;
flash_oe<=1;
flash_ce<=0;
mem_we<=0;
sram_oe<=1;
ext_data_out<=flash_write_data;
ext_data_is_output<=1;
ext_address_bus<=flash_write_address[19:0];
delay_cycles<=FLASH_ACCESS_TIME_CYCLES;
end
else
flash_write_idle<=1;
end
if (next_state==STATE_IDLE)
begin
flash_oe<=1;
flash_ce<=1;
sram_oe<=1;
mem_we<=1;
end
end
state<=next_state;
end
end
end
endmodule