-
Notifications
You must be signed in to change notification settings - Fork 3
/
eSpiMasterBfm.vhd
3722 lines (3500 loc) · 212 KB
/
eSpiMasterBfm.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
--************************************************************************
-- @author: Andreas Kaeberlein
-- @copyright: Copyright 2021
-- @credits: AKAE
--
-- @license: BSDv3
-- @maintainer: Andreas Kaeberlein
-- @email: [email protected]
--
-- @file: eSpiMasterBfm.vhd
-- @note: VHDL'93
-- @date: 2020-01-04
--
-- @see: https://www.intel.com/content/dam/support/us/en/documents/software/chipset-software/327432-004_espi_base_specification_rev1.0_cb.pdf
-- @see: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_embedded_ip.pdf
-- @see: https://github.com/akaeba/eSpiMasterBfm
-- @brief: bus functional model for enhanced SPI (eSPI)
-- provides function to interact with an eSPI
-- slave
--************************************************************************
--------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.realmin;
use ieee.math_real.realmax;
use ieee.math_real.round;
library std;
use std.textio.all;
--------------------------------------------------------------------------
--------------------------------------------------------------------------
-- eSpiMasterBfm: eSPI Master Bus functional model package
package eSpiMasterBfm is
----------------------------------------------
-- Typs
----------------------------------------------
--***************************
-- Arrays
type tMemX08 is array (natural range <>) of std_logic_vector (7 downto 0); --! byte array
type tMemX32 is array (natural range <>) of std_logic_vector (31 downto 0); --! dword array
--***************************
--***************************
-- Virtual Wires Index/Name resolving
type tSysEventName is array(2 to 7, 0 to 3) of string(1 to 22); --! System Event Virtual Wires; resolves index to name, required by print
type tServerPfmName is array(64 to 71, 0 to 3) of string(1 to 15); --! Server Platform Specific Virtual Wire Index; resolves index to name, required by print
--***************************
--***************************
-- ESPI Slave Response
type tESpiRsp is
(
ACCEPT, --! Command was successfully received
DEFER, --! Only valid in response to a PUT_NP
NON_FATAL_ERROR, --! The received command had an error with nonfatal severity
FATAL_ERROR, --! The received command had a fatal error that prevented the transaction layer packet from being successfully processed
WAIT_STATE, --! Adds one byte-time of delay when responding to a transaction on the bus.
NO_RESPONSE, --! The response encoding of all 1's is defined as no response
NO_DECODE --! not in eSPI Spec, no decoding possible
);
--***************************
--***************************
-- Configures the BFM
type tESpiBfm is record
sigSkew : time; --! defines Signal Skew to prevent timing errors in back-anno
verbose : natural; --! message level; 0: no message, 1: errors, 2: error + warnings
tiout : time; --! time out when master give up an interaction
tioutAlert : natural; --! number of clock cycles before BFM gives with time out up
tioutStatusPoll : natural; --! tiout how often is Status polled before giving up
slaveRegs : tMemX32(0 to 16); --! Mirrored Slave Configuration Registers (0x00 - 0x40)
virtualWires : tMemX08(0 to 255); --! Table 9: Virtual Wire Index Definition; 0-1: Interrupt event, 2-7: System Event
slaveStatus : std_logic_vector(15 downto 0); --! Slaves status register
slaveResponse : tESpiRsp; --! decoded Slave response
end record tESpiBfm;
--***************************
--***************************
-- BFM message level
type tMsgLevel is
(
NOMSG, --! no messages are printed to console
ERROR, --! errors are logged
WARNING, --! errors + warnings are logged
INFO --! errors + warnings + info are logged
);
--***************************
----------------------------------------------
-----------------------------
-- Functions (public)
-- CRC calculation
function crc8
(
constant msg : in tMemX08;
constant polynom : in std_logic_vector(7 downto 0) := x"07"
)
return std_logic_vector;
-- get current set espi clock period
function tespi
(
constant this : in tESpiBfm
)
return time;
-----------------------------
-----------------------------
-- Procedures
-- INIT: initializes espi system
-- bfm common handle only
procedure INIT
(
variable this : inout tESpiBfm --! common handle
);
-- bfm and slave 'Exit G3' sequence
procedure INIT
(
variable this : inout tESpiBfm; --! common handle
signal RESETn : out std_logic; --! reset signal
signal CSn : out std_logic; --! slave select
signal SCK : out std_logic; --! shift clock
signal DIO : inout std_logic_vector(3 downto 0); --! bidirectional data
signal ALERTn : in std_logic; --! slaves alert pin
variable good : inout boolean; --! successful
constant log : in tMsgLevel := ERROR; --! BFM log level
constant crc : in boolean := false; --! true: CRC is enabled
constant maxClk : in boolean := true; --! true: enable maximum supported SPI clock, false: reset settings used
constant maxDIO : in boolean := true --! true: max supported data lines are used, false: reset setting used
);
-- setLogLevel: sets bfm log level
procedure setLogLevel
(
variable this : inout tESpiBfm; --! common handle
constant log : in tMsgLevel := INFO --! BFM log level
);
-- RESET: apply reset sequence
-- @see Figure 63: In-band RESET Command
procedure RESET
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic; --! shift clock
signal DIO : inout std_logic_vector(3 downto 0) --! bidirectional data
);
-- GET_CONFIGURATION:
-- @see Figure 22: GET_CONFIGURATION Command
-- w/ status
procedure GET_CONFIGURATION
(
variable this : inout tESpiBfm; --! common BFM handle
signal CSn : out std_logic; --! slave select
signal SCK : out std_logic; --! shift clock
signal DIO : inout std_logic_vector(3 downto 0); --! data lines
constant adr : in std_logic_vector(15 downto 0); --! config address
variable config : out std_logic_vector(31 downto 0) --! config data
);
-- w/o status, response; instead general good, updates BFMs shadows registers of slaves capabilities regs
procedure GET_CONFIGURATION
(
variable this : inout tESpiBfm; --! common BFM handle
signal CSn : out std_logic; --! slave select
signal SCK : out std_logic; --! shift clock
signal DIO : inout std_logic_vector(3 downto 0); --! data lines
constant adr : in std_logic_vector(15 downto 0); --! slave registers address
variable config : out std_logic_vector(31 downto 0); --! read value
variable good : inout boolean --! successful?
);
-- SET_CONFIGURATION:
-- @see Figure 23: SET_CONFIGURATION Command
-- w/ status
procedure SET_CONFIGURATION
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(15 downto 0);
constant config : in std_logic_vector(31 downto 0)
);
-- w/o status, response; Writes changed registers into BFM shadow registers (slaveRegs) back
procedure SET_CONFIGURATION
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(15 downto 0);
constant config : in std_logic_vector(31 downto 0);
variable good : inout boolean
);
-- GET_STATUS
-- @see Figure 20: GET_STATUS Command
-- w/o any print to console
procedure GET_STATUS
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0)
);
-- print to console only
procedure GET_STATUS
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
variable good : inout boolean;
constant prtStatus : in boolean := true --! print read slave status to simulator log
);
-- MEMWR32
-- @see Figure 35: Short Peripheral Memory or Short I/O Write Packet Format (Master Initiated only)
-- arbitrary number of data bytes, response and status register
procedure MEMWR32
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(31 downto 0); --! memory address
constant data : in tMemX08 --! arbitrary number of data bytes
);
-- single data byte, w/o response and status register
procedure MEMWR32
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(31 downto 0); --! memory address
constant data : in std_logic_vector(7 downto 0); --! single data word
variable good : inout boolean --! successful?
);
-- multiple data bytes, w/o response and status register
procedure MEMWR32
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(31 downto 0); --! memory address
constant data : in tMemX08; --! multiple data
variable good : inout boolean --! successful
);
-- MEMRD32
-- @see Figure 37: Short Peripheral Memory or Short I/O Read Packet Format (Master Initiated only)
-- arbitrary number of data bytes, response and status register
procedure MEMRD32
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(31 downto 0); --! memory address
variable data : out tMemX08 --! arbitrary number of data bytes
);
-- single data byte, w/o response and status register
procedure MEMRD32
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(31 downto 0); --! memory address
variable data : out std_logic_vector(7 downto 0); --! single data word
variable good : inout boolean --! successful
);
-- IOWR
-- @see Figure 26: Master Initiated Short Non-Posted Transaction
-- data byte, w/o response and status register
procedure IOWR_BYTE
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(15 downto 0); --! IO space address, 16Bits
constant data : in std_logic_vector(7 downto 0); --! data byte
variable good : inout boolean --! successful?
);
-- data word, w/o response and status register
procedure IOWR_WORD
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(15 downto 0); --! IO space address, 16Bits
constant data : in std_logic_vector(15 downto 0); --! data word
variable good : inout boolean --! successful?
);
-- dual data word, w/o response and status register
procedure IOWR_DWORD
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(15 downto 0); --! IO space address, 16Bits
constant data : in std_logic_vector(31 downto 0); --! dual data word
variable good : inout boolean --! successful?
);
-- Default IOWR is byte orientated access
-- data byte, w/o response and status register
procedure IOWR
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(15 downto 0); --! IO space address, 16Bits
constant data : in std_logic_vector(7 downto 0); --! data byte
variable good : inout boolean --! successful?
);
-- IORD
-- @see Figure 26: Master Initiated Short Non-Posted Transaction
-- data byte, w/o response and status register
procedure IORD_BYTE
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(15 downto 0); --! IO space address, 16Bits
variable data : out std_logic_vector(7 downto 0); --! single data byte
variable good : inout boolean --! successful?
);
-- data word, w/o response and status register
procedure IORD_WORD
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(15 downto 0); --! IO space address, 16Bits
variable data : out std_logic_vector(15 downto 0); --! data word
variable good : inout boolean --! successful?
);
-- data dual word, w/o response and status register
procedure IORD_DWORD
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(15 downto 0); --! IO space address, 16Bits
variable data : out std_logic_vector(31 downto 0); --! data dual word
variable good : inout boolean --! successful?
);
-- Default IORD is byte orientated access
-- data byte, w/o response and status register
procedure IORD
(
variable this : inout tESpiBfm;
signal CSn : out std_logic;
signal SCK : out std_logic;
signal DIO : inout std_logic_vector(3 downto 0);
constant adr : in std_logic_vector(15 downto 0); --! IO space address, 16Bits
variable data : out std_logic_vector(7 downto 0); --! data byte
variable good : inout boolean --! successful?
);
-- VWIREWR
-- @see Figure 41: Virtual Wire Packet Format, Master Initiated Virtual Wire Transfer
-- arbitrary number (<64) of vwire data, response and status register
procedure VWIREWR
(
variable this : inout tESpiBfm;
signal CSn : out std_logic; --! slave select
signal SCK : out std_logic; --! shift clock
signal DIO : inout std_logic_vector(3 downto 0); --! data lines
constant virtualWire : in tMemX08 --! virtual wire index/data pairs, @see Table 9: Virtual Wire Index Definition
);
-- arbitrary vwire instruction, w/o response and status register
procedure VWIREWR
(
variable this : inout tESpiBfm;
signal CSn : out std_logic; --! slave select
signal SCK : out std_logic; --! shift clock
signal DIO : inout std_logic_vector(3 downto 0); --! data lines
constant virtualWire : in tMemX08; --! virtual wire index/data pairs, @see Table 9: Virtual Wire Index Definition
variable good : inout boolean --! successful
);
-- single vwire instruction, wire via name selected, see "System Event Virtual Wires" in spec or 'C_SYSEVENT_NAME' in bfm
procedure VWIREWR
(
variable this : inout tESpiBfm;
signal CSn : out std_logic; --! slave select
signal SCK : out std_logic; --! shift clock
signal DIO : inout std_logic_vector(3 downto 0); --! data lines
constant name : in string; --! Virtual wire name
constant value : in bit; --! virtual wire value
variable good : inout boolean --! successful
);
-- VWIRERD
-- @see Figure 41: Virtual Wire Packet Format, Master Initiated Virtual Wire Transfer
-- arbitrary number (<64) of vwire data, response and status register
procedure VWIRERD
(
variable this : inout tESpiBfm;
signal CSn : out std_logic; --! slave select
signal SCK : out std_logic; --! shift clock
signal DIO : inout std_logic_vector(3 downto 0); --! data lines
variable virtualWire : out tMemX08(0 to 127); --! virtual wire index/data pairs, @see Table 9: Virtual Wire Index Definition
variable virtualWireLen : out integer range 0 to 64 --! number of wire pairs
);
-- read wires into BFM buffer
procedure VWIRERD
(
variable this : inout tESpiBfm;
signal CSn : out std_logic; --! slave select
signal SCK : out std_logic; --! shift clock
signal DIO : inout std_logic_vector(3 downto 0); --! data lines
variable good : inout boolean --! successful
);
-- Virtual Wires Helper
-- VW_ADD: adds based on string virtual wire entry to list
procedure VW_ADD
(
variable this : inout tESpiBfm; --! common storage element
constant name : in string; --! Virtual wire name
constant value : in bit; --! virtual wire value
variable vw : inout tMemX08; --! virtual wire index/data pairs, @see Table 9: Virtual Wire Index Definition
variable vwLen : inout natural; --! effective list length
variable good : inout boolean --! successful
);
-- Virtual Wire: Waits until is equal
-- waits until a virtual wire has the given value
-- @see Table 9: Virtual Wire Index Definition
-- arbitrary number of wires
procedure WAIT_VW_IS_EQ
(
variable this : inout tESpiBfm; --! common bfm handle
signal CSn : out std_logic; --! slave select
signal SCK : out std_logic; --! shift clock
signal DIO : inout std_logic_vector(3 downto 0); --! data lines
signal ALERTn : in std_logic; --! Alert
constant vwNeedle : in tMemX08; --! virtual wire index/data pairs to look for
variable good : inout boolean --! successful?
);
-- single wire
procedure WAIT_VW_IS_EQ
(
variable this : inout tESpiBfm;
signal CSn : out std_logic; --! slave select
signal SCK : out std_logic; --! shift clock
signal DIO : inout std_logic_vector(3 downto 0); --! data lines
signal ALERTn : in std_logic; --! Alert
constant wireName : in string; --! name of the virtual wire
constant wireVal : in bit; --! value of the virtual wire
variable good : inout boolean --! successful?
);
-----------------------------
end package eSpiMasterBfm;
--------------------------------------------------------------------------
--------------------------------------------------------------------------
-- eSpiMasterBfmPKG: eSPI Master Bus functional model package
package body eSpiMasterBfm is
----------------------------------------------
-- Constant BFM Handling
----------------------------------------------
--***************************
-- BFM
constant C_BFM_LICENSE : string := "BSDv3";
constant C_BFM_AUTHORS : string := "Andreas Kaeberlein";
constant C_BFM_VERSION : string := "v0.1.4";
--***************************
--***************************
-- Message Levels
constant C_MSG_NO : integer := 0;
constant C_MSG_ERROR : integer := 1;
constant C_MSG_WARN : integer := 2;
constant C_MSG_INFO : integer := 3;
--***************************
--***************************
-- Time-out
constant C_TIOUT_CYC_ALERT : integer := 100; --! number of clock cycles before BFM gives with time out up
constant C_TIOUT_STS_POLL : integer := 20; --! number of status retries before BFM giving up
--***************************
----------------------------------------------
----------------------------------------------
-- Early Help Functions
-- f.e. needed for constant initialization
----------------------------------------------
--***************************
-- padStr
-- creates an string with a fixed length, padded with pad
function padStr
(
constant str : in string; --! input string
constant pad : in character; --! pad with
constant len : in positive --! resulting length
)
return string is
alias alignStr : string(1 to str'length) is str; --! make one aligned
variable padedStr : string(1 to len); --! padded string
begin
-- no padding
if ( alignStr'length = len ) then
return alignStr;
end if;
-- pad with template
padedStr := (others => pad);
-- pad
padedStr(1 to alignStr'length) := alignStr;
return padedStr;
end function padStr;
--***************************
--***************************
-- padStr
-- creates an string with a fixed length, padded with pad
function padStr
(
constant str : in string; --! input string
constant len : in positive --! resulting length
)
return string is
begin
-- padStr( str, pad, len )
return padStr( str, ' ', len );
end function padStr;
--***************************
----------------------------------------------
----------------------------------------------
-- Constant eSPI Handling
----------------------------------------------
--***************************
-- Command Opcode Encodings (Table 3)
constant C_PUT_PC : std_logic_vector(7 downto 0) := "00000000"; --! Put a posted or completion header and optional data.
constant C_PUT_NP : std_logic_vector(7 downto 0) := "00000010"; --! Put a non-posted header and optional data.
constant C_GET_PC : std_logic_vector(7 downto 0) := "00000001"; --! Get a posted or completion header and optional data.
constant C_GET_NP : std_logic_vector(7 downto 0) := "00000011"; --! Get a non-posted header and optional data.
constant C_PUT_IORD_SHORT : std_logic_vector(7 downto 2) := "010000"; --! Put a short (1, 2 or 4 bytes) non-posted I/O Read packet.
constant C_PUT_IOWR_SHORT : std_logic_vector(7 downto 2) := "010001"; --! Put a short (1, 2 or 4 bytes) non-posted I/O Write packet.
constant C_PUT_MEMRD32_SHORT : std_logic_vector(7 downto 2) := "010010"; --! Put a short (1, 2 or 4 bytes) non-posted Memory Read 32 packet.
constant C_PUT_MEMWR32_SHORT : std_logic_vector(7 downto 2) := "010011"; --! Put a short (1, 2 or 4 bytes) posted Memory Write 32 packet.
constant C_PUT_VWIRE : std_logic_vector(7 downto 0) := "00000100"; --! Put a Tunneled virtual wire packet.
constant C_GET_VWIRE : std_logic_vector(7 downto 0) := "00000101"; --! Get a Tunneled virtual wire packet.
constant C_PUT_OOB : std_logic_vector(7 downto 0) := "00000110"; --! Put an OOB (Tunneled SMBus) message.
constant C_GET_OOB : std_logic_vector(7 downto 0) := "00000111"; --! Get an OOB (Tunneled SMBus) message.
constant C_PUT_FLASH_C : std_logic_vector(7 downto 0) := "00001000"; --! Put a Flash Access completion.
constant C_GET_FLASH_NP : std_logic_vector(7 downto 0) := "00001001"; --! Get a non-posted Flash Access request.
constant C_GET_STATUS : std_logic_vector(7 downto 0) := "00100101"; --! Command initiated by the master to read the status register of the slave.
constant C_SET_CONFIGURATION : std_logic_vector(7 downto 0) := "00100010"; --! Command to set the capabilities of the slave as part of the initialization. This is typically done after the master discovers the capabilities of the slave.
constant C_GET_CONFIGURATION : std_logic_vector(7 downto 0) := "00100001"; --! Command to discover the capabilities of the slave as part of the initialization.
constant C_RESET : std_logic_vector(7 downto 0) := "11111111"; --! In-band RESET command.
--***************************
--***************************
-- Config Register eSpi Slave
-- @see Table 20: Slave Registers
constant C_DEVICE_IDENTIFICATION : std_logic_vector(15 downto 0) := x"0004"; --! Device Identification
constant C_GENERAL : std_logic_vector(15 downto 0) := x"0008"; --! General Capabilities and Configurations
constant C_PERIPHERAL_CHANNEL : std_logic_vector(15 downto 0) := x"0010"; --! Channel 0 Capabilities and Configurations (Peripheral Channel)
constant C_VIRTUAL_WIRE_CHANNEL : std_logic_vector(15 downto 0) := x"0020"; --! Channel 1 Capabilities and Configurations (Virtual Wire Channel)
constant C_OOB_CHANNEL : std_logic_vector(15 downto 0) := x"0030"; --! Channel 2 Capabilities and Configurations (OOB Channel)
constant C_FLASH_CHANNEL : std_logic_vector(15 downto 0) := x"0040"; --! Channel 3 Capabilities and Configurations (Flash Channel)
--***************************
--***************************
-- Capabilities and Configuration Registers
-- @see 7.2.1.3 Offset 08h: General Capabilities and Configurations
-- constants are initialized with Specs defaults
constant C_GENERAL_CRC : std_logic_vector(31 downto 31) := "0"; --! CRC Checking Enable: 0b: CRC checking is disabled. 1b: CRC checking is enabled.
constant C_GENERAL_RSP_MOD : std_logic_vector(30 downto 30) := "0"; --! Response Modifier Enable: This bit is set to '1' to enable the use of Response Modifier
constant C_GENERAL_ALERT_MODE : std_logic_vector(28 downto 28) := "0"; --! Alert Mode: 0b: I/O[1] pin is used to signal the Alert event. 1b: Alert# pin is used to signal the Alert event.
constant C_GENERAL_IO_MODE_SEL : std_logic_vector(27 downto 26) := "00"; --! I/O Mode Select:
constant C_GENERAL_IO_MODE_SEL_SGL : std_logic_vector(01 downto 00) := "00"; --! 00: Single I/O.
constant C_GENERAL_IO_MODE_SEL_DUAL : std_logic_vector(01 downto 00) := "01"; --! 01: Dual I/O.
constant C_GENERAL_IO_MODE_SEL_QUAD : std_logic_vector(01 downto 00) := "10"; --! 10: Quad I/O.
constant C_GENERAL_IO_MODE_SEL_RSV : std_logic_vector(01 downto 00) := "11"; --! 11: Reserved.
constant C_GENERAL_IO_MODE_SUP : std_logic_vector(25 downto 24) := "--"; --! I/O Mode Support:
constant C_GENERAL_IO_MODE_SUP_SGL : std_logic_vector(01 downto 00) := "00"; --! 00: Single I/O.
constant C_GENERAL_IO_MODE_SUP_SGL_DUAL : std_logic_vector(01 downto 00) := "01"; --! 01: Single and Dual I/O.
constant C_GENERAL_IO_MODE_SUP_SGL_QUAD : std_logic_vector(01 downto 00) := "10"; --! 10: Single and Quad I/O.
constant C_GENERAL_IO_MODE_SUP_SGL_DUAL_QUAD : std_logic_vector(01 downto 00) := "11"; --! 11: Single, Dual and Quad I/O
constant C_GENERAL_OD_ALERT_PIN : std_logic_vector(23 downto 23) := "0"; --! Open Drain Alert# Select: 0b: Alert# pin is a driven output. 1b: Alert# pin is an open-drain output.
constant C_GENERAL_OD_ALERT_SUP : std_logic_vector(19 downto 19) := "-"; --! Open Drain Alert# Supported: 0b: Open-drain Alert# pin is not supported. 1b: Open-drain Alert# pin is supported.
constant C_GENERAL_OP_FREQ_SEL : std_logic_vector(22 downto 20) := "000"; --! Operating Frequency: 000: 20 MHz. 001: 25 MHz. 010: 33 MHz. 011: 50 MHz. 100: 66 MHz. others: Reserved.
constant C_GENERAL_OP_FREQ_SUP : std_logic_vector(18 downto 16) := "---"; --! Maximum Frequency Supported: 000: 20 MHz. 001: 25 MHz. 010: 33 MHz. 011: 50 MHz. 100: 66 MHz. others: Reserved.
constant C_GENERAL_OP_FREQ_20MHz : std_logic_vector(02 downto 00) := "000"; --! 000: 20 MHz.
constant C_GENERAL_OP_FREQ_25MHz : std_logic_vector(02 downto 00) := "001"; --! 001: 25 MHz.
constant C_GENERAL_OP_FREQ_33MHz : std_logic_vector(02 downto 00) := "010"; --! 010: 33 MHz.
constant C_GENERAL_OP_FREQ_50MHz : std_logic_vector(02 downto 00) := "011"; --! 011: 50 MHz.
constant C_GENERAL_OP_FREQ_66MHz : std_logic_vector(02 downto 00) := "100"; --! 100: 66 MHz.
constant C_GENERAL_MAX_WAIT : std_logic_vector(15 downto 12) := "0000"; --! Maximum WAIT STATE Allowed: This is a 1-based field in the granularity of byte time. When "0", it indicates a value of 16 byte time.
constant C_GENERAL_CHN_SUP : std_logic_vector(07 downto 00) := "--------"; --! Channel Supported: Each of the bits when set indicates that the corresponding channel is supported by the slave.
constant C_GENERAL_CHN_SUP_PERI : std_logic_vector(00 downto 00) := "1"; --! Peripheral Channel
constant C_GENERAL_CHN_SUP_VW : std_logic_vector(01 downto 01) := "1"; --! Virtual Wire Channel
constant C_GENERAL_CHN_SUP_OOB : std_logic_vector(02 downto 02) := "1"; --! OOB Message Channel
constant C_GENERAL_CHN_SUP_FLASH : std_logic_vector(03 downto 03) := "1"; --! Flash Access Channel
--***************************
--***************************
-- Channel 0 Capabilities and Configurations (Peripheral Channel)
-- @see 7.2.1.4 Offset 10h: Channel 0 Capabilities and Configurations
-- constants are initialized with Specs defaults
constant C_PERI_READY : std_logic_vector(01 downto 01) := "1"; --! Virtual Wire Channel Ready: 0b: Channel is not ready. 1b: Channel is ready.
constant C_PERI_ENABLE : std_logic_vector(00 downto 00) := "1"; --! Virtual Wire Channel Enable: his bit is set to '1' by eSPI master to enable the Virtual Wire channel.
--***************************
--***************************
-- Channel 1 Capabilities and Configurations (Virtual Wire Channel)
-- @see 7.2.1.5 Offset 20h: Channel 1 Capabilities and Configurations
-- constants are initialized with Specs defaults
constant C_VW_READY : std_logic_vector(01 downto 01) := "1"; --! Virtual Wire Channel Ready: 0b: Channel is not ready. 1b: Channel is ready.
constant C_VW_ENABLE : std_logic_vector(00 downto 00) := "1"; --! Virtual Wire Channel Enable: his bit is set to '1' by eSPI master to enable the Virtual Wire channel.
--***************************
--***************************
-- Channel 3 Capabilities and Configurations (Flash Channel)
-- 7.2.1.7 Offset 40h: Channel 3 Capabilities and Configurations
-- constants are initialized with Specs defaults
constant C_FLASH_READY : std_logic_vector(01 downto 01) := "1"; --! Flash Access Channel Ready: 0b: Channel is not ready. 1b: Channel is ready.
constant C_FLASH_ENABLE : std_logic_vector(00 downto 00) := "1"; --! Flash Access Channel Enable: This bit is set to '1' by eSPI master to enable the Flash Access channel.
--***************************
--***************************
-- Response Fields, Table 4: Response Field Encodings
constant C_ACCEPT : std_logic_vector(5 downto 0) := "001000"; --! Command was successfully received
constant C_DEFER : std_logic_vector(7 downto 0) := "00000001"; --! Only valid in response to a PUT_NP
constant C_NON_FATAL_ERROR : std_logic_vector(7 downto 0) := "00000010"; --! The received command had an error with nonfatal severity
constant C_FATAL_ERROR : std_logic_vector(7 downto 0) := "00000011"; --! The received command had a fatal error that prevented the transaction layer packet from being successfully processed
constant C_WAIT_STATE : std_logic_vector(7 downto 0) := "00001111"; --! Adds one byte-time of delay when responding to a transaction on the bus.
constant C_NO_RESPONSE : std_logic_vector(7 downto 0) := "11111111"; --! The response encoding of all 1's is defined as no response
--***************************
--***************************
-- Cycle Type Encodings, Table 6: Cycle Types
constant C_CT_MEMRD32 : std_logic_vector(7 downto 0) := "00000000"; --! 32 bit addressing Memory Read Request. LPC Memory Read and LPC Bus Master Memory Read requests are mapped to this cycle type.
constant C_CT_MEMRD64 : std_logic_vector(7 downto 0) := "00000010"; --! 64 bit addressing Memory Read Request. Support of upstream Memory Read 64 is mandatory for eSPI slaves that are bus mastering capable.
constant C_CT_MEMWR32 : std_logic_vector(7 downto 0) := "00000001"; --! 32 bit addressing Memory Write Request. LPC Memory Write and LPC Bus Master Memory Write requests are mapped to this cycle type.
constant C_CT_MEMWR64 : std_logic_vector(7 downto 0) := "00000011"; --! 64 bit addressing Memory Write Request. Support of upstream Memory Write 64 is mandatory for eSPI slaves that are bus mastering capable.
constant C_CT_MSG : std_logic_vector(7 downto 0) := "000---00"; --! Message Request.
constant C_CT_MSG_W_DAT : std_logic_vector(7 downto 0) := "000---01"; --! Message Request with data payload.
constant C_CT_CPL_OK_WO_DAT : std_logic_vector(7 downto 0) := "00000110"; --! Successful Completion Without Data. Corresponds to I/O Write.
constant C_CT_CPL_OK_W_DAT : std_logic_vector(7 downto 0) := "00001--1"; --! Successful Completion With Data. Corresponds to Memory Read or I/O Read.
constant C_CT_CPL_FAIL_W_DAT : std_logic_vector(7 downto 0) := "00001--0"; --! Unsuccessful Completion Without Data. Corresponds to Memory or I/O.
--***************************
--***************************
-- Status Register, Figure 16: Slave's Status Register Definition
constant C_STS_PC_FREE : std_logic_vector(00 downto 00) := "-"; --! Peripheral Posted/Completion Rx Queue Free
constant C_STS_NP_FREE : std_logic_vector(01 downto 01) := "-"; --! Peripheral Non-Posted Rx Queue Free
constant C_STS_VWIRE_FREE : std_logic_vector(02 downto 02) := "-"; --! Virtual Wire Rx Queue Free
constant C_STS_OOB_FREE : std_logic_vector(03 downto 03) := "-"; --! OOB Posted Rx Queue Free
constant C_STS_PC_AVAIL : std_logic_vector(04 downto 04) := "-"; --! Peripheral Posted/Completion Tx Queue Avail
constant C_STS_NP_AVAIL : std_logic_vector(05 downto 05) := "-"; --! Peripheral Non-Posted Tx Queue Avail
constant C_STS_VWIRE_AVAIL : std_logic_vector(06 downto 06) := "-"; --! Virtual Wire Tx Queue Avail
constant C_STS_OOB_AVAIL : std_logic_vector(07 downto 07) := "-"; --! OOB Posted Tx Queue Avail
constant C_STS_FLASH_C_FREE : std_logic_vector(08 downto 08) := "-"; --! Flash Completion Rx Queue Free
constant C_STS_FLASH_NP_FREE : std_logic_vector(09 downto 09) := "-"; --! Flash Non-Posted Rx Queue Free
constant C_STS_FLASH_C_AVAIL : std_logic_vector(12 downto 12) := "-"; --! Flash Completion Tx Queue Avail
constant C_STS_FLASH_NP_AVAIL : std_logic_vector(13 downto 13) := "-"; --! Flash Non-Posted Tx Queue Avail
--***************************
--***************************
-- System Event Wires
-- @see 5.2.2.2 System Event Virtual Wires
-- @ https://stackoverflow.com/questions/17160878/how-to-declare-two-dimensional-arrays-and-their-elements-in-vhdl/17161967
constant C_SYSEVENT_NAME : tSysEventName := ( (padStr("SLP_S3#", 22), padStr("SLP_S4#", 22), padStr("SLP_S5#", 22), padStr("RSV", 22)),
(padStr("SUS_STAT#", 22), padStr("PLTRST#", 22), padStr("OOB_RST_WARN", 22), padStr("RSV", 22)),
(padStr("OOB_RST_ACK", 22), padStr("RSV", 22), padStr("WAKE#", 22), padStr("PME#", 22)),
(padStr("SLAVE_BOOT_LOAD_DONE", 22), padStr("ERROR_FATAL", 22), padStr("ERROR_NONFATAL", 22), padStr("SLAVE_BOOT_LOAD_STATUS", 22)),
(padStr("SCI#", 22), padStr("SMI#", 22), padStr("RCIN#", 22), padStr("HOST_RST_ACK", 22)),
(padStr("HOST_RST_WARN", 22), padStr("SMIOUT#", 22), padStr("NMIOUT#", 22), padStr("RSV", 22))
);
--***************************
--***************************
-- Server Platform Wires
-- @see Table 24 Server Platform Specific Virtual Wire Index
-- @see https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_embedded_ip.pdf
constant C_SRV_PFM_NAME : tServerPfmName := ( (padStr("SUS_ACK#", 15), padStr("RSV", 15), padStr("RSV", 15), padStr("RSV", 15)),
(padStr("SUS_WARN#", 15), padStr("SUS_PWRDN_ACK", 15), padStr("RSV", 15), padStr("SLP_A#", 15)),
(padStr("SLP_LAN#", 15), padStr("SLP_WLAN#", 15), padStr("RSV", 15), padStr("RSV", 15)),
(padStr("PCH_TO_EC_0", 15), padStr("PCH_TO_EC_1", 15), padStr("PCH_TO_EC_2", 15), padStr("PCH_TO_EC_3", 15)),
(padStr("PCH_TO_EC_4", 15), padStr("PCH_TO_EC_5", 15), padStr("PCH_TO_EC_6", 15), padStr("PCH_TO_EC_7", 15)),
(padStr("EC_TO_PCH_0", 15), padStr("EC_TO_PCH_1", 15), padStr("EC_TO_PCH_2", 15), padStr("EC_TO_PCH_3", 15)),
(padStr("EC_TO_PCH_4", 15), padStr("EC_TO_PCH_5", 15), padStr("EC_TO_PCH_6", 15), padStr("EC_TO_PCH_7", 15)),
(padStr("HOST_C10", 15), padStr("RSV", 15), padStr("RSV", 15), padStr("RSV", 15))
);
--***************************
--***************************
-- Timing Parameters
-- @see Table 22: AC Timing Specification
constant C_TINIT : time := 1 us; --! eSPI Reset# Deassertion to First Transaction (GET_CONFIGURATION)
--***************************
----------------------------------------------
----------------------------------------------
-- Functions
----------------------------------------------
--***************************
-- get max integer number
function max
(
constant op1 : in integer; --! operand 1
constant op2 : in integer --! operand 2
)
return integer is
begin
return integer(round(realmax(real(op1), real(op2))));
end function max;
--***************************
--***************************
-- calc crc
function crc8
(
constant msg : in tMemX08;
constant polynom : in std_logic_vector(7 downto 0) := x"07"
)
return std_logic_vector is
variable remainder : std_logic_vector(7 downto 0);
begin
-- init
remainder := (others => '0');
-- calculate crc
-- @see: https://barrgroup.com/embedded-systems/how-to/crc-calculation-c-code
-- @see: https://crccalc.com
-- iterate over byte messages
for i in msg'low to msg'high loop
remainder := remainder xor msg(i); --! add new message
-- iterate over bit in byte of message
for j in msg(i)'high downto msg(i)'low loop
if ( '1' = remainder(remainder'left) ) then --! Topbit is one
remainder := std_logic_vector(unsigned(remainder) sll 1) xor polynom;
else
remainder := std_logic_vector(unsigned(remainder) sll 1);
end if;
end loop;
end loop;
-- release
return remainder;
end function crc8;
--***************************
--***************************
-- TO_01
-- converts slv to 0/1 value
function TO_01
(
constant s : in std_logic_vector; --! convert to 0/1
constant xmap : in std_logic := '0' --! default mapping
)
return std_logic_vector is
alias inp : std_logic_vector(s'length-1 downto 0) is s;
variable to01 : std_logic_vector(s'length-1 downto 0);
begin
for i in to01'range loop
to01(i) := to_stdulogic(to_bit(std_ulogic'(inp(i)), to_bit(xmap))); --! converts bit by bit
end loop;
return to01;
end function TO_01;
--***************************
--***************************
-- TO_01
-- converts array to 0/1 value
function TO_01
(
constant s : in tMemX08; --! convert to 0/1
constant xmap : in std_logic := '0' --! default mapping
)
return tMemX08 is
alias inp : tMemX08(0 to s'length-1) is s;
variable to01 : tMemX08(0 to s'length-1);
begin
for i in 0 to to01'length-1 loop
to01(i) := TO_01(inp(i), xmap);
end loop;
return to01;
end function TO_01;
--***************************
--***************************
-- or_dc
-- bypassing std_ulogic resolution function for don't cares, they are preserved
function or_dc
(
constant i1 : in std_logic_vector; --! input
constant i2 : in std_logic_vector
)
return std_logic_vector is
alias in1 : std_logic_vector(i1'length-1 downto 0) is i1;
alias in2 : std_logic_vector(i2'length-1 downto 0) is i2;
variable slv : std_logic_vector(i1'length-1 downto 0);
begin
for i in slv'range loop
if ( ('-' = in1(i)) and ('-' = in2(i)) ) then
slv(i) := '-';
else
slv(i) := to_stdulogic(to_bit(in1(i))) or to_stdulogic(to_bit(in2(i)));
end if;
end loop;
return slv;
end function or_dc;
--***************************
--***************************
-- TO_HSTRING (STD_ULOGIC_VECTOR)
-- SRC: http://www.eda-stds.org/vhdl-200x/vhdl-200x-ft/packages_old/std_logic_1164_additions.vhdl
function to_hstring (value : STD_ULOGIC_VECTOR) return STRING is
constant nus : STRING := " ";
constant ne : INTEGER := (value'length+3)/4;
variable pad : STD_ULOGIC_VECTOR(0 to (ne*4 - value'length) - 1);
variable ivalue : STD_ULOGIC_VECTOR(0 to ne*4 - 1);
variable result : STRING(1 to ne);
variable quad : STD_ULOGIC_VECTOR(0 to 3);
begin
if value'length < 1 then
return nus;
else
if value (value'left) = 'Z' then
pad := (others => 'Z');
else
pad := (others => '0');
end if;
ivalue := pad & value;
for i in 0 to ne-1 loop
quad := ivalue(4*i to 4*i+3);
case quad is
when x"0" => result(i+1) := '0';
when x"1" => result(i+1) := '1';
when x"2" => result(i+1) := '2';
when x"3" => result(i+1) := '3';
when x"4" => result(i+1) := '4';
when x"5" => result(i+1) := '5';
when x"6" => result(i+1) := '6';
when x"7" => result(i+1) := '7';
when x"8" => result(i+1) := '8';
when x"9" => result(i+1) := '9';
when x"A" => result(i+1) := 'A';
when x"B" => result(i+1) := 'B';
when x"C" => result(i+1) := 'C';
when x"D" => result(i+1) := 'D';
when x"E" => result(i+1) := 'E';
when x"F" => result(i+1) := 'F';
when "ZZZZ" => result(i+1) := 'Z';
when "----" => result(i+1) := '-';
when "UUUU" => result(i+1) := 'U';
when "HHHH" => result(i+1) := 'H';
when "LLLL" => result(i+1) := 'L';
when others => result(i+1) := 'X';
end case;
end loop;
return result;
end if;
end function to_hstring;
--***************************
--***************************
-- TO_HSTRING (STD_LOGIC_VECTOR)
function to_hstring (value : STD_LOGIC_VECTOR) return STRING is
begin
return to_hstring(STD_ULOGIC_VECTOR(value));
end function to_hstring;
--***************************
--***************************
-- upper
-- converts upper/lower letters to upper letters only
function upper
(
constant str : in string --! mixed letter string
)
return string is
variable upperStr : string(str'range); --! converted upper string
variable intChar : integer; --! to character corresponding integer
begin
for i in str'range loop
intChar := character'pos(character(str(i)));
-- lower characters in ASCII table
-- @see: http://www.asciitable.com
if ( (intChar >= 97) and (intChar <= 122) ) then
intChar := intChar - 32; --! make upper
end if;
upperStr(i) := character'val(intChar);
end loop;
return upperStr;
end function upper;
--***************************
--***************************
-- strtrim
-- removes leading/trailing blanks from string
function strtrim
(
constant str : in string --! input string
)
return string is
variable strStart : positive;
variable strStop : positive;
variable tmpStr : string(1 to str'length);
begin
-- init
strStart := str'left;
strStop := str'right;
-- determine leading blank index
for i in str'left to str'right loop
if ( character(' ') /= str(i) ) then
strStart := i;
exit;
end if;
end loop;
-- determine trailing blank indexes
for i in str'right downto strStart loop
if ( character(' ') /= str(i) ) then
strStop := i;
exit;
end if;
end loop;
-- empty string
if ( strStop = strStart ) then
return "";
end if;
-- assemble result string
tmpStr(1 to (strStop-strStart)+1) := str(strStart to strStop);
return tmpStr(1 to (strStop-strStart)+1);
end function strtrim;
--***************************
--***************************
-- strlen
-- appends string on other string
function strlen
(
constant str : in string --! input string
)
return natural is
alias tmp : string(1 to str'length) is str; --! alignment
variable idx : integer;
begin
if ( 0 = tmp'length ) then --! empty string
return 0;
end if;
idx := tmp'length; --! if no breakout in loop, string has full length
for i in tmp'range loop --! iterate over string
if ( character(NUL) = tmp(i) ) then --! end of string reached?
idx := i - 1; --! last valid character is one position before