4 * Zilog 8530 SCC module for minimigmac.
6 * Located on high data bus, but writes are done at odd addresses as
7 * LDS is used as WR signals or something like that on a Mac Plus.
9 * We don't care here and just ignore which side was used.
11 * NOTE: We don't implement the 85C30 or ESCC additions such as WR7'
12 * for now, it's all very simplified
15 module scc(input sysclk,
18 /* Bus interface. 2-bit address, to be wired
19 * appropriately upstream (to A1..A2).
23 input [1:0] rs, /* [1] = data(1)/ctl [0] = a_side(1)/b_side */
28 /* A single serial port on Minimig */
31 input cts, /* normally wired to device DTR output
32 * on Mac cables. That same line is also
33 * connected to the TRxC input of the SCC
34 * to do fast clocking but we don't do that
37 output rts, /* on a real mac this activates line
40 /* DCD for both ports are hijacked by mouse interface */
41 input dcd_a, /* We don't synchronize those inputs */
48 /* Register access is semi-insane */
57 /* Resets via WR9, one clk pulses */
78 /* Write registers. Only some are implemented,
79 * some result in actions on write and don't
132 wire [2:0] rr2_vec_stat;
134 /* Register/Data access helpers */
135 assign wreg_a = cs & we & (~rs[1]) & rs[0];
136 assign wreg_b = cs & we & (~rs[1]) & ~rs[0];
137 assign wdata_a = cs & we & (rs[1] | (rindex == 8)) & rs[0];
138 assign wdata_b = cs & we & (rs[1] | (rindex == 8)) & ~rs[0];
139 assign rdata_a = cs & (~we) & (rs[1] | (rindex == 8)) & rs[0];
140 assign rdata_b = cs & (~we) & (rs[1] | (rindex == 8)) & ~rs[0];
142 /* Register index is set by a write to WR0 and reset
143 * after any subsequent write. We ignore the side
145 always@(posedge sysclk or posedge reset) begin
148 else if (cs && !rs[1]) begin
149 /* Default, reset index */
153 if (we && rindex == 0) begin
154 /* Get low index bits */
155 rindex[2:0] <= wdata[2:0];
158 rindex[3] <= (wdata[5:3] == 3'b001);
163 /* Reset logic (write to WR9 cmd)
165 * Note about resets: Some bits are documented as unchanged/undefined on
166 * HW reset by the doc. We apply this to channel and soft resets, however
167 * we _do_ reset every bit on an external HW reset in this implementation
168 * to make the FPGA & synthesis tools happy.
170 assign reset = ((wreg_a | wreg_b) & (rindex == 9) & (wdata[7:6] == 2'b11)) | reset_hw;
171 assign reset_a = ((wreg_a | wreg_b) & (rindex == 9) & (wdata[7:6] == 2'b10)) | reset;
172 assign reset_b = ((wreg_a | wreg_b) & (rindex == 9) & (wdata[7:6] == 2'b01)) | reset;
175 * Reset: bit 5 and 2 unchanged */
176 always@(posedge sysclk or posedge reset_hw) begin
181 wr1_a <= { 2'b00, wr1_a[5], 2'b00, wr1_a[2], 2'b00 };
182 else if (wreg_a && rindex == 1)
186 always@(posedge sysclk or posedge reset_hw) begin
191 wr1_b <= { 2'b00, wr1_b[5], 2'b00, wr1_b[2], 2'b00 };
192 else if (wreg_b && rindex == 1)
200 always@(posedge sysclk or posedge reset_hw) begin
203 else if ((wreg_a || wreg_b) && rindex == 2)
208 * Reset: bit 0 to 0, otherwise unchanged.
210 always@(posedge sysclk or posedge reset_hw) begin
216 else if (wreg_a && rindex == 3)
220 always@(posedge sysclk or posedge reset_hw) begin
226 else if (wreg_b && rindex == 3)
232 * Reset: Bit 2 to 1, otherwise unchanged
234 always@(posedge sysclk or posedge reset_hw) begin
240 else if (wreg_a && rindex == 4)
244 always@(posedge sysclk or posedge reset_hw) begin
250 else if (wreg_b && rindex == 4)
256 * Reset: Bits 7,4,3,2,1 to 0
258 always@(posedge sysclk or posedge reset_hw) begin
263 wr5_a <= { 1'b0, wr5_a[6:5], 4'b0000, wr5_a[0] };
264 else if (wreg_a && rindex == 5)
268 always@(posedge sysclk or posedge reset_hw) begin
273 wr5_b <= { 1'b0, wr5_b[6:5], 4'b0000, wr5_b[0] };
274 else if (wreg_b && rindex == 5)
282 always@(posedge sysclk or posedge reset_hw) begin
285 else if (wreg_a && rindex == 6)
288 always@(posedge sysclk or posedge reset_hw) begin
291 else if (wreg_b && rindex == 6)
298 always@(posedge sysclk or posedge reset_hw) begin
301 else if (wreg_a && rindex == 7)
304 always@(posedge sysclk or posedge reset_hw) begin
307 else if (wreg_b && rindex == 7)
311 /* WR9. Special: top bits are reset, handled separately, bottom
312 * bits are only reset by a hw reset
314 always@(posedge sysclk or posedge reset_hw) begin
317 else if ((wreg_a || wreg_b) && rindex == 9)
322 * Reset: all 0, except chanel reset retains 6 and 5
324 always@(posedge sysclk or posedge reset) begin
329 wr10_a <= { 1'b0, wr10_a[6:5], 5'b00000 };
330 else if (wreg_a && rindex == 10)
334 always@(posedge sysclk or posedge reset) begin
339 wr10_b <= { 1'b0, wr10_b[6:5], 5'b00000 };
340 else if (wreg_b && rindex == 10)
346 * Reset: On full reset only, not channel reset
348 always@(posedge sysclk or posedge reset) begin
350 wr11_a <= 8'b00001000;
351 else if (wreg_a && rindex == 11)
354 always@(posedge sysclk or posedge reset) begin
356 wr11_b <= 8'b00001000;
357 else if (wreg_b && rindex == 11)
364 always@(posedge sysclk or posedge reset_hw) begin
367 else if (wreg_a && rindex == 12)
370 always@(posedge sysclk or posedge reset_hw) begin
373 else if (wreg_b && rindex == 12)
380 always@(posedge sysclk or posedge reset_hw) begin
383 else if (wreg_a && rindex == 13)
386 always@(posedge sysclk or posedge reset_hw) begin
389 else if (wreg_b && rindex == 13)
394 * Reset: Full reset maintains top 2 bits,
395 * Chan reset also maitains bottom 2 bits, bit 4 also
396 * reset to a different value
398 always@(posedge sysclk or posedge reset_hw) begin
403 wr14_a <= { wr14_a[7:6], 6'b110000 };
405 wr14_a <= { wr14_a[7:6], 4'b1000, wr14_a[1:0] };
406 else if (wreg_a && rindex == 14)
410 always@(posedge sysclk or posedge reset_hw) begin
415 wr14_b <= { wr14_b[7:6], 6'b110000 };
417 wr14_b <= { wr14_b[7:6], 4'b1000, wr14_b[1:0] };
418 else if (wreg_b && rindex == 14)
424 always@(posedge sysclk or posedge reset) begin
426 wr15_a <= 8'b11111000;
427 else if (wreg_a && rindex == 15)
430 always@(posedge sysclk or posedge reset) begin
432 wr15_b <= 8'b11111000;
433 else if (wreg_b && rindex == 15)
438 assign rdata = rs[1] && rs[0] ? data_a :
440 rindex == 0 && rs[0] ? rr0_a :
441 rindex == 0 ? rr0_b :
442 rindex == 1 && rs[0] ? rr1_a :
443 rindex == 1 ? rr1_b :
444 rindex == 2 && rs[0] ? wr2 :
445 rindex == 2 ? rr2_b :
446 rindex == 3 && rs[0] ? rr3_a :
448 rindex == 4 && rs[0] ? rr0_a :
449 rindex == 4 ? rr0_b :
450 rindex == 5 && rs[0] ? rr1_a :
451 rindex == 5 ? rr1_b :
452 rindex == 6 && rs[0] ? wr2 :
453 rindex == 6 ? rr2_b :
454 rindex == 7 && rs[0] ? rr3_a :
457 rindex == 8 && rs[0] ? data_a :
458 rindex == 8 ? data_b :
459 rindex == 9 && rs[0] ? wr13_a :
460 rindex == 9 ? wr13_b :
461 rindex == 10 && rs[0] ? rr10_a :
462 rindex == 10 ? rr10_b :
463 rindex == 11 && rs[0] ? rr15_a :
464 rindex == 11 ? rr15_b :
465 rindex == 12 && rs[0] ? wr12_a :
466 rindex == 12 ? wr12_b :
467 rindex == 13 && rs[0] ? wr13_a :
468 rindex == 13 ? wr13_b :
469 rindex == 14 && rs[0] ? rr10_a :
470 rindex == 14 ? rr10_b :
471 rindex == 15 && rs[0] ? rr15_a :
472 rindex == 15 ? rr15_b : 8'hff;
475 assign rr0_a = { 1'b0, /* Break */
476 1'b1, /* Tx Underrun/EOM */
478 1'b0, /* Sync/Hunt */
479 wr15_a[3] ? dcd_latch_a : dcd_a, /* DCD */
481 1'b0, /* Zero Count */
482 1'b0 /* Rx Available */
484 assign rr0_b = { 1'b0, /* Break */
485 1'b1, /* Tx Underrun/EOM */
487 1'b0, /* Sync/Hunt */
488 wr15_b[3] ? dcd_latch_b : dcd_b, /* DCD */
490 1'b0, /* Zero Count */
491 1'b0 /* Rx Available */
495 assign rr1_a = { 1'b0, /* End of frame */
496 1'b0, /* CRC/Framing error */
497 1'b0, /* Rx Overrun error */
498 1'b0, /* Parity error */
499 1'b0, /* Residue code 0 */
500 1'b1, /* Residue code 1 */
501 1'b1, /* Residue code 2 */
505 assign rr1_b = { 1'b0, /* End of frame */
506 1'b0, /* CRC/Framing error */
507 1'b0, /* Rx Overrun error */
508 1'b0, /* Parity error */
509 1'b0, /* Residue code 0 */
510 1'b1, /* Residue code 1 */
511 1'b1, /* Residue code 2 */
515 /* RR2 (Chan B only, A is just WR2) */
516 assign rr2_b = { wr2[7],
517 wr9[4] ? rr2_vec_stat[0] : wr2[6],
518 wr9[4] ? rr2_vec_stat[1] : wr2[5],
519 wr9[4] ? rr2_vec_stat[2] : wr2[4],
520 wr9[4] ? wr2[3] : rr2_vec_stat[2],
521 wr9[4] ? wr2[2] : rr2_vec_stat[1],
522 wr9[4] ? wr2[1] : rr2_vec_stat[0],
527 /* RR3 (Chan A only) */
528 assign rr3_a = { 2'b0,
529 rx_irq_pend_a, /* Rx interrupt pending */
530 tx_irq_pend_a, /* Tx interrupt pending */
531 ex_irq_pend_a, /* Status/Ext interrupt pending */
538 assign rr10_a = { 1'b0, /* One clock missing */
539 1'b0, /* Two clocks missing */
541 1'b0, /* Loop sending */
547 assign rr10_b = { 1'b0, /* One clock missing */
548 1'b0, /* Two clocks missing */
550 1'b0, /* Loop sending */
558 assign rr15_a = { wr15_a[7],
568 assign rr15_b = { wr15_b[7],
578 /* Interrupts. Simplified for now
580 * Need to add latches. Tx irq is latched when buffer goes from full->empty,
581 * it's not a permanent state. For now keep it clear. Will have to fix that.
583 assign rx_irq_pend_a = 0;
584 assign tx_irq_pend_a = 0 /*& wr1_a[1]*/; /* Tx always empty for now */
585 assign ex_irq_pend_a = ex_irq_ip_a;
586 assign rx_irq_pend_b = 0;
587 assign tx_irq_pend_b = 0 /*& wr1_b[1]*/; /* Tx always empty for now */
588 assign ex_irq_pend_b = ex_irq_ip_b;
590 assign _irq = ~(wr9[3] & (rx_irq_pend_a |
597 /* XXX Verify that... also missing special receive condition */
598 assign rr2_vec_stat = rx_irq_pend_a ? 3'b110 :
599 tx_irq_pend_a ? 3'b100 :
600 ex_irq_pend_a ? 3'b101 :
601 rx_irq_pend_b ? 3'b010 :
602 tx_irq_pend_b ? 3'b000 :
603 ex_irq_pend_b ? 3'b001 : 3'b011;
605 /* External/Status interrupt & latch logic */
606 assign do_extreset_a = wreg_a & (rindex == 0) & (wdata[5:3] == 3'b010);
607 assign do_extreset_b = wreg_b & (rindex == 0) & (wdata[5:3] == 3'b010);
609 /* Internal IP bit set if latch different from source and
610 * corresponding interrupt is enabled in WR15
612 assign dcd_ip_a = (dcd_a != dcd_latch_a) & wr15_a[3];
613 assign dcd_ip_b = (dcd_b != dcd_latch_b) & wr15_b[3];
615 /* Latches close when an enabled IP bit is set and latches
618 assign do_latch_a = latch_open_a & (dcd_ip_a /* | cts... */);
619 assign do_latch_b = latch_open_b & (dcd_ip_b /* | cts... */);
621 /* "Master" interrupt, set when latch close & WR1[0] is set */
622 always@(posedge sysclk or posedge reset) begin
625 else if (do_extreset_a)
627 else if (do_latch_a && wr1_a[0])
630 always@(posedge sysclk or posedge reset) begin
633 else if (do_extreset_b)
635 else if (do_latch_b && wr1_b[0])
639 /* Latch open/close control */
640 always@(posedge sysclk or posedge reset) begin
650 always@(posedge sysclk or posedge reset) begin
662 always@(posedge sysclk or posedge reset) begin
668 dcd_latch_a <= dcd_a;
672 always@(posedge sysclk or posedge reset) begin
678 dcd_latch_b <= dcd_b;