summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--PLAN10
-rw-r--r--hdl/core.sv484
-rw-r--r--hdl/top.sv3
3 files changed, 259 insertions, 238 deletions
diff --git a/PLAN b/PLAN
index ffc0ba1..bdf6256 100644
--- a/PLAN
+++ b/PLAN
@@ -1,18 +1,10 @@
1Turn on blinkenlights from the PDP core 1Turn on blinkenlights from the PDP core
2 2
3There's probably a bug in the UART TX code that's dropping characters when it gets full
4
5Debounce switches
6
7Implement switch features: 3Implement switch features:
8 Start 4 Start
9 Load_Add 5 Load_Add
10 Deposit 6 Deposit
11 Examine 7 Examine
12 Continue
13 Stop
14 Single_Step
15 Single_Inst
16 The DF* IF* and SR* data switches 8 The DF* IF* and SR* data switches
17 9
18Don't ignore 6000 and 6001 10Don't ignore 6000 and 6001
@@ -23,6 +15,8 @@ Add "interrupts enabled" flag
23 6001 - enable interrupts (after next instruction) 15 6001 - enable interrupts (after next instruction)
24 6002 - disable interrupts (we should probably do this immediately) 16 6002 - disable interrupts (we should probably do this immediately)
25 17
18Implement remaining TTY output instructions
19
26Jules thinks clock is most likely interrupt source 20Jules thinks clock is most likely interrupt source
27 pdp8 source tries to map clock interrupts to "real time" - we might want to mangle that to make it deterministic 21 pdp8 source tries to map clock interrupts to "real time" - we might want to mangle that to make it deterministic
28 22
diff --git a/hdl/core.sv b/hdl/core.sv
index eceea78..43a4a1a 100644
--- a/hdl/core.sv
+++ b/hdl/core.sv
@@ -8,6 +8,9 @@ module core
8 , input bit reset 8 , input bit reset
9 9
10 , input bit switch_cont 10 , input bit switch_cont
11 , input bit switch_stop
12 , input bit switch_sing_step
13 , input bit switch_sing_inst
11 14
12 // verilator lint_off UNDRIVEN 15 // verilator lint_off UNDRIVEN
13 , output bit [ADDR_BITS-1:0] led_pc 16 , output bit [ADDR_BITS-1:0] led_pc
@@ -40,6 +43,7 @@ module core
40 ); 43 );
41 44
42bit run; 45bit run;
46bit switch_cont_observed;
43assign led_run = run; 47assign led_run = run;
44 48
45bit mem_ready; 49bit mem_ready;
@@ -47,6 +51,7 @@ bit mem_valid;
47bit mem_write; 51bit mem_write;
48bit [ADDR_BITS-1:0] mem_address; 52bit [ADDR_BITS-1:0] mem_address;
49bit [DATA_BITS-1:0] mem_write_data; 53bit [DATA_BITS-1:0] mem_write_data;
54assign led_current_address = mem_valid;
50 55
51assign led_df = 0; 56assign led_df = 0;
52assign led_if = 0; 57assign led_if = 0;
@@ -106,7 +111,6 @@ bit [8:0] operand;
106bit [DATA_BITS-1:0] acc; 111bit [DATA_BITS-1:0] acc;
107bit link; 112bit link;
108 113
109assign led_pc = pc;
110assign led_acc = acc; 114assign led_acc = acc;
111assign led_link = link; 115assign led_link = link;
112 116
@@ -147,17 +151,28 @@ assign led_pause = state == MEMWAIT || state == HALT;
147always_ff @(posedge clk) begin 151always_ff @(posedge clk) begin
148 if (reset) begin 152 if (reset) begin
149 run = 0; 153 run = 0;
154 switch_cont_observed = 0;
150 mem_valid = 0; 155 mem_valid = 0;
151 rx_ready = 0; 156 rx_ready = 0;
152 tx_valid = 0; 157 tx_valid = 0;
153 tx_data = 0; 158 tx_data = 0;
154 pc = 'o200; 159 pc = 'o200;
160 led_pc = pc;
155 acc = 0; 161 acc = 0;
156 link = 1; 162 link = 1;
157 kbd_valid = 0; 163 kbd_valid = 0;
158 state = state.first; 164 state = state.first;
159 end else if (run || switch_cont) begin 165 end else begin
160 run = 1; 166 if (switch_cont && !switch_cont_observed) begin
167 run = 1;
168 switch_cont_observed = 1;
169 end
170
171 if (!switch_cont)
172 switch_cont_observed = 0;
173
174 if (switch_stop)
175 run = 0;
161 176
162 if (`lag(tx_ready)) tx_valid = 0; 177 if (`lag(tx_ready)) tx_valid = 0;
163 if (rx_ready && `lag(rx_valid)) begin 178 if (rx_ready && `lag(rx_valid)) begin
@@ -165,259 +180,268 @@ always_ff @(posedge clk) begin
165 kbd_data = {4'b0, 1'b1, `lag(rx_data[6:0])}; 180 kbd_data = {4'b0, 1'b1, `lag(rx_data[6:0])};
166 end 181 end
167 182
168 case (state) 183 if (run) begin
169 FETCH: begin 184 case (state)
170 mem_valid = 1; 185 FETCH: begin
171 mem_address = pc; 186 mem_valid = 1;
172 mem_write = 0; 187 mem_address = pc;
173 if (`lag(mem_ready)) begin 188 mem_write = 0;
174 state = DECODE; 189 if (`lag(mem_ready)) begin
175 page = pc[ADDR_BITS-1:7]; 190 state = DECODE;
176 ++pc; 191 page = pc[ADDR_BITS-1:7];
192 led_pc = pc;
193 ++pc;
194 end
177 end 195 end
178 end
179 196
180 DECODE: begin 197 DECODE: begin
181 mem_valid = 0; 198 mem_valid = 0;
182 mem_write = 0; 199 mem_write = 0;
183 if (`lag(mem_read_valid)) begin 200 if (`lag(mem_read_valid)) begin
184 state = FETCH; 201 state = FETCH;
185 led_memdata = `lag(mem_read_data); 202 led_memdata = `lag(mem_read_data);
186 {opcode, operand} = `lag(mem_read_data); 203 {opcode, operand} = `lag(mem_read_data);
187// $display("%o: decode %o %o", pc-1, opcode, operand); 204 // $display("%o: decode %o %o", pc-1, opcode, operand);
188 // verilator lint_off WIDTH 205 // verilator lint_off WIDTH
189// $display("%o %b %o 0000", 14'(pc-1), link, acc); 206 // $display("%o %b %o 0000", 14'(pc-1), link, acc);
190 // verilator lint_on WIDTH 207 // verilator lint_on WIDTH
191 {i, z, wip} = operand; 208 {i, z, wip} = operand;
192 if (z) 209 if (z)
193 address = {page, wip}; 210 address = {page, wip};
194 else 211 else
195 address = {5'b0, wip}; 212 address = {5'b0, wip};
196 case (opcode) 213 case (opcode)
197 'o0, 'o1, 'o2: state = i ? INDIRECT : AGEN; 214 'o0, 'o1, 'o2: state = i ? INDIRECT : AGEN;
198 'o3, 'o4: state = i ? INDIRECT : EXEC; 215 'o3, 'o4: state = i ? INDIRECT : EXEC;
199 'o5: begin 216 'o5: begin
200 if (i) begin 217 if (i) begin
201 state = INDIRECT; 218 state = INDIRECT;
202 end else begin 219 end else begin
203 pc = address; 220 pc = address;
204 end
205 end
206 'o7: begin
207 casez (operand)
208 'b0????????: begin
209 automatic bit cla, cll, cma, cml, rar, ral, bsw, iac;
210 {cla, cll, cma, cml, rar, ral, bsw, iac} = operand[7:0];
211 if (cla) acc = 0;
212 if (cll) link = 0;
213 if (cma) acc = ~acc;
214 if (cml) link = ~link;
215 if (iac) {link, acc} += 1;
216 if (rar && !ral) begin
217 {link, acc} = {acc[0], link, acc[11:1]};
218 if (bsw) {link, acc} = {acc[0], link, acc[11:1]};
219 end
220 if (ral && !rar) begin
221 {link, acc} = {acc, link};
222 if (bsw) {link, acc} = {acc, link};
223 end
224 if (bsw && !(rar || ral)) acc = {acc[5:0], acc[11:6]};
225 end
226 'b1????0??0: begin
227 automatic bit cla, sma, sza, snl, osr, hlt;
228 automatic bit skip;
229 {cla, sma, sza, snl, osr, hlt} = {operand[7:4], operand[2:1]};
230 skip = 0;
231 if (sma && acc[11]) skip = 1;
232 if (sza && acc == 0) skip = 1;
233 if (snl && link != 0) skip = 1;
234 if (skip) pc++;
235 if (cla) acc = 0;
236 if (osr) begin
237 $display("%o: unsupported front panel switch test", pc);
238 $finish;
239 end
240 if (hlt) state = HALT;
241 end
242 'b1????1??0: begin
243 automatic bit cla, spa, sna, szl, osr, hlt;
244 automatic bit skip;
245 {cla, spa, sna, szl, osr, hlt} = {operand[7:4], operand[2:1]};
246 skip = 1;
247 if (spa && acc[11]) skip = 0;
248 if (sna && acc == 0) skip = 0;
249 if (szl && link != 0) skip = 0;
250 if (skip) pc++;
251 if (cla) acc = 0;
252 if (osr) begin
253 $display("%o: unsupported front panel switch test", pc);
254 $finish;
255 end
256 if (hlt) state = HALT;
257 end
258 default: begin
259 $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand);
260 $finish;
261 end
262 endcase
263 end
264 'o6: begin
265 case (operand[8:3])
266 'o00: begin
267 case (operand[2:0])
268 'o0, 'o1: ;
269 default: $display("%o: unsupported 600%o op", pc-1, operand[2:0]);
270 endcase
271 end 221 end
272 'o03: begin 222 end
273 case (operand[2:0]) 223 'o7: begin
274 'o1: if (kbd_valid) pc++; 224 casez (operand)
275 'o6: begin 225 'b0????????: begin
276 acc = kbd_data; 226 automatic bit cla, cll, cma, cml, rar, ral, bsw, iac;
277 kbd_valid = 0; 227 {cla, cll, cma, cml, rar, ral, bsw, iac} = operand[7:0];
228 if (cla) acc = 0;
229 if (cll) link = 0;
230 if (cma) acc = ~acc;
231 if (cml) link = ~link;
232 if (iac) {link, acc} += 1;
233 if (rar && !ral) begin
234 {link, acc} = {acc[0], link, acc[11:1]};
235 if (bsw) {link, acc} = {acc[0], link, acc[11:1]};
278 end 236 end
279 default: begin 237 if (ral && !rar) begin
280 $display("%o: unsupported keyboard op %o", pc-1, operand[2:0]); 238 {link, acc} = {acc, link};
281 $finish; 239 if (bsw) {link, acc} = {acc, link};
282 end 240 end
283 endcase 241 if (bsw && !(rar || ral)) acc = {acc[5:0], acc[11:6]};
284 end 242 end
285 'o04: begin 243 'b1????0??0: begin
286 case (operand[2:0]) 244 automatic bit cla, sma, sza, snl, osr, hlt;
287 'o1: if (!tx_valid) pc++; 245 automatic bit skip;
288 'o6: begin 246 {cla, sma, sza, snl, osr, hlt} = {operand[7:4], operand[2:1]};
289 tx_valid = 1; 247 skip = 0;
290 tx_data = {1'b0, acc[6:0]}; 248 if (sma && acc[11]) skip = 1;
249 if (sza && acc == 0) skip = 1;
250 if (snl && link != 0) skip = 1;
251 if (skip) pc++;
252 if (cla) acc = 0;
253 if (osr) begin
254 $display("%o: unsupported front panel switch test", pc);
255 $finish;
291 end 256 end
292 default: begin 257 if (hlt) state = HALT;
293 $display("%o: unsupported tty op %o", pc-1, operand[2:0]); 258 end
259 'b1????1??0: begin
260 automatic bit cla, spa, sna, szl, osr, hlt;
261 automatic bit skip;
262 {cla, spa, sna, szl, osr, hlt} = {operand[7:4], operand[2:1]};
263 skip = 1;
264 if (spa && acc[11]) skip = 0;
265 if (sna && acc == 0) skip = 0;
266 if (szl && link != 0) skip = 0;
267 if (skip) pc++;
268 if (cla) acc = 0;
269 if (osr) begin
270 $display("%o: unsupported front panel switch test", pc);
294 $finish; 271 $finish;
295 end 272 end
296 endcase 273 if (hlt) state = HALT;
297 end 274 end
298 default: begin 275 default: begin
299 $display("%o: unsupported device %o (operation %o)", pc-1, operand[8:3], operand[2:0]); 276 $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand);
277 $finish;
278 end
279 endcase
280 end
281 'o6: begin
282 case (operand[8:3])
283 'o00: begin
284 case (operand[2:0])
285 'o0, 'o1: ;
286 default: $display("%o: unsupported 600%o op", pc-1, operand[2:0]);
287 endcase
288 end
289 'o03: begin
290 case (operand[2:0])
291 'o1: if (kbd_valid) pc++;
292 'o6: begin
293 acc = kbd_data;
294 kbd_valid = 0;
295 end
296 default: begin
297 $display("%o: unsupported keyboard op %o", pc-1, operand[2:0]);
298 $finish;
299 end
300 endcase
301 end
302 'o04: begin
303 case (operand[2:0])
304 'o1: if (!tx_valid) pc++;
305 'o6: begin
306 tx_valid = 1;
307 tx_data = {1'b0, acc[6:0]};
308 end
309 default: begin
310 $display("%o: unsupported tty op %o", pc-1, operand[2:0]);
311 $finish;
312 end
313 endcase
314 end
315 default: begin
316 $display("%o: unsupported device %o (operation %o)", pc-1, operand[8:3], operand[2:0]);
317 end
318 endcase
319 end
320 default: begin
321 $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand);
322 $finish;
323 end
324 endcase
325 end
326 end
327
328 INDIRECT: begin
329 mem_valid = 1;
330 mem_write = 0;
331 mem_address = address;
332 state = `lag(mem_ready) ? INDIRECTED : INDIRECT;
333 end
334
335 INDIRECTED: begin
336 if (`lag(mem_ready)) begin
337 mem_valid = 0;
338 mem_write = 0;
339 end
340 if (`lag(mem_read_valid)) begin
341 if (address[7:3] == 5'b00001) begin
342 led_memdata = `lag(mem_read_data);
343 address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)};
344 address += 1;
345 state = PREINC;
346 end else begin
347 led_memdata = `lag(mem_read_data);
348 address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)};
349 case (opcode)
350 'o0, 'o1, 'o2: state = AGEN;
351 'o3, 'o4: state = EXEC;
352 'o5: begin
353 pc = address;
354 state = FETCH;
300 end 355 end
301 endcase 356 endcase
302 end 357 end
303 default: begin 358 end
304 $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand);
305 $finish;
306 end
307 endcase
308 end 359 end
309 end
310 360
311 INDIRECT: begin 361 PREINC: begin
312 mem_valid = 1; 362 mem_valid = 1;
313 mem_write = 0; 363 mem_write = 1;
314 mem_address = address; 364 mem_write_data = address[DATA_BITS-1:0];
315 state = `lag(mem_ready) ? INDIRECTED : INDIRECT; 365 led_memdata = mem_write_data;
316 end 366 case (opcode)
367 'o0, 'o1, 'o2: state = `lag(mem_ready) ? AGEN : PREINC;
368 'o3, 'o4, 'o5: state = `lag(mem_ready) ? EXEC : PREINC;
369 endcase
370 end
317 371
318 INDIRECTED: begin 372 AGEN: begin
319 if (`lag(mem_ready)) begin 373 mem_valid = 1;
320 mem_valid = 0; 374 case (opcode)
321 mem_write = 0; 375 'o0, 'o1, 'o2: mem_write = 0;
376 endcase
377 mem_address = address;
378 state = `lag(mem_ready) ? EXEC : AGEN;
322 end 379 end
323 if (`lag(mem_read_valid)) begin 380
324 if (address[7:3] == 5'b00001) begin 381 EXEC: begin
325 led_memdata = `lag(mem_read_data); 382 automatic bit stall = 0;
326 address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; 383 if (`lag(mem_ready)) begin
327 address += 1; 384 mem_valid = 0;
328 state = PREINC; 385 mem_write = 0;
329 end else begin 386 end else if (mem_valid) begin
330 led_memdata = `lag(mem_read_data); 387 stall = 1;
331 address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; 388 end
389 case (opcode)
390 'o0, 'o1, 'o2: if (! `lag(mem_read_valid)) stall = 1;
391 endcase
392 if (! stall) begin
393 state = FETCH;
332 case (opcode) 394 case (opcode)
333 'o0, 'o1, 'o2: state = AGEN; 395 'o0: begin led_memdata = `lag(mem_read_data); acc &= `lag(mem_read_data); end
334 'o3, 'o4: state = EXEC; 396 'o1: begin led_memdata = `lag(mem_read_data); {link, acc} += {1'b0, `lag(mem_read_data)}; end
335 'o5: begin 397 'o2: begin
336 pc = address; 398 mem_valid = 1;
337 state = FETCH; 399 mem_address = address;
400 mem_write = 1;
401 mem_write_data = `lag(mem_read_data) + 1;
402 led_memdata = mem_write_data;
403 if (mem_write_data == 0) ++pc;
404 state = MEMWAIT;
405 end
406 'o3: begin
407 mem_valid = 1;
408 mem_address = address;
409 mem_write = 1;
410 mem_write_data = acc;
411 led_memdata = mem_write_data;
412 acc = 0;
413 state = MEMWAIT;
338 end 414 end
415 'o4: begin
416 mem_valid = 1;
417 mem_address = address;
418 mem_write = 1;
419 mem_write_data = pc[DATA_BITS-1:0];
420 led_memdata = mem_write_data;
421 pc = address + 1;
422 state = MEMWAIT;
423 end
424 'o5: pc = address;
339 endcase 425 endcase
340 end 426 end
341 end 427 end
342 end
343
344 PREINC: begin
345 mem_valid = 1;
346 mem_write = 1;
347 mem_write_data = address[DATA_BITS-1:0];
348 led_memdata = mem_write_data;
349 case (opcode)
350 'o0, 'o1, 'o2: state = `lag(mem_ready) ? AGEN : PREINC;
351 'o3, 'o4, 'o5: state = `lag(mem_ready) ? EXEC : PREINC;
352 endcase
353 end
354 428
355 AGEN: begin 429 MEMWAIT: state = `lag(mem_ready) ? FETCH : MEMWAIT;
356 mem_valid = 1;
357 case (opcode)
358 'o0, 'o1, 'o2: mem_write = 0;
359 endcase
360 mem_address = address;
361 state = `lag(mem_ready) ? EXEC : AGEN;
362 end
363 430
364 EXEC: begin 431 HALT: begin
365 automatic bit stall = 0; 432 $display("\nhalt state reached");
366 if (`lag(mem_ready)) begin 433 $finish;
367 mem_valid = 0;
368 mem_write = 0;
369 end else if (mem_valid) begin
370 stall = 1;
371 end 434 end
372 case (opcode) 435 endcase
373 'o0, 'o1, 'o2: if (! `lag(mem_read_valid)) stall = 1;
374 endcase
375 if (! stall) begin
376 state = FETCH;
377 case (opcode)
378 'o0: begin led_memdata = `lag(mem_read_data); acc &= `lag(mem_read_data); end
379 'o1: begin led_memdata = `lag(mem_read_data); {link, acc} += {1'b0, `lag(mem_read_data)}; end
380 'o2: begin
381 mem_valid = 1;
382 mem_address = address;
383 mem_write = 1;
384 mem_write_data = `lag(mem_read_data) + 1;
385 led_memdata = mem_write_data;
386 if (mem_write_data == 0) ++pc;
387 state = MEMWAIT;
388 end
389 'o3: begin
390 mem_valid = 1;
391 mem_address = address;
392 mem_write = 1;
393 mem_write_data = acc;
394 led_memdata = mem_write_data;
395 acc = 0;
396 state = MEMWAIT;
397 end
398 'o4: begin
399 mem_valid = 1;
400 mem_address = address;
401 mem_write = 1;
402 mem_write_data = pc[DATA_BITS-1:0];
403 led_memdata = mem_write_data;
404 pc = address + 1;
405 state = MEMWAIT;
406 end
407 'o5: pc = address;
408 endcase
409 end
410 end
411 436
412 MEMWAIT: state = `lag(mem_ready) ? FETCH : MEMWAIT; 437 if (switch_sing_step)
438 run = 0;
413 439
414 HALT: begin 440 if (state == FETCH && switch_sing_inst)
415 $display("\nhalt state reached"); 441 run = 0;
416 $finish;
417 end
418 endcase
419 442
420 rx_ready = !kbd_valid; 443 rx_ready = !kbd_valid;
444 end
421 end 445 end
422end 446end
423 447
diff --git a/hdl/top.sv b/hdl/top.sv
index 214ea1b..00225ee 100644
--- a/hdl/top.sv
+++ b/hdl/top.sv
@@ -114,6 +114,9 @@ core cpu
114 , .reset(reset) 114 , .reset(reset)
115 115
116 , .switch_cont(switch_cont) 116 , .switch_cont(switch_cont)
117 , .switch_stop(switch_stop)
118 , .switch_sing_step(switch_sing_step)
119 , .switch_sing_inst(switch_sing_inst)
117 120
118 , .led_pc(led_pc) 121 , .led_pc(led_pc)
119 , .led_memaddr(led_memaddr) 122 , .led_memaddr(led_memaddr)