Finalizing Flash Programmer CPLD
OK, getting the flash programmer CPLD verilog finalized. This one seems to work as I want it to. It lets me have fine control over low address bits, coarse control over high ones, and control over the RD, WR, and CS going to the flash chip as well as when to drive the data lines and when to read in the read data from the flash.
1 // This module has a set of serial registers that can be used to
2 // interface to an 8 bit wide 2MB chip.
3 // drive/strobe rd works by driving data when RD is high or pos edge
4 // of CLK reads in while nRD is low
5 //
6 // Toggle nCtrl high low high to strobe chip control register to pins
7 // Usage requires a software driver that does the following:
8 //
9 // Reset:
10 // bring pin_ENABLE high,
11 // bring pin_nCTRL high
12 // toggle pin_CLK low high low
13 // bring pin_nCTRL low
14 // toggle pin_CLK low high low
15 // toggle pin_CLK low high low
16 // toggle pin_CLK low high low
17 // bring pin_nCTRL high
18 // bring pin_ENABLE low
19 //
20 // Write A[3:0] bits of address bus;
21 // bring pin_nCTRL low
22 // put 0 on pin_Din
23 // toggle pin_CLK high low
24 // put 0 on pin_Din
25 // toggle pin_CLK high low
26 // put 1 on pin_Din
27 // toggle pin_CLK high low
28 // bring pin_nCTRL high
29 // put A[0] in pin_Din
30 // toggle pin_CLK high low
31 // put A[1] in pin_Din
32 // toggle pin_CLK high low
33 // put A[2] in pin_Din
34 // toggle pin_CLK high low
35 // put A[3] in pin_Din
36 // toggle pin_CLK high low
37 //
38 // Write A[7:4] bits of address bus;
39 // bring pin_nCTRL low
40 // put 0 on pin_Din
41 // toggle pin_CLK high low
42 // put 1 on pin_Din
43 // toggle pin_CLK high low
44 // put 0 on pin_Din
45 // toggle pin_CLK high low
46 // bring pin_nCTRL high
47 // put A[4] in pin_Din
48 // toggle pin_CLK high low
49 // put A[5] in pin_Din
50 // toggle pin_CLK high low
51 // put A[6] in pin_Din
52 // toggle pin_CLK high low
53 // put A[7] in pin_Din
54 // toggle pin_CLK high low
55 //
56 // Write A[17:8] bits of address bus;
57 // bring pin_nCTRL low
58 // put 1 on pin_Din
59 // toggle pin_CLK high low
60 // put 1 on pin_Din
61 // toggle pin_CLK high low
62 // put 0 on pin_Din
63 // toggle pin_CLK high low
64 // bring pin_nCTRL high
65 // put A[8] in pin_Din
66 // toggle pin_CLK high low
67 // put A[9] in pin_Din
68 // toggle pin_CLK high low
69 // put A[10] in pin_Din
70 // toggle pin_CLK high low
71 // put A[11] in pin_Din
72 // toggle pin_CLK high low
73 // put A[12] in pin_Din
74 // toggle pin_CLK high low
75 // put A[13] in pin_Din
76 // toggle pin_CLK high low
77 // put A[14] in pin_Din
78 // toggle pin_CLK high low
79 // put A[15] in pin_Din
80 // toggle pin_CLK high low
81 // put A[16] in pin_Din
82 // toggle pin_CLK high low
83 // put A[17] in pin_Din
84 // toggle pin_CLK high low
85 //
86 // Write drive/rdstrobe RD* WR* CS*
87 // bring pin_nCTRL low
88 // put 1 on pin_Din
89 // toggle pin_CLK high low
90 // put 1 on pin_Din
91 // toggle pin_CLK high low
92 // put 1 on pin_Din
93 // toggle pin_CLK high low
94 // bring pin_nCTRL high
95 // put RD* in pin_Din
96 // toggle pin_CLK high low
97 // put WR* in pin_Din
98 // toggle pin_CLK high low
99 // put CS* in pin_Din
100 // toggle pin_CLK high low
101 // put drive/rdstrobe in pin_Din
102 // toggle pin_CLK high low
103 //
104 // Write data bus to be asserted while WR* low;
105 // bring pin_nCTRL low
106 // put 0 on pin_Din
107 // toggle pin_CLK high low
108 // put 0 on pin_Din
109 // toggle pin_CLK high low
110 // put 0 on pin_Din
111 // toggle pin_CLK high low
112 // bring pin_nCTRL high
113 // put D[0] in pin_Din
114 // toggle pin_CLK high low
115 // put D[1] in pin_Din
116 // toggle pin_CLK high low
117 // put D[2] in pin_Din
118 // toggle pin_CLK high low
119 // put D[3] in pin_Din
120 // toggle pin_CLK high low
121 // put D[4] in pin_Din
122 // toggle pin_CLK high low
123 // put D[5] in pin_Din
124 // toggle pin_CLK high low
125 // put D[6] in pin_Din
126 // toggle pin_CLK high low
127 // put D[7] in pin_Din
128 // toggle pin_CLK high low
129 //
130 // Load data bus read on RD* rising edge;
131 // bring pin_nCTRL low
132 // put 0 on pin_Din
133 // toggle pin_CLK high low
134 // put 0 on pin_Din
135 // toggle pin_CLK high low
136 // put 0 on pin_Din
137 // toggle pin_CLK high low
138 // bring pin_nCTRL high
139 // toggle pin_CLK high low
140 // data = (data >> 1) | (pin_Dout << 7)
141 // toggle pin_CLK high low
142 // data = (data >> 1) | (pin_Dout << 7)
143 // toggle pin_CLK high low
144 // data = (data >> 1) | (pin_Dout << 7)
145 // toggle pin_CLK high low
146 // data = (data >> 1) | (pin_Dout << 7)
147 // toggle pin_CLK high low
148 // data = (data >> 1) | (pin_Dout << 7)
149 // toggle pin_CLK high low
150 // data = (data >> 1) | (pin_Dout << 7)
151 // toggle pin_CLK high low
152 // data = (data >> 1) | (pin_Dout << 7)
153 // toggle pin_CLK high low
154 // data = (data >> 1) | (pin_Dout << 7)
155 //
156 //
157
158
159 `define ACTIVELOW 1'b0
160 `define ACTIVEHIGH 1'b1
161
162 module flashProgrammer(
163 input pin_ENABLE,
164 input pin_CLK,
165 input pin_Din,
166 input pin_nCTRL,
167 output reg pin_Dout,
168
169 output [17:0] pins_A,
170 output pin_nWR,
171 output pin_nRD,
172 output pin_nCS,
173 inout [7:0] pins_D
174 );
175
176 reg [2:0] ctrlReg;
177 reg [7:0] dataReg;
178 reg [17:0] addrReg;
179 reg [3:0] chipReg;
180 wire nOE;
181 reg nRDint;
182 reg nWRint;
183 reg nCSint;
184 reg nOEint;
185 assign pin_nRD = nRDint | pin_ENABLE;
186 assign pin_nWR = nWRint | pin_ENABLE;
187 assign pin_nCS = nCSint | pin_ENABLE;
188 assign nOE = nOEint | pin_ENABLE;
189 assign pins_D = (nOE==`ACTIVELOW && pin_ENABLE==`ACTIVELOW && pin_nRD==1'b1) ? dataReg : 8'bzzzzzzzz;
190 assign pins_A = (pin_ENABLE == `ACTIVELOW) ? addrReg : 18'bzzzzzzzzzzzzzzzzzz;
191 always @(posedge pin_nCTRL) begin
192 // Strobe out of the chip
193 nRDint <= chipReg[0];
194 nWRint <= chipReg[1];
195 nCSint <= chipReg[2];
196 nOEint <= chipReg[3];
197 end
198 always @(posedge pin_CLK) begin
199 if (pin_nCTRL == `ACTIVELOW) begin
200 // clocking in control
201 pin_Dout <= ctrlReg[2];
202 ctrlReg <= {pin_Din, ctrlReg[2:1]};
203 if (pin_ENABLE == 1'b1) begin
204 chipReg <= 4'b1111;
205 end
206 end
207 else begin
208 case (ctrlReg)
209 3'b000 : begin
210 pin_Dout <= dataReg[0];
211 dataReg <= { pin_Din, dataReg[7:1]};
212 end
213 3'b001 : begin
214 pin_Dout <= addrReg[0];
215 addrReg[3:0] <= { pin_Din, addrReg[3:1]};
216 end
217 3'b010 : begin
218 pin_Dout <= addrReg[4];
219 addrReg[7:4] <= { pin_Din, addrReg[7:5]};
220 end
221 3'b011 : begin
222 pin_Dout <= addrReg[8];
223 addrReg[17:8] <= { pin_Din, addrReg[17:9]};
224 end
225 3'b100 : begin
226 end
227 3'b101 : begin
228 end
229 3'b110 : begin
230 end
231 3'b111 : begin
232 pin_Dout <= chipReg[0];
233 chipReg <= { pin_Din, chipReg[3:1]};
234 // If reading, read now
235 if ((pin_nRD | nOE) == `ACTIVELOW) begin
236 dataReg <= pins_D;
237 end
238 end
239 endcase
240 end
241 end
242 endmodule
And here is the test bench:
1 // TOOL: vlog2tf
2 // DATE: 07/11/15 10:39:08
3 // TITLE: Lattice Semiconductor Corporation
4 // MODULE: flashProgrammer
5 // DESIGN: flashProgrammer
6 // FILENAME: flashProgrammer.tft
7 // PROJECT: flashprog
8 // VERSION: 1.0
9 // This file is auto generated by the ispLEVER
10
11
12
13 `timescale 1 ns / 1 ns
14
15
16 // Define Module for Test Fixture
17
18 module flashProgrammer_tf();
19
20 // Inputs
21
22
23 reg pin_ENABLE;
24 reg pin_CLK;
25 reg pin_Din;
26 reg pin_nCTRL;
27
28 // Outputs
29 wire pin_Dout;
30 wire [17:0] pins_A;
31 wire pin_nWR;
32 wire pin_nRD;
33 wire pin_nCS;
34
35 // Bidirs
36 wire [7:0] pins_D;
37
38 // Instantiate the UUT
39
40
41 flashProgrammer UUT (
42 .pin_ENABLE(pin_ENABLE),
43 .pin_CLK(pin_CLK),
44 .pin_Din(pin_Din),
45 .pin_nCTRL(pin_nCTRL),
46 .pin_Dout(pin_Dout),
47 .pins_A(pins_A),
48 .pin_nWR(pin_nWR),
49 .pin_nRD(pin_nRD),
50 .pin_nCS(pin_nCS),
51 .pins_D(pins_D)
52 );
53
54
55 flash simFlash (
56 .A(pins_A),
57 .D(pins_D),
58 .nWR(pin_nWR),
59 .nRD(pin_nRD),
60 .nCS(pin_nCS)
61 );
62
63 reg [2:0] ctrlToSend;
64 reg [17:0] aToSend;
65 reg [7:0] dToSend;
66 reg [3:0] cswrrdToSend;
67 reg [7:0] dRcvd;
68 reg [7:0] dShift;
69
70
71
72
73 initial begin
74
75
76 resetSequence();
77 write(17'h12345, 8'haa);
78 simFlash.testRdD = 8'hC3;
79 $display("simFlash.testRdD = %h", simFlash.testRdD);
80 read(17'h0abcd, dRcvd);
81 resetSequence();
82
83
84 write(17'h14567, 8'h55);
85 write(17'h14568, 8'h77);
86
87
88 simFlash.testRdD = 8'h3C;
89 $display("simFlash.testRdD = %h", simFlash.testRdD);
90 read(17'h19876, dRcvd);
91 simFlash.testRdD = 8'h55;
92 read(17'h19877, dRcvd);
93 #10
94 $finish;
95 end
96
97
98 task resetSequence;
99 begin
100 aToSend = 0;
101 dToSend = 0;
102 pin_ENABLE = 1;
103 pin_CLK = 0;
104 pin_Din = 0;
105 pin_nCTRL = 1;
106
107
108 pulseClk();
109
110
111 #5
112 pin_nCTRL = 0; // negedge resets outputs:w
113
114 pulseClk(); // CLK pulse resets flash_control
115 pulseClk(); // CLK pulse resets flash_control
116 pulseClk(); // CLK pulse resets flash_control
117 #5
118 pin_nCTRL = 1; // stobes chip control out
119 #5
120 pin_ENABLE = 0;
121 end
122 endtask
123
124
125 task write;
126 input [17:0] A;
127 input [7:0] D;
128 begin
129 $display("Writing %h to %h.", D, A);
130 setFullAddress(A);
131 setCtrl(3'b000);
132 sendData(D);
133 setCtrl(3'b111);
134 setDriveCsWrRd(0, 0, 1, 1); // drive, CS
135 pulseCtrl();
136 setDriveCsWrRd(0, 0, 0, 1); // drive CS WR
137 pulseCtrl();
138 setDriveCsWrRd(0, 0, 1, 1); // drive CS
139 pulseCtrl();
140 setDriveCsWrRd(1, 1, 1, 1); // done
141 pulseCtrl();
142 $display("SimFlash saw %h<-%h", simFlash.testWrA, simFlash.testWrD);
143
144
145 if (A != simFlash.testWrA) begin
146 $display("ERROR!");
147 $finish;
148 end
149 if (D != simFlash.testWrD) begin
150 $display("ERROR!");
151 $finish;
152 end
153 end
154 endtask
155
156
157 task read;
158 input [17:0] A;
159 output [7:0] D;
160 begin
161 $display("Reading %h.", A);
162 setFullAddress(A);
163 setCtrl(3'b111);
164 setDriveCsWrRd(0, 0, 1, 0); // drive CS RD
165 pulseCtrl();
166 setDriveCsWrRd(1, 0, 1, 0); // CS RD
167 pulseCtrl();
168 setDriveCsWrRd(1, 1, 1, 1); // done
169 pulseCtrl();
170 setCtrl(3'b000);
171 recvData();
172 D = dShift;
173 dShift = 8'bxxxxxxxx;
174 $display("Read %h", D);
175 $display("SimFlash saw %h", simFlash.testRdA);
176 if (D != simFlash.testRdD) begin
177 $display("ERROR!");
178 $finish;
179 end
180 end
181 endtask
182
183
184 task setFullAddress;
185 input [17:0] A;
186 begin
187 if (A[3:0] != aToSend[3:0]) begin
188 //$display("Writing A[3:0]");
189 setCtrl(3'b001);
190 setAddr3_0(A[3:0]);
191 end
192 if (A[7:4] != aToSend[7:4]) begin
193 //$display("Writing A[7:4]");
194 setCtrl(3'b010);
195 setAddr7_4(A[7:4]);
196 end
197 if (A[17:8] != aToSend[17:8]) begin
198 //$display("Writing A[17:8]");
199 setCtrl(3'b011);
200 setAddr17_8(A[17:8]);
201 end
202 end
203 endtask
204
205
206 task setCtrl;
207 input [2:0] regNo;
208 begin
209 ctrlToSend = regNo;
210 #5
211 pin_nCTRL = 0;
212 pin_Din = ctrlToSend[0];
213 pulseClk();
214 pin_Din = ctrlToSend[1];
215 pulseClk();
216 pin_Din = ctrlToSend[2];
217 pulseClk();
218 #5
219 pin_nCTRL = 1;
220 end
221 endtask
222
223 task pulseCtrl;
224 begin
225 #5
226 pin_nCTRL = 0;
227 #5
228 pin_nCTRL = 1;
229 end
230 endtask
231
232 task pulseClk;
233 begin
234 #2
235 pin_CLK = 0;
236 #5
237 pin_CLK = 1;
238 #2
239 pin_CLK = 0;
240 end
241 endtask
242
243
244
245
246
247 task setAddr3_0;
248 input [3:0] addrPart;
249 begin
250 aToSend[3:0] = addrPart;
251 pin_Din = aToSend[0];
252 pulseClk();
253 pin_Din = aToSend[1];
254 pulseClk();
255 pin_Din = aToSend[2];
256 pulseClk();
257 pin_Din = aToSend[3];
258 pulseClk();
259 end
260 endtask
261
262
263 task setAddr7_4;
264 input [3:0] addrPart;
265 begin
266 aToSend[7:4] = addrPart;
267 pin_Din = aToSend[4];
268 pulseClk();
269 pin_Din = aToSend[5];
270 pulseClk();
271 pin_Din = aToSend[6];
272 pulseClk();
273 pin_Din = aToSend[7];
274 pulseClk();
275 end
276 endtask
277
278
279 task setAddr17_8;
280 input [9:0] addrPart;
281 begin
282 aToSend[17:8] = addrPart;
283 pin_Din = aToSend[8];
284 pulseClk();
285 pin_Din = aToSend[9];
286 pulseClk();
287 pin_Din = aToSend[10];
288 pulseClk();
289 pin_Din = aToSend[11];
290 pulseClk();
291 pin_Din = aToSend[12];
292 pulseClk();
293 pin_Din = aToSend[13];
294 pulseClk();
295 pin_Din = aToSend[14];
296 pulseClk();
297 pin_Din = aToSend[15];
298 pulseClk();
299 pin_Din = aToSend[16];
300 pulseClk();
301 pin_Din = aToSend[17];
302 pulseClk();
303 end
304 endtask
305
306
307 task setDriveCsWrRd;
308 input rqDrive;
309 input rqCs;
310 input rqWr;
311 input rqRd;
312 begin
313 cswrrdToSend = { rqDrive, rqCs, rqWr, rqRd };
314 pin_Din = cswrrdToSend[0];
315 pulseClk();
316 pin_Din = cswrrdToSend[1];
317 pulseClk();
318 pin_Din = cswrrdToSend[2];
319 pulseClk();
320 pin_Din = cswrrdToSend[3];
321 pulseClk();
322 end
323 endtask
324
325 task sendData;
326 input [7:0] data;
327 begin
328 dToSend = data;
329 pin_Din = dToSend[0];
330 pulseClk();
331 pin_Din = dToSend[1];
332 pulseClk();
333 pin_Din = dToSend[2];
334 pulseClk();
335 pin_Din = dToSend[3];
336 pulseClk();
337 pin_Din = dToSend[4];
338 pulseClk();
339 pin_Din = dToSend[5];
340 pulseClk();
341 pin_Din = dToSend[6];
342 pulseClk();
343 pin_Din = dToSend[7];
344 pulseClk();
345 end
346 endtask
347
348 task recvData;
349 begin
350 pulseClk();
351 dShift[0] = pin_Dout;
352 pulseClk();
353 dShift[1] = pin_Dout;
354 pulseClk();
355 dShift[2] = pin_Dout;
356 pulseClk();
357 dShift[3] = pin_Dout;
358 pulseClk();
359 dShift[4] = pin_Dout;
360 pulseClk();
361 dShift[5] = pin_Dout;
362 pulseClk();
363 dShift[6] = pin_Dout;
364 pulseClk();
365 dShift[7] = pin_Dout;
366 end
367
368 endtask
369 endmodule // flashProgrammer_tf
370
371 module flash(
372 input [78:0] A,
373 inout [7:0] D,
374 input nWR,
375 input nRD,
376 input nCS,
377 );
378
379 reg [7:0] testWrD;
380 reg [17:0] testWrA;
381 reg [7:0] testRdD;
382 reg [17:0] testRdA;
383
384 assign D = ((nRD | nCS) == 1'b0) ? testRdD : 8'bzzzzzzzz;
385
386 always @(posedge nRD) begin
387 if (nCS == 1'b0) begin
388 testRdA <= A;
389 end
390 end
391
392 always @(posedge nWR) begin
393
394 if (nCS == 1'b0) begin
395 testWrA <= A;
396 testWrD <= D;
397 end
398 end
399
400 endmodule