Verilog for Flash Programmer, First Draft
OK, so I’m working on the Verilog for 3 CPLDs. A memory bank switcher, a UART SPI controller, and a flash programmer that I’ll interface to an Arduino. This is my attempt to write the flash programmer.
The Arduino will use a nCTRL, Din, Dout, CLK, and ENABLE pins to control it serially.
When nCTRL is low, three bits are clocked (CLK high then low) into an address register. Then when nCTRL is high, the data is clocked into the registers addressed by the 3 bit register specified when nCTRL was low.
The comments in the header are no longer accurate. I now have a single clock pulse after nCRTL goes high that just strobes data from the registers to the pins without changing nay register contents. So they need to be updated. But this is the preliminary verilog.
Reg 0: Data read/write Reg 1: Lowest 4 bits of the address Reg 2: Bits 8:5 of the address Reg 3: Bits 17:9 of the address Reg7: nRD, nWR, nCS, and data pin drive.
I’m sure this verilog will be very different once it’s done. I’ll post the test-bench and the final version later.
I’ll also post my C driver on the Arduino and a C# program on my PC.
1 // This module has a set of serial registers that can be used to
2 // interface to an 8 bit wide 2MB chip.
3 // Usage requires a software driver that does the following:
4 //
5 // Reset:
6 // bring pin_ENABLE high,
7 // toggle pin_nCTRL low high low
8 // toggle pin_CLK low high low
9 // bring pin_ENABLE low
10 //
11 // Write A[3:0] bits of address bus;
12 // bring pin_nCTRL low
13 // put 0 on pin_Din
14 // toggle pin_CLK high low
15 // put 0 on pin_Din
16 // toggle pin_CLK high low
17 // put 1 on pin_Din
18 // toggle pin_CLK high low
19 // bring pin_nCTRL high
20 // put A[0] in pin_Din
21 // toggle pin_CLK high low
22 // put A[1] in pin_Din
23 // toggle pin_CLK high low
24 // put A[2] in pin_Din
25 // toggle pin_CLK high low
26 // put A[3] in pin_Din
27 // toggle pin_CLK high low
28 //
29 // Write A[7:4] bits of address bus;
30 // bring pin_nCTRL low
31 // put 0 on pin_Din
32 // toggle pin_CLK high low
33 // put 1 on pin_Din
34 // toggle pin_CLK high low
35 // put 0 on pin_Din
36 // toggle pin_CLK high low
37 // bring pin_nCTRL high
38 // put A[4] in pin_Din
39 // toggle pin_CLK high low
40 // put A[5] in pin_Din
41 // toggle pin_CLK high low
42 // put A[6] in pin_Din
43 // toggle pin_CLK high low
44 // put A[7] in pin_Din
45 // toggle pin_CLK high low
46 //
47 // Write A[17:8] bits of address bus;
48 // bring pin_nCTRL low
49 // put 1 on pin_Din
50 // toggle pin_CLK high low
51 // put 1 on pin_Din
52 // toggle pin_CLK high low
53 // put 0 on pin_Din
54 // toggle pin_CLK high low
55 // bring pin_nCTRL high
56 // put A[8] in pin_Din
57 // toggle pin_CLK high low
58 // put A[9] in pin_Din
59 // toggle pin_CLK high low
60 // put A[10] in pin_Din
61 // toggle pin_CLK high low
62 // put A[11] in pin_Din
63 // toggle pin_CLK high low
64 // put A[12] in pin_Din
65 // toggle pin_CLK high low
66 // put A[13] in pin_Din
67 // toggle pin_CLK high low
68 // put A[14] in pin_Din
69 // toggle pin_CLK high low
70 // put A[15] in pin_Din
71 // toggle pin_CLK high low
72 // put A[16] in pin_Din
73 // toggle pin_CLK high low
74 // put A[17] in pin_Din
75 // toggle pin_CLK high low
76 //
77 // Write RD* WR* CS*
78 // bring pin_nCTRL low
79 // put 1 on pin_Din
80 // toggle pin_CLK high low
81 // put 1 on pin_Din
82 // toggle pin_CLK high low
83 // put 1 on pin_Din
84 // toggle pin_CLK high low
85 // bring pin_nCTRL high
86 // put RD* in pin_Din
87 // toggle pin_CLK high low
88 // put WR* in pin_Din
89 // toggle pin_CLK high low
90 // put CS* in pin_Din
91 // toggle pin_CLK high low
92 //
93 // Write data bus to be asserted while WR* low;
94 // bring pin_nCTRL low
95 // put 0 on pin_Din
96 // toggle pin_CLK high low
97 // put 0 on pin_Din
98 // toggle pin_CLK high low
99 // put 0 on pin_Din
100 // toggle pin_CLK high low
101 // bring pin_nCTRL high
102 // put D[0] in pin_Din
103 // toggle pin_CLK high low
104 // put D[1] in pin_Din
105 // toggle pin_CLK high low
106 // put D[2] in pin_Din
107 // toggle pin_CLK high low
108 // put D[3] in pin_Din
109 // toggle pin_CLK high low
110 // put D[4] in pin_Din
111 // toggle pin_CLK high low
112 // put D[5] in pin_Din
113 // toggle pin_CLK high low
114 // put D[6] in pin_Din
115 // toggle pin_CLK high low
116 // put D[7] in pin_Din
117 // toggle pin_CLK high low
118 //
119 // Load data bus read on RD* rising edge;
120 // bring pin_nCTRL low
121 // put 0 on pin_Din
122 // toggle pin_CLK high low
123 // put 0 on pin_Din
124 // toggle pin_CLK high low
125 // put 0 on pin_Din
126 // toggle pin_CLK high low
127 // bring pin_nCTRL high
128 // toggle pin_CLK high low
129 // data = (data >> 1) | (pin_Dout << 7)
130 // toggle pin_CLK high low
131 // data = (data >> 1) | (pin_Dout << 7)
132 // toggle pin_CLK high low
133 // data = (data >> 1) | (pin_Dout << 7)
134 // toggle pin_CLK high low
135 // data = (data >> 1) | (pin_Dout << 7)
136 // toggle pin_CLK high low
137 // data = (data >> 1) | (pin_Dout << 7)
138 // toggle pin_CLK high low
139 // data = (data >> 1) | (pin_Dout << 7)
140 // toggle pin_CLK high low
141 // data = (data >> 1) | (pin_Dout << 7)
142 // toggle pin_CLK high low
143 // data = (data >> 1) | (pin_Dout << 7)
144 //
145 //
146
147 module cpld(
148 input pin_ENABLE,
149 input pin_CLK,
150 input pin_Din,
151 input pin_nCTRL,
152 output reg pin_Dout,
153
154 output [17:0] pins_A,
155 output reg pin_nWR,
156 output reg pin_nRD,
157 output reg pin_nCS,
158 inout [7:0] pins_D
159 );
160
161 reg [2:0] ctrlReg;
162 reg [7:0] dataReg;
163 reg [17:0] addrReg;
164 reg [3:0] chipReg;
165 reg nOE;
166 reg prev_n_Ctrl;
167
168 wire nRDint;
169 wire nWRint;
170 wire nCSint;
171 wire nOEint;
172
173 assign nRDint = chipReg[0];
174 assign nWRint = chipReg[1];
175 assign nCSint = chipReg[2];
176 assign nOEint = chipReg[3];
177
178 assign pins_D = ((nOE | pin_ENABLE) == 1'b0) ? dataReg : 8'bzzzzzzzz;
179 assign pins_A = (pin_ENABLE == 1'b1) ? addrReg : 18'bzzzzzzzzzzzzzzzzzz;
180
181 always @(posedge pin_CLK) begin
182
183 prev_nCtrl <= pin_nCtrl;
184
185 if (pin_nCTRL == 1'b0) begin
186
187 // clocking in control
188 pin_Dout <= ctrlReg[2];
189 ctrlReg <= {pin_Din, ctrlReg[2:1]};
190
191 if (pin_ENABLE == 1'b1) begin
192 chipReg <= 4'b1111;
193 end
194 end
195 else if (prev_nCtrl == 1'b0) begin
196
197 // first rising pulse after nCtrl was programmed
198
199 // If readinbg, read now
200 if (pin_nRD == 1'b0) begin
201 dataReg <= D;
202 end
203
204 // Strobe out of the chip
205 pins_A <= reg_a;
206 pin_nRD <= nRDint;
207 pin_nWR <= nWRint;
208 pin_nCS <= nCSint;
209 nOE <= nOEint;
210 end
211 else begin
212 case (ctrlReg)
213 3'b000 : begin
214 pin_Dout <= dataReg[0];
215 dataReg <= { pin_Din, dataReg[7:1]};
216 end
217 3'b001 : begin
218 pin_Dout <= addrReg[0];
219 addrReg[3:0] <= { pin_Din, addrReg[3:1]};
220 end
221 3'b010 : begin
222 pin_Dout <= addrReg[4];
223 addrReg[7:4] <= { pin_Din, addrReg[7:5]};
224 end
225 3'b011 : begin
226 pin_Dout <= addrReg[8];
227 addrReg[17:8] <= { pin_Din, addrReg[17:9]};
228 end
229 3'b100 : begin
230 end
231 3'b101 : begin
232 end
233 3'b110 : begin
234 end
235 3'b111 : begin
236 pin_Dout <= chipReg[0];
237 chipReg <= { pin_Din, chipReg[3:1]};
238 end
239 endcase
240 end
241 end
242
243
244 endmodule