-
Notifications
You must be signed in to change notification settings - Fork 231
/
neorv32_package.vhd
1146 lines (1067 loc) · 66.1 KB
/
neorv32_package.vhd
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
-- ================================================================================ --
-- NEORV32 - Main VHDL Package File --
-- -------------------------------------------------------------------------------- --
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
-- Copyright (c) NEORV32 contributors. --
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
-- Licensed under the BSD-3-Clause license, see LICENSE for details. --
-- SPDX-License-Identifier: BSD-3-Clause --
-- ================================================================================ --
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package neorv32_package is
-- **********************************************************************************************************
-- Architecture Configuration and Constants
-- **********************************************************************************************************
-- Architecture Configuration -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- max response time for processor-internal bus transactions --
-- cycles after which an unacknowledged internal bus access will timeout raising a bus fault exception
constant bus_timeout_c : natural := 15; -- default = 15
-- instruction monitor: raise exception if multi-cycle operation times out --
constant monitor_mc_tmo_c : natural := 9; -- = log2 of max execution cycles; default = 2^9 = 512 cycles
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100301"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width
-- Check if we're inside the Matrix -------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant is_simulation_c : boolean := false -- seems like we're on real hardware
-- pragma translate_off
-- RTL_SYNTHESIS OFF
or true -- this MIGHT be a simulation
-- RTL_SYNTHESIS ON
-- pragma translate_on
;
-- **********************************************************************************************************
-- Processor Address Space Layout
-- **********************************************************************************************************
-- Main Address Regions (base address must be aligned to the region's size) ---
constant mem_imem_base_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- IMEM size via generic
constant mem_dmem_base_c : std_ulogic_vector(31 downto 0) := x"80000000"; -- DMEM size via generic
constant mem_xip_base_c : std_ulogic_vector(31 downto 0) := x"e0000000"; -- page (4MSBs) only!
constant mem_xip_size_c : natural := 256*1024*1024;
constant mem_boot_base_c : std_ulogic_vector(31 downto 0) := x"ffffc000";
constant mem_boot_size_c : natural := 8*1024;
constant mem_io_base_c : std_ulogic_vector(31 downto 0) := x"ffffe000";
constant mem_io_size_c : natural := 8*1024; -- = 32 * iodev_size_c
-- Start of uncached memory access (256MB page / 4MSBs only) --
constant uncached_begin_c : std_ulogic_vector(31 downto 0) := x"f0000000";
-- IO Address Map (base address must be aligned to the region's size) --
constant iodev_size_c : natural := 256; -- size of a single IO device (bytes)
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe000"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe100"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe200"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe300"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe400"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe500"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe600"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe700"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe800"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe900"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffea00"; -- reserved
constant base_io_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffeb00";
constant base_io_slink_c : std_ulogic_vector(31 downto 0) := x"ffffec00";
constant base_io_dma_c : std_ulogic_vector(31 downto 0) := x"ffffed00";
constant base_io_crc_c : std_ulogic_vector(31 downto 0) := x"ffffee00";
constant base_io_xip_c : std_ulogic_vector(31 downto 0) := x"ffffef00";
constant base_io_pwm_c : std_ulogic_vector(31 downto 0) := x"fffff000";
constant base_io_gptmr_c : std_ulogic_vector(31 downto 0) := x"fffff100";
constant base_io_onewire_c : std_ulogic_vector(31 downto 0) := x"fffff200";
constant base_io_xirq_c : std_ulogic_vector(31 downto 0) := x"fffff300";
constant base_io_mtime_c : std_ulogic_vector(31 downto 0) := x"fffff400";
constant base_io_uart0_c : std_ulogic_vector(31 downto 0) := x"fffff500";
constant base_io_uart1_c : std_ulogic_vector(31 downto 0) := x"fffff600";
constant base_io_sdi_c : std_ulogic_vector(31 downto 0) := x"fffff700";
constant base_io_spi_c : std_ulogic_vector(31 downto 0) := x"fffff800";
constant base_io_twi_c : std_ulogic_vector(31 downto 0) := x"fffff900";
constant base_io_trng_c : std_ulogic_vector(31 downto 0) := x"fffffa00";
constant base_io_wdt_c : std_ulogic_vector(31 downto 0) := x"fffffb00";
constant base_io_gpio_c : std_ulogic_vector(31 downto 0) := x"fffffc00";
constant base_io_neoled_c : std_ulogic_vector(31 downto 0) := x"fffffd00";
constant base_io_sysinfo_c : std_ulogic_vector(31 downto 0) := x"fffffe00";
constant base_io_dm_c : std_ulogic_vector(31 downto 0) := x"ffffff00";
-- On-Chip Debugger - Debug Module Entry Points (Code ROM) --
constant dm_exc_entry_c : std_ulogic_vector(31 downto 0) := x"ffffff00"; -- = base_io_dm_c + 0, exceptions entry point
constant dm_park_entry_c : std_ulogic_vector(31 downto 0) := x"ffffff08"; -- = base_io_dm_c + 8, normal entry point
-- **********************************************************************************************************
-- SoC Definitions
-- **********************************************************************************************************
-- SoC Clock Select -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant clk_div2_c : natural := 0;
constant clk_div4_c : natural := 1;
constant clk_div8_c : natural := 2;
constant clk_div64_c : natural := 3;
constant clk_div128_c : natural := 4;
constant clk_div1024_c : natural := 5;
constant clk_div2048_c : natural := 6;
constant clk_div4096_c : natural := 7;
-- Internal Memory Types ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
type mem32_t is array (natural range <>) of std_ulogic_vector(31 downto 0); -- memory with 32-bit entries
type mem8_t is array (natural range <>) of std_ulogic_vector(7 downto 0); -- memory with 8-bit entries
-- Internal Bus Interface -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- bus request --
type bus_req_t is record
addr : std_ulogic_vector(31 downto 0); -- access address
data : std_ulogic_vector(31 downto 0); -- write data
ben : std_ulogic_vector(3 downto 0); -- byte enable
stb : std_ulogic; -- request strobe, single-shot
rw : std_ulogic; -- 0=read, 1=write
src : std_ulogic; -- access source (1=instruction fetch, 0=data access)
priv : std_ulogic; -- set if privileged (machine-mode) access
rvso : std_ulogic; -- set if reservation set operation (atomic LR/SC)
fence : std_ulogic; -- set if fence(.i) operation, single-shot, independent of STB
end record;
-- bus response --
type bus_rsp_t is record
data : std_ulogic_vector(31 downto 0); -- read data, valid if ack=1
ack : std_ulogic; -- access acknowledge, single-shot
err : std_ulogic; -- access error, single-shot
end record;
-- source (request) termination --
constant req_terminate_c : bus_req_t := (
addr => (others => '0'),
data => (others => '0'),
ben => (others => '0'),
stb => '0',
rw => '0',
src => '0',
priv => '0',
rvso => '0',
fence => '0'
);
-- endpoint (response) termination --
constant rsp_terminate_c : bus_rsp_t := (
data => (others => '0'),
ack => '0',
err => '0'
);
-- Debug Module Interface -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- request --
type dmi_req_t is record
addr : std_ulogic_vector(6 downto 0);
op : std_ulogic_vector(1 downto 0);
data : std_ulogic_vector(31 downto 0);
end record;
-- request operation --
constant dmi_req_nop_c : std_ulogic_vector(1 downto 0) := "00"; -- no operation
constant dmi_req_rd_c : std_ulogic_vector(1 downto 0) := "01"; -- read access
constant dmi_req_wr_c : std_ulogic_vector(1 downto 0) := "10"; -- write access
-- response --
type dmi_rsp_t is record
data : std_ulogic_vector(31 downto 0);
ack : std_ulogic;
end record;
-- **********************************************************************************************************
-- RISC-V ISA Definitions
-- **********************************************************************************************************
-- RISC-V 32-Bit Instruction Word Layout --------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant instr_opcode_lsb_c : natural := 0; -- opcode bit 0
constant instr_opcode_msb_c : natural := 6; -- opcode bit 6
constant instr_rd_lsb_c : natural := 7; -- destination register address bit 0
constant instr_rd_msb_c : natural := 11; -- destination register address bit 4
constant instr_funct3_lsb_c : natural := 12; -- funct3 bit 0
constant instr_funct3_msb_c : natural := 14; -- funct3 bit 2
constant instr_rs1_lsb_c : natural := 15; -- source register 1 address bit 0
constant instr_rs1_msb_c : natural := 19; -- source register 1 address bit 4
constant instr_rs2_lsb_c : natural := 20; -- source register 2 address bit 0
constant instr_rs2_msb_c : natural := 24; -- source register 2 address bit 4
constant instr_funct7_lsb_c : natural := 25; -- funct7 bit 0
constant instr_funct7_msb_c : natural := 31; -- funct7 bit 6
constant instr_funct12_lsb_c : natural := 20; -- funct12 bit 0
constant instr_funct12_msb_c : natural := 31; -- funct12 bit 11
constant instr_imm12_lsb_c : natural := 20; -- immediate12 bit 0
constant instr_imm12_msb_c : natural := 31; -- immediate12 bit 11
constant instr_imm20_lsb_c : natural := 12; -- immediate20 bit 0
constant instr_imm20_msb_c : natural := 31; -- immediate20 bit 21
constant instr_funct5_lsb_c : natural := 27; -- funct5 select bit 0
constant instr_funct5_msb_c : natural := 31; -- funct5 select bit 4
-- RISC-V Opcodes -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- alu --
constant opcode_alui_c : std_ulogic_vector(6 downto 0) := "0010011"; -- ALU operation with immediate
constant opcode_alu_c : std_ulogic_vector(6 downto 0) := "0110011"; -- ALU operation
constant opcode_lui_c : std_ulogic_vector(6 downto 0) := "0110111"; -- load upper immediate
constant opcode_auipc_c : std_ulogic_vector(6 downto 0) := "0010111"; -- add upper immediate to PC
-- control flow --
constant opcode_jal_c : std_ulogic_vector(6 downto 0) := "1101111"; -- jump and link
constant opcode_jalr_c : std_ulogic_vector(6 downto 0) := "1100111"; -- jump and link with register
constant opcode_branch_c : std_ulogic_vector(6 downto 0) := "1100011"; -- branch
-- memory access --
constant opcode_load_c : std_ulogic_vector(6 downto 0) := "0000011"; -- load
constant opcode_store_c : std_ulogic_vector(6 downto 0) := "0100011"; -- store
constant opcode_amo_c : std_ulogic_vector(6 downto 0) := "0101111"; -- atomic memory access
constant opcode_fence_c : std_ulogic_vector(6 downto 0) := "0001111"; -- fence / fence.i
-- system/csr --
constant opcode_system_c : std_ulogic_vector(6 downto 0) := "1110011"; -- system/csr access
-- floating point operations --
constant opcode_fop_c : std_ulogic_vector(6 downto 0) := "1010011"; -- dual/single operand instruction
-- official custom RISC-V opcodes - free for custom instructions --
constant opcode_cust0_c : std_ulogic_vector(6 downto 0) := "0001011"; -- custom-0 (NEORV32 CFU)
constant opcode_cust1_c : std_ulogic_vector(6 downto 0) := "0101011"; -- custom-1 (NEORV32 CFU)
constant opcode_cust2_c : std_ulogic_vector(6 downto 0) := "1011011"; -- custom-2 (reserved)
constant opcode_cust3_c : std_ulogic_vector(6 downto 0) := "1111011"; -- custom-3 (reserved)
-- RISC-V Funct3 --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- control flow --
constant funct3_beq_c : std_ulogic_vector(2 downto 0) := "000"; -- branch if equal
constant funct3_bne_c : std_ulogic_vector(2 downto 0) := "001"; -- branch if not equal
constant funct3_blt_c : std_ulogic_vector(2 downto 0) := "100"; -- branch if less than
constant funct3_bge_c : std_ulogic_vector(2 downto 0) := "101"; -- branch if greater than or equal
constant funct3_bltu_c : std_ulogic_vector(2 downto 0) := "110"; -- branch if less than (unsigned)
constant funct3_bgeu_c : std_ulogic_vector(2 downto 0) := "111"; -- branch if greater than or equal (unsigned)
-- memory access --
constant funct3_lb_c : std_ulogic_vector(2 downto 0) := "000"; -- load byte (signed)
constant funct3_lh_c : std_ulogic_vector(2 downto 0) := "001"; -- load half word (signed)
constant funct3_lw_c : std_ulogic_vector(2 downto 0) := "010"; -- load word (signed)
constant funct3_lbu_c : std_ulogic_vector(2 downto 0) := "100"; -- load byte (unsigned)
constant funct3_lhu_c : std_ulogic_vector(2 downto 0) := "101"; -- load half word (unsigned)
constant funct3_lwu_c : std_ulogic_vector(2 downto 0) := "110"; -- load word (unsigned)
constant funct3_sb_c : std_ulogic_vector(2 downto 0) := "000"; -- store byte
constant funct3_sh_c : std_ulogic_vector(2 downto 0) := "001"; -- store half word
constant funct3_sw_c : std_ulogic_vector(2 downto 0) := "010"; -- store word
-- alu --
constant funct3_subadd_c : std_ulogic_vector(2 downto 0) := "000"; -- sub/add
constant funct3_sll_c : std_ulogic_vector(2 downto 0) := "001"; -- shift logical left
constant funct3_slt_c : std_ulogic_vector(2 downto 0) := "010"; -- set on less
constant funct3_sltu_c : std_ulogic_vector(2 downto 0) := "011"; -- set on less unsigned
constant funct3_xor_c : std_ulogic_vector(2 downto 0) := "100"; -- logical exclusive-or
constant funct3_sr_c : std_ulogic_vector(2 downto 0) := "101"; -- shift right
constant funct3_or_c : std_ulogic_vector(2 downto 0) := "110"; -- logical or
constant funct3_and_c : std_ulogic_vector(2 downto 0) := "111"; -- logical and
-- system/csr --
constant funct3_env_c : std_ulogic_vector(2 downto 0) := "000"; -- ecall, ebreak, mret, wfi, ...
constant funct3_csrrw_c : std_ulogic_vector(2 downto 0) := "001"; -- csr r/w
constant funct3_csrrs_c : std_ulogic_vector(2 downto 0) := "010"; -- csr read & set
constant funct3_csrrc_c : std_ulogic_vector(2 downto 0) := "011"; -- csr read & clear
constant funct3_csril_c : std_ulogic_vector(2 downto 0) := "100"; -- undefined/illegal csr command
constant funct3_csrrwi_c : std_ulogic_vector(2 downto 0) := "101"; -- csr r/w immediate
constant funct3_csrrsi_c : std_ulogic_vector(2 downto 0) := "110"; -- csr read & set immediate
constant funct3_csrrci_c : std_ulogic_vector(2 downto 0) := "111"; -- csr read & clear immediate
-- fence --
constant funct3_fence_c : std_ulogic_vector(2 downto 0) := "000"; -- fence - order IO/memory access
constant funct3_fencei_c : std_ulogic_vector(2 downto 0) := "001"; -- fence.i - instruction stream sync
-- RISC-V Funct12 - SYSTEM ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant funct12_ecall_c : std_ulogic_vector(11 downto 0) := x"000"; -- ecall
constant funct12_ebreak_c : std_ulogic_vector(11 downto 0) := x"001"; -- ebreak
constant funct12_wfi_c : std_ulogic_vector(11 downto 0) := x"105"; -- wfi
constant funct12_mret_c : std_ulogic_vector(11 downto 0) := x"302"; -- mret
constant funct12_dret_c : std_ulogic_vector(11 downto 0) := x"7b2"; -- dret
-- RISC-V Floating-Point Stuff ------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- number class flags --
constant fp_class_neg_inf_c : natural := 0; -- negative infinity
constant fp_class_neg_norm_c : natural := 1; -- negative normal number
constant fp_class_neg_denorm_c : natural := 2; -- negative subnormal number
constant fp_class_neg_zero_c : natural := 3; -- negative zero
constant fp_class_pos_zero_c : natural := 4; -- positive zero
constant fp_class_pos_denorm_c : natural := 5; -- positive subnormal number
constant fp_class_pos_norm_c : natural := 6; -- positive normal number
constant fp_class_pos_inf_c : natural := 7; -- positive infinity
constant fp_class_snan_c : natural := 8; -- signaling NaN (sNaN)
constant fp_class_qnan_c : natural := 9; -- quiet NaN (qNaN)
-- exception flags --
constant fp_exc_nx_c : natural := 0; -- inexact
constant fp_exc_uf_c : natural := 1; -- underflow
constant fp_exc_of_c : natural := 2; -- overflow
constant fp_exc_dz_c : natural := 3; -- division by zero
constant fp_exc_nv_c : natural := 4; -- invalid operation
-- special values (single-precision) --
constant fp_single_qnan_c : std_ulogic_vector(31 downto 0) := x"7fc00000"; -- quiet NaN
constant fp_single_snan_c : std_ulogic_vector(31 downto 0) := x"7fa00000"; -- signaling NaN
constant fp_single_pos_max_c : std_ulogic_vector(31 downto 0) := x"7f7FFFFF"; -- positive max
constant fp_single_neg_max_c : std_ulogic_vector(31 downto 0) := x"Ff7FFFFF"; -- negative max
constant fp_single_pos_inf_c : std_ulogic_vector(31 downto 0) := x"7f800000"; -- positive infinity
constant fp_single_neg_inf_c : std_ulogic_vector(31 downto 0) := x"ff800000"; -- negative infinity
constant fp_single_pos_zero_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- positive zero
constant fp_single_neg_zero_c : std_ulogic_vector(31 downto 0) := x"80000000"; -- negative zero
-- RISC-V CSRs ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- user floating-point CSRs --
constant csr_fflags_c : std_ulogic_vector(11 downto 0) := x"001";
constant csr_frm_c : std_ulogic_vector(11 downto 0) := x"002";
constant csr_fcsr_c : std_ulogic_vector(11 downto 0) := x"003";
-- machine trap setup --
constant csr_mstatus_c : std_ulogic_vector(11 downto 0) := x"300";
constant csr_misa_c : std_ulogic_vector(11 downto 0) := x"301";
constant csr_mie_c : std_ulogic_vector(11 downto 0) := x"304";
constant csr_mtvec_c : std_ulogic_vector(11 downto 0) := x"305";
constant csr_mcounteren_c : std_ulogic_vector(11 downto 0) := x"306";
constant csr_mstatush_c : std_ulogic_vector(11 downto 0) := x"310";
-- machine configuration --
constant csr_menvcfg_c : std_ulogic_vector(11 downto 0) := x"30a";
constant csr_menvcfgh_c : std_ulogic_vector(11 downto 0) := x"31a";
-- machine counter setup --
constant csr_mcountinhibit_c : std_ulogic_vector(11 downto 0) := x"320";
constant csr_mhpmevent3_c : std_ulogic_vector(11 downto 0) := x"323";
constant csr_mhpmevent4_c : std_ulogic_vector(11 downto 0) := x"324";
constant csr_mhpmevent5_c : std_ulogic_vector(11 downto 0) := x"325";
constant csr_mhpmevent6_c : std_ulogic_vector(11 downto 0) := x"326";
constant csr_mhpmevent7_c : std_ulogic_vector(11 downto 0) := x"327";
constant csr_mhpmevent8_c : std_ulogic_vector(11 downto 0) := x"328";
constant csr_mhpmevent9_c : std_ulogic_vector(11 downto 0) := x"329";
constant csr_mhpmevent10_c : std_ulogic_vector(11 downto 0) := x"32a";
constant csr_mhpmevent11_c : std_ulogic_vector(11 downto 0) := x"32b";
constant csr_mhpmevent12_c : std_ulogic_vector(11 downto 0) := x"32c";
constant csr_mhpmevent13_c : std_ulogic_vector(11 downto 0) := x"32d";
constant csr_mhpmevent14_c : std_ulogic_vector(11 downto 0) := x"32e";
constant csr_mhpmevent15_c : std_ulogic_vector(11 downto 0) := x"32f";
-- machine trap handling --
constant csr_mscratch_c : std_ulogic_vector(11 downto 0) := x"340";
constant csr_mepc_c : std_ulogic_vector(11 downto 0) := x"341";
constant csr_mcause_c : std_ulogic_vector(11 downto 0) := x"342";
constant csr_mtval_c : std_ulogic_vector(11 downto 0) := x"343";
constant csr_mip_c : std_ulogic_vector(11 downto 0) := x"344";
constant csr_mtinst_c : std_ulogic_vector(11 downto 0) := x"34a";
-- physical memory protection - configuration --
constant csr_pmpcfg0_c : std_ulogic_vector(11 downto 0) := x"3a0";
constant csr_pmpcfg1_c : std_ulogic_vector(11 downto 0) := x"3a1";
constant csr_pmpcfg2_c : std_ulogic_vector(11 downto 0) := x"3a2";
constant csr_pmpcfg3_c : std_ulogic_vector(11 downto 0) := x"3a3";
-- physical memory protection - address --
constant csr_pmpaddr0_c : std_ulogic_vector(11 downto 0) := x"3b0";
constant csr_pmpaddr1_c : std_ulogic_vector(11 downto 0) := x"3b1";
constant csr_pmpaddr2_c : std_ulogic_vector(11 downto 0) := x"3b2";
constant csr_pmpaddr3_c : std_ulogic_vector(11 downto 0) := x"3b3";
constant csr_pmpaddr4_c : std_ulogic_vector(11 downto 0) := x"3b4";
constant csr_pmpaddr5_c : std_ulogic_vector(11 downto 0) := x"3b5";
constant csr_pmpaddr6_c : std_ulogic_vector(11 downto 0) := x"3b6";
constant csr_pmpaddr7_c : std_ulogic_vector(11 downto 0) := x"3b7";
constant csr_pmpaddr8_c : std_ulogic_vector(11 downto 0) := x"3b8";
constant csr_pmpaddr9_c : std_ulogic_vector(11 downto 0) := x"3b9";
constant csr_pmpaddr10_c : std_ulogic_vector(11 downto 0) := x"3ba";
constant csr_pmpaddr11_c : std_ulogic_vector(11 downto 0) := x"3bb";
constant csr_pmpaddr12_c : std_ulogic_vector(11 downto 0) := x"3bc";
constant csr_pmpaddr13_c : std_ulogic_vector(11 downto 0) := x"3bd";
constant csr_pmpaddr14_c : std_ulogic_vector(11 downto 0) := x"3be";
constant csr_pmpaddr15_c : std_ulogic_vector(11 downto 0) := x"3bf";
-- trigger module registers --
constant csr_tselect_c : std_ulogic_vector(11 downto 0) := x"7a0";
constant csr_tdata1_c : std_ulogic_vector(11 downto 0) := x"7a1";
constant csr_tdata2_c : std_ulogic_vector(11 downto 0) := x"7a2";
constant csr_tinfo_c : std_ulogic_vector(11 downto 0) := x"7a4";
-- debug registers --
constant csr_dcsr_c : std_ulogic_vector(11 downto 0) := x"7b0";
constant csr_dpc_c : std_ulogic_vector(11 downto 0) := x"7b1";
constant csr_dscratch0_c : std_ulogic_vector(11 downto 0) := x"7b2";
-- NEORV32-specific user registers --
constant csr_cfureg0_c : std_ulogic_vector(11 downto 0) := x"800";
constant csr_cfureg1_c : std_ulogic_vector(11 downto 0) := x"801";
constant csr_cfureg2_c : std_ulogic_vector(11 downto 0) := x"802";
constant csr_cfureg3_c : std_ulogic_vector(11 downto 0) := x"803";
-- machine counters/timers --
constant csr_mcycle_c : std_ulogic_vector(11 downto 0) := x"b00";
--constant csr_mtime_c : std_ulogic_vector(11 downto 0) := x"b01";
constant csr_minstret_c : std_ulogic_vector(11 downto 0) := x"b02";
constant csr_mhpmcounter3_c : std_ulogic_vector(11 downto 0) := x"b03";
constant csr_mhpmcounter4_c : std_ulogic_vector(11 downto 0) := x"b04";
constant csr_mhpmcounter5_c : std_ulogic_vector(11 downto 0) := x"b05";
constant csr_mhpmcounter6_c : std_ulogic_vector(11 downto 0) := x"b06";
constant csr_mhpmcounter7_c : std_ulogic_vector(11 downto 0) := x"b07";
constant csr_mhpmcounter8_c : std_ulogic_vector(11 downto 0) := x"b08";
constant csr_mhpmcounter9_c : std_ulogic_vector(11 downto 0) := x"b09";
constant csr_mhpmcounter10_c : std_ulogic_vector(11 downto 0) := x"b0a";
constant csr_mhpmcounter11_c : std_ulogic_vector(11 downto 0) := x"b0b";
constant csr_mhpmcounter12_c : std_ulogic_vector(11 downto 0) := x"b0c";
constant csr_mhpmcounter13_c : std_ulogic_vector(11 downto 0) := x"b0d";
constant csr_mhpmcounter14_c : std_ulogic_vector(11 downto 0) := x"b0e";
constant csr_mhpmcounter15_c : std_ulogic_vector(11 downto 0) := x"b0f";
--
constant csr_mcycleh_c : std_ulogic_vector(11 downto 0) := x"b80";
--constant csr_mtimeh_c : std_ulogic_vector(11 downto 0) := x"b81";
constant csr_minstreth_c : std_ulogic_vector(11 downto 0) := x"b82";
constant csr_mhpmcounter3h_c : std_ulogic_vector(11 downto 0) := x"b83";
constant csr_mhpmcounter4h_c : std_ulogic_vector(11 downto 0) := x"b84";
constant csr_mhpmcounter5h_c : std_ulogic_vector(11 downto 0) := x"b85";
constant csr_mhpmcounter6h_c : std_ulogic_vector(11 downto 0) := x"b86";
constant csr_mhpmcounter7h_c : std_ulogic_vector(11 downto 0) := x"b87";
constant csr_mhpmcounter8h_c : std_ulogic_vector(11 downto 0) := x"b88";
constant csr_mhpmcounter9h_c : std_ulogic_vector(11 downto 0) := x"b89";
constant csr_mhpmcounter10h_c : std_ulogic_vector(11 downto 0) := x"b8a";
constant csr_mhpmcounter11h_c : std_ulogic_vector(11 downto 0) := x"b8b";
constant csr_mhpmcounter12h_c : std_ulogic_vector(11 downto 0) := x"b8c";
constant csr_mhpmcounter13h_c : std_ulogic_vector(11 downto 0) := x"b8d";
constant csr_mhpmcounter14h_c : std_ulogic_vector(11 downto 0) := x"b8e";
constant csr_mhpmcounter15h_c : std_ulogic_vector(11 downto 0) := x"b8f";
-- NEORV32-specific read-write machine registers --
--constant csr_mxstatus_c : std_ulogic_vector(11 downto 0) := x"bc0";
-- user counters/timers --
constant csr_cycle_c : std_ulogic_vector(11 downto 0) := x"c00";
--constant csr_time_c : std_ulogic_vector(11 downto 0) := x"c01";
constant csr_instret_c : std_ulogic_vector(11 downto 0) := x"c02";
--
constant csr_cycleh_c : std_ulogic_vector(11 downto 0) := x"c80";
--constant csr_timeh_c : std_ulogic_vector(11 downto 0) := x"c81";
constant csr_instreth_c : std_ulogic_vector(11 downto 0) := x"c82";
-- machine information registers --
constant csr_mvendorid_c : std_ulogic_vector(11 downto 0) := x"f11";
constant csr_marchid_c : std_ulogic_vector(11 downto 0) := x"f12";
constant csr_mimpid_c : std_ulogic_vector(11 downto 0) := x"f13";
constant csr_mhartid_c : std_ulogic_vector(11 downto 0) := x"f14";
constant csr_mconfigptr_c : std_ulogic_vector(11 downto 0) := x"f15";
-- NEORV32-specific read-only machine registers --
constant csr_mxisa_c : std_ulogic_vector(11 downto 0) := x"fc0";
-- **********************************************************************************************************
-- CPU Control
-- **********************************************************************************************************
-- Main CPU Control Bus -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
type ctrl_bus_t is record
-- register file --
rf_wb_en : std_ulogic; -- write back enable
rf_rs1 : std_ulogic_vector(4 downto 0); -- source register 1 address
rf_rs2 : std_ulogic_vector(4 downto 0); -- source register 2 address
rf_rd : std_ulogic_vector(4 downto 0); -- destination register address
rf_zero_we : std_ulogic; -- allow/force write access to x0
-- alu --
alu_op : std_ulogic_vector(2 downto 0); -- operation select
alu_sub : std_ulogic; -- addition/subtraction control
alu_opa_mux : std_ulogic; -- operand A select (0=rs1, 1=PC)
alu_opb_mux : std_ulogic; -- operand B select (0=rs2, 1=IMM)
alu_unsigned : std_ulogic; -- is unsigned ALU operation
alu_cp_trig : std_ulogic_vector(5 downto 0); -- co-processor trigger (one-hot)
-- load/store unit --
lsu_req : std_ulogic; -- trigger memory access request
lsu_rw : std_ulogic; -- 0: read access, 1: write access
lsu_mo_we : std_ulogic; -- memory address and data output register write enable
lsu_fence : std_ulogic; -- fence(.i) operation
lsu_priv : std_ulogic; -- effective privilege mode for load/store
-- instruction word --
ir_funct3 : std_ulogic_vector(2 downto 0); -- funct3 bit field
ir_funct12 : std_ulogic_vector(11 downto 0); -- funct12 bit field
ir_opcode : std_ulogic_vector(6 downto 0); -- opcode bit field
-- cpu status --
cpu_priv : std_ulogic; -- effective privilege mode
cpu_sleep : std_ulogic; -- set when CPU is in sleep mode
cpu_trap : std_ulogic; -- set when CPU is entering trap exec
cpu_debug : std_ulogic; -- set when CPU is in debug mode
end record;
-- control bus reset initializer --
constant ctrl_bus_zero_c : ctrl_bus_t := (
rf_wb_en => '0',
rf_rs1 => (others => '0'),
rf_rs2 => (others => '0'),
rf_rd => (others => '0'),
rf_zero_we => '0',
alu_op => (others => '0'),
alu_sub => '0',
alu_opa_mux => '0',
alu_opb_mux => '0',
alu_unsigned => '0',
alu_cp_trig => (others => '0'),
lsu_req => '0',
lsu_rw => '0',
lsu_mo_we => '0',
lsu_fence => '0',
lsu_priv => '0',
ir_funct3 => (others => '0'),
ir_funct12 => (others => '0'),
ir_opcode => (others => '0'),
cpu_priv => '0',
cpu_sleep => '0',
cpu_trap => '0',
cpu_debug => '0'
);
-- Comparator Bus -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant cmp_equal_c : natural := 0;
constant cmp_less_c : natural := 1; -- for signed and unsigned comparisons
-- CPU Co-Processor IDs -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant cp_sel_shifter_c : natural := 0; -- CP0: shift operations (base ISA)
constant cp_sel_muldiv_c : natural := 1; -- CP1: multiplication/division operations ('M' extensions)
constant cp_sel_bitmanip_c : natural := 2; -- CP2: bit manipulation ('B' extensions)
constant cp_sel_fpu_c : natural := 3; -- CP3: floating-point unit ('Zfinx' extension)
constant cp_sel_cfu_c : natural := 4; -- CP4: custom instructions CFU ('Zxcfu' extension)
constant cp_sel_cond_c : natural := 5; -- CP5: conditional operations ('Zicond' extension)
-- ALU Function Codes ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant alu_op_zero_c : std_ulogic_vector(2 downto 0) := "000"; -- result <= 0
constant alu_op_add_c : std_ulogic_vector(2 downto 0) := "001"; -- result <= A + (-)B
constant alu_op_cp_c : std_ulogic_vector(2 downto 0) := "010"; -- result <= ALU co-processor
constant alu_op_slt_c : std_ulogic_vector(2 downto 0) := "011"; -- result <= A < B
constant alu_op_movb_c : std_ulogic_vector(2 downto 0) := "100"; -- result <= B
constant alu_op_xor_c : std_ulogic_vector(2 downto 0) := "101"; -- result <= A xor B
constant alu_op_or_c : std_ulogic_vector(2 downto 0) := "110"; -- result <= A or B
constant alu_op_and_c : std_ulogic_vector(2 downto 0) := "111"; -- result <= A and B
-- Register File Input Select -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant rf_mux_alu_c : std_ulogic_vector(1 downto 0) := "00"; -- register file <= alu result
constant rf_mux_mem_c : std_ulogic_vector(1 downto 0) := "01"; -- register file <= memory read data
constant rf_mux_csr_c : std_ulogic_vector(1 downto 0) := "10"; -- register file <= CSR read data
constant rf_mux_ret_c : std_ulogic_vector(1 downto 0) := "11"; -- register file <= link-PC (return address)
-- Trap ID Codes --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- MSB: 1 = interrupt, 0 = sync. exception
-- MSB-1: 1 = entry to debug mode, 0 = normal trapping
-- RISC-V compliant synchronous exceptions --
constant trap_ima_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00000"; -- 0: instruction misaligned
constant trap_iaf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00001"; -- 1: instruction access fault
constant trap_iil_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00010"; -- 2: illegal instruction
constant trap_brk_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00011"; -- 3: environment breakpoint
constant trap_lma_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00100"; -- 4: load address misaligned
constant trap_laf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00101"; -- 5: load access fault
constant trap_sma_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00110"; -- 6: store address misaligned
constant trap_saf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00111"; -- 7: store access fault
constant trap_env_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "010UU"; -- 8..11: environment call from u/s/h/m
-- RISC-V compliant asynchronous exceptions (interrupts) --
constant trap_msi_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "00011"; -- 3: machine software interrupt
constant trap_mti_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "00111"; -- 7: machine timer interrupt
constant trap_mei_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "01011"; -- 11: machine external interrupt
-- NEORV32-specific (RISC-V custom) asynchronous exceptions (interrupts) --
constant trap_firq0_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10000"; -- 16: fast interrupt 0
constant trap_firq1_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10001"; -- 17: fast interrupt 1
constant trap_firq2_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10010"; -- 18: fast interrupt 2
constant trap_firq3_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10011"; -- 19: fast interrupt 3
constant trap_firq4_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10100"; -- 20: fast interrupt 4
constant trap_firq5_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10101"; -- 21: fast interrupt 5
constant trap_firq6_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10110"; -- 22: fast interrupt 6
constant trap_firq7_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10111"; -- 23: fast interrupt 7
constant trap_firq8_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11000"; -- 24: fast interrupt 8
constant trap_firq9_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11001"; -- 25: fast interrupt 9
constant trap_firq10_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11010"; -- 26: fast interrupt 10
constant trap_firq11_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11011"; -- 27: fast interrupt 11
constant trap_firq12_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11100"; -- 28: fast interrupt 12
constant trap_firq13_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11101"; -- 29: fast interrupt 13
constant trap_firq14_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11110"; -- 30: fast interrupt 14
constant trap_firq15_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11111"; -- 31: fast interrupt 15
-- entering debug mode (sync./async. exceptions) --
constant trap_db_break_c : std_ulogic_vector(6 downto 0) := "0" & "1" & "00001"; -- 1: break instruction (sync)
constant trap_db_trig_c : std_ulogic_vector(6 downto 0) := "0" & "1" & "00010"; -- 2: hardware trigger (sync)
constant trap_db_halt_c : std_ulogic_vector(6 downto 0) := "1" & "1" & "00011"; -- 3: external halt request (async)
constant trap_db_step_c : std_ulogic_vector(6 downto 0) := "1" & "1" & "00100"; -- 4: single-stepping (async)
-- Trap System ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- exception source bits --
constant exc_iaccess_c : natural := 0; -- instruction access fault
constant exc_illegal_c : natural := 1; -- illegal instruction
constant exc_ialign_c : natural := 2; -- instruction address misaligned
constant exc_ecall_c : natural := 3; -- environment call
constant exc_ebreak_c : natural := 4; -- breakpoint
constant exc_salign_c : natural := 5; -- store address misaligned
constant exc_lalign_c : natural := 6; -- load address misaligned
constant exc_saccess_c : natural := 7; -- store access fault
constant exc_laccess_c : natural := 8; -- load access fault
constant exc_db_break_c : natural := 9; -- enter debug mode via ebreak instruction
constant exc_db_hw_c : natural := 10; -- enter debug mode via hw trigger
constant exc_width_c : natural := 11; -- length of this list in bits
-- interrupt source bits --
constant irq_msi_irq_c : natural := 0; -- machine software interrupt
constant irq_mti_irq_c : natural := 1; -- machine timer interrupt
constant irq_mei_irq_c : natural := 2; -- machine external interrupt
constant irq_firq_0_c : natural := 3; -- fast interrupt channel 0
constant irq_firq_1_c : natural := 4; -- fast interrupt channel 1
constant irq_firq_2_c : natural := 5; -- fast interrupt channel 2
constant irq_firq_3_c : natural := 6; -- fast interrupt channel 3
constant irq_firq_4_c : natural := 7; -- fast interrupt channel 4
constant irq_firq_5_c : natural := 8; -- fast interrupt channel 5
constant irq_firq_6_c : natural := 9; -- fast interrupt channel 6
constant irq_firq_7_c : natural := 10; -- fast interrupt channel 7
constant irq_firq_8_c : natural := 11; -- fast interrupt channel 8
constant irq_firq_9_c : natural := 12; -- fast interrupt channel 9
constant irq_firq_10_c : natural := 13; -- fast interrupt channel 10
constant irq_firq_11_c : natural := 14; -- fast interrupt channel 11
constant irq_firq_12_c : natural := 15; -- fast interrupt channel 12
constant irq_firq_13_c : natural := 16; -- fast interrupt channel 13
constant irq_firq_14_c : natural := 17; -- fast interrupt channel 14
constant irq_firq_15_c : natural := 18; -- fast interrupt channel 15
constant irq_db_halt_c : natural := 19; -- enter debug mode via external halt request
constant irq_db_step_c : natural := 20; -- enter debug mode via single-stepping
constant irq_width_c : natural := 21; -- length of this list in bits
-- Privilege Modes ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant priv_mode_m_c : std_ulogic := '1'; -- machine mode
constant priv_mode_u_c : std_ulogic := '0'; -- user mode
-- HPM Events -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- RISC-V-compliant --
constant hpmcnt_event_cy_c : natural := 0; -- active cycle
constant hpmcnt_event_tm_c : natural := 1; -- time (unused/reserved)
constant hpmcnt_event_ir_c : natural := 2; -- retired instruction
-- NEORV32-specific --
constant hpmcnt_event_compr_c : natural := 3; -- executed compressed instruction
constant hpmcnt_event_wait_dis_c : natural := 4; -- instruction dispatch wait cycle
constant hpmcnt_event_wait_alu_c : natural := 5; -- multi-cycle ALU co-processor wait cycle
constant hpmcnt_event_branch_c : natural := 6; -- executed branch instruction
constant hpmcnt_event_branched_c : natural := 7; -- control flow transfer
constant hpmcnt_event_load_c : natural := 8; -- load operation
constant hpmcnt_event_store_c : natural := 9; -- store operation
constant hpmcnt_event_wait_lsu_c : natural := 10; -- load-store unit memory wait cycle
constant hpmcnt_event_trap_c : natural := 11; -- entered trap
--
constant hpmcnt_event_width_c : natural := 12; -- length of this list
-- **********************************************************************************************************
-- Helper Functions
-- **********************************************************************************************************
function index_size_f(input : natural) return natural;
function cond_sel_natural_f(cond : boolean; val_t : natural; val_f : natural) return natural;
function cond_sel_suv_f(cond : boolean; val_t : std_ulogic_vector; val_f : std_ulogic_vector) return std_ulogic_vector;
function cond_sel_string_f(cond : boolean; val_t : string; val_f : string) return string;
function max_natural_f(a : natural; b : natural) return natural;
function min_natural_f(a : natural; b : natural) return natural;
function bool_to_ulogic_f(cond : boolean) return std_ulogic;
function or_reduce_f(input : std_ulogic_vector) return std_ulogic;
function and_reduce_f(input : std_ulogic_vector) return std_ulogic;
function xor_reduce_f(input : std_ulogic_vector) return std_ulogic;
function to_hexchar_f(input : std_ulogic_vector(3 downto 0)) return character;
function bit_rev_f(input : std_ulogic_vector) return std_ulogic_vector;
function is_power_of_two_f(input : natural) return boolean;
function bswap_f(input : std_ulogic_vector) return std_ulogic_vector;
function popcount_f(input : std_ulogic_vector) return natural;
function leading_zeros_f(input : std_ulogic_vector) return natural;
function replicate_f(input : std_ulogic; num : natural) return std_ulogic_vector;
impure function mem32_init_f(init : mem32_t; depth : natural) return mem32_t;
function print_version_f(version : std_ulogic_vector(31 downto 0)) return string;
-- **********************************************************************************************************
-- NEORV32 Processor Top Entity (component prototype)
-- **********************************************************************************************************
component neorv32_top
generic (
-- General --
CLOCK_FREQUENCY : natural;
CLOCK_GATING_EN : boolean := false;
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000";
JEDEC_ID : std_ulogic_vector(10 downto 0) := "00000000000";
INT_BOOTLOADER_EN : boolean := false;
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN : boolean := false;
DM_LEGACY_MODE : boolean := false;
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false;
CPU_EXTENSION_RISCV_B : boolean := false;
CPU_EXTENSION_RISCV_C : boolean := false;
CPU_EXTENSION_RISCV_E : boolean := false;
CPU_EXTENSION_RISCV_M : boolean := false;
CPU_EXTENSION_RISCV_U : boolean := false;
CPU_EXTENSION_RISCV_Zfinx : boolean := false;
CPU_EXTENSION_RISCV_Zicntr : boolean := true;
CPU_EXTENSION_RISCV_Zicond : boolean := false;
CPU_EXTENSION_RISCV_Zihpm : boolean := false;
CPU_EXTENSION_RISCV_Zmmul : boolean := false;
CPU_EXTENSION_RISCV_Zxcfu : boolean := false;
-- Tuning Options --
FAST_MUL_EN : boolean := false;
FAST_SHIFT_EN : boolean := false;
REGFILE_HW_RST : boolean := false;
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural range 0 to 16 := 0;
PMP_MIN_GRANULARITY : natural := 4;
PMP_TOR_MODE_EN : boolean := true;
PMP_NAP_MODE_EN : boolean := true;
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural range 0 to 13 := 0;
HPM_CNT_WIDTH : natural range 0 to 64 := 40;
-- Internal Instruction memory (IMEM) --
MEM_INT_IMEM_EN : boolean := false;
MEM_INT_IMEM_SIZE : natural := 16*1024;
-- Internal Data memory (DMEM) --
MEM_INT_DMEM_EN : boolean := false;
MEM_INT_DMEM_SIZE : natural := 8*1024;
-- Internal Instruction Cache (iCACHE) --
ICACHE_EN : boolean := false;
ICACHE_NUM_BLOCKS : natural range 1 to 256 := 4;
ICACHE_BLOCK_SIZE : natural range 4 to 2**16 := 64;
-- Internal Data Cache (dCACHE) --
DCACHE_EN : boolean := false;
DCACHE_NUM_BLOCKS : natural range 1 to 256 := 4;
DCACHE_BLOCK_SIZE : natural range 4 to 2**16 := 64;
-- External bus interface (XBUS) --
XBUS_EN : boolean := false;
XBUS_TIMEOUT : natural := 255;
XBUS_REGSTAGE_EN : boolean := false;
XBUS_CACHE_EN : boolean := false;
XBUS_CACHE_NUM_BLOCKS : natural range 1 to 256 := 64;
XBUS_CACHE_BLOCK_SIZE : natural range 1 to 2**16 := 32;
-- Execute in-place module (XIP) --
XIP_EN : boolean := false;
XIP_CACHE_EN : boolean := false;
XIP_CACHE_NUM_BLOCKS : natural range 1 to 256 := 8;
XIP_CACHE_BLOCK_SIZE : natural range 1 to 2**16 := 256;
-- External Interrupts Controller (XIRQ) --
XIRQ_NUM_CH : natural range 0 to 32 := 0;
-- Processor peripherals --
IO_DISABLE_SYSINFO : boolean := false;
IO_GPIO_NUM : natural range 0 to 64 := 0;
IO_MTIME_EN : boolean := false;
IO_UART0_EN : boolean := false;
IO_UART0_RX_FIFO : natural range 1 to 2**15 := 1;
IO_UART0_TX_FIFO : natural range 1 to 2**15 := 1;
IO_UART1_EN : boolean := false;
IO_UART1_RX_FIFO : natural range 1 to 2**15 := 1;
IO_UART1_TX_FIFO : natural range 1 to 2**15 := 1;
IO_SPI_EN : boolean := false;
IO_SPI_FIFO : natural range 1 to 2**15 := 1;
IO_SDI_EN : boolean := false;
IO_SDI_FIFO : natural range 1 to 2**15 := 1;
IO_TWI_EN : boolean := false;
IO_TWI_FIFO : natural range 1 to 2**15 := 1;
IO_PWM_NUM_CH : natural range 0 to 12 := 0;
IO_WDT_EN : boolean := false;
IO_TRNG_EN : boolean := false;
IO_TRNG_FIFO : natural range 1 to 2**15 := 1;
IO_CFS_EN : boolean := false;
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000";
IO_CFS_IN_SIZE : natural := 32;
IO_CFS_OUT_SIZE : natural := 32;
IO_NEOLED_EN : boolean := false;
IO_NEOLED_TX_FIFO : natural range 1 to 2**15 := 1;
IO_GPTMR_EN : boolean := false;
IO_ONEWIRE_EN : boolean := false;
IO_DMA_EN : boolean := false;
IO_SLINK_EN : boolean := false;
IO_SLINK_RX_FIFO : natural range 1 to 2**15 := 1;
IO_SLINK_TX_FIFO : natural range 1 to 2**15 := 1;
IO_CRC_EN : boolean := false
);
port (
-- Global control --
clk_i : in std_ulogic;
rstn_i : in std_ulogic;
-- JTAG on-chip debugger interface --
jtag_tck_i : in std_ulogic := 'L';
jtag_tdi_i : in std_ulogic := 'L';
jtag_tdo_o : out std_ulogic;
jtag_tms_i : in std_ulogic := 'L';
-- External bus interface (available if XBUS_EN = true) --
xbus_adr_o : out std_ulogic_vector(31 downto 0);
xbus_dat_o : out std_ulogic_vector(31 downto 0);
xbus_tag_o : out std_ulogic_vector(2 downto 0);
xbus_we_o : out std_ulogic;
xbus_sel_o : out std_ulogic_vector(3 downto 0);
xbus_stb_o : out std_ulogic;
xbus_cyc_o : out std_ulogic;
xbus_dat_i : in std_ulogic_vector(31 downto 0) := (others => 'L');
xbus_ack_i : in std_ulogic := 'L';
xbus_err_i : in std_ulogic := 'L';
-- Stream Link Interface (available if IO_SLINK_EN = true) --
slink_rx_dat_i : in std_ulogic_vector(31 downto 0) := (others => 'L');
slink_rx_src_i : in std_ulogic_vector(3 downto 0) := (others => 'L');
slink_rx_val_i : in std_ulogic := 'L';
slink_rx_lst_i : in std_ulogic := 'L';
slink_rx_rdy_o : out std_ulogic;
slink_tx_dat_o : out std_ulogic_vector(31 downto 0);
slink_tx_dst_o : out std_ulogic_vector(3 downto 0);
slink_tx_val_o : out std_ulogic;
slink_tx_lst_o : out std_ulogic;
slink_tx_rdy_i : in std_ulogic := 'L';
-- XIP (execute in-place via SPI) signals (available if XIP_EN = true) --
xip_csn_o : out std_ulogic;
xip_clk_o : out std_ulogic;
xip_dat_i : in std_ulogic := 'L';
xip_dat_o : out std_ulogic;
-- GPIO (available if IO_GPIO_NUM > 0) --
gpio_o : out std_ulogic_vector(63 downto 0);
gpio_i : in std_ulogic_vector(63 downto 0) := (others => 'L');
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o : out std_ulogic;
uart0_rxd_i : in std_ulogic := 'L';
uart0_rts_o : out std_ulogic;
uart0_cts_i : in std_ulogic := 'L';
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o : out std_ulogic;
uart1_rxd_i : in std_ulogic := 'L'; -- UART1 receive data
uart1_rts_o : out std_ulogic;
uart1_cts_i : in std_ulogic := 'L';
-- SPI (available if IO_SPI_EN = true) --
spi_clk_o : out std_ulogic;
spi_dat_o : out std_ulogic;
spi_dat_i : in std_ulogic := 'L';
spi_csn_o : out std_ulogic_vector(7 downto 0); -- SPI CS
-- SDI (available if IO_SDI_EN = true) --
sdi_clk_i : in std_ulogic := 'L';
sdi_dat_o : out std_ulogic;
sdi_dat_i : in std_ulogic := 'L';
sdi_csn_i : in std_ulogic := 'H';
-- TWI (available if IO_TWI_EN = true) --
twi_sda_i : in std_ulogic := 'H';
twi_sda_o : out std_ulogic;
twi_scl_i : in std_ulogic := 'H';
twi_scl_o : out std_ulogic;
-- 1-Wire Interface (available if IO_ONEWIRE_EN = true) --
onewire_i : in std_ulogic := 'H';
onewire_o : out std_ulogic;
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o : out std_ulogic_vector(11 downto 0); -- pwm channels
-- Custom Functions Subsystem IO --
cfs_in_i : in std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0) := (others => 'L');
cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0);
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o : out std_ulogic;
-- Machine timer system time (available if IO_MTIME_EN = true) --
mtime_time_o : out std_ulogic_vector(63 downto 0);
-- External platform interrupts (available if XIRQ_NUM_CH > 0) --
xirq_i : in std_ulogic_vector(31 downto 0) := (others => 'L');
-- CPU Interrupts --
mtime_irq_i : in std_ulogic := 'L';
msw_irq_i : in std_ulogic := 'L';
mext_irq_i : in std_ulogic := 'L'
);
end component;
end neorv32_package;
package body neorv32_package is
-- **********************************************************************************************************
-- Helper Functions
-- **********************************************************************************************************
-- Minimal required number of bits to represent <input> numbers ---------------------------
-- -------------------------------------------------------------------------------------------
function index_size_f(input : natural) return natural is
begin
for i in 0 to natural'high loop
if (2**i >= input) then
return i;
end if;
end loop;
return 0;
end function index_size_f;
-- Conditional select natural -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function cond_sel_natural_f(cond : boolean; val_t : natural; val_f : natural) return natural is
begin
if cond then
return val_t;
else
return val_f;
end if;
end function cond_sel_natural_f;
-- Conditional select std_ulogic_vector ---------------------------------------------------
-- -------------------------------------------------------------------------------------------
function cond_sel_suv_f(cond : boolean; val_t : std_ulogic_vector; val_f : std_ulogic_vector) return std_ulogic_vector is
begin
if cond then
return val_t;
else
return val_f;
end if;
end function cond_sel_suv_f;
-- Conditional select string --------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function cond_sel_string_f(cond : boolean; val_t : string; val_f : string) return string is
begin
if cond then
return val_t;
else
return val_f;
end if;
end function cond_sel_string_f;
-- Select minimal natural value -----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function max_natural_f(a : natural; b : natural) return natural is
begin
if a < b then
return b;
else
return a;
end if;
end function max_natural_f;
-- Select maximal natural value -----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function min_natural_f(a : natural; b : natural) return natural is
begin
if a < b then
return a;
else
return b;
end if;
end function min_natural_f;
-- Convert boolean to std_ulogic ----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function bool_to_ulogic_f(cond : boolean) return std_ulogic is
begin
if cond then
return '1';
else
return '0';
end if;
end function bool_to_ulogic_f;
-- OR all bits ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function or_reduce_f(input : std_ulogic_vector) return std_ulogic is
variable tmp_v : std_ulogic := '0';
begin
for i in input'range loop
tmp_v := tmp_v or input(i);
end loop;
return tmp_v;
end function or_reduce_f;
-- AND all bits ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function and_reduce_f(input : std_ulogic_vector) return std_ulogic is
variable tmp_v : std_ulogic := '1';
begin
for i in input'range loop
tmp_v := tmp_v and input(i);
end loop;
return tmp_v;
end function and_reduce_f;
-- XOR all bits ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function xor_reduce_f(input : std_ulogic_vector) return std_ulogic is
variable tmp_v : std_ulogic := '0';
begin
for i in input'range loop
tmp_v := tmp_v xor input(i);
end loop;
return tmp_v;
end function xor_reduce_f;
-- Convert 4-bit std_ulogic_vector to lowercase hex char ----------------------------------
-- -------------------------------------------------------------------------------------------
function to_hexchar_f(input : std_ulogic_vector(3 downto 0)) return character is
variable hex_v : string(1 to 16) := "0123456789abcdef";
begin
if ((input(0) /= '0') and (input(0) /= '1')) or
((input(1) /= '0') and (input(1) /= '1')) or
((input(2) /= '0') and (input(2) /= '1')) or
((input(3) /= '0') and (input(3) /= '1')) then
return '?';
else
return hex_v(to_integer(unsigned(input)) + 1);
end if;
end function to_hexchar_f;
-- Bit reversal ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function bit_rev_f(input : std_ulogic_vector) return std_ulogic_vector is
variable output_v : std_ulogic_vector(input'range);
begin
for i in 0 to input'length-1 loop
output_v(input'length-i-1) := input(i);
end loop;
return output_v;
end function bit_rev_f;
-- Test if input number is a power of two -------------------------------------------------