-
Notifications
You must be signed in to change notification settings - Fork 22
/
vm2_wb.v
2025 lines (1859 loc) · 63.8 KB
/
vm2_wb.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//
// Copyright (c) 2014-2019 by 1801BM1@gmail.com
//______________________________________________________________________________
//
// Wishbone compatible version of 1801VM2 processor
// has 2 dedicated wishbone interfaces:
// - master interface, on this one VM2 core performs addressed I/O, the address
// most significant bit is for sel (high means access to halt mode space)
// - interrupt vector interface for interrupt acknowlegement and
// unaddressed read access (wbi_una_o tag is high)
//
module vm2_wb
#(parameter
//______________________________________________________________________________
//
// If VM2_CORE_FIX_PREFETCH is nonzero the PC2 prefetch bugfix is applied.
//
// Original 1801BM2 processor contains microcode bug at the following conditions:
// - two operands PDP-11 instruction is being executed
// - source has addressing method @PC, -(PC) or @-(PC)
// - destination does not involve PC (dst register field !=7)
// - no extra instruction words are used by destination (no E(Rn), @E(Rn))
// - Q-bus is slow and opcode prefetch is not completed before microcode
// starts source field processing and fetching the source data (slow RPLY/AR)
//
// The bug is related to inapropriate handling of buffer instruction register,
// if Q-bus slow and the prefetch is in not complete the CPU waits for completion
// and requests the another prefetch to BIR. The microcode fix is very complicated
// hence the approach to wait prefectch completion was chosen.
//
// If zero parameter is specified the model follows the original 1801BM2 behaviour
// (with prefetch bug).
//
VM2_CORE_FIX_PREFETCH = 0
)
(
//
// Processor core clock section:
// - vm_clk_p - processor core positive clock, also feeds the wishbone buses
// - vm_clk_n - processor core negative clock, should be vm_clk_p 180 degree phase shifted
// - vm_clk_ena - slow clock simulation strobe, enables clock at vm_clk_p
// - vm_clk_slow - clock mode selector, enables clock slowdown simulation,
// the external I/O cycles is launched with rate of vm_clk_ena
//
input vm_clk_p, // positive edge clock
input vm_clk_n, // negative edge clock
input vm_clk_ena, // slow clock enable
input vm_clk_slow, // slow clock sim mode
//
output vm_init, // peripheral reset output
input vm_dclo, // processor reset
input vm_aclo, // power fail notificaton
input vm_halt, // halt mode interrupt
input vm_evnt, // timer interrupt requests
input vm_virq, // vectored interrupt request
//
// adr MSB is halt mode flag
input wbm_gnt_i, // master wishbone granted
output wbm_ios_o, // master wishbone I/O select
output [16:0] wbm_adr_o, // master wishbone address
output [15:0] wbm_dat_o, // master wishbone data output
input [15:0] wbm_dat_i, // master wishbone data input
output wbm_cyc_o, // master wishbone cycle
output wbm_we_o, // master wishbone direction
output [1:0] wbm_sel_o, // master wishbone byte selection
output wbm_stb_o, // master wishbone strobe
input wbm_ack_i, // master wishbone acknowledgement
//
input [15:0] wbi_dat_i, // interrupt vector input
input wbi_ack_i, // interrupt vector acknowledgement
output wbi_stb_o, // interrupt vector strobe
output wbi_una_o // unaddressed read access
);
//______________________________________________________________________________
//
reg virq, halt, evnt; // interrupt requests
//
reg ac0; // initial ACLO rising edge detected
reg dble_cnt0; // double QBUS timeout error counter
reg dble_cnt1; //
reg evnt_fall; // EVNT rising edge detector
reg aclo_fall; // ACLO falling edge detector
reg aclo_rise; // ACLO rising edge detector
//
wire evnt_ack; // clear system timer request
wire aclo_ack; // clear system ACLO requests
wire tovf_ack; // clear Q-bus timeout request
//
reg acok_rq; // nACLO rise interrupt request
reg aclo_rq; // nACLO fall interrupt request
reg tout_rq; // bus timeout exception request
reg dble_rq; // double bus timeout request
reg evnt_rq; // system timer interrupt request
reg vec_stb; // vector interrupt acknowlegement
//
reg sel; //
wire init; //
reg init_out; //
reg adr_req; //
reg drdy; //
reg rdat; //
//
wire io_start; // start IO transaction
wire io_rdy; //
wire io_in; // prefetch cmd & read data
wire io_wr; //
wire io_rd; //
wire io_sel; //
wire io_wri; //
wire io_iak; //
wire io_alt; //
wire io_x001; //
wire io_rcd; //
reg io_rcd1; //
wire io_rcd1_xt; //
wire io_cmd; //
reg io_cmdr; //
reg io_rcdr; //
reg io_pswr; //
//
reg iop_in; // prefetch cmd & read data
reg iop_rcd; // prefetch cmd
reg iop_una; // unaddressed access
wire iop_stb; // IO opcode strobe
reg iop_sta; //
//
wire reset; // system reset
wire abort; // abort by bus timeout
wire mc_res; // microcode reset
reg mc_stb; // mc read phase strobe
wire pi_stb_rc; // peripheral strobe
reg pi_stb; //
wire all_rdy; //
reg alu_nrdy; // ALU not ready
reg sta_nrdy; // branch state not ready
reg cmd_nrdy; // instruction completion
wire pli_nrdy; // interrupt polling not ready
reg tim_nrdy0; // wait abort exception status
reg tim_nrdy1; // wait nINIT pulse generation
wire mc_rdy_rc; //
reg br_iocmd; // instruction read IO in progress
reg br_ready; // breg contains valid read instruction
reg ir_stb; //
wire bir_stb; //
wire bra_req; //
wire mdfy; // write modifies prefetched location
wire tena; // Q-bus timer count enable
wire tovf; // Q-bus timeout interrupt
wire thang; // prefetch was timed out
//
reg rta_fall; //
wire creq; //
reg get_state; //
wire wt_state_rc; //
wire set_cend_rc; //
reg set_cend; // set command end flag
reg acmp_en; // PC address comparator enable
wire rcmd_set; //
//
reg [15:0] ireg; // primary instruction register
reg [15:0] breg; // prefetch instruction register
reg [5:0] ia; // microinstuction address register
reg [2:0] ri; // interrupt acknowlegement register
reg [2:0] ix; // auxiliary conditions register
//
reg [11:0] br; // branch processing matrix input register
wire [15:0] qri; // interrupt processing matrix input aliases
wire [9:0] pli; // interrupt priority encode matrix output
wire [11:0] pld; // preliminary instruction decoder matrix output
wire plb; // branch processing matrix output
//
wire [5:0] na_rc; //
reg [5:0] na; // microcode next address field
reg [30:0] plm; // main matrix result register (first stage)
reg [30:21] plm_wt; //
wire [30:21] plr; //
wire [36:0] pla; //
//
reg [4:0] plm_rn; //
wire [6:0] rn_wa; //
wire pc2_wa; //
wire wa_pc; // program counter selected
wire wa_r1, wa_r2; //
wire ra_wa; // write address register from X*-bus
wire ra_wx; // write address register from X-bus
reg ra_fw; //
wire ra_fwn; //
wire ra_fr, ra_fr1; //
wire ra_fr_rc, ra_fwn_rc; //
wire pc1_wr, pc_wax; //
wire pc_wr; //
wire rs_wa, acc_wa; //
wire cpsw_wa; //
wire cpsw_stb; //
wire ea1_wa, ea2_wa; //
wire ea_ctld; //
wire pswt_wa; //
wire psw_wa, psw8_wa; //
wire psw_stb, pswc_stb; //
wire wr_psw; //
wire qswp, rd2h; //
reg qa0; //
reg wr7; // read command start cycle
//
reg [15:0] cmux; // constant generator multiplexer
wire [3:0] csel; // constant generator selector
reg [7:0] vmux; // vector generator multiplexer
wire [3:0] vsel; // vector generator selector
//
reg [15:0] ea22; // extended arithmetics register 2.2
reg [15:0] ear1; // extended arithmetics register 1
reg [15:0] ear2; // extended arithmetics register 2
reg [15:0] acc; // accumulator
reg [15:0] sreg; // source register
reg [15:0] r[6:0]; // general purpose register files
reg [15:0] pc2; // prefetch PC pointer
reg [15:0] pc1; // actual PC pointer
reg [15:0] cpc; // copy of PC saved for halt mode
wire [8:0] psw_rc; //
reg [8:0] psw; // PSW
reg [8:0] cpsw; // PSW copy
reg [15:0] qreg; // ALU Q register (Q-bus data)
reg [15:0] areg; // ALU A register (Q-bus address)
//
wire [15:0] alu_inx; // ALU X operand selector
wire [15:0] alu_iny; // ALU Y operand selector
wire [15:0] alu_an; // ALU operands 'and'
wire [15:0] alu_or; // ALU operands 'or'
wire [15:0] alu_cf; // ALU carry
wire [15:0] alu_cp; //
wire [15:0] alu_af; // ALU function
wire [15:0] alu_sh; //
reg [15:0] alu_fr; // ALU function register
reg [15:0] alu_cr; // ALU carry register
reg [15:0] xb; // ALU result register
wire [15:0] xbo; // byte xchanger output
wire [15:0] ax; // ALU X* output bus
reg [15:0] x; // ALU X input multiplexer
reg [15:0] y; // ALU Y input multiplexer
//
wire alu_cin; //
wire alu_a, alu_b; // ALU function controls
wire alu_c, alu_d; //
wire alu_e, alu_f; //
wire alu_g; //
wire rshift, lshift, nshift; // ALU shifter controls
wire sh_ci1, sh_ci2, sh_ci3; //
wire alu_xb; //
//
wire sf_sum; //
reg sf_inv, sf_dir; //
reg sf_lr, sf_rr; //
reg sf_sub; //
reg sf_byte; //
reg sf_xchg; //
reg sxt_y; //
wire sxt_rxy; //
wire axy_wh; //
//
wire zl, zh, eq1; //
wire ea_22z; //
reg ea_20r; //
//
wire cond_c0; //
wire cond_c1; //
wire cond_c2; //
//
wire cond_c; //
wire cond_v; //
wire cond_z; //
wire cond_n; //
//
wire plm1m; //
wire plm13m; //
wire plm14m; //
wire plm18m; //
wire plm19m; //
wire plm20m; //
//
wire en_alu_rc; //
wire mc_drdy_rc; //
reg mc_drdy0, mc_drdy1; //
reg [1:0] alu_st; // ALU state machine
reg [5:0] iocmd_st; //
reg [1:0] iopc_st; //
reg [5:1] io_st; //
reg buf_res; //
reg bir_fix; // need prefetch fix needed decoded
wire wr1; // ALU read args phase strobe
wire wr2; // ALU write result phase strobe
wire alu_wr; // ALU write result
wire brd_wq; // buffer data register write from Q-bus
wire brd_wa; // buffer data register write from ALU
//
reg pli_arq; // interrupt query after IO abort
reg pli_ack; // interrupt module ack
wire pli_req; // interrupt module query
wire sd_word; //
reg word27; //
reg pli6r; //
reg pli8r; //
reg wcpu; //
reg tbit; //
//
reg dc_b7; //
wire dc_f2; //
wire dc_i7; //
wire dc_j7; //
wire dc_bi; //
wire dc_fl; //
wire dc_aux; //
reg dc_fb; //
reg dc_rtt; //
reg dc_iord; //
reg dc_iowr; //
wire alt_cnst; //
//
reg ea_nrdy; // EA unit internal operations
wire ea_shr; //
wire ea_vdiv; //
wire ea_mxin; //
reg ea_mxinr; //
wire ea_muls; //
wire sh_cin; //
wire [15:0] ea_mux; //
wire ea_sh2; //
wire ea_shl; //
wire ea_shr2; //
wire ea_div; //
wire ea_mul; //
wire ea_mop0, ea_mop1; //
wire ea_rdy; //
reg ea_trdy0, ea_trdy1; //
wire ea_trdy0_set; //
wire ea_trdy0_clr; //
wire ea_trdy1_clr; //
reg ea_trdy2_clr; //
//
reg tlz; //
reg wait_div; //
reg zero_div; //
reg div_vfr; // sticky division overflow flag
wire div_vf; // result division overflow flag
//
reg [4:0] ea_ct; // internal EA phase counter
wire [4:0] ea_cta; //
reg ea_1tm, ea_1tc; // first cycle after counter load
reg [20:0] ea_f; // counter phases
reg ea_f0r, ea_f4r; //
reg ea_fn23r; //
reg ea_fn12; //
reg ea_f218; //
wire ea_ctse; //
//
wire eas_dir; //
wire eas_left; //
wire eas_right; //
//
reg bra; //
reg bra_stb; //
wire ws_cend, ws_wait; //
//
reg [8:0] qtim; // Q-bus/nINIT timer counter
reg tend; // Q-bus/nINIT timer counting end pulse
reg tadone; // suppress repetitive timeout aborts
reg tabort; // Q-bus false reply strobe
reg tevent; // Q-bus timeout exception request
wire tout; // Q-bus/nINIT timer 1/64 pulses
//
reg br_cmdrq; // breg read cmd request
wire to_block; // block false reply on timeout
wire wra; //
reg to_rply; //
//
//______________________________________________________________________________
//
reg [16:0] wb_adr; // Wishbone master output address
reg [15:0] wb_dat; // Wishbone master input data
//
wire wb_start; //
wire wb_wclr, wb_wset; //
reg wb_swait; //
reg [5:0] wb_wcnt; //
//
reg wb_cyc; //
reg wb_stb; //
reg wb_we; //
reg [1:0] wb_sel; //
reg wb_una; //
reg wb_iak; //
wire wb_wdone, //
wb_rdone, //
wb_idone; //
wire wb_done; //
//
wire wio_ia_rc, wio_ia, // interrupt acknowledgement
wio_ua_rc, wio_ua, // unaddressed read
wio_wr_rc, wio_wr, // write operation
wio_rd_rc, wio_rd, // read operation
wio_wo_rc, wio_wo, // word operation
wio_dc_rc; // decoded IO operations
//
reg wio_ia_xt, //
wio_ua_xt, //
wio_wr_xt, //
wio_rd_xt, //
wio_wo_xt; //
//______________________________________________________________________________
//
// Reset and phase clock generator
//
assign init = init_out | vm_dclo;
assign vm_init = init;
always @(posedge vm_clk_p)
begin
if (reset | tout)
init_out <= 1'b0;
else
if (pi_stb & plm[13])
init_out <= 1'b1;
end
always @(posedge vm_clk_p)
begin
//
// ac0 flag is introduced to wait nACLO raise
// reset will not be deasserted till the nACLO rise
//
if (reset)
ac0 <= 1'b0;
else
if (pli_ack)
ac0 <= pli[3];
end
assign reset = vm_dclo | (~ac0 & vm_aclo);
assign mc_res = abort | reset;
//______________________________________________________________________________
//
// Interrupt inputs latches
//
always @(posedge vm_clk_p)
begin
evnt <= vm_evnt & ~init;
halt <= vm_halt;
virq <= vm_virq;
end
//______________________________________________________________________________
//
// QBus state machine
//
assign creq = wb_cyc | adr_req;
always @(posedge vm_clk_p)
begin
if (iop_sta | mc_res)
rta_fall <= 1'b0;
else
if (wra)
rta_fall <= 1'b1;
end
always @(posedge vm_clk_n)
begin
if (mc_res | to_block | iop_sta)
adr_req <= 1'b0;
else
if (wra)
adr_req <= 1'b1;
end
always @(posedge vm_clk_n) to_rply <= iop_rcd & ~word27 & tabort & ~to_rply;
assign io_iak = (plr[24:21] == 4'b1111); // Interrupt acknowlegement
assign io_sel = (plr[24:21] == 4'b1011) // Unaddressed read
| (plr[24:21] == 4'b1101); //
assign io_rcd = (plr[24:21] == 4'b0111); // Read command ahead
assign io_cmd = (plr[24:21] == 4'b0010) // Read command
| (plr[24:21] == 4'b0110); //
assign io_wri = (plr[24:21] == 4'b0100) // Write data
| (plr[24:21] == 4'b0101); // Write alt data
assign io_alt = (plr[24:21] == 4'b0011) // Read alternating space
| (plr[24:21] == 4'b0101); // Write alternating space
assign io_x001 = (plr[24:21] == 4'b0001) // Operation is defined
| (plr[24:21] == 4'b1001); // by dc_mop field
assign io_wr = (io_x001 & dc_iowr) | io_wri;
assign io_rd = (io_x001 & dc_iord) | plr[22];
assign io_in = io_rcd | (io_rd & ~io_cmd);
assign io_rcd1_xt = ra_fr1 & na[1];
always @(posedge vm_clk_p) if (wr1) iop_una <= io_iak | io_sel;
always @(posedge vm_clk_n) if (wr2) io_rcd1 <= io_rcd1_xt;
always @(posedge vm_clk_p)
begin
if (iop_stb)
iop_in <= io_in;
if (to_rply)
iop_rcd <= 1'b0;
else
if (iop_stb)
iop_rcd <= io_rcd;
end
always @(posedge vm_clk_p)
begin
if (wb_done)
drdy <= 1'b0;
else
if (brd_wa)
drdy <= 1'b1;
end
//______________________________________________________________________________
//
// Q-bus timer, also involved in INIT command pulse timing
//
assign tout = qtim[0] & qtim[2] & qtim[4] & qtim[5];
always @(posedge vm_clk_n)
begin
if (!tena)
qtim <= 9'o000;
else
qtim <= qtim + 9'o001;
//
// Single shot pulse at the timer counting ends
//
if (!tena | tend)
tend <= 1'b0;
else
tend <= (qtim == 9'o776);
//
// Q-bus false reply strobe
//
if (!tena | tabort | tend | tadone)
tabort <= 1'b0;
else
tabort <= ~tim_nrdy1 & qtim[0] & qtim[1] & qtim[4] & qtim[5];
//
// Suppress multiple timeout abort requests
//
if (!tena)
tadone <= 1'b0;
else
if (tabort)
tadone <= 1'b1;
end
always @(posedge vm_clk_p)
tevent <= tabort & (~iop_rcd | word27);
//______________________________________________________________________________
//
// QBus and INIT timer counter
//
assign tena = ~reset & (pli_nrdy | (wbm_stb_o & wbm_gnt_i) | wbi_stb_o);
assign tovf = tevent | thang;
assign pli_nrdy = tend | tim_nrdy0 | tim_nrdy1;
always @(posedge vm_clk_p)
begin
//
// tim_nrdy0 is used to stop mcu for waiting
// Q-bus abort exception status from interrupt unit
//
if (reset | pli_arq & ~abort)
tim_nrdy0 <= 1'b0;
else
if (abort)
tim_nrdy0 <= 1'b1;
end
always @(posedge vm_clk_n)
begin
//
// tim_nrdy1 is used to stop mcu for waiting
// nINIT pusle generating completion
//
if (reset | tend)
tim_nrdy1 <= 1'b0;
else
if (pi_stb & plm[13])
tim_nrdy1 <= 1'b1;
end
//______________________________________________________________________________
//
assign mdfy = acmp_en & (pc1 == areg);
always @(posedge vm_clk_p) acmp_en <= wra & io_wr;
always @(posedge vm_clk_n) if (alu_wr) io_rcdr <= io_rcd;
always @(posedge vm_clk_n) if (alu_wr) io_cmdr <= io_cmd;
always @(posedge vm_clk_p)
begin
if (mc_res | wb_wdone)
io_pswr <= 1'b0;
else
if (wra & io_wr & ~na[0])
io_pswr <= 1'b1;
end
//______________________________________________________________________________
//
// Instruction registers - primary and preliminary decoder
//
always @(posedge vm_clk_p)
begin
if (bir_stb) breg <= wb_dat;
if (ir_stb)
begin
ireg <= breg;
dc_iord <= pld[4];
dc_iowr <= pld[3];
dc_rtt <= ~pld[2];
end
end
vm2_pld pld_matrix(.rq(breg), .sp(pld));
assign dc_f2 = (breg[11:9] != 3'b000)
& ((breg[8:6] == 3'b111) | (breg[11:10] == 2'b11));
assign dc_j7 = ir_stb
& (breg[8:6] == 3'b111)
& (breg[14:12] != 3'b000);
assign dc_i7 = (breg[2:0] == 3'b111);
assign dc_bi = pld[5];
assign dc_fl = (ir_stb ? pld[10] : ~dc_fb) & ((ir_stb & dc_bi) | (dc_iord & ~dc_iowr));
assign dc_aux = dc_j7 | br_cmdrq;
assign alt_cnst = (~dc_fb & plm[30]) | (dc_fb & plm[30] & plm[5] & plm[6]);
always @(posedge vm_clk_p)
begin
if (ir_stb) dc_fb <= ~pld[10];
if (wr2) dc_b7 <= (ax[15:13] == 3'b111);
end
always @(posedge vm_clk_n)
begin
if (io_cmdr | (alu_wr & io_cmd))
br_cmdrq <= 1'b0;
else
if (rcmd_set)
br_cmdrq <= 1'b1;
end
//______________________________________________________________________________
//
// Main microcode state machine
//
assign pi_stb_rc = ~pla[0] & mc_stb;
always @(posedge vm_clk_p) pi_stb <= pi_stb_rc;
assign all_rdy = ~mc_res & ~alu_nrdy & (~sta_nrdy | bra_stb)
& ~pli_nrdy & ~cmd_nrdy & ~mc_stb;
always @(posedge vm_clk_p) mc_stb <= all_rdy;
always @(posedge vm_clk_n)
begin
if (mc_res | pi_stb | alu_wr)
alu_nrdy <= 1'b0;
else
if (mc_stb)
alu_nrdy <= 1'b1;
end
assign mc_rdy_rc = alu_nrdy & (mc_stb ? pla[0] : plm[0]);
always @(posedge vm_clk_p) set_cend <= set_cend_rc;
always @(posedge vm_clk_n) cmd_nrdy <= ~mc_res & ~ir_stb & (set_cend | cmd_nrdy);
always @(posedge vm_clk_p) sta_nrdy <= ~mc_res & ~bra_stb & (sta_nrdy | wt_state_rc);
//______________________________________________________________________________
//
always @(posedge vm_clk_n)
begin
if (io_cmd & wra)
br_iocmd <= 1'b0;
else
if (iop_sta)
br_iocmd <= 1'b1;
end
always @(posedge vm_clk_n)
begin
if ( reset
| ~br_iocmd
| buf_res
| word27
| ir_stb)
br_ready <= 1'b0;
else
if (br_iocmd & bir_stb)
br_ready <= 1'b1;
end
assign bra_req = br_ready & (cmd_nrdy | set_cend_rc & ~ir_stb & ~mc_res);
always @(posedge vm_clk_p)
begin
if (reset)
ir_stb <= 1'b0;
else
begin
if (mc_stb & ir_stb)
ir_stb <= 1'b0;
else
if (bra_req)
ir_stb <= 1'b1;
end
end
//______________________________________________________________________________
//
// Instructions with two operands and sources address mode is @PC
// For this instruction we force prefetch completion wait
//
always @(posedge vm_clk_p)
begin
if (mc_res)
bir_fix <= 1'b0;
else
if (ir_stb)
bir_fix = (breg[14:12] != 3'o0) // two ops instructions
& (breg[14:12] != 3'o7) //
& (breg[8:6] == 3'o7) // source is PC related
& (breg[10:9] == 2'o1) // source @PC or @-(PC) mode
& (breg[2:0] != 3'o7) // not PC related destination
& (breg[5:3] != 3'o6) // not E(Rn) destination
& (breg[5:3] != 3'o7) // not @E(Rn) destination
& (VM2_CORE_FIX_PREFETCH != 0);
end
//______________________________________________________________________________
//
// Main microcode matrix
//
vm2_plm plm_matrix(.ir(ireg), .ix(ix), .ri(ri), .ia(ia), .sp(pla));
assign na_rc[0] = reset | ~pla[31] & ~abort;
assign na_rc[1] = mc_res | ~pla[32];
assign na_rc[2] = mc_res | ~pla[33];
assign na_rc[3] = mc_res | pla[34];
assign na_rc[4] = mc_res | pla[35];
assign na_rc[5] = mc_res | pla[36];
always @(posedge vm_clk_p)
begin
if (reset)
na[0] <= 1'b1;
else
if (abort)
na[0] <= 1'b0;
else
if (mc_stb)
na[0] <= ~pla[31];
if (mc_res)
na[5:1] <= 5'b11111;
else
if (mc_stb)
begin
na[1] <= ~pla[32];
na[2] <= ~pla[33];
na[3] <= pla[34];
na[4] <= pla[35];
na[5] <= pla[36];
end
end
always @(posedge vm_clk_p)
if (wr1)
plm_wt[30:21] <= plm[30:21];
always @(posedge vm_clk_p)
if (mc_stb)
begin
plm[0] <= pla[0];
plm[1] <= ~pla[1];
plm[2] <= ~pla[2];
plm[3] <= ~pla[3];
plm[4] <= ~pla[4];
plm[5] <= ~pla[5];
plm[6] <= ~pla[6];
plm[7] <= ~pla[7];
plm[8] <= ~pla[8];
plm[9] <= ~pla[9];
plm[10] <= ~pla[10];
plm[11] <= ~pla[11];
plm[12] <= ~pla[12];
plm[13] <= ~pla[13];
plm[14] <= ~pla[14];
plm[15] <= ~pla[15];
plm[16] <= ~pla[16];
plm[17] <= ~pla[17];
plm[18] <= ~pla[18];
plm[19] <= pla[19];
plm[20] <= pla[20];
plm[21] <= pla[21];
plm[22] <= pla[22];
plm[23] <= pla[23];
plm[24] <= pla[24];
plm[25] <= pla[25];
plm[26] <= pla[26];
plm[27] <= ~pla[27];
plm[28] <= pla[28];
plm[29] <= pla[29];
plm[30] <= ~pla[30];
end
assign plr[21] = wr1 ? ~plm[21] : ~plm_wt[21];
assign plr[22] = wr1 ? ~plm[22] : ~plm_wt[22];
assign plr[23] = wr1 ? ~plm[23] : ~plm_wt[23];
assign plr[24] = wr1 ? ~plm[24] : ~plm_wt[24];
assign plr[30] = wr1 ? plm[30] : plm_wt[30];
assign set_cend_rc = mc_stb & na_rc[0] & pla[25] & ~pla[26];
assign wt_state_rc = mc_stb & ~na_rc[0] & pla[25] & ~pla[26];
//
// ALU operation is modifiable from extended arithmetics unit
//
assign plm1m = plm[1] | (~plm[25] & ~dc_fb);
assign plm18m = plm[18] | (~ea_1tc & ea_sh2 & ea_shl);
assign plm19m = plm[19] & ( ea_1tc | ~ea_shl);
assign plm20m = plm[20] & ~ea_shr;
assign plm13m = plm[13] & ~ea_mop0 & ~ea_mop1 & (~ea_div | ~ea_f[1] | (tlz ^ ear1[15]));
assign plm14m = plm[14]
& (~acc[15] | ~ea_mul | ~ea_f[0])
& ((tlz ^ acc[15]) | ~ea_div | ~ea_f[19])
& (~(tlz ^ ear1[15]) | ~ea_f[1] | ~ea_div | ea_mop0 | (acc[15] ^ ear1[15]))
& (~ea_div | ea_mop0 | ~ea_f218 | ~ear2[0]);
always @(posedge vm_clk_p)
begin
//
// Current microinstruction address latch
// - direct branch from preliminary decoder
// - next address field
//
if (~mc_stb)
if (ir_stb)
ia <= {pld[0], pld[8], pld[7], ~pld[6], ~pld[9], ~pld[11]};
else
ia <= na;
//
// Auxiliary conditions register
//
if (~mc_stb) ix[0] <= dc_fl;
if (~mc_stb) ix[1] <= dc_aux | (bra_stb ? ~plb : bra);
if (ir_stb) ix[2] <= dc_bi;
//
// Interrupt query register
//
if (ir_stb & ~dc_i7)
ri[0] <= 1'b0;
else
if (pi_stb)
ri[0] <= plm[3];
else
if (pli_ack)
ri[0] <= ~pli[1];
if (ir_stb & psw[8])
ri[1] <= 1'b1;
else
if (pi_stb)
ri[1] <= plm[2];
else
if (pli_ack)
ri[1] <= ~pli[5];
if (ir_stb & dc_f2)
ri[2] <= 1'b1;
else
if (pi_stb)
ri[2] <= plm[1];
else
if (pli_ack)
ri[2] <= pli[4];
end
assign pli_req = mc_stb & na_rc[1] & pla[28];
assign sd_word = mc_stb & ~na_rc[1] & pla[28];
always @(posedge vm_clk_p)
begin
if (sd_word)
word27 <= 1'b1;
else
if (mc_res | (wr1 & plm[27]))
word27 <= 1'b0;
end
//______________________________________________________________________________
//
// Interrupt processing unit
//
vm2_pli pli_matrix(.rq(qri), .sp(pli));
assign qri[0] = acok_rq; // nACLO rise interrupt request
assign qri[1] = psw[7] & psw[8]; // halt mode interrupt disable
assign qri[2] = 1'b0; // reserved entry
assign qri[3] = halt; // external halt mode interrupt
assign qri[4] = tout_rq; // bus timeout exception request
assign qri[5] = virq; // external vectored interrupt
assign qri[6] = aclo_rq; // nACLO fall interrupt request
assign qri[7] = vec_stb; // vectored interrupt ack
assign qri[8] = dble_rq; // double bus timeout exception
assign qri[9] = wcpu; // WAIT instruction execution
assign qri[10] = evnt_rq; // system timer interrupt request
assign qri[11] = tbit | psw[4]; // T-bit step trap request
assign qri[12] = dc_rtt & (tbit | psw[4]);
assign qri[13] = psw[8]; // halt mode flag
assign qri[14] = psw[7]; // interrupt disable flag
assign qri[15] = ac0; // wait initial nACLO rise
//______________________________________________________________________________
//
// External pin assignments
//
always @(posedge vm_clk_p)
begin
pli_arq <= abort;
pli_ack <= ~reset & (pli_arq & ~abort | pli_req);
end
always @(posedge vm_clk_p)
begin
//
// Hold interrupt acknowledge cycle flag on bus timeout
// to allow interrupt controller generate correct vector
// SEL 274
//
if (tovf_ack | tovf | ~tout_rq)
vec_stb <= wbi_stb_o & ~wbi_una_o;
//
// Interrupt requests acknowlegement and reset
//
if (reset)
begin
acok_rq <= 1'b0;
tout_rq <= 1'b0;
aclo_rq <= 1'b0;
dble_rq <= 1'b0;
end
else
begin
if (aclo_ack)
acok_rq <= 1'b0;
else
if (~vm_aclo & aclo_rise)
acok_rq <= 1'b1;
if (aclo_ack)
aclo_rq <= 1'b0;
else
if (vm_aclo & aclo_fall)
aclo_rq <= 1'b1;
if (tovf_ack)
tout_rq <= 1'b0;
else
if (tovf)
tout_rq <= 1'b1;
if (ir_stb)
dble_rq <= 1'b0;
else
if (tovf & dble_cnt1)
dble_rq <= 1'b1;
end
if (init | evnt_ack)
evnt_rq <= 1'b0;
else
if (evnt & evnt_fall)
evnt_rq <= 1'b1;
end
always @(posedge vm_clk_p)
begin
//
// nEVNT falling edge detector
//
if (~evnt)
evnt_fall <= 1'b1;
else
if (init | evnt_ack)
evnt_fall <= 1'b0;
//
// nACLO falling edge detector
//
if (~vm_aclo)