/
lm32_cpu.v
2935 lines (2773 loc) · 98.9 KB
/
lm32_cpu.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 NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// ------------------------------------------------------------------
// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
// ALL RIGHTS RESERVED
// ------------------------------------------------------------------
//
// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
//
// Permission:
//
// Lattice Semiconductor grants permission to use this code
// pursuant to the terms of the Lattice Semiconductor Corporation
// Open Source License Agreement.
//
// Disclaimer:
//
// Lattice Semiconductor provides no warranty regarding the use or
// functionality of this code. It is the user's responsibility to
// verify the user's design for consistency and functionality through
// the use of formal verification methods.
//
// --------------------------------------------------------------------
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97214
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 503-286-8001 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
// FILE DETAILS
// Project : LatticeMico32
// File : lm32_cpu.v
// Title : Top-level of CPU.
// Dependencies : lm32_include.v
//
// Version 3.8
// 1. Feature: Support for dynamically switching EBA to DEBA via a GPIO.
// 2. Bug: EA now reports instruction that caused the data abort, rather than
// next instruction.
//
// Version 3.4
// 1. Bug Fix: In a tight infinite loop (add, sw, bi) incoming interrupts were
// never serviced.
//
// Version 3.3
// 1. Feature: Support for memory that is tightly coupled to processor core, and
// has a single-cycle access latency (same as caches). Instruction port has
// access to a dedicated physically-mapped memory. Data port has access to
// a dedicated physically-mapped memory. In order to be able to manipulate
// values in both these memories via the debugger, these memories also
// interface with the data port of LM32.
// 2. Feature: Extended Configuration Register
// 3. Bug Fix: Removed port names that conflict with keywords reserved in System-
// Verilog.
//
// Version 3.2
// 1. Bug Fix: Single-stepping a load/store to invalid address causes debugger to
// hang. At the same time CPU fails to register data bus error exception. Bug
// is caused because (a) data bus error exception occurs after load/store has
// passed X stage and next sequential instruction (e.g., brk) is already in X
// stage, and (b) data bus error exception had lower priority than, say, brk
// exception.
// 2. Bug Fix: If a brk (or scall/eret/bret) sequentially follows a load/store to
// invalid location, CPU will fail to register data bus error exception. The
// solution is to stall scall/eret/bret/brk instructions in D pipeline stage
// until load/store has completed.
// 3. Feature: Enable precise identification of load/store that causes seg fault.
// 4. SYNC resets used for register file when implemented in EBRs.
//
// Version 3.1
// 1. Feature: LM32 Register File can now be mapped in to on-chip block RAM (EBR)
// instead of distributed memory by enabling the option in LM32 GUI.
// 2. Feature: LM32 also adds a static branch predictor to improve branch
// performance. All immediate-based forward-pointing branches are predicted
// not-taken. All immediate-based backward-pointing branches are predicted taken.
//
// Version 7.0SP2, 3.0
// No Change
//
// Version 6.1.17
// Initial Release
// =============================================================================
`include "lm32_include.v"
/////////////////////////////////////////////////////
// Module interface
/////////////////////////////////////////////////////
module lm32_cpu (
// ----- Inputs -------
clk_i,
`ifdef CFG_EBR_NEGEDGE_REGISTER_FILE
clk_n_i,
`endif
rst_i,
`ifdef CFG_DEBUG_ENABLED
`ifdef CFG_ALTERNATE_EBA
at_debug,
`endif
`endif
// From external devices
`ifdef CFG_INTERRUPTS_ENABLED
interrupt,
`endif
// From user logic
`ifdef CFG_USER_ENABLED
user_result,
user_complete,
`endif
`ifdef CFG_JTAG_ENABLED
// From JTAG
jtag_clk,
jtag_update,
jtag_reg_q,
jtag_reg_addr_q,
`endif
`ifdef CFG_EXTERNAL_BREAK_ENABLED
ext_break,
`endif
`ifdef CFG_IWB_ENABLED
// Instruction Wishbone master
I_DAT_I,
I_ACK_I,
I_ERR_I,
I_RTY_I,
`endif
// Data Wishbone master
D_DAT_I,
D_ACK_I,
D_ERR_I,
D_RTY_I,
// ----- Outputs -------
`ifdef CFG_TRACE_ENABLED
trace_pc,
trace_pc_valid,
trace_exception,
trace_eid,
trace_eret,
`ifdef CFG_DEBUG_ENABLED
trace_bret,
`endif
`endif
`ifdef CFG_JTAG_ENABLED
jtag_reg_d,
jtag_reg_addr_d,
`endif
`ifdef CFG_USER_ENABLED
user_valid,
user_opcode,
user_operand_0,
user_operand_1,
`endif
`ifdef CFG_IWB_ENABLED
// Instruction Wishbone master
I_DAT_O,
I_ADR_O,
I_CYC_O,
I_SEL_O,
I_STB_O,
I_WE_O,
I_CTI_O,
I_LOCK_O,
I_BTE_O,
`endif
// Data Wishbone master
D_DAT_O,
D_ADR_O,
D_CYC_O,
D_SEL_O,
D_STB_O,
D_WE_O,
D_CTI_O,
D_LOCK_O,
D_BTE_O
);
/////////////////////////////////////////////////////
// Parameters
/////////////////////////////////////////////////////
parameter eba_reset = `CFG_EBA_RESET; // Reset value for EBA CSR
`ifdef CFG_DEBUG_ENABLED
parameter deba_reset = `CFG_DEBA_RESET; // Reset value for DEBA CSR
`endif
`ifdef CFG_ICACHE_ENABLED
parameter icache_associativity = `CFG_ICACHE_ASSOCIATIVITY; // Associativity of the cache (Number of ways)
parameter icache_sets = `CFG_ICACHE_SETS; // Number of sets
parameter icache_bytes_per_line = `CFG_ICACHE_BYTES_PER_LINE; // Number of bytes per cache line
parameter icache_base_address = `CFG_ICACHE_BASE_ADDRESS; // Base address of cachable memory
parameter icache_limit = `CFG_ICACHE_LIMIT; // Limit (highest address) of cachable memory
`else
parameter icache_associativity = 1;
parameter icache_sets = 512;
parameter icache_bytes_per_line = 16;
parameter icache_base_address = 0;
parameter icache_limit = 0;
`endif
`ifdef CFG_DCACHE_ENABLED
parameter dcache_associativity = `CFG_DCACHE_ASSOCIATIVITY; // Associativity of the cache (Number of ways)
parameter dcache_sets = `CFG_DCACHE_SETS; // Number of sets
parameter dcache_bytes_per_line = `CFG_DCACHE_BYTES_PER_LINE; // Number of bytes per cache line
parameter dcache_base_address = `CFG_DCACHE_BASE_ADDRESS; // Base address of cachable memory
parameter dcache_limit = `CFG_DCACHE_LIMIT; // Limit (highest address) of cachable memory
`else
parameter dcache_associativity = 1;
parameter dcache_sets = 512;
parameter dcache_bytes_per_line = 16;
parameter dcache_base_address = 0;
parameter dcache_limit = 0;
`endif
`ifdef CFG_DEBUG_ENABLED
parameter watchpoints = `CFG_WATCHPOINTS; // Number of h/w watchpoint CSRs
`else
parameter watchpoints = 0;
`endif
`ifdef CFG_ROM_DEBUG_ENABLED
parameter breakpoints = `CFG_BREAKPOINTS; // Number of h/w breakpoint CSRs
`else
parameter breakpoints = 0;
`endif
`ifdef CFG_INTERRUPTS_ENABLED
parameter interrupts = `CFG_INTERRUPTS; // Number of interrupts
`else
parameter interrupts = 0;
`endif
/////////////////////////////////////////////////////
// Inputs
/////////////////////////////////////////////////////
input clk_i; // Clock
`ifdef CFG_EBR_NEGEDGE_REGISTER_FILE
input clk_n_i; // Inverted clock
`endif
input rst_i; // Reset
`ifdef CFG_DEBUG_ENABLED
`ifdef CFG_ALTERNATE_EBA
input at_debug; // GPIO input that maps EBA to DEBA
`endif
`endif
`ifdef CFG_INTERRUPTS_ENABLED
input [`LM32_INTERRUPT_RNG] interrupt; // Interrupt pins
`endif
`ifdef CFG_USER_ENABLED
input [`LM32_WORD_RNG] user_result; // User-defined instruction result
input user_complete; // User-defined instruction execution is complete
`endif
`ifdef CFG_JTAG_ENABLED
input jtag_clk; // JTAG clock
input jtag_update; // JTAG state machine is in data register update state
input [`LM32_BYTE_RNG] jtag_reg_q;
input [2:0] jtag_reg_addr_q;
`endif
`ifdef CFG_IWB_ENABLED
input [`LM32_WORD_RNG] I_DAT_I; // Instruction Wishbone interface read data
input I_ACK_I; // Instruction Wishbone interface acknowledgement
input I_ERR_I; // Instruction Wishbone interface error
input I_RTY_I; // Instruction Wishbone interface retry
`endif
input [`LM32_WORD_RNG] D_DAT_I; // Data Wishbone interface read data
input D_ACK_I; // Data Wishbone interface acknowledgement
input D_ERR_I; // Data Wishbone interface error
input D_RTY_I; // Data Wishbone interface retry
`ifdef CFG_EXTERNAL_BREAK_ENABLED
input ext_break;
`endif
/////////////////////////////////////////////////////
// Outputs
/////////////////////////////////////////////////////
`ifdef CFG_TRACE_ENABLED
output [`LM32_PC_RNG] trace_pc; // PC to trace
reg [`LM32_PC_RNG] trace_pc;
output trace_pc_valid; // Indicates that a new trace PC is valid
reg trace_pc_valid;
output trace_exception; // Indicates an exception has occured
reg trace_exception;
output [`LM32_EID_RNG] trace_eid; // Indicates what type of exception has occured
reg [`LM32_EID_RNG] trace_eid;
output trace_eret; // Indicates an eret instruction has been executed
reg trace_eret;
`ifdef CFG_DEBUG_ENABLED
output trace_bret; // Indicates a bret instruction has been executed
reg trace_bret;
`endif
`endif
`ifdef CFG_JTAG_ENABLED
output [`LM32_BYTE_RNG] jtag_reg_d;
wire [`LM32_BYTE_RNG] jtag_reg_d;
output [2:0] jtag_reg_addr_d;
wire [2:0] jtag_reg_addr_d;
`endif
`ifdef CFG_USER_ENABLED
output user_valid; // Indicates if user_opcode is valid
wire user_valid;
output [`LM32_USER_OPCODE_RNG] user_opcode; // User-defined instruction opcode
reg [`LM32_USER_OPCODE_RNG] user_opcode;
output [`LM32_WORD_RNG] user_operand_0; // First operand for user-defined instruction
wire [`LM32_WORD_RNG] user_operand_0;
output [`LM32_WORD_RNG] user_operand_1; // Second operand for user-defined instruction
wire [`LM32_WORD_RNG] user_operand_1;
`endif
`ifdef CFG_IWB_ENABLED
output [`LM32_WORD_RNG] I_DAT_O; // Instruction Wishbone interface write data
wire [`LM32_WORD_RNG] I_DAT_O;
output [`LM32_WORD_RNG] I_ADR_O; // Instruction Wishbone interface address
wire [`LM32_WORD_RNG] I_ADR_O;
output I_CYC_O; // Instruction Wishbone interface cycle
wire I_CYC_O;
output [`LM32_BYTE_SELECT_RNG] I_SEL_O; // Instruction Wishbone interface byte select
wire [`LM32_BYTE_SELECT_RNG] I_SEL_O;
output I_STB_O; // Instruction Wishbone interface strobe
wire I_STB_O;
output I_WE_O; // Instruction Wishbone interface write enable
wire I_WE_O;
output [`LM32_CTYPE_RNG] I_CTI_O; // Instruction Wishbone interface cycle type
wire [`LM32_CTYPE_RNG] I_CTI_O;
output I_LOCK_O; // Instruction Wishbone interface lock bus
wire I_LOCK_O;
output [`LM32_BTYPE_RNG] I_BTE_O; // Instruction Wishbone interface burst type
wire [`LM32_BTYPE_RNG] I_BTE_O;
`endif
output [`LM32_WORD_RNG] D_DAT_O; // Data Wishbone interface write data
wire [`LM32_WORD_RNG] D_DAT_O;
output [`LM32_WORD_RNG] D_ADR_O; // Data Wishbone interface address
wire [`LM32_WORD_RNG] D_ADR_O;
output D_CYC_O; // Data Wishbone interface cycle
wire D_CYC_O;
output [`LM32_BYTE_SELECT_RNG] D_SEL_O; // Data Wishbone interface byte select
wire [`LM32_BYTE_SELECT_RNG] D_SEL_O;
output D_STB_O; // Data Wishbone interface strobe
wire D_STB_O;
output D_WE_O; // Data Wishbone interface write enable
wire D_WE_O;
output [`LM32_CTYPE_RNG] D_CTI_O; // Data Wishbone interface cycle type
wire [`LM32_CTYPE_RNG] D_CTI_O;
output D_LOCK_O; // Date Wishbone interface lock bus
wire D_LOCK_O;
output [`LM32_BTYPE_RNG] D_BTE_O; // Data Wishbone interface burst type
wire [`LM32_BTYPE_RNG] D_BTE_O;
/////////////////////////////////////////////////////
// Internal nets and registers
/////////////////////////////////////////////////////
// Pipeline registers
`ifdef LM32_CACHE_ENABLED
reg valid_a; // Instruction in A stage is valid
`endif
reg valid_f; // Instruction in F stage is valid
reg valid_d; // Instruction in D stage is valid
reg valid_x; // Instruction in X stage is valid
reg valid_m; // Instruction in M stage is valid
reg valid_w; // Instruction in W stage is valid
wire q_x;
wire [`LM32_WORD_RNG] immediate_d; // Immediate operand
wire load_d; // Indicates a load instruction
reg load_x;
reg load_m;
wire load_q_x;
wire store_q_x;
wire store_d; // Indicates a store instruction
reg store_x;
reg store_m;
wire [`LM32_SIZE_RNG] size_d; // Size of load/store (byte, hword, word)
reg [`LM32_SIZE_RNG] size_x;
wire branch_d; // Indicates a branch instruction
wire branch_predict_d; // Indicates a branch is predicted
wire branch_predict_taken_d; // Indicates a branch is predicted taken
wire [`LM32_PC_RNG] branch_predict_address_d; // Address to which predicted branch jumps
wire [`LM32_PC_RNG] branch_target_d;
wire bi_unconditional;
wire bi_conditional;
reg branch_x;
reg branch_predict_x;
reg branch_predict_taken_x;
reg branch_m;
reg branch_predict_m;
reg branch_predict_taken_m;
wire branch_mispredict_taken_m; // Indicates a branch was mispredicted as taken
wire branch_flushX_m; // Indicates that instruction in X stage must be squashed
wire branch_reg_d; // Branch to register or immediate
wire [`LM32_PC_RNG] branch_offset_d; // Branch offset for immediate branches
reg [`LM32_PC_RNG] branch_target_x; // Address to branch to
reg [`LM32_PC_RNG] branch_target_m;
wire [`LM32_D_RESULT_SEL_0_RNG] d_result_sel_0_d; // Which result should be selected in D stage for operand 0
wire [`LM32_D_RESULT_SEL_1_RNG] d_result_sel_1_d; // Which result should be selected in D stage for operand 1
wire x_result_sel_csr_d; // Select X stage result from CSRs
reg x_result_sel_csr_x;
`ifdef LM32_MC_ARITHMETIC_ENABLED
wire x_result_sel_mc_arith_d; // Select X stage result from multi-cycle arithmetic unit
reg x_result_sel_mc_arith_x;
`endif
`ifdef LM32_NO_BARREL_SHIFT
wire x_result_sel_shift_d; // Select X stage result from shifter
reg x_result_sel_shift_x;
`endif
`ifdef CFG_SIGN_EXTEND_ENABLED
wire x_result_sel_sext_d; // Select X stage result from sign-extend logic
reg x_result_sel_sext_x;
`endif
wire x_result_sel_logic_d; // Select X stage result from logic op unit
reg x_result_sel_logic_x;
`ifdef CFG_USER_ENABLED
wire x_result_sel_user_d; // Select X stage result from user-defined logic
reg x_result_sel_user_x;
`endif
wire x_result_sel_add_d; // Select X stage result from adder
reg x_result_sel_add_x;
wire m_result_sel_compare_d; // Select M stage result from comparison logic
reg m_result_sel_compare_x;
reg m_result_sel_compare_m;
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
wire m_result_sel_shift_d; // Select M stage result from shifter
reg m_result_sel_shift_x;
reg m_result_sel_shift_m;
`endif
wire w_result_sel_load_d; // Select W stage result from load/store unit
reg w_result_sel_load_x;
reg w_result_sel_load_m;
reg w_result_sel_load_w;
`ifdef CFG_PL_MULTIPLY_ENABLED
wire w_result_sel_mul_d; // Select W stage result from multiplier
reg w_result_sel_mul_x;
reg w_result_sel_mul_m;
reg w_result_sel_mul_w;
`endif
wire x_bypass_enable_d; // Whether result is bypassable in X stage
reg x_bypass_enable_x;
wire m_bypass_enable_d; // Whether result is bypassable in M stage
reg m_bypass_enable_x;
reg m_bypass_enable_m;
wire sign_extend_d; // Whether to sign-extend or zero-extend
reg sign_extend_x;
wire write_enable_d; // Register file write enable
reg write_enable_x;
wire write_enable_q_x;
reg write_enable_m;
wire write_enable_q_m;
reg write_enable_w;
wire write_enable_q_w;
wire read_enable_0_d; // Register file read enable 0
wire [`LM32_REG_IDX_RNG] read_idx_0_d; // Register file read index 0
wire read_enable_1_d; // Register file read enable 1
wire [`LM32_REG_IDX_RNG] read_idx_1_d; // Register file read index 1
wire [`LM32_REG_IDX_RNG] write_idx_d; // Register file write index
reg [`LM32_REG_IDX_RNG] write_idx_x;
reg [`LM32_REG_IDX_RNG] write_idx_m;
reg [`LM32_REG_IDX_RNG] write_idx_w;
wire [`LM32_CSR_RNG] csr_d; // CSR read/write index
reg [`LM32_CSR_RNG] csr_x;
wire [`LM32_CONDITION_RNG] condition_d; // Branch condition
reg [`LM32_CONDITION_RNG] condition_x;
`ifdef CFG_DEBUG_ENABLED
wire break_d; // Indicates a break instruction
reg break_x;
`endif
wire scall_d; // Indicates a scall instruction
reg scall_x;
wire eret_d; // Indicates an eret instruction
reg eret_x;
wire eret_q_x;
reg eret_m;
`ifdef CFG_TRACE_ENABLED
reg eret_w;
`endif
`ifdef CFG_DEBUG_ENABLED
wire bret_d; // Indicates a bret instruction
reg bret_x;
wire bret_q_x;
reg bret_m;
`ifdef CFG_TRACE_ENABLED
reg bret_w;
`endif
`endif
wire csr_write_enable_d; // CSR write enable
reg csr_write_enable_x;
wire csr_write_enable_q_x;
`ifdef CFG_USER_ENABLED
wire [`LM32_USER_OPCODE_RNG] user_opcode_d; // User-defined instruction opcode
`endif
`ifdef CFG_BUS_ERRORS_ENABLED
wire bus_error_d; // Indicates an bus error occured while fetching the instruction in this pipeline stage
reg bus_error_x;
reg data_bus_error_exception_m;
reg [`LM32_PC_RNG] memop_pc_w;
`endif
reg [`LM32_WORD_RNG] d_result_0; // Result of instruction in D stage (operand 0)
reg [`LM32_WORD_RNG] d_result_1; // Result of instruction in D stage (operand 1)
reg [`LM32_WORD_RNG] x_result; // Result of instruction in X stage
reg [`LM32_WORD_RNG] m_result; // Result of instruction in M stage
reg [`LM32_WORD_RNG] w_result; // Result of instruction in W stage
reg [`LM32_WORD_RNG] operand_0_x; // Operand 0 for X stage instruction
reg [`LM32_WORD_RNG] operand_1_x; // Operand 1 for X stage instruction
reg [`LM32_WORD_RNG] store_operand_x; // Data read from register to store
reg [`LM32_WORD_RNG] operand_m; // Operand for M stage instruction
reg [`LM32_WORD_RNG] operand_w; // Operand for W stage instruction
// To/from register file
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
reg [`LM32_WORD_RNG] reg_data_live_0;
reg [`LM32_WORD_RNG] reg_data_live_1;
reg use_buf; // Whether to use reg_data_live or reg_data_buf
reg [`LM32_WORD_RNG] reg_data_buf_0;
reg [`LM32_WORD_RNG] reg_data_buf_1;
`endif
`ifdef LM32_EBR_REGISTER_FILE
`else
reg [`LM32_WORD_RNG] registers[0:(1<<`LM32_REG_IDX_WIDTH)-1]; // Register file
`endif
wire [`LM32_WORD_RNG] reg_data_0; // Register file read port 0 data
wire [`LM32_WORD_RNG] reg_data_1; // Register file read port 1 data
reg [`LM32_WORD_RNG] bypass_data_0; // Register value 0 after bypassing
reg [`LM32_WORD_RNG] bypass_data_1; // Register value 1 after bypassing
wire reg_write_enable_q_w;
reg interlock; // Indicates pipeline should be stalled because of a read-after-write hazzard
wire stall_a; // Stall instruction in A pipeline stage
wire stall_f; // Stall instruction in F pipeline stage
wire stall_d; // Stall instruction in D pipeline stage
wire stall_x; // Stall instruction in X pipeline stage
wire stall_m; // Stall instruction in M pipeline stage
// To/from adder
wire adder_op_d; // Whether to add or subtract
reg adder_op_x;
reg adder_op_x_n; // Inverted version of adder_op_x
wire [`LM32_WORD_RNG] adder_result_x; // Result from adder
wire adder_overflow_x; // Whether a signed overflow occured
wire adder_carry_n_x; // Whether a carry was generated
// To/from logical operations unit
wire [`LM32_LOGIC_OP_RNG] logic_op_d; // Which operation to perform
reg [`LM32_LOGIC_OP_RNG] logic_op_x;
wire [`LM32_WORD_RNG] logic_result_x; // Result of logical operation
`ifdef CFG_SIGN_EXTEND_ENABLED
// From sign-extension unit
wire [`LM32_WORD_RNG] sextb_result_x; // Result of byte sign-extension
wire [`LM32_WORD_RNG] sexth_result_x; // Result of half-word sign-extenstion
wire [`LM32_WORD_RNG] sext_result_x; // Result of sign-extension specified by instruction
`endif
// To/from shifter
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
`ifdef CFG_ROTATE_ENABLED
wire rotate_d; // Whether we should rotate or shift
reg rotate_x;
`endif
wire direction_d; // Which direction to shift in
reg direction_x;
wire [`LM32_WORD_RNG] shifter_result_m; // Result of shifter
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
wire shift_left_d; // Indicates whether to perform a left shift or not
wire shift_left_q_d;
wire shift_right_d; // Indicates whether to perform a right shift or not
wire shift_right_q_d;
`endif
`ifdef LM32_NO_BARREL_SHIFT
wire [`LM32_WORD_RNG] shifter_result_x; // Result of single-bit right shifter
`endif
// To/from multiplier
`ifdef LM32_MULTIPLY_ENABLED
wire [`LM32_WORD_RNG] multiplier_result_w; // Result from multiplier
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
wire multiply_d; // Indicates whether to perform a multiply or not
wire multiply_q_d;
`endif
// To/from divider
`ifdef CFG_MC_DIVIDE_ENABLED
wire divide_d; // Indicates whether to perform a divider or not
wire divide_q_d;
wire modulus_d;
wire modulus_q_d;
wire divide_by_zero_x; // Indicates an attempt was made to divide by zero
`endif
// To from multi-cycle arithmetic unit
`ifdef LM32_MC_ARITHMETIC_ENABLED
wire mc_stall_request_x; // Multi-cycle arithmetic unit stall request
wire [`LM32_WORD_RNG] mc_result_x;
`endif
wire [`LM32_WORD_RNG] load_store_csr_read_data_x;// Data read from load store unit CSRs
wire [`LM32_WORD_RNG] instruction_csr_read_data_x;// Data read from instruction unit CSRs
// From CSRs
`ifdef CFG_INTERRUPTS_ENABLED
wire [`LM32_WORD_RNG] interrupt_csr_read_data_x;// Data read from interrupt CSRs
`endif
wire [`LM32_WORD_RNG] cfg; // Configuration CSR
wire [`LM32_WORD_RNG] cfg2; // Extended Configuration CSR
`ifdef CFG_CYCLE_COUNTER_ENABLED
reg [`LM32_WORD_RNG] cc; // Cycle counter CSR
`endif
reg [`LM32_WORD_RNG] csr_read_data_x; // Data read from CSRs
// To/from instruction unit
`ifdef CFG_PIPELINE_TRACES
wire [`LM32_PC_RNG] pc_a;
`endif
wire [`LM32_PC_RNG] pc_f; // PC of instruction in F stage
wire [`LM32_PC_RNG] pc_d; // PC of instruction in D stage
wire [`LM32_PC_RNG] pc_x; // PC of instruction in X stage
wire [`LM32_PC_RNG] pc_m; // PC of instruction in M stage
wire [`LM32_PC_RNG] pc_w; // PC of instruction in W stage
`ifdef CFG_PIPELINE_TRACES
always @(posedge clk_i `CFG_RESET_SENSITIVITY)
begin
if (~rst_i)
begin
if (~stall_a)
$display("[%t] Addressing inst @ 0x%08X", $time, pc_a);
/* if (~stall_f)
$display("[%t] Fetching inst @ 0x%08X", $time, pc_f);
if (~stall_d)
$display("[%t] Decoding inst @ 0x%08X", $time, pc_d);
if (~stall_x)
$display("[%t] Executing inst @ 0x%08X", $time, pc_x);*/
end
end
`endif
`ifdef CFG_TRACE_ENABLED
reg [`LM32_PC_RNG] pc_c; // PC of last commited instruction
`endif
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
wire [`LM32_INSTRUCTION_RNG] instruction_f; // Instruction in F stage
`endif
//pragma attribute instruction_d preserve_signal true
//pragma attribute instruction_d preserve_driver true
wire [`LM32_INSTRUCTION_RNG] instruction_d; // Instruction in D stage
`ifdef CFG_ICACHE_ENABLED
wire iflush; // Flush instruction cache
wire icache_stall_request; // Stall pipeline because instruction cache is busy
wire icache_restart_request; // Restart instruction that caused an instruction cache miss
wire icache_refill_request; // Request to refill instruction cache
wire icache_refilling; // Indicates the instruction cache is being refilled
`endif
`ifdef CFG_IROM_ENABLED
wire [`LM32_WORD_RNG] irom_store_data_m; // Store data to instruction ROM
wire [`LM32_WORD_RNG] irom_address_xm; // Address to instruction ROM from load-store unit
wire [`LM32_WORD_RNG] irom_data_m; // Load data from instruction ROM
wire irom_we_xm; // Indicates data needs to be written to instruction ROM
wire irom_stall_request_x; // Indicates D stage needs to be stalled on a store to instruction ROM
`endif
// To/from load/store unit
`ifdef CFG_DCACHE_ENABLED
wire dflush_x; // Flush data cache
reg dflush_m;
wire dcache_stall_request; // Stall pipeline because data cache is busy
wire dcache_restart_request; // Restart instruction that caused a data cache miss
wire dcache_refill_request; // Request to refill data cache
wire dcache_refilling; // Indicates the data cache is being refilled
`endif
wire [`LM32_WORD_RNG] load_data_w; // Result of a load instruction
wire stall_wb_load; // Stall pipeline because of a load via the data Wishbone interface
// To/from JTAG interface
`ifdef CFG_JTAG_ENABLED
`ifdef CFG_JTAG_UART_ENABLED
wire [`LM32_WORD_RNG] jtx_csr_read_data; // Read data for JTX CSR
wire [`LM32_WORD_RNG] jrx_csr_read_data; // Read data for JRX CSR
`endif
`ifdef CFG_HW_DEBUG_ENABLED
wire jtag_csr_write_enable; // Debugger CSR write enable
wire [`LM32_WORD_RNG] jtag_csr_write_data; // Data to write to specified CSR
wire [`LM32_CSR_RNG] jtag_csr; // Which CSR to write
wire jtag_read_enable;
wire [`LM32_BYTE_RNG] jtag_read_data;
wire jtag_write_enable;
wire [`LM32_BYTE_RNG] jtag_write_data;
wire [`LM32_WORD_RNG] jtag_address;
wire jtag_access_complete;
`endif
`ifdef CFG_DEBUG_ENABLED
wire jtag_break; // Request from debugger to raise a breakpoint
`endif
`endif
// Hazzard detection
wire raw_x_0; // RAW hazzard between instruction in X stage and read port 0
wire raw_x_1; // RAW hazzard between instruction in X stage and read port 1
wire raw_m_0; // RAW hazzard between instruction in M stage and read port 0
wire raw_m_1; // RAW hazzard between instruction in M stage and read port 1
wire raw_w_0; // RAW hazzard between instruction in W stage and read port 0
wire raw_w_1; // RAW hazzard between instruction in W stage and read port 1
// Control flow
wire cmp_zero; // Result of comparison is zero
wire cmp_negative; // Result of comparison is negative
wire cmp_overflow; // Comparison produced an overflow
wire cmp_carry_n; // Comparison produced a carry, inverted
reg condition_met_x; // Condition of branch instruction is met
reg condition_met_m;
`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
wire branch_taken_x; // Branch is taken in X stage
`endif
wire branch_taken_m; // Branch is taken in M stage
wire kill_f; // Kill instruction in F stage
wire kill_d; // Kill instruction in D stage
wire kill_x; // Kill instruction in X stage
wire kill_m; // Kill instruction in M stage
wire kill_w; // Kill instruction in W stage
reg [`LM32_PC_WIDTH+2-1:8] eba; // Exception Base Address (EBA) CSR
`ifdef CFG_DEBUG_ENABLED
reg [`LM32_PC_WIDTH+2-1:8] deba; // Debug Exception Base Address (DEBA) CSR
`endif
reg [`LM32_EID_RNG] eid_x; // Exception ID in X stage
`ifdef CFG_TRACE_ENABLED
reg [`LM32_EID_RNG] eid_m; // Exception ID in M stage
reg [`LM32_EID_RNG] eid_w; // Exception ID in W stage
`endif
`ifdef CFG_DEBUG_ENABLED
`ifdef LM32_SINGLE_STEP_ENABLED
wire dc_ss; // Is single-step enabled
`endif
wire dc_re; // Remap all exceptions
wire exception_x; // An exception occured in the X stage
reg exception_m; // An instruction that caused an exception is in the M stage
wire debug_exception_x; // Indicates if a debug exception has occured
reg debug_exception_m;
reg debug_exception_w;
wire debug_exception_q_w;
wire non_debug_exception_x; // Indicates if a non debug exception has occured
reg non_debug_exception_m;
reg non_debug_exception_w;
wire non_debug_exception_q_w;
`else
wire exception_x; // Indicates if a debug exception has occured
reg exception_m;
reg exception_w;
wire exception_q_w;
`endif
`ifdef CFG_DEBUG_ENABLED
wire reset_exception; // Indicates if a reset exception has occured
`endif
`ifdef CFG_INTERRUPTS_ENABLED
wire interrupt_exception; // Indicates if an interrupt exception has occured
`endif
`ifdef CFG_DEBUG_ENABLED
wire breakpoint_exception; // Indicates if a breakpoint exception has occured
wire watchpoint_exception; // Indicates if a watchpoint exception has occured
`endif
`ifdef CFG_BUS_ERRORS_ENABLED
wire instruction_bus_error_exception; // Indicates if an instruction bus error exception has occured
wire data_bus_error_exception; // Indicates if a data bus error exception has occured
`endif
`ifdef CFG_MC_DIVIDE_ENABLED
wire divide_by_zero_exception; // Indicates if a divide by zero exception has occured
`endif
wire system_call_exception; // Indicates if a system call exception has occured
`ifdef CFG_BUS_ERRORS_ENABLED
reg data_bus_error_seen; // Indicates if a data bus error was seen
`endif
`ifdef CFG_EXTERNAL_BREAK_ENABLED
reg ext_break_r;
`endif
`ifdef CFG_MMU_ENABLED
wire dtlb_miss_exception;
wire itlb_miss_exception;
reg [`LM32_WORD_RNG] lm32_csr_psw_reg;
`endif
/////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////
`include "lm32_functions.v"
/////////////////////////////////////////////////////
// Instantiations
/////////////////////////////////////////////////////
// Instruction unit
lm32_instruction_unit #(
.associativity (icache_associativity),
.sets (icache_sets),
.bytes_per_line (icache_bytes_per_line),
.base_address (icache_base_address),
.limit (icache_limit)
) instruction_unit (
// ----- Inputs -------
.clk_i (clk_i),
.rst_i (rst_i),
`ifdef CFG_DEBUG_ENABLED
`ifdef CFG_ALTERNATE_EBA
.at_debug (at_debug),
`endif
`endif
// From pipeline
.stall_a (stall_a),
.stall_f (stall_f),
.stall_d (stall_d),
.stall_x (stall_x),
.stall_m (stall_m),
.valid_f (valid_f),
.valid_d (valid_d),
.kill_f (kill_f),
.branch_predict_taken_d (branch_predict_taken_d),
.branch_predict_address_d (branch_predict_address_d),
`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
.branch_taken_x (branch_taken_x),
.branch_target_x (branch_target_x),
`endif
.exception_m (exception_m),
`ifdef CFG_MMU_ENABLED
.exception_x (exception_x),
`endif
.branch_taken_m (branch_taken_m),
.branch_mispredict_taken_m (branch_mispredict_taken_m),
.branch_target_m (branch_target_m),
`ifdef CFG_ICACHE_ENABLED
.iflush (iflush),
`endif
`ifdef CFG_IROM_ENABLED
.irom_store_data_m (irom_store_data_m),
.irom_address_xm (irom_address_xm),
.irom_we_xm (irom_we_xm),
`endif
`ifdef CFG_DCACHE_ENABLED
.dcache_restart_request (dcache_restart_request),
.dcache_refill_request (dcache_refill_request),
.dcache_refilling (dcache_refilling),
`endif
`ifdef CFG_MMU_ENABLED
.csr (csr_x),
.csr_write_data (operand_1_x),
.csr_write_enable (csr_write_enable_q_x),
.eret_q_x (eret_q_x),
.csr_psw (lm32_csr_psw_reg),
.q_x (q_x),
`endif
`ifdef CFG_IWB_ENABLED
// From Wishbone
.i_dat_i (I_DAT_I),
.i_ack_i (I_ACK_I),
.i_err_i (I_ERR_I),
`endif
`ifdef CFG_HW_DEBUG_ENABLED
.jtag_read_enable (jtag_read_enable),
.jtag_write_enable (jtag_write_enable),
.jtag_write_data (jtag_write_data),
.jtag_address (jtag_address),
`endif
// ----- Outputs -------
// To pipeline
`ifdef CFG_PIPELINE_TRACES
.pc_a (pc_a),
`endif
.pc_f (pc_f),
.pc_d (pc_d),
.pc_x (pc_x),
.pc_m (pc_m),
.pc_w (pc_w),
`ifdef CFG_ICACHE_ENABLED
.icache_stall_request (icache_stall_request),
.icache_restart_request (icache_restart_request),
.icache_refill_request (icache_refill_request),
.icache_refilling (icache_refilling),
`endif
`ifdef CFG_IROM_ENABLED
.irom_data_m (irom_data_m),
`endif
`ifdef CFG_MMU_ENABLED
.itlb_miss (itlb_miss_exception),
.csr_read_data (instruction_csr_read_data_x),
`endif
`ifdef CFG_IWB_ENABLED
// To Wishbone
.i_dat_o (I_DAT_O),
.i_adr_o (I_ADR_O),
.i_cyc_o (I_CYC_O),
.i_sel_o (I_SEL_O),
.i_stb_o (I_STB_O),
.i_we_o (I_WE_O),
.i_cti_o (I_CTI_O),
.i_lock_o (I_LOCK_O),
.i_bte_o (I_BTE_O),
`endif
`ifdef CFG_HW_DEBUG_ENABLED
.jtag_read_data (jtag_read_data),
.jtag_access_complete (jtag_access_complete),
`endif
`ifdef CFG_BUS_ERRORS_ENABLED
.bus_error_d (bus_error_d),
`endif
`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
.instruction_f (instruction_f),
`endif
.instruction_d (instruction_d)
);
// Instruction decoder
lm32_decoder decoder (
// ----- Inputs -------
.instruction (instruction_d),
// ----- Outputs -------
.d_result_sel_0 (d_result_sel_0_d),
.d_result_sel_1 (d_result_sel_1_d),
.x_result_sel_csr (x_result_sel_csr_d),
`ifdef LM32_MC_ARITHMETIC_ENABLED
.x_result_sel_mc_arith (x_result_sel_mc_arith_d),
`endif
`ifdef LM32_NO_BARREL_SHIFT
.x_result_sel_shift (x_result_sel_shift_d),
`endif
`ifdef CFG_SIGN_EXTEND_ENABLED
.x_result_sel_sext (x_result_sel_sext_d),
`endif
.x_result_sel_logic (x_result_sel_logic_d),
`ifdef CFG_USER_ENABLED
.x_result_sel_user (x_result_sel_user_d),
`endif
.x_result_sel_add (x_result_sel_add_d),
.m_result_sel_compare (m_result_sel_compare_d),
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
.m_result_sel_shift (m_result_sel_shift_d),
`endif
.w_result_sel_load (w_result_sel_load_d),
`ifdef CFG_PL_MULTIPLY_ENABLED
.w_result_sel_mul (w_result_sel_mul_d),
`endif
.x_bypass_enable (x_bypass_enable_d),
.m_bypass_enable (m_bypass_enable_d),
.read_enable_0 (read_enable_0_d),
.read_idx_0 (read_idx_0_d),
.read_enable_1 (read_enable_1_d),
.read_idx_1 (read_idx_1_d),
.write_enable (write_enable_d),
.write_idx (write_idx_d),
.immediate (immediate_d),
.branch_offset (branch_offset_d),
.load (load_d),
.store (store_d),
.size (size_d),
.sign_extend (sign_extend_d),
.adder_op (adder_op_d),
.logic_op (logic_op_d),
`ifdef CFG_PL_BARREL_SHIFT_ENABLED
.direction (direction_d),
`endif
`ifdef CFG_MC_BARREL_SHIFT_ENABLED
.shift_left (shift_left_d),
.shift_right (shift_right_d),
`endif
`ifdef CFG_MC_MULTIPLY_ENABLED
.multiply (multiply_d),
`endif
`ifdef CFG_MC_DIVIDE_ENABLED
.divide (divide_d),
.modulus (modulus_d),
`endif
.branch (branch_d),
.bi_unconditional (bi_unconditional),
.bi_conditional (bi_conditional),
.branch_reg (branch_reg_d),