suotherctl.v
38.1 KB
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
// Module instances modified by /home/rws/workarea/rf/sw/bbplayer/tools/necprimfix
//
// 1 instance of an02d2 changed to j_an02.
// 2 instances of an05d2 changed to j_an05.
// 2 instances of an06d2 changed to j_an06.
// 6 instances of in01d5 changed to j_in01.
// 4 instances of mx21d1 changed to j_mx21.
// 2 instances of mx21d2 changed to j_mx21.
// 3 instances of mx41d1 changed to j_mx41.
// 1 instance of ni01d3 changed to j_ni01.
// 8 instances of ni01d4 changed to j_ni01.
// 1 instance of nr02d2 changed to j_nr02.
// 4 instances of nr03d2 changed to j_nr03.
// 1 instance of nr04d2 changed to j_nr04.
// 1 instance of nr05d2 changed to j_nr05.
// 1 instance of nr06d1 changed to j_nr06.
// 2 instances of or02d3 changed to j_or02.
// 1 instance of or03d2 changed to j_or03.
// 1 instance of or06d1 changed to j_or06.
// 6 instances of xo02d1 changed to j_xo02.
//
/**************************************************************************
* *
* Copyright (C) 1994, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
*************************************************************************/
// $Id:
// suotherctl.v: RSP scalar unit and pipeline control
`timescale 1ns / 10ps
`include "sopcodes.vh"
module suotherctl (clk, reset_l, halt, single_step, su_inst,
kill_su_issue, kill_vu_issue, vu_reg_hazard_comp, vu_reg_hazard_ls,
dma_dm_to_rd, dma_rd_to_dm, dma_imem_select,
sushvamt, vu_comp, sualu_cout, sualu_ovr, sualumsb,
suexasign, suexbsign, suonesdet_z,
halting, imem_dma_pif, adv_ir, kill_re_non_vu, kill_re,
ex_su_inst, taken,
surf_ra, surf_rb,
surdamux, surdbmux, suimmmux, suvulsoffsetmux, suimmlsmux,
set_broke, break_inst_debug,
sualuamux, sualubmux, sushamux, sushbmux,
suslten, susltlt, sualuen, sualu, sualu_cin, sudrivels, shiftamt,
su_ex_store, su_ex_load, vu_ex_store, vu_ex_load,
ex_mfc2, ex_mtc2, ex_cfc2, ex_su_byte_ls, ex_su_half_ls, ex_su_uns_ls,
chip_sel, rd_base, ls_drive_rd_base, rd_offset, rd_elem_num,
vu_rd_ld_dec_k, vu_rd_st_dec_k, df_ls_drive_ls_in_wb, df_pass_thru,
surf_w, surf_wen, suwben, vu_comp_k,
cp0_address, cp0_write, cp0_enable, ex_mfc0, imem_dma_cycle);
input clk;
input reset_l;
input halt;
input single_step;
input [31:0] su_inst;
input kill_su_issue;
input kill_vu_issue;
input vu_reg_hazard_comp;
input vu_reg_hazard_ls;
input dma_dm_to_rd;
input dma_rd_to_dm;
input dma_imem_select;
input [4:0] sushvamt;
input vu_comp;
// EX stage from SU DP
input sualu_cout;
input sualu_ovr;
input sualumsb;
input suexasign;
input suexbsign;
input suonesdet_z;
output halting;
output imem_dma_pif;
output adv_ir;
output kill_re_non_vu;
output kill_re;
output [4:0] ex_su_inst;
output taken;
// RD stage to SU DP
output [4:0] surf_ra; // encoded ra addr
output [4:0] surf_rb; // encoded rb addr
output [2:0] surdamux;
output [2:0] surdbmux;
output [1:0] suimmmux; // imm sxt, zxt, lui
output suimmlsmux;
output [2:0] suvulsoffsetmux; // vu l/s offset generation
// RD stage to LS
output [3:0] rd_base;
output ls_drive_rd_base; // ls_data to rd_base bypass
output [3:0] rd_offset;
output [3:0] rd_elem_num;
output [11:0] vu_rd_ld_dec_k; // type of vu ld data
output [11:0] vu_rd_st_dec_k; // type of vu st data
// RD stage to DMA
output set_broke;
// RD stage to nowhere
output break_inst_debug;
output sualuamux; // EX stage to SU DP
output sualubmux;
output [1:0] sushamux;
output [1:0] sushbmux;
output sudrivels;
output suslten; // enable slt result
output susltlt; // set, lt true
output sualuen;
output [4:0] sualu;
output sualu_cin;
output [4:0] shiftamt;
// EX stage to LS
output su_ex_store;
output su_ex_load;
output vu_ex_store;
output vu_ex_load;
output ex_mfc2;
output ex_mtc2;
output ex_cfc2;
output ex_su_byte_ls;
output ex_su_half_ls;
output ex_su_uns_ls;
output chip_sel; // dmem chip select
// DF stage to LS
output df_ls_drive_ls_in_wb;
output df_pass_thru; // df_inst is MT, MF, CT, CF
// WB stage to SU DP
output [4:0] surf_w; // encoded rf write en
output surf_wen; // rf write enable
output suwben; // en wb_data into SU RFile
// RD stage to VU
output vu_comp_k;
// EX stage to CP0
output [3:0] cp0_address;
output cp0_write; // CTC0
output cp0_enable; // !CTC0
output ex_mfc0;
output imem_dma_cycle; // IF stage to BIST
wire rd_broke_k;
wire kill_re_break;
wire single_step_halt;
wire prev_halt;
wire imem_dma_ppif;
wire imem_dma_if;
wire imem_dma_rd;
wire start_imem_dma;
wire [5:0] opc;
wire [5:0] func;
wire [4:0] rs;
wire [4:0] rt;
wire [4:0] rd;
wire [4:0] lsopc;
wire ex_break;
wire load_use_stall;
wire load_store_stall;
wire rd_dma_cycle;
wire ex_dma_cycle;
wire df_dma_cycle;
wire dmem_dma_stall;
wire [4:0] rd_wr_reg;
wire [4:0] ex_wr_reg;
wire [4:0] df_wr_reg;
wire [4:0] wb_wr_reg;
wire rd_wr_en;
wire rd_wr_en_k;
wire ex_wr_en;
wire df_wr_en;
wire wb_wr_en;
wire use_a;
wire use_b;
wire rt_zero;
wire a_gets0;
wire a_ex_byp;
wire a_df_byp;
wire a_wb_byp;
wire b_ex_byp;
wire b_df_byp;
wire b_wb_byp;
wire rd_sh_en; // shifter drives ex_out
wire rd_sh_l; // left shift
wire rd_sh_lv; // left shift, variable
wire rd_sh_left; // left, either type
wire [4:0] ex_sushvamt;
wire ex_sh_left;
wire ex_sh_l;
wire ex_sh_lv;
wire rd_sh_r; // right shift
wire rd_sh_right; // right, any type
wire ex_sh_right;
wire ex_sh_r;
wire rd_sh_ra; // arithmetic right shift
wire ex_sh_ra;
wire rd_mfc2;
wire rd_mfc2_k;
wire rd_mtc2;
wire rd_mtc2_k;
wire rd_cfc2;
wire rd_cfc2_k;
wire rd_alubmux1;
wire ex_alubmux1;
wire rd_sslt_en; // slt signed
wire rd_uslt_en; // slt unsigned
wire ex_sslt_en; // slt signed drives ex_out
wire ex_uslt_en; // slt unsigned drives ex_out
wire rd_alu_en; // alu drives ex_out
wire [4:0] rd_alu; // alu function control
wire rd_alu_cin;
wire rd_imm; // inst has imm operand
wire rd_branch;
wire rd_branch_k;
wire rd_branch1; // 1-source branches
wire rd_br_al; // branch and link
wire rd_br_al_k;
wire ex_br_al;
wire ex_branch;
wire [5:0] rd_br_type;
wire [5:0] rd_br_type_k;
wire [5:0] ex_br_type;
wire rd_jump_imm;
wire rd_jump;
wire rd_jump_k;
wire ex_jump;
wire rd_broke;
wire rd_su_load; // dmem load
wire rd_su_load_k;
wire su_df_load;
wire su_wb_load_type;
wire su_rd_load_type; // dmem load or MFCx or CFCx
wire su_rd_load_type_k;
wire su_ex_load_type;
wire su_df_load_type;
wire vu_rd_load;
wire vu_rd_load_k;
wire vu_rd_ls;
wire vu_df_load;
wire vu_byte_ls;
wire vu_short_ls;
wire vu_word_ls;
wire vu_double_ls;
wire vu_quad_ls;
wire vu_rest_ls;
wire vu_pack_ls;
wire vu_upack_ls;
wire vu_half_ls;
wire vu_fourth_ls;
wire vu_trans_ls;
wire vu_wrap_ls;
wire su_rd_store; // dmem store
wire su_rd_store_k;
wire vu_rd_store; // dmem store
wire vu_rd_store_k;
wire rd_su_byte_ls;
wire rd_su_half_ls;
wire rd_su_uns_ls;
wire rd_su_byte_ls_k;
wire rd_su_half_ls_k;
wire rd_su_uns_ls_k;
wire rd_pass_thru;
wire rd_pass_thru_k;
wire ex_pass_thru;
wire rd_sudrivels;
wire rd_sudrivels_k;
wire rd_ls_drive_ls_in_wb;
wire rd_ls_drive_ls_in_wb_k;
wire ex_ls_drive_ls_in_wb;
// CP0 Signals:
wire rd_mtc0;
wire rd_mtc0_k;
wire ex_mtc0;
wire rd_mfc0;
wire rd_mfc0_k;
//
// RD stage signals: instruction decode, bypasses
//
assign opc = su_inst[31:26];
assign func = su_inst[5:0];
assign rs = su_inst[25:21];
assign rt = su_inst[20:16];
assign rd = su_inst[15:11];
assign lsopc = su_inst[15:11];
assign rd_elem_num = su_inst[10:7];
// Note that rd_su_load and rd_su_store are *not* mutually exclusive
// with VU load/store decodes:
/*
assign rd_offset =
(rd_su_load || su_rd_store) ? su_inst[3:0] :
(vu_quad_ls || vu_rest_ls || vu_half_ls ||
vu_fourth_ls || vu_trans_ls || vu_wrap_ls) ? 4'b0 :
(vu_double_ls || vu_pack_ls || vu_upack_ls) ? {su_inst[0], 3'b0} :
vu_word_ls ? {su_inst[1:0], 2'b0} :
vu_short_ls ? {su_inst[2:0], 1'b0} :
su_inst[3:0]; // vu_byte_ls or su
*/
wire [1:0] vu_offset_sel;
wire vu_none_sel;
wire [3:0] vu_offset;
assign vu_offset_sel[0] = vu_double_ls || vu_pack_ls || vu_upack_ls || vu_short_ls;
assign vu_offset_sel[1] = vu_word_ls || vu_short_ls;
assign vu_none_sel = !(vu_quad_ls || vu_rest_ls || vu_half_ls || vu_fourth_ls || vu_trans_ls ||
vu_wrap_ls || vu_double_ls || vu_pack_ls || vu_upack_ls || vu_word_ls ||
vu_short_ls);
assign vu_offset[0] = 1'b0;
j_mx41 vu_offset_mx1 (.i0(1'b0), .i1(1'b0), .i2(1'b0), .i3(su_inst[0]), .s0(vu_offset_sel[0]), .s1(vu_offset_sel[1]), .z(vu_offset[1]));
j_mx41 vu_offset_mx2 (.i0(1'b0), .i1(1'b0), .i2(su_inst[0]), .i3(su_inst[1]), .s0(vu_offset_sel[0]), .s1(vu_offset_sel[1]), .z(vu_offset[2]));
j_mx41 vu_offset_mx3 (.i0(1'b0), .i1(su_inst[0]), .i2(su_inst[1]), .i3(su_inst[2]), .s0(vu_offset_sel[0]), .s1(vu_offset_sel[1]), .z(vu_offset[3]));
/*
assign rd_offset = (rd_su_load || su_rd_store || vu_none_sel) ? su_inst[3:0] : vu_offset;
*/
wire [3:0] rd_offset_unbuf;
wire rd_offset_mx_sel;
assign rd_offset_mx_sel = rd_su_load || su_rd_store || vu_none_sel;
j_mx21 rd_offset_mx0(.i0(vu_offset[0]), .i1(su_inst[0]), .s(rd_offset_mx_sel), .z(rd_offset_unbuf[0]));
j_mx21 rd_offset_mx1(.i0(vu_offset[1]), .i1(su_inst[1]), .s(rd_offset_mx_sel), .z(rd_offset_unbuf[1]));
j_mx21 rd_offset_mx2(.i0(vu_offset[2]), .i1(su_inst[2]), .s(rd_offset_mx_sel), .z(rd_offset_unbuf[2]));
j_mx21 rd_offset_mx3(.i0(vu_offset[3]), .i1(su_inst[3]), .s(rd_offset_mx_sel), .z(rd_offset_unbuf[3]));
j_ni01 rd_offset_buf0(.i(rd_offset_unbuf[0]), .z(rd_offset[0]));
j_ni01 rd_offset_buf1(.i(rd_offset_unbuf[1]), .z(rd_offset[1]));
j_ni01 rd_offset_buf2(.i(rd_offset_unbuf[2]), .z(rd_offset[2]));
j_ni01 rd_offset_buf3(.i(rd_offset_unbuf[3]), .z(rd_offset[3]));
/*
assign rd_base = sushvamt[3:0];
*/
j_ni01 rd_base_buf0(.i(sushvamt[0]), .z(rd_base[0]));
j_ni01 rd_base_buf1(.i(sushvamt[1]), .z(rd_base[1]));
j_ni01 rd_base_buf2(.i(sushvamt[2]), .z(rd_base[2]));
j_ni01 rd_base_buf3(.i(sushvamt[3]), .z(rd_base[3]));
// ls_data is being bypassed into the A src:
assign ls_drive_rd_base =
su_wb_load_type && (a_wb_byp && !a_df_byp && !a_ex_byp && !a_gets0);
assign surf_ra = rs;
assign surf_rb = rt;
assign rd_wr_reg =
(su_rd_load_type || rd_imm) ? rt : // su loads, MFCx, CFCx, imm
(`JAL || `REGIMM) ? 31 : // (`JAL || rd_br_al)
rd;
assign rd_wr_en = !(
(rd_wr_reg==5'b0) || // write to R0
(rd_branch && !rd_br_al) || // non-link branches
`LWC2 || `SB || `SH || `SW || `SWC2 || // stores, vu load
`J || (`SPECIAL && (`JR || `BREAK)) || // non-link jumps, break
((opc[5:4]==2'b01) && (rs[4:2]!=3'b000))); // VU, MTCx, CTCx
assign rd_mfc2 = (opc[5:4]==2'b01) && (opc[1]==1'b1) &&
(rs[4]==0) && (rs[2:1]==2'b00);
assign rd_mtc2 = (opc[5:4]==2'b01) && (opc[1]==1'b1) &&
(rs[4]==0) && (rs[2:1]==2'b10);
assign rd_cfc2 = (opc[5:4]==2'b01) && (opc[1]==1'b1) &&
(rs[4]==0) && (rs[2:1]==2'b01);
assign rd_sslt_en = `SLTI || (`SPECIAL && `SLT);
assign rd_uslt_en = `SLTIU || (`SPECIAL && `SLTU);
assign rd_alu_en = `ADDI || `ADDIU || `ANDI || `ORI || `XORI || `LUI ||
(`SPECIAL &&
(`ADD || `ADDU || `SUB || `SUBU || `AND || `OR || `XOR || `NOR));
assign rd_alu_cin = `SLTI || `SLTIU ||
`SPECIAL && (`SLT || `SLTU || `SUB || `SUBU);
assign rd_alu[4] = `ANDI || `ORI || `XORI || `LUI ||
(`SPECIAL && (`AND || `OR || `XOR || `NOR)); // logical ops
assign rd_alu[3] = `ORI || `LUI || (`SPECIAL && (`OR)); // NAND, OR, LUI
assign rd_alu[2] = `ANDI || `ORI || `LUI ||
(`SPECIAL && (`AND || `OR || `NOR)); // AND, NAND, OR, NOR, LUI
assign rd_alu[1] = `ORI || `XORI || `LUI || `SLTI || `SLTIU ||
(`SPECIAL && (`OR || `NOR || `XOR || `SLT || `SLTU || `SUB || `SUBU));
// OR, NOR, XOR, LUI, SUB, SLT
assign rd_alu[0] = `ORI || `LUI || (`SPECIAL && (`OR || `NOR));
// OR, NOR, LUI
assign rd_sh_l = `SPECIAL && `SLL;
assign rd_sh_lv = `SPECIAL && `SLLV;
assign rd_sh_left = `SPECIAL && (`SLL || `SLLV);
assign rd_sh_r = `SPECIAL && (`SRL || `SRA);
assign rd_sh_ra = `SPECIAL && (`SRA || `SRAV);
assign rd_sh_right = `SPECIAL && (`SRL || `SRLV || `SRA || `SRAV);
assign rd_sh_en = rd_br_al || `JAL || (`SPECIAL && (`JALR)) ||
rd_sh_left || rd_sh_right;
assign rd_imm = (opc[5:3] == 3'b001);
assign suimmlsmux = vu_rd_ls;
assign suimmmux[1] = rd_branch || `J || `JAL || // 3 br, J, JAL
`LUI || (`SPECIAL && (`JR || `JALR)); // 2 lui,JxR(0)
assign suimmmux[0] = rd_branch || `J || `JAL || // 3 br, J, JAL
`LB || `LBU || `LH || `LHU || `LW || // 1
`SB || `SH || `SW || // 1
`ADDI || `ADDIU || `SLTI || `SLTIU; // 1 sxt
// unused: `ANDI || `ORI || `XORI; // 0 zxt
assign suvulsoffsetmux[2] =
vu_quad_ls || vu_rest_ls || vu_half_ls || vu_fourth_ls || // 4
vu_trans_ls || vu_wrap_ls;
assign suvulsoffsetmux[1] =
vu_double_ls || vu_pack_ls || vu_upack_ls || // 3
vu_word_ls; // 2
assign suvulsoffsetmux[0] =
vu_double_ls || vu_pack_ls || vu_upack_ls || // 3
vu_short_ls; // 1
// unused:
// vu_byte_ls // 0
assign rd_jump = `J || `JAL || (`SPECIAL && (`JR || `JALR));
assign rd_jump_imm = `J || `JAL;
assign rd_branch = `BEQ || `BNE || `BLEZ || `BGTZ ||
(`REGIMM && (`BLTZ || `BGEZ || `BLTZAL || `BGEZAL));
// *** really any REGIMM
assign rd_branch1 = `BLEZ || `BGTZ ||
(`REGIMM && (`BLTZ || `BGEZ || `BLTZAL || `BGEZAL));
// *** really any REGIMM
assign rd_br_al = `REGIMM && (`BLTZAL || `BGEZAL);
assign rd_br_type[0] = `BEQ;
assign rd_br_type[1] = `BNE;
assign rd_br_type[2] = `BLEZ || (`REGIMM && (`BLTZ || `BLTZAL)); // < 0
assign rd_br_type[3] = `BLEZ || (`REGIMM && (`BGEZ || `BGEZAL)); // = 0
assign rd_br_type[4] = `BGTZ || (`REGIMM && (`BGEZ || `BGEZAL)); // > 0
assign rd_br_type[5] = rd_br_al; // link
assign rd_su_load = (opc[5:3] == 3'b100); // LB, LBU, LH, LHU, LW
assign su_rd_load_type =
(opc[5:3] == 3'b100) || (opc[5:3]==3'b010 && rs[4:2]==3'b000);
// loads or MFCx or CFCx
assign vu_byte_ls = (lsopc==5'h0);
assign vu_short_ls = (lsopc==5'h1);
assign vu_word_ls = (lsopc==5'h2);
assign vu_double_ls = (lsopc==5'h3);
assign vu_quad_ls = (lsopc==5'h4);
assign vu_rest_ls = (lsopc==5'h5);
assign vu_pack_ls = (lsopc==5'h6);
assign vu_upack_ls = (lsopc==5'h7);
assign vu_half_ls = (lsopc==5'h8);
assign vu_fourth_ls = (lsopc==5'h9);
assign vu_wrap_ls = (lsopc==5'ha); // does not include lwt
assign vu_trans_ls = (lsopc==5'hb); // includes lwt
assign vu_rd_ld_dec_k[0] = vu_byte_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_ld_dec_k[1] = vu_short_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_ld_dec_k[2] = vu_word_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_ld_dec_k[3] = vu_double_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_ld_dec_k[4] = vu_quad_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_ld_dec_k[5] = vu_rest_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_ld_dec_k[6] = vu_pack_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_ld_dec_k[7] = vu_upack_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_ld_dec_k[8] = vu_half_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_ld_dec_k[9] = vu_fourth_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_ld_dec_k[10] = vu_trans_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_ld_dec_k[11] = vu_wrap_ls && vu_rd_load && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[0] = vu_byte_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[1] = vu_short_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[2] = vu_word_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[3] = vu_double_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[4] = vu_quad_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[5] = vu_rest_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[6] = vu_pack_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[7] = vu_upack_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[8] = vu_half_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[9] = vu_fourth_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[10] = vu_trans_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_st_dec_k[11] = vu_wrap_ls && vu_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_load = (opc[5:3]==3'b110);
assign rd_pass_thru = ((`COP2 || `COP0) && (rs[4:3] == 2'b00)); // MT/F,CT/F
wire rd_ctc2;
assign rd_ctc2 = `COP2 && `CTC;
assign rd_sudrivels = su_rd_store || rd_mtc0 || rd_mtc2 || rd_ctc2;
assign rd_ls_drive_ls_in_wb = `LWC2 || rd_su_load || rd_pass_thru;
// *** Optimization: combine vu_xx_store and su_xx_store? Check load, too.
assign su_rd_store = (opc[5:3] == 3'b101);
assign vu_rd_store = (opc[5:3] == 3'b111);
assign rd_su_byte_ls = (opc[5:4] == 3'b10) && (opc[1:0] == 2'b00);
assign rd_su_half_ls = (opc[5:4] == 3'b10) && (opc[1:0] == 2'b01);
assign rd_su_uns_ls = (opc[5:4] == 3'b10) && (opc[2] == 1'b1);
assign rd_alubmux1 = (vu_rd_load || rd_su_load || // imm_data for l/s/br
vu_rd_store || su_rd_store ||
rd_branch || rd_jump);
// Bypasses // *** try all x==y in one level, then do combinations in next
// *** Based on QTV, instantiate XORS in wr_reg comparisons:
/* suRdAMux: suRdBMux:
0 rFile A src 0 rFile B src
1 EX bypass 1 EX bypass
2 DF bypass 2 DF bypass
3 WB bypass 3 WB bypass
4 zeros (J, JAL, R0) 4 imm_data
5 zeros (R0)
*/
/*
assign a_ex_byp = ({rs, 1'b1} == {ex_wr_reg, ex_wr_en});
assign a_df_byp = ({rs, 1'b1} == {df_wr_reg, df_wr_en});
assign a_wb_byp = ({rs, 1'b1} == {wb_wr_reg, wb_wr_en});
// Second term was (use_a && (rs==5'b0)) but it should be ok to ignore
// use_a. This is *not* the case, however, for use_b and rt_zero.
assign a_gets0 = rd_jump_imm || (rs==5'b0) || `LUI;
assign surdamux[2] = a_gets0; // 4 zeroes
assign surdamux[1] =
!a_ex_byp && !a_gets0 && (a_wb_byp || a_df_byp); // 3 wb byp, 2 df byp
assign surdamux[0] =
(a_wb_byp && !a_df_byp && !a_ex_byp && !a_gets0) || // 3 wb byp
(a_ex_byp && !a_gets0); // 1 ex byp
// unused:
// !a_wb_byp && !a_df_byp && !a_ex_byp && !a_gets0; // 0
assign use_a = !(opc[5:1]==5'b00001x || (opc[5:2]==4'b0100 && opc[0]==0) ||
(opc=='h00 && (func[5:2] == 4'b0000))); // non-variable shifts
= !(opc_l[5] && opc_l[3] &&
(opc[4:1]==4'b0x01x) ||
(opc[4:0]==4'b1x0x0) ||
(opc[4:0]==5'b0x000 && (func[5:2] == 4'b0000))));
*/
surdamux_unit surdamux_unit (rs, ex_wr_reg, df_wr_reg, wb_wr_reg,
ex_wr_en, df_wr_en, wb_wr_en, opc, func,
surdamux, a_ex_byp, a_df_byp, a_wb_byp, use_a);
assign b_ex_byp = ({rt, 1'b1} == {ex_wr_reg, ex_wr_en});
assign b_df_byp = ({rt, 1'b1} == {df_wr_reg, df_wr_en});
assign b_wb_byp = ({rt, 1'b1} == {wb_wr_reg, wb_wr_en});
assign vu_rd_ls = `LWC2 || `SWC2;
// Note offsets for loads and stores (and branches?) do not go through
// surdbmux, but through a FF then sualubmux.
assign rt_zero = use_b && (rt==5'b0);
assign surdbmux[2] = rd_branch1 || rt_zero || // 5 0's
rd_imm; // 4 inst_data
assign surdbmux[1] = (b_wb_byp && !b_df_byp && !b_ex_byp && // 3 wb_byp
!rd_imm && !rd_branch1 && !rt_zero) ||
(b_df_byp && !b_ex_byp && // 2 df byp
!rd_imm && !rd_branch1 && !rt_zero);
assign surdbmux[0] = rd_branch1 || rt_zero || // 5 0's
(b_wb_byp && !b_df_byp && !b_ex_byp && // 3 wb_byp
!rd_imm && !rd_branch1 && !rt_zero) ||
(b_ex_byp && // 1 ex byp
!rd_imm && !rd_branch1 && !rt_zero);
//unused: !b_wb_byp && !b_df_byp && !b_ex_byp && // 0
// !rd_imm && !rd_branch1 && !rt_zero;
// Pipe Control
assign rd_broke = `SPECIAL && `BREAK;
// Instruction in RD uses as a souce a register that is the destination
// of a load in progress. Hold RD, kill EX, advance DF and WB.
/*
assign use_a = !(`J || `JAL || `COP0 || `COP2 ||
(`SPECIAL && (func[5:2] == 4'b0000))); // non-variable shifts
*/
assign use_b =
`SPECIAL ||
(opc[5:2] == 4'b0001) || // branches
(opc[5:3]== 3'b101) || // su stores
((opc[5:4] == 2'b01) && rs[2]); // MT, CT
assign load_use_stall =
(use_a && a_ex_byp && su_ex_load_type) ||
(use_a && a_df_byp && su_df_load_type) ||
(use_b && b_ex_byp && su_ex_load_type) ||
(use_b && b_df_byp && su_df_load_type);
assign load_store_stall =
(su_rd_store || vu_rd_store || rd_pass_thru) && // store or mf/mt/cf/ct
(su_df_load || vu_df_load || df_pass_thru); // load or mf/mt/cf/ct
assign rd_dma_cycle = (dma_dm_to_rd || dma_rd_to_dm) && !dma_imem_select;
assign dmem_dma_stall = (rd_dma_cycle || df_dma_cycle) &&
(su_rd_store || vu_rd_store || rd_pass_thru || rd_su_load || vu_rd_load);
// Adv_ir causes the RD stage latches to be held if deasserted.
// Kill_re causes the EX stage signals to be deasserted.
// To stall the pipe, adv_ir = 0 and kill_re = 1.
// To restart execution after a halt, for one cycle adv_ir = 1 and kill_re = 0.
assign adv_ir = !(vu_reg_hazard_comp && !kill_vu_issue) &&
!(vu_reg_hazard_ls && !kill_su_issue) && !(load_use_stall && !kill_su_issue) &&
!(load_store_stall && !kill_su_issue) && !(dmem_dma_stall && !kill_su_issue);
// When halt is deasserted the first non-halt cycle is valid in IF but not
// RD. The use of prev_halt in kill_re prevents issue of an RD instruction
// before a valid instruction has reached RD.
assign kill_re = (vu_reg_hazard_comp && !kill_vu_issue) ||
(vu_reg_hazard_ls && !kill_su_issue) ||
(load_use_stall && !kill_su_issue) || (load_store_stall && !kill_su_issue) ||
(dmem_dma_stall && !kill_su_issue) || imem_dma_rd || halt || prev_halt;
assign kill_re_non_vu = imem_dma_rd || halt || prev_halt ||
(!kill_su_issue && (load_use_stall || load_store_stall || dmem_dma_stall));
assign vu_comp_k = vu_comp && !(kill_vu_issue || kill_re_non_vu || vu_reg_hazard_comp || (vu_reg_hazard_ls && !kill_su_issue));
/*
// Logically this is correct, but reset_l, adv_ir and pc_sel are too late to
// be used by imem_chip_sel.
assign imem_chip_sel =
!reset_l ||
imem_dma_if || // dma access to imem
(!halt && adv_ir && !imem_stall) || // more to execute in IR FF
(!halt && adv_ir && (pc_sel[2] || pc_sel[3])); // take a branch
*/
assign single_step_halt = single_step && !prev_halt && !halt;
// *** In single step mode, halt is deasserted in 2-cycle quanta. During the
// *** first cycle rd_bubble is set, so no instruction is issued. During the
// *** second cycle an instruction is issued and rd_broke_k is asserted.
/*
assign rd_broke_k = rd_broke && !(kill_su_issue || kill_re_break);
assign set_broke = single_step_halt || rd_broke_k;
*/
wire set_broke_kill_issue_t; // set_broke when kill_su_issue = 1
wire set_broke_kill_issue_f; // set_broke when kill_su_issue = 0
assign set_broke_kill_issue_t = single_step_halt;
assign set_broke_kill_issue_f = single_step_halt || (rd_broke && !kill_re_break);
j_mx21 set_broke_mx (.i0(set_broke_kill_issue_f), .i1(set_broke_kill_issue_t), .s(kill_su_issue), .z(set_broke));
// Kill: optionally kill EX stage signals
/*
A special "kill" signal is generated for rd_broke for timing reasons.
(Rd_broke_k is used to generate halting, which is critical to several
paths ending in issue at ff's.) We start with the normal kill_re and observe
that:
there can be no load_use_stall because break does not use a source
register.
there can be no load_store_stall because break is neither a store nor a
move instruction.
there can be no dmem_dma_stall because break is not a load, store, or
move instruction.
there can be no vu_reg_hazard_comp because break is single issued, so
there is no vu computation instruction.
there can be no vu_reg_hazard_ls because break is neither a VU store
nor a move instruction.
Therefore, kill_re reduces to:
assign kill_re_break = imem_dma_rd || halt || prev_halt;
*/
assign kill_re_break = imem_dma_rd || halt || prev_halt;
assign rd_wr_en_k = rd_wr_en && !(kill_su_issue || kill_re);
assign rd_su_load_k = rd_su_load && !(kill_su_issue || kill_re);
assign rd_su_byte_ls_k = rd_su_byte_ls && !(kill_su_issue || kill_re);
assign rd_su_half_ls_k = rd_su_half_ls && !(kill_su_issue || kill_re);
assign rd_su_uns_ls_k = rd_su_uns_ls && !(kill_su_issue || kill_re);
assign su_rd_load_type_k = su_rd_load_type && !(kill_su_issue || kill_re);
assign vu_rd_load_k = vu_rd_load && !(kill_su_issue || kill_re);
assign rd_mfc2_k = rd_mfc2 && !(kill_su_issue || kill_re);
assign rd_mtc2_k = rd_mtc2 && !(kill_su_issue || kill_re);
assign rd_cfc2_k = rd_cfc2 && !(kill_su_issue || kill_re);
assign rd_ls_drive_ls_in_wb_k = rd_ls_drive_ls_in_wb && !(kill_su_issue || kill_re);
assign rd_pass_thru_k = rd_pass_thru && !(kill_su_issue || kill_re);
assign rd_sudrivels_k = rd_sudrivels && !(kill_su_issue || kill_re);
assign su_rd_store_k = su_rd_store && !(kill_su_issue || kill_re);
assign vu_rd_store_k = vu_rd_store && !(kill_su_issue || kill_re);
assign rd_branch_k = rd_branch && !(kill_su_issue || kill_re);
assign rd_br_al_k = rd_br_al && !(kill_su_issue || kill_re);
assign rd_br_type_k = rd_br_type & {6{!(kill_su_issue || kill_re)}};
assign rd_jump_k = rd_jump && !(kill_su_issue || kill_re);
assign rd_broke_k = rd_broke && !(kill_su_issue || kill_re_break);
assign break_inst_debug = rd_broke_k;
//
// EX stage signals
//
// *** How should functional enables be set at reset? Currently all 0's.
// *** What uses of reset_l can be eliminated?
spasdff_1_0 su_re_break_ff (ex_break, set_broke, clk, reset_l);
spasdff_5_0 su_re_wr_reg_ff (ex_wr_reg, rd_wr_reg, clk,1'b1);
spasdff_1_0 su_re_wr_en_ff (ex_wr_en, rd_wr_en_k, clk, reset_l);
spasdff_1_0 su_re_sslt_en_ff (ex_sslt_en,rd_sslt_en,clk,reset_l);
spasdff_1_0 su_re_uslt_en_ff (ex_uslt_en,rd_uslt_en,clk,reset_l);
spasdff_1_0 su_re_alu_en_ff (sualuen, rd_alu_en, clk, reset_l);
spasdff_1_0 su_re_alu_cin_ff (sualu_cin, rd_alu_cin,clk,reset_l);
spasdff_5_0 su_re_alu_ff (sualu, rd_alu, clk, reset_l);
spasdff_1_0 su_re_alubmux_ff (ex_alubmux1, rd_alubmux1, clk, reset_l);
spasdff_5_0 su_re_shamt_ff (ex_sushvamt, sushvamt, clk, reset_l);
spasdff_1_0 su_re_sh_left_ff (ex_sh_left, rd_sh_left, clk, reset_l);
spasdff_1_0 su_re_sh_l_ff (ex_sh_l, rd_sh_l, clk, reset_l);
spasdff_1_0 su_re_sh_lv_ff (ex_sh_lv, rd_sh_lv, clk, reset_l);
spasdff_1_0 su_re_sh_right_ff (ex_sh_right, rd_sh_right, clk, reset_l);
spasdff_1_0 su_re_sh_r_ff (ex_sh_r, rd_sh_r, clk, reset_l);
spasdff_1_0 su_re_sh_ra_ff (ex_sh_ra, rd_sh_ra, clk, reset_l);
spasdff_5_0 su_re_suinst_ff(ex_su_inst, su_inst[10:6], clk,reset_l);
spasdff_1_0 su_re_load_ff(su_ex_load, rd_su_load_k, clk,reset_l);
spasdff_1_0 su_re_ldty_ff(su_ex_load_type, su_rd_load_type_k,clk,reset_l);
spasdff_1_0 su_re_vu_load_ff(vu_ex_load, vu_rd_load_k,clk,reset_l);
spasdff_1_0 su_re_mfc2_ff(ex_mfc2, rd_mfc2_k, clk, reset_l);
spasdff_1_0 su_re_mtc2_ff(ex_mtc2, rd_mtc2_k, clk, reset_l);
spasdff_1_0 su_re_cfc2_ff(ex_cfc2, rd_cfc2_k, clk, reset_l);
spasdff_1_0 su_re_lsls_ff(ex_ls_drive_ls_in_wb, rd_ls_drive_ls_in_wb_k, clk, reset_l);
spasdff_1_0 su_re_drvls_ff(sudrivels, rd_sudrivels_k,clk,reset_l);
spasdff_1_0 su_re_pss_ff(ex_pass_thru, rd_pass_thru_k,clk,reset_l);
spasdff_1_0 su_re_dma_ff(ex_dma_cycle, rd_dma_cycle, clk, reset_l);
spasdff_1_0 su_re_store_ff(su_ex_store, su_rd_store_k,clk,reset_l);
spasdff_1_0 su_re_vu_st_ff(vu_ex_store, vu_rd_store_k,clk,reset_l);
spasdff_1_0 su_re_byte_ff(ex_su_byte_ls, rd_su_byte_ls_k,clk,reset_l);
spasdff_1_0 su_re_half_ff(ex_su_half_ls, rd_su_half_ls_k,clk,reset_l);
spasdff_1_0 su_re_uns_ff(ex_su_uns_ls, rd_su_uns_ls_k,clk,reset_l);
spasdff_1_0 su_re_branch_ff(ex_branch, rd_branch_k,clk, reset_l);
spasdff_1_0 su_re_br_al_ff(ex_br_al, rd_br_al_k, clk, reset_l);
spasdff_6_0 su_re_br_type_ff(ex_br_type, rd_br_type_k,clk,reset_l);
spasdff_1_0 su_re_jump_ff(ex_jump, rd_jump_k, clk, reset_l);
assign sualuamux = ex_branch; // next_pc for br
assign sualubmux = ex_alubmux1; // imm_data for l/s/br
// Left shifts are converted to right shifts, because that's the kind of
// shifter we have. Data to be shifted is preshifted right by one bit,
// and put in the high order half of the 64-bit shift input. It's then
// right shifted by the inverse of the left shift amount. This results
// in a right shift of 32-(left shift amount), which is equivalent to the
// desired left shift.
assign sushamux = (ex_jump || ex_br_al) ? 2'b11 : // link_pc
ex_sh_right ? 2'b10 : // b src
ex_sh_left ? 2'b01 : // b<0>, zeroes
2'b00; // a src
assign sushbmux = (ex_sh_ra && suexbsign) ? 2'b10 : // ones
ex_sh_left ? 2'b00 : // b src >> 1
2'b01; // zeroes
assign shiftamt = ex_br_al || ex_jump ? 5'b01100 :
ex_sh_l ? ~ex_su_inst[4:0] :
ex_sh_r ? ex_su_inst[4:0] :
ex_sh_lv ? ~ex_sushvamt :
/* ex_sh_rv */ ex_sushvamt;
// Branch checks
assign taken = ex_jump ||
(ex_br_type[0] && suonesdet_z) || // BEQ
(ex_br_type[1] && !suonesdet_z) || // BNE
(ex_br_type[2] && suexasign) || // < 0
(ex_br_type[3] && suonesdet_z) || // = 0
(ex_br_type[4] && !suexasign && !suonesdet_z); // > 0
// If there's a taken branch in EX, but no adv_ir (or we are halting),
// we need to save the information that there has been a branch and the
// target must be fetched.
spasdff_1_1 su_halt_ff (prev_halt, halt, clk, reset_l);
assign imem_dma_ppif = (dma_dm_to_rd || dma_rd_to_dm) && dma_imem_select;
spasdff_1_0 su_pif_idma_ff (imem_dma_pif, imem_dma_ppif, clk, reset_l);
spasdff_1_0 su_if_idma_ff (imem_dma_if, imem_dma_pif, clk, reset_l);
spasdff_1_0 su_idma_ff (imem_dma_rd, imem_dma_if, clk, reset_l);
assign imem_dma_cycle = imem_dma_if;
assign start_imem_dma = imem_dma_if && !imem_dma_rd;
/*
assign rd_broke_k = rd_broke && !(kill_su_issue || kill_re_break);
assign halting =
(halt && !prev_halt && !ex_break) || // external halt
(!halt && start_imem_dma) || // imem dma starting
rd_broke_k || // break inst encountered
single_step_halt; // single instruction issued
*/
wire halting_k_issue_f;
wire halting_k_issue_t;
assign halting_k_issue_f = (halt && !prev_halt && !ex_break) ||
(!halt && start_imem_dma) ||
(rd_broke && !kill_re_break) ||
single_step_halt;
assign halting_k_issue_t = (halt && !prev_halt && !ex_break) ||
(!halt && start_imem_dma) ||
single_step_halt;
/*
assign halting = kill_su_issue ? halting_k_issue_t : halting_k_issue_f;
*/
j_mx21 halting_mx (.i0(halting_k_issue_f), .i1(halting_k_issue_t), .s(kill_su_issue), .z(halting));
// SLT checks
assign susltlt = (ex_uslt_en && !sualu_cout) ||
(ex_sslt_en && ((!sualu_ovr && sualu_cout) ||
(!(sualu_ovr ^ sualu_cout) && sualumsb)));
assign suslten = ex_sslt_en || ex_uslt_en;
assign chip_sel = vu_ex_load || su_ex_load || vu_ex_store || su_ex_store;
//
// DF stage signals
//
spasdff_5_0 su_ed_wr_reg_ff(df_wr_reg, ex_wr_reg, clk, reset_l);
spasdff_1_0 su_ed_wr_en_ff(df_wr_en, ex_wr_en, clk, reset_l);
spasdff_1_0 su_ed_load_ff(su_df_load, su_ex_load, clk, reset_l);
spasdff_1_0 su_ed_ld_ty_ff(su_df_load_type, su_ex_load_type, clk,reset_l);
spasdff_1_0 vu_ed_load_ff(vu_df_load, vu_ex_load, clk, reset_l);
spasdff_1_0 su_ed_lsls_ff(df_ls_drive_ls_in_wb, ex_ls_drive_ls_in_wb, clk, reset_l);
spasdff_1_0 su_ed_pass_ff(df_pass_thru, ex_pass_thru,clk,reset_l);
spasdff_1_0 su_ed_dma_ff(df_dma_cycle, ex_dma_cycle, clk, reset_l);
//
// WB stage signals
//
spasdff_5_0 su_dw_wr_reg_ff(wb_wr_reg, df_wr_reg, clk, reset_l);
// Write to R0 during reset. Purpose is to eliminate x's from QSim log.
wire df_wr_en_r;
assign df_wr_en_r = df_wr_en || !reset_l;
spasdff_1_0 su_dw_wr_en_ff(wb_wr_en, df_wr_en_r, clk, 1'b1);
spasdff_1_0 su_dw_ld_type_ff(su_wb_load_type, su_df_load_type,clk,reset_l);
assign suwben = !su_wb_load_type;
assign surf_w = wb_wr_reg;
assign surf_wen = wb_wr_en;
// CP0 Control
assign rd_mtc0 = (opc[5:4]==2'b01) && (opc[1]==1'b0) &&
(rs[4]==0) && (rs[2:1]==2'b10);
assign rd_mtc0_k = rd_mtc0 && !(kill_su_issue || kill_re);
spasdff_1_0 su_re_mtc0_ff(ex_mtc0, rd_mtc0_k, clk, reset_l);
spasdff_4_0 su_re_c0_addr_ff(cp0_address, rd[3:0], clk, reset_l);
assign cp0_write = ex_mtc0;
assign cp0_enable = !ex_mtc0 && !halt;
assign rd_mfc0 = (opc[5:4]==2'b01) && (opc[1]==1'b0) &&
(rs[4]==0) && (rs[2:1]==2'b00);
assign rd_mfc0_k = rd_mfc0 && !(kill_su_issue || kill_re);
spasdff_1_0 su_re_mfc0_ff(ex_mfc0, rd_mfc0_k, clk, reset_l);
endmodule
module xor_6 (a1, a2, eq, neq);
input [5:0] a1;
input [5:0] a2;
output eq;
output neq;
wire [5:0] z;
j_xo02 xor_bit_0 (.a1(a1[0]), .a2(a2[0]), .z(z[0]));
j_xo02 xor_bit_1 (.a1(a1[1]), .a2(a2[1]), .z(z[1]));
j_xo02 xor_bit_2 (.a1(a1[2]), .a2(a2[2]), .z(z[2]));
j_xo02 xor_bit_3 (.a1(a1[3]), .a2(a2[3]), .z(z[3]));
j_xo02 xor_bit_4 (.a1(a1[4]), .a2(a2[4]), .z(z[4]));
j_xo02 xor_bit_5 (.a1(a1[5]), .a2(a2[5]), .z(z[5]));
j_nr06 xor_6 (.a1(z[0]), .a2(z[1]), .a3(z[2]), .a4(z[3]), .a5(z[4]), .a6(z[5]), .zn(eq));
j_or06 xnor_6 (.a1(z[0]), .a2(z[1]), .a3(z[2]), .a4(z[3]), .a5(z[4]), .a6(z[5]), .z(neq));
endmodule
module surdamux_unit (rs, ex_wr_reg, df_wr_reg, wb_wr_reg,
ex_wr_en, df_wr_en, wb_wr_en, opc, func,
surdamux, a_ex_byp, a_df_byp, a_wb_byp, use_a);
input [4:0] rs;
input [4:0] ex_wr_reg;
input [4:0] df_wr_reg;
input [4:0] wb_wr_reg;
input ex_wr_en;
input df_wr_en;
input wb_wr_en;
input [5:0] opc;
input [5:0] func;
output [2:0] surdamux;
output a_ex_byp;
output a_df_byp;
output a_wb_byp;
output use_a;
wire [5:0] opc_l;
wire use_a_term0;
wire use_a_term1;
wire use_a_term2;
wire use_a_term3;
wire use_a_term4;
wire rs_eq0;
wire rd_lui;
wire a_ex_byp_l;
wire a_df_byp_l;
wire a_wb_byp_l;
wire surdamux_1_a;
wire surdamux_1_b;
wire surdamux_0_a;
wire surdamux_0_b;
/* If necessary for timing, redo using a_gets0 as mux select for final
value. Remove a_gets0 from preliminary logic.
*/
j_in01 in_opc_0 (.i(opc[0]), .zn(opc_l[0]));
j_in01 in_opc_1 (.i(opc[1]), .zn(opc_l[1]));
j_in01 in_opc_2 (.i(opc[2]), .zn(opc_l[2]));
j_in01 in_opc_3 (.i(opc[3]), .zn(opc_l[3]));
j_in01 in_opc_4 (.i(opc[4]), .zn(opc_l[4]));
j_in01 in_opc_5 (.i(opc[5]), .zn(opc_l[5]));
j_an05 an_use_a_0 (.a1(opc_l[5]), .a2(opc_l[4]), .a3(opc_l[3]), .a4(opc_l[2]), .a5(opc[1]), .z(rd_jump_imm));
j_an05 an_use_a_1 (.a1(opc_l[5]), .a2(opc[4]), .a3(opc_l[3]), .a4(opc_l[2]), .a5(opc_l[0]), .z(use_a_term1));
j_an06 an_use_a_2 (.a1(opc_l[5]), .a2(opc_l[4]), .a3(opc_l[3]), .a4(opc_l[2]), .a5(opc_l[1]), .a6(opc_l[0]), .z(use_a_term2));
j_nr04 nr_use_a_3 (.a1(func[5]), .a2(func[4]), .a3(func[3]), .a4(func[2]), .zn(use_a_term3));
j_an02 an_use_a_4 (.a1(use_a_term2), .a2(use_a_term3), .z(use_a_term4));
j_nr03 nr_use_a_5 (.a1(rd_jump_imm), .a2(use_a_term1), .a3(use_a_term4), .zn(use_a));
j_nr05 nr_rs_0 (.a1(rs[4]), .a2(rs[3]), .a3(rs[2]), .a4(rs[1]), .a5(rs[0]), .zn(rs_eq0));
j_an06 an_rd_lui (.a1(opc_l[5]), .a2(opc_l[4]), .a3(opc[3]), .a4(opc[2]), .a5(opc[1]), .a6(opc[0]), .z(rd_lui));
j_or03 or_a_gets0 (.a1(rd_jump_imm), .a2(rs_eq0), .a3(rd_lui), .z(a_gets0));
xor_6 xor_ex_byp (.a1({rs, 1'b1}), .a2({ex_wr_reg, ex_wr_en}), .eq(a_ex_byp), .neq(a_ex_byp_l));
xor_6 xor_df_byp (.a1({rs, 1'b1}), .a2({df_wr_reg, df_wr_en}), .eq(a_df_byp), .neq(a_df_byp_l));
xor_6 xor_wb_byp (.a1({rs, 1'b1}), .a2({wb_wr_reg, wb_wr_en}), .eq(a_wb_byp), .neq(a_wb_byp_l));
j_ni01 surdamux_2 (.i(a_gets0), .z(surdamux[2]));
// surdamux_1 = (!a_ex_byp && !a_gets0 && !a_df_byp_l) || (!a_ex_byp && !a_gets0 && !a_wb_byp_l);
j_nr03 nr_surdamux_1_a (.a1(a_ex_byp), .a2(a_gets0), .a3(a_df_byp_l), .zn(surdamux_1_a));
j_nr03 nr_surdamux_1_b (.a1(a_ex_byp), .a2(a_gets0), .a3(a_wb_byp_l), .zn(surdamux_1_b));
j_or02 nr_surdamux_1 (.a1(surdamux_1_a), .a2(surdamux_1_b), .z(surdamux[1]));
// surdamux[0] = (!a_wb_byp_l && !a_df_byp && !a_gets0) || (!a_ex_byp_l && !a_gets0);
j_nr03 nr_surdamux_0_a (.a1(a_wb_byp_l), .a2(a_df_byp), .a3(a_gets0), .zn(surdamux_0_a));
j_nr02 nr_surdamux_0_b (.a1(a_ex_byp_l), .a2(a_gets0), .zn(surdamux_0_b));
j_or02 nr_surdamux_0 (.a1(surdamux_0_a), .a2(surdamux_0_b), .z(surdamux[0]));
endmodule