-
Notifications
You must be signed in to change notification settings - Fork 1
/
SimpleCore.v
2804 lines (2657 loc) · 79.9 KB
/
SimpleCore.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
/* Basic opcodes.
*
* IMPORTANT NOTE:
*
* In the descriptions, "a" represents the target register (and is only used where a general purpose register
* is written to), "b" and "c" represent the source registers and "i" represents an immediate value. "?" is
* used as a wildcard in situations where any value matches the description.
*
* ENCODING STYLE:
*
* Instructions are generally categorised by the highest nibble with the nibble below that
* usually being an ALU operation or other sub-instruction. For example, to add registers you'd use 0xA1 (ALU op #1)
* whereas to add an immediate value you'd use the same ALU subcode but the immediate supercode: 0x11 (immediate op #1).
*
* These categories aren't a hard-and-fast rule, future processors may condense additional instructions into
* unused opcodes regardless of categories, but it is designed to make recognising and producing the basic
* instructions easier for humans.
*
* For this same reason, opcodes and operands are generally aligned on 4- or
* 8-bit boundaries, so e.g. register #3 either looks like "3" or "03" in hex (depending on whether it's in a
* 4-bit or 8-bit operand). This encoding allows for addressing up to 256 different registers in most instructions
* and up to 16 in instructions with more bits reserved for immediate values.
*
* Immediate values are always stored in the lower 16 bits of an instruction and are always sign-extended (whether
* or not that's important depends on the instruction and context).
*
* BRANCHING & IF INSTRUCTIONS:
*
* Originally I planned to use a combined instruction for all jumps and then optimised variants. However, I settled
* on a slightly-more-complicated but slightly-more-practical scheme: Jumps are separated into "branches", which
* generally represent function call/return operations (or simplified jump-to-address or get-program-counter variants),
* and "ifs", which only perform a simple jump to a nearby address but can also perform conditional jumps based on an
* ALU operation (to perform an unconditional jump, you can just use an operation that would always evaluate to true).
*
* A variant of the "branch" set of instructions is also used to return from system mode after a system call or other
* exception. That functionality is much more specialised than the other branch instructions, but essentially does
* the same thing except using system registers instead of the normal register locations (but importantly, it also
* switches the system flags and is only accessible if system mode is already enabled in the flags).
*
* MEMORY, CONTROL & I/O INSTRUCTIONS:
*
* For read/write operations (whether on data, control or extended I/O channels) the supercode represents
* the bus (0xC? for Control, 0xD for Data or 0xE for Extensions) whereas the subcode holds the write bit
* and the size order: 0xD2 doesn't have the high bit of the low nibble set, so it's a read, whereas 0xDA
* does so it would be a write. The lowest two bits (or the whole low nibble if it's a read) determine the
* size: 0 for a single byte, 1 for 16 bits, 2 for 32 bits, 3 for 64 bits.
*
* 0x2? instructions are reserved for optimised/immediate jumps, 0x3? instructions are reserved for optimised
* loads.
*
* Currently, all of the control and I/O family of instructions are limited to access from system mode, however in the
* future they may be configurable for user-mode operation as well (e.g. by only allowing low locations and using a
* configurable bitmask to enable/disable access).
*
* The I/O bus is essentially meant to just be a redundant extra memory bus. It could either be used to access a
* specific bus for external hardware devices (separate to normal memory) or it could be ignored or just used
* to bypass MMU or (perhaps most importantly) just for debugging designs. Designs without an I/O bus can
* just treat I/O instructions as invalid instructions and let the system software decide how to handle them.
*
* EXCEPTIONS & INTERRUPTS:
*
* The current exception-handling system tracks a last-exception-number value in a read-only control register.
* A number of internal exceptions are supported (e.g. bad instruction) as well as a simple timer countdown alarm
* run from the core's clock and a single external interrupt line with an acknowledge pin (the expectation being
* that if the device needs multiple hardware interrupts it should probably have it's own mechanisms to prioritise
* and describe the different kinds).
*
* Exception-handling behaviour is to swap the flags and xaddr registers with mirrorflags and mirrorxaddr, jumping to
* the original xaddr and setting the new mirrorxaddr to the interrupted instruction. (TODO: Test/check/dwell upon this
* behaviour.) Generally speaking, the system software must set up the flags and mirrorflags so that exceptions are
* disabled while it's performing any sensitive operations that can't be interrupted but enabled while running any
* code which needs to be debugged or otherwise monitored.
*
* Besides which registers are used, the most important semantics are that the interrupted instruction *wasn't
* executed yet*, and the saved address points to that specific instruction (not to the one before or after it).
* One notable edge case is that if an instruction jumps to an invalid memory address, an exception will be
* triggered when landing at the invalid address. In that case, the system software must take extra care not to
* try and read that instruction or return to that address. (This is called a bad dog exception because it won't
* fetch and you have to be careful.)
*
* All unrecognised instructions should trigger a recoverable decoding exception.
*/
`define ENCODING_BAD 3'b000 // 0xop??????
`define ENCODING_OPABC 3'b010 // 0xopaabbcc
`define ENCODING_OPABI 3'b011 // 0xopabiiii
`define ENCODING_OPBCI 3'b001 // 0xopbciiii NOTE: Similar to OPABI encoding except two input registers
`define ENCODING_OPL24 3'b100 // 0xoaiiiiii NOTE: Target register is suboperation, 24 bit immediate. (An optimised encoding for loading constants.)
`define ENCODING_OPXLU 3'b101 // 0xoabciiii NOTE: This is for extended a=b+c type operations (with up to 65536 operators)
// These are only needed for 'RISC' emulation
`define ENCODING_RE_R 3'b000
`define ENCODING_RE_I 3'b001
`define ENCODING_RE_S 3'b010
`define ENCODING_RE_U 3'b011
`define ENCODING_RE_B 3'b100 // NOTE: The B and J variants are based on the others but with special handling of immediates
`define ENCODING_RE_J 3'b101
`define OP_SYSCALL 8'h00 // 0x00??????: invalid instruction, but reserved for encoding system calls
`define OP_ADDIMM 8'h11 // 0x11abiiii: a=b+i; // NOTE: Can only access lower 16 registers due to encoding
`define OP_LDSL16IMM 8'h1D // 0x11abiiii: a=(b<<16)|(c&0xFF);
`define OP_ADD 8'hA1 // 0xA1aabbcc: a=b+c; // NOTE: Encoding allows up to 256 registers, but higher ones might be disabled
`define OP_SUB 8'hA2 // 0xA2aabbcc: a=b-c;
`define OP_AND 8'hA3
`define OP_OR 8'hA4
`define OP_XOR 8'hA5
`define OP_SHL 8'hA6
`define OP_SHRZ 8'hA7
`define OP_SHRS 8'hA8
`define OP_BLINK 8'hB1 // 0xB1aaxxxx: a = pc + 4;
`define OP_BTO 8'hB2 // 0xB2xxxxcc: npc = c;
`define OP_BE 8'hB3 // 0xB3aaxxcc: a = pc + 4; npc = c; // This is short for branch-and-enter
`define OP_BEFORE 8'hB4 // 0xB4xxxxxx: npc = before; nflags = mirrorflags; nmirrorflags = flags; nbefore = mirrorbefore; nmirrorbefore = before;
`define OP_BAIT 8'hB8 // 0xB8xxxxxx: invalid instruction, but reserved for traps.
// NOTE: 32-/64-bit variants use different operations for ctrlin/ctrlout, since internal registers share the same logical size
`define OP_CTRLIN64 8'hC3 // 0xC3axiiii: a=ctrl[i]; // Similar to memory ops but with no dynamic base
`define OP_CTRLOUT64 8'hCB // 0xCBxciiii: ctrl[i]=c;
`define OP_CTRLIN32 8'hC2 // 0xC3axiiii: a=ctrl[i]; // Similar to memory ops but with no dynamic base
`define OP_CTRLOUT32 8'hCA // 0xCBxciiii: ctrl[i]=c;
`define OP_READ32 8'hD2 // 0xD2abiiii: a=data[b+i];
`define OP_READ32H 8'hD6
`define OP_WRITE32 8'hDA // 0xDAbciiii: data[b+i]=c;
`define OP_WRITE32H 8'hDE
`define OP_IN32 8'hE2 // 0xE2abiiii: a=ext[b+i];
`define OP_IN32H 8'hE6
`define OP_OUT32 8'hEA // 0xEAbciiii: ext[b+i]=c;
`define OP_OUT32H 8'hEE
`define OP_IFABOVE 8'hFA // 0xFAbciiii: if((unsigned) b > (unsigned) c){npc = (pc & (-1 << 18)) | (i<<2);}
`define OP_IFBELOWS 8'hFB // 0xFBbciiii: if((signed) b < (signed) c){npc = (pc & (-1 << 18)) | (i<<2);}
`define OP_IFEQUALS 8'hFE // 0xFEbciiii: if(b == c){npc = pc + (i<<2);}
// The ld24 operations treat the minor opcode as the target register, and sign-extend the lower 24-bits to fill it
// These can be considered a mere optimisation or optional set of instructions, but they can especially be handy for
// loading many program constants.
`define OP_LD24_0 8'h30 // 0x3aiiiiii: a = i;
`define OP_LD24_1 8'h31
`define OP_LD24_2 8'h32
`define OP_LD24_3 8'h33
`define OP_LD24_4 8'h34
`define OP_LD24_5 8'h35
`define OP_LD24_6 8'h36
`define OP_LD24_7 8'h37
`define OP_LD24_8 8'h38
`define OP_LD24_9 8'h39
`define OP_LD24_A 8'h3A
`define OP_LD24_B 8'h3B
`define OP_LD24_C 8'h3C
`define OP_LD24_D 8'h3D
`define OP_LD24_E 8'h3E
`define OP_LD24_F 8'h3F
// The XLU operations have a special encoding, allowing up to 65536 different operators in a=b+c style.
`define OP_XLU_0 8'h90 // 0x9abciiii: a = (b i c); // Where 'i' is the operator number
`define OP_XLU_1 8'h91
`define OP_XLU_2 8'h92
`define OP_XLU_3 8'h93
`define OP_XLU_4 8'h94
`define OP_XLU_5 8'h95
`define OP_XLU_6 8'h96
`define OP_XLU_7 8'h97
`define OP_XLU_8 8'h98
`define OP_XLU_9 8'h99
`define OP_XLU_A 8'h9A
`define OP_XLU_B 8'h9B
`define OP_XLU_C 8'h9C
`define OP_XLU_D 8'h9D
`define OP_XLU_E 8'h9E
`define OP_XLU_F 8'h9F
// Earlier design with combined branch/if instruction (decided to combine system-return function with branch instead)
//`define OP_BRIF 8'hBF // 0xBFaabbcc: if(b != 0){a = pc + 4; nflags = mirrorflags; nmirrorflags = flags; npc = c;}
// These are only used for 'RISC' emulation (note, these define the major opcodes, the complete opcode usually has separate sub-operation)
`define OP_RE_OP 7'b0110011
`define OP_RE_OP_IMM 7'b0010011
`define OP_RE_BRANCH 7'b1100011
`define OP_RE_LUI 7'b0110111
`define OP_RE_AUIPC 7'b0010011
`define OP_RE_JAL 7'b1101111
`define OP_RE_JALR 7'b1100111
`define OP_RE_LOAD 7'b0000011
`define OP_RE_STORE 7'b0100011
`define OP_RE_MISC_MEM 7'b0001111
`define ALU_NOP 5'h00
`define ALU_ADD 5'h01
`define ALU_SUB 5'h02
`define ALU_AND 5'h03
`define ALU_OR 5'h04
`define ALU_XOR 5'h05
`define ALU_SHL 5'h06
`define ALU_SHRZ 5'h07
`define ALU_SHRS 5'h08
`define ALU_MULS 5'h09
`define ALU_ABOVE 5'h0A
`define ALU_BELOWS 5'h0B
`define ALU_CRUMBS 5'h0C
`define ALU_LDSL16 5'h0D // a=(b<<16)|(c&0xFFFF) - basically for loading extra bits into a register
`define ALU_EQUALS 5'h0E
`define ALU_LOADC 5'h10
`define ALU_DIVS 5'h11
`define ALU_NEQUALS 5'h12
`define ALU_BELOW 5'h13
`define ALU_ABOVEEQ 5'h14
`define ALU_ABOVESEQ 5'h15
// These are only used for 'RISC' emulation (they get converted to regular ALU codes internally):
`define ALU_RE_ADD 3'b000
`define ALU_RE_SLL 3'b001
`define ALU_RE_SLT 3'b010
`define ALU_RE_SLTU 3'b011
`define ALU_RE_XOR 3'b100
`define ALU_RE_SRL 3'b101
`define ALU_RE_OR 3'b110
`define ALU_RE_AND 3'b111
`define BRANCH_RE_EQ 3'b000
`define BRANCH_RE_NE 3'b001
`define BRANCH_RE_LT 3'b100
`define BRANCH_RE_GE 3'b101
`define BRANCH_RE_LTU 3'b110
`define BRANCH_RE_GEU 3'b111
`define CTRL_CPUID 6'h0
`define CTRL_EXCN 6'h1
`define CTRL_FLAGS 6'h2
`define CTRL_MIRRORFLAGS 6'h3
`define CTRL_XADDR 6'h4
`define CTRL_MIRRORXADDR 6'h5
`define CTRL_TIMER0 6'h6
`define CTRL_SYSTEM0 6'h8 // This one has no hard-coded purpose. It's mostly designed for holding task info in an operating system.
`define CTRL_SYSTEM1 6'h9 // This is another control register for storing system-specific stuff.
`define CTRL_GPIOA_PINS 6'hA // GPIO A = CTRL #A. Almost by design.
`define CTRL_MMU_CFG 6'hE // Interface for MMU info (not used right now)
`define CTRL_PROCESSORS 6'hF // Used for controlling parallel processors
// The 0x1x and 0x2x range of control registers are used for the lower slots of the MMU
`define CTRL_MMU_X0 6'h10
`define CTRL_MMU_Y0 7'h20
`define CTRL_MMU_X1 6'h11
`define CTRL_MMU_Y1 7'h21
`define CTRL_MMU_X2 6'h12
`define CTRL_MMU_Y2 7'h22
`define CTRL_MMU_X3 6'h13
`define CTRL_MMU_Y3 7'h23
`define CTRL_MMU_X4 6'h14
`define CTRL_MMU_Y4 7'h24
`define CTRL_MMU_X5 6'h15
`define CTRL_MMU_Y5 7'h25
`define CTRL_MMU_X6 6'h16
`define CTRL_MMU_Y6 7'h26
`define CTRL_MMU_X7 6'h17
`define CTRL_MMU_Y7 7'h27
// The 0x3x range of control registers is used to configure instruction overloading
// These registers are 32-bit (for the sake of working the same on 32-bit implementations)
// each bit represents a combination of major+minor opcode; If overlord mode is enabled
// and that instruction is reached it will trigger an overlord instruction exception instead
// of executing that instruction, regardless of whether or not the processor supports that
// particular instruction.
// This serves a few purposes, including the ability to patch instruction-specific bugs in
// software if necessary and the ability to emulate extended instructions on earlier versions
// of hardware (without being limited to emulating only those instructions not being defined
// in hardware).
`define CTRL_OVERLORD_0 7'h30
`define CTRL_OVERLORD_1 7'h30
`define CTRL_OVERLORD_2 7'h30
`define CTRL_OVERLORD_3 7'h30
`define CTRL_OVERLORD_4 7'h30
`define CTRL_OVERLORD_5 7'h30
`define CTRL_OVERLORD_6 7'h30
`define CTRL_OVERLORD_7 7'h30
`define EXCN_BADDOG 1 // Unable to fetch instruction (i.e. bad instruction address or fatal bus error)
`define EXCN_INVALIDINSTR 2 // Instruction was fetched but not recognised as valid by the decoder
`define EXCN_SYSMODEINSTR 3 // Instruction was fetched and could presumably be decoded, but requires system mode and was run in user mode
`define EXCN_BUSERROR 4 // The instruction was fetched/decoded but the memory or extension I/O triggered a bus exception
`define EXCN_REGISTERERROR 6 // The instruction was fetched/decoded but referred to a register which was unimplemented or blocked
`define EXCN_ALUERROR 7 // The instruction was fetched/decoded but the ALU operation triggered an error (e.g. bad operation or division by zero)
`define EXCN_RESEREED 8 // This exception number is reserved for system calls (which would currently trigger an EXCN_INVALIDINSTR)
`define EXCN_DINGDONG 9 // This exception is triggered by the internal timer unit (if enabled) i.e. for multitasking or other regular checks
`define EXCN_HARDWARE 10 // This exception is triggered by external hardware, typically an interrupt controller (which should have it's own mechanism for interrupt numbers)
`define EXCN_COPROCESSOR 11 // This exception is triggered explicitly by another processor core (i.e. for synchronisation)
`define EXCN_OVERLORDINSTR 12 // This exception is triggered (similarly to INVALIDINSTR) if the instruction is overloaded
`define STAGE_INITIAL 0
`define STAGE_FETCH 1
`define STAGE_DECODE 2
`define STAGE_SETBUS 3
`define STAGE_GETBUS 4
`define STAGE_SAVE 5
`define STAGE_CLEANUP 6
//`define STAGE_DECODEHACK 7
//`define STAGE_EXECUTE 3
//`define STAGE_RW1 4
`define STAGE_NOTREADY 8
`define STAGE_EXCEPTION 16
`define STAGE_XACK 17
`define STAGE_XWAIT 18
`define STAGE_ERROR 32
`define FLAGS_INITIAL 64'hf01
`define MIRRORFLAGS_INITIAL 64'hf01
/* Defines the value of the CPUID register, which should identify basic features/version as well as a vendor id.
* Low byte is the maximum addressable register, next is ISA version, then number of MMU slots, high bytes are a
* signature.
*
* NOTE: Additional CPUID-like registers will probably be added in the future to detect other features (e.g. which
* timer devices are present, what the actual CPU number is, and probably some way for the external bus to give some
* additional configuration data too).
*/
`define CPUIDVALUE 64'h110
module SimpleDecoder(ins, isregalu, isimmalu, isvalid, issystem, regA, regB, regC, regwrite, aluop, imm, valsize, ctrlread, ctrlwrite, dataread, datawrite, extnread, extnwrite, highA, highB, highC, getpc, setpc, blink, bto, bswitch, bif, signbus, btorelative);
//input decodeclk;
input [31:0] ins;
output reg isregalu;
output reg isimmalu;
output reg isvalid;
output reg issystem;
output wire [7:0]regA;
output wire [7:0]regB;
output wire [7:0]regC;
output reg regwrite;
output reg [4:0]aluop;
output [63:0]imm;
output reg [1:0]valsize;
output reg ctrlread;
output reg ctrlwrite;
output reg dataread;
output reg datawrite;
output reg extnread;
output reg extnwrite;
output reg highA;
output reg highB;
output reg highC;
output reg getpc;
output reg setpc;
output reg blink;
output reg bto;
output reg bswitch;
output reg bif;
output reg signbus = 0; // Not sure if will be needed in the future (added for parity with 'RISC' decoder)
output reg btorelative = 0; // Also only used in the 'RISC' decoder
reg [2:0]encoding = 0;
wire [7:0]opcode = ins[31:24];
/* The immediate output is usually just the sign-extended version of the lower half (16 bits) of the instruction, or
* otherwise the lower 24 bits (for instructions starting with 0x2 or 0x3). It will produce output
* regardless of whether the immediate is used by the instruction.
*/
wire [47:0] ext16 = ins[15] ? 48'b111111111111111111111111111111111111111111111111 : 0;
wire [63:0] imm16 = {ext16, ins[15:0]};
wire [39:0] ext24 = ins[23] ? 40'b1111111111111111111111111111111111111111 : 0;
wire [63:0] imm24 = {ext24, ins[23:0]};
assign imm = (encoding == `ENCODING_OPL24) ? imm24 : imm16;
/* The registers are easy to decode in ABC-format instructions but need some specialisation/defaults for others. */
assign regA = (encoding == `ENCODING_OPABC) ? ins[23:16] : ((encoding == `ENCODING_OPABI) ? ins[23:20] : (((encoding == `ENCODING_OPL24) || (encoding == `ENCODING_OPXLU)) ? ins[27:24] : 8'b0));
assign regB = (encoding == `ENCODING_OPABC) ? ins[15:8] : ((encoding == `ENCODING_OPABI) ? ins[19:16] : (((encoding == `ENCODING_OPBCI) || (encoding == `ENCODING_OPXLU)) ? ins[23:20] : 8'b0));
assign regC = (encoding == `ENCODING_OPABC) ? ins[7:0] : (((encoding == `ENCODING_OPBCI) || (encoding == `ENCODING_OPXLU)) ? ins[19:16] : 8'b0);
always @(opcode or ins[4:0] /* bit hacky, avoids warnings... */ /*posedge decodeclk*/) begin
case (opcode)
`OP_ADDIMM: begin
encoding = `ENCODING_OPABI;
isimmalu = 1;
isvalid = 1;
regwrite = 1;
aluop = `ALU_ADD; //[7:0] = {4'b0000:opcode[3:0]};
isregalu = 0;
//isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
//aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_LDSL16IMM: begin
encoding = `ENCODING_OPABI;
isimmalu = 1;
isvalid = 1;
regwrite = 1;
aluop = `ALU_LDSL16; //[7:0] = {4'b0000:opcode[3:0]};
isregalu = 0;
//isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
//aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_ADD: begin
encoding = `ENCODING_OPABC;
isregalu = 1;
isvalid = 1;
regwrite = 1;
aluop = `ALU_ADD; //[7:0] = {4'b0000:opcode[3:0]};
//isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
//aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_SUB: begin
encoding = `ENCODING_OPABC;
isregalu = 1;
isvalid = 1;
regwrite = 1;
aluop = `ALU_SUB; //[7:0] = {4'b0000:opcode[3:0]};
//isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
//aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_AND: begin
encoding = `ENCODING_OPABC;
isregalu = 1;
isvalid = 1;
regwrite = 1;
aluop = `ALU_AND;
//isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
//aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_OR: begin
encoding = `ENCODING_OPABC;
isregalu = 1;
isvalid = 1;
regwrite = 1;
aluop = `ALU_OR;
//isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
//aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_XOR: begin
encoding = `ENCODING_OPABC;
isregalu = 1;
isvalid = 1;
regwrite = 1;
aluop = `ALU_XOR;
//isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
//aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_SHL: begin
encoding = `ENCODING_OPABC;
isregalu = 1;
isvalid = 1;
regwrite = 1;
aluop = `ALU_SHL;
//isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
//aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_SHRZ: begin
encoding = `ENCODING_OPABC;
isregalu = 1;
isvalid = 1;
regwrite = 1;
aluop = `ALU_SHRZ;
//isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
//aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_SHRS: begin
encoding = `ENCODING_OPABC;
isregalu = 1;
isvalid = 1;
regwrite = 1;
aluop = `ALU_SHRS;
//isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
//aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_BLINK: begin
encoding = `ENCODING_OPABC;
isvalid = 1;
blink = 1;
regwrite = 1;
isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
//blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_BTO: begin
encoding = `ENCODING_OPABC; // Note, destination register is ignored in a plain bto
isvalid = 1;
bto = 1;
isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
regwrite = 0;
aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
//bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_BE: begin
encoding = `ENCODING_OPABC;
isvalid = 1;
blink = 1;
regwrite = 1;
bto = 1;
isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
//blink = 0;
//bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_BEFORE: begin
encoding = `ENCODING_OPABC; // Note, destination register is ignored in a plain before
isvalid = 1;
issystem = 1;
bswitch = 1;
isregalu = 0;
isimmalu = 0;
//isvalid = 0;
//issystem = 0;
regwrite = 0;
aluop = 0;
valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
//bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
/*
`OP_BRIF: begin
isvalid = 1;
getpc = 1;
setpc = 1;
breg = 1;
bif = 1;
end*/
`OP_CTRLIN64: begin
encoding = `ENCODING_OPABI;
isvalid = 1;
issystem = 1;
ctrlread = 1;
valsize = 3;
regwrite = 1;
isregalu = 0;
isimmalu = 0;
//isvalid = 0;
//issystem = 0;
//regwrite = 0;
aluop = 0;
//valsize = 0;
//ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_CTRLOUT64: begin
encoding = `ENCODING_OPBCI;
isvalid = 1;
issystem = 1;
ctrlwrite = 1;
valsize = 3;
isregalu = 0;
isimmalu = 0;
//isvalid = 0;
//issystem = 0;
regwrite = 0;
aluop = 0;
//valsize = 0;
ctrlread = 0;
//ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_READ32: begin
encoding = `ENCODING_OPABI;
isvalid = 1;
dataread = 1;
valsize = 2;
regwrite = 1;
isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
//regwrite = 0;
aluop = 0;
//valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
//dataread = 0;
datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_WRITE32: begin
encoding = `ENCODING_OPBCI;
isvalid = 1;
datawrite = 1;
valsize = 2;
isregalu = 0;
isimmalu = 0;
//isvalid = 0;
issystem = 0;
regwrite = 0;
aluop = 0;
//valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
//datawrite = 0;
extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_IN32: begin
encoding = `ENCODING_OPABI;
isvalid = 1;
issystem = 1;
extnread = 1;
valsize = 2;
regwrite = 1;
isregalu = 0;
isimmalu = 0;
//isvalid = 0;
//issystem = 0;
//regwrite = 0;
aluop = 0;
//valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
//extnread = 0;
extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_OUT32: begin
encoding = `ENCODING_OPBCI;
isvalid = 1;
issystem = 1;
extnwrite = 1;
valsize = 2;
isregalu = 0;
isimmalu = 0;
//isvalid = 0;
//issystem = 0;
regwrite = 0;
aluop = 0;
//valsize = 0;
ctrlread = 0;
ctrlwrite = 0;
dataread = 0;
datawrite = 0;
extnread = 0;
//extnwrite = 0;
getpc = 0;
setpc = 0;
blink = 0;
bto = 0;
bif = 0;
//encoding = 0;
bswitch = 0;
highA = 0;
highB = 0;
highC = 0;
end
`OP_READ32H: begin
encoding = `ENCODING_OPABI;
isvalid = 1;
dataread = 1;
valsize = 2;