blob: cd33c11b34ce4c88390e5c4a703506e6b41fa166 [file] [log] [blame]
dineshannayya52e8a342022-02-15 14:19:56 +05301`default_nettype none
2/*
3 * SPDX-FileCopyrightText: 2022 <Dinesh Annayya>
4 *
5 * Riscdunio
6 *
7 * Copyright (C) 2022 Dinesh Annayya <dinesha.opencore.org>
8 *
9 * Permission to use, copy, modify, and/or distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 * SPDX-License-Identifier: ISC
22 */
23
24`timescale 1 ns / 1 ps
25
26//
27// Simple SPI Ram simulation model for 128Kx8 LOW VOLTAGE, FAST SERIAL SRAM
28// (IS62/65WVS1288GALL)
29//
30// This model samples io input signals 1ns before the SPI clock edge and
31// updates output signals 1ns after the SPI clock edge.
32//
33// Supported commands:
34// 0x03, 0x02, 0x3B , 0x38, 0xFF, 0x05 , 0x01
35// Instruction Hex Description
36// READ 0x03 Read data from memory array beginning at selected address
37// WRITE 0x02 Write data to memory array beginning at selected address
38// ESDI 0x3B Enter SDI mode
39// ESQI 0x38 Enter SQI mode
40// RSTDQI 0xFF Reset SDI/SQI mode
41// RDMR 0x05 Read Mode Register
42// WRMR 0x01 Write Mode Register
43//
44
45module spiram #(
46 parameter mem_file_name = "firmware.hex"
47)(
48 input csb,
49 input clk,
50 inout io0, // MOSI
51 inout io1, // MISO
52 inout io2,
53 inout io3
54);
55 localparam verbose = 0;
56 localparam integer latency = 8;
57
58 reg [7:0] buffer;
59 reg [3:0] reset_count = 0;
60 reg [3:0] reset_monitor = 0;
61 integer bitcount = 0;
62 integer bytecount = 0;
63 integer dummycount = 0;
64
65 reg [7:0] spi_cmd;
66 reg [23:0] spi_addr;
67
68 reg [7:0] spi_in;
69 reg [7:0] spi_out;
70 reg spi_io_vld;
71
72
73 localparam [1:0] sspi = 1;
74 localparam [1:0] dspi = 2;
75 localparam [1:0] qspi = 3;
76
77 localparam [3:0] mode_sspi_rd = 1;
78 localparam [3:0] mode_sspi_wr = 2;
79 localparam [3:0] mode_dspi_rd = 3;
80 localparam [3:0] mode_dspi_wr = 4;
81 localparam [3:0] mode_qspi_rd = 5;
82 localparam [3:0] mode_qspi_wr = 6;
83
84 reg [3:0] spi_phase = mode_sspi_rd;
85 reg [3:0] spi_data_phase = 0;
86 reg [3:0] spi_mode = sspi;
87
88 reg io0_oe = 0;
89 reg io1_oe = 0;
90 reg io2_oe = 0;
91 reg io3_oe = 0;
92
93 reg io0_dout = 0;
94 reg io1_dout = 0;
95 reg io2_dout = 0;
96 reg io3_dout = 0;
97
98 assign #1 io0 = io0_oe ? io0_dout : 1'bz;
99 assign #1 io1 = io1_oe ? io1_dout : 1'bz;
100 assign #1 io2 = io2_oe ? io2_dout : 1'bz;
101 assign #1 io3 = io3_oe ? io3_dout : 1'bz;
102
103 wire io0_delayed;
104 wire io1_delayed;
105 wire io2_delayed;
106 wire io3_delayed;
107
108 assign #1 io0_delayed = io0;
109 assign #1 io1_delayed = io1;
110 assign #1 io2_delayed = io2;
111 assign #1 io3_delayed = io3;
112
113 // 128KB RAM
114 reg [7:0] memory [0:128*1024-1];
115
116 initial begin
117 if (!(mem_file_name == "none"))
118 $readmemh(mem_file_name,memory);
119 end
120
121 task spi_action;
122 begin
123 spi_in = buffer;
124
125 if (bytecount == 1) begin
126 spi_cmd = buffer;
127
128 if (spi_cmd == 8'h 3b) begin
129 spi_mode = dspi;
130 end
131
132 if (spi_cmd == 8'h 38) begin
133 spi_mode = qspi;
134 end
135
136 if (spi_cmd == 8'h ff) begin
137 spi_mode = sspi;
138 end
139
140 // spi read
141 if (spi_cmd == 8'h 03 && spi_mode == sspi)
142 spi_phase = mode_sspi_rd;
143
144 // spi write
145 if (spi_cmd == 8'h 02 && spi_mode == sspi)
146 spi_phase = mode_sspi_wr;
147
148 // dual spi read
149 if (spi_cmd == 8'h 03 && spi_mode == dspi)
150 spi_phase = mode_dspi_rd;
151
152 // dual spi write
153 if (spi_cmd == 8'h 02 && spi_mode == dspi)
154 spi_phase = mode_dspi_wr;
155
156 // quad spi read
157 if (spi_cmd == 8'h 03 && spi_mode == qspi)
158 spi_phase = mode_qspi_rd;
159
160 // quad spi write
161 if (spi_cmd == 8'h 02 && spi_mode == qspi)
162 spi_phase = mode_qspi_wr;
163 end
164
165 if (spi_cmd == 'h 03 || (spi_cmd == 'h 02)) begin
166 if (bytecount == 2)
167 spi_addr[23:16] = buffer;
168
169 if (bytecount == 3)
170 spi_addr[15:8] = buffer;
171
172 if (bytecount == 4) begin
173 spi_addr[7:0] = buffer;
174 spi_data_phase = spi_phase;
175 end
176
177 // Dummy by selection at end of address phase for read
178 // mode only
179 if (bytecount == 4 && spi_mode == sspi && spi_cmd ==8'h03 )
180 dummycount = 8;
181 if (bytecount == 4 && spi_mode == dspi && spi_cmd ==8'h03)
182 dummycount = 4;
183 if (bytecount == 4 && spi_mode == qspi && spi_cmd ==8'h03)
184 dummycount = 2;
185
186 if (bytecount >= 4 && spi_cmd ==8'h03) begin // Data Read Phase
187 buffer = memory[spi_addr];
188 //$display("%m: Read Memory Address: %x Data: %x",spi_addr,buffer);
189 spi_addr = spi_addr + 1;
190 end
191 if (bytecount > 4 && spi_cmd ==8'h02) begin // Data Write Phase
192 memory[spi_addr] = buffer;
193 //$display("%m: Write Memory Address: %x Data: %x",spi_addr,buffer);
194 spi_addr = spi_addr + 1;
195 end
196 end
197
198 spi_out = buffer;
199 spi_io_vld = 1;
200
201 if (verbose) begin
202 if (bytecount == 1)
203 $write("<SPI-START>");
204 $write("<SPI:%02x:%02x>", spi_in, spi_out);
205 end
206
207 end
208 endtask
209
210
211 always @(csb) begin
212 if (csb) begin
213 if (verbose) begin
214 $display("");
215 $fflush;
216 end
217 buffer = 0;
218 bitcount = 0;
219 bytecount = 0;
220 io0_oe = 0;
221 io1_oe = 0;
222 io2_oe = 0;
223 io3_oe = 0;
224 spi_data_phase = 0;
225
226 end
227 end
228
229
230 always @(csb, clk) begin
231 spi_io_vld = 0;
232 if (!csb && !clk) begin
233 if (dummycount > 0) begin
234 io0_oe = 0;
235 io1_oe = 0;
236 io2_oe = 0;
237 io3_oe = 0;
238 end else
239 case (spi_data_phase)
240 mode_sspi_rd: begin
241 io0_oe = 0;
242 io1_oe = 1;
243 io2_oe = 0;
244 io3_oe = 0;
245 io1_dout = buffer[7];
246 end
247 mode_sspi_wr: begin
248 io0_oe = 0;
249 io1_oe = 0;
250 io2_oe = 0;
251 io3_oe = 0;
252 end
253 mode_dspi_wr: begin
254 io0_oe = 0;
255 io1_oe = 0;
256 io2_oe = 0;
257 io3_oe = 0;
258 end
259 mode_dspi_rd: begin
260 io0_oe = 1;
261 io1_oe = 1;
262 io2_oe = 0;
263 io3_oe = 0;
264 io0_dout = buffer[6];
265 io1_dout = buffer[7];
266 end
267 mode_qspi_wr: begin
268 io0_oe = 0;
269 io1_oe = 0;
270 io2_oe = 0;
271 io3_oe = 0;
272 end
273 mode_qspi_rd: begin
274 io0_oe = 1;
275 io1_oe = 1;
276 io2_oe = 1;
277 io3_oe = 1;
278 io0_dout = buffer[4];
279 io1_dout = buffer[5];
280 io2_dout = buffer[6];
281 io3_dout = buffer[7];
282 end
283 default: begin
284 io0_oe = 0;
285 io1_oe = 0;
286 io2_oe = 0;
287 io3_oe = 0;
288 end
289 endcase
290 end
291 end
292
293 always @(posedge clk) begin
294 if (!csb) begin
295 if (dummycount > 0) begin
296 dummycount = dummycount - 1;
297 end else
298 case (spi_mode)
299 sspi: begin
300 buffer = {buffer, io0};
301 bitcount = bitcount + 1;
302 if (bitcount == 8) begin
303 bitcount = 0;
304 bytecount = bytecount + 1;
305 spi_action;
306 end
307 end
308 dspi: begin
309 buffer = {buffer, io1, io0};
310 bitcount = bitcount + 2;
311 if (bitcount == 8) begin
312 bitcount = 0;
313 bytecount = bytecount + 1;
314 spi_action;
315 end
316 end
317 qspi: begin
318 buffer = {buffer, io3, io2, io1, io0};
319 bitcount = bitcount + 4;
320 if (bitcount == 8) begin
321 bitcount = 0;
322 bytecount = bytecount + 1;
323 spi_action;
324 end
325 end
326 endcase
327 end
328 end
329endmodule