Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec57dcbe66 | ||
|
|
faa81b57e9 | ||
|
|
fec1234493 | ||
|
|
d56aec5d03 | ||
|
|
921b1e8876 | ||
|
|
127ed5b3f7 | ||
|
|
840fcb7de1 | ||
|
|
4a1d1df404 | ||
|
|
03c23a0271 | ||
|
|
6cb8c135e2 | ||
|
|
cb503294da | ||
|
|
2858222d97 | ||
|
|
a2f631f4de | ||
|
|
f265661633 | ||
|
|
5430521f4f | ||
|
|
97a19e0eb7 | ||
|
|
5a3e859d59 | ||
|
|
e28d864e40 | ||
|
|
ec301f5710 | ||
|
|
26a0a30fdc | ||
|
|
66514fbf7c | ||
|
|
dff1254bd9 | ||
|
|
5c37f43fcb | ||
|
|
c7f8eea244 | ||
|
|
197e65fc28 | ||
|
|
0af5d4e58c | ||
|
|
b5feee8447 | ||
|
|
80f75ce136 | ||
|
|
17e00a420a | ||
|
|
3e81496d67 | ||
|
|
cd4b4bb99a | ||
|
|
d51a303d9c | ||
|
|
64ebb3af9e | ||
|
|
073acdd2ff | ||
|
|
eba2e4e3b9 | ||
|
|
7f6678d85a | ||
|
|
e7f4a5642a | ||
|
|
330b7e019e | ||
|
|
9991abfebf | ||
|
|
5fbcc211b9 | ||
|
|
17bcf20d9d | ||
|
|
6936064c01 | ||
|
|
a23e3325c9 | ||
|
|
964b08a53c | ||
|
|
11a46a6ef8 | ||
|
|
43f11d43a9 | ||
|
|
0737dc8c74 | ||
|
|
e40bb138ba | ||
|
|
c00c254636 | ||
|
|
1abe64b3b4 | ||
|
|
76eb2dfe32 | ||
|
|
68d0a4cf50 | ||
|
|
3faea6675b | ||
|
|
37d4fe76dc | ||
|
|
328cb7309e | ||
|
|
d7e039dc77 | ||
|
|
59da541fca | ||
|
|
1f1d858f18 | ||
|
|
3a58fbb7af | ||
|
|
4b88e122f2 | ||
|
|
615b776ead | ||
|
|
edc389931a | ||
|
|
cfa1a3f8a2 | ||
|
|
433ff23c41 | ||
|
|
6cdd8d566b | ||
|
|
063019e23e | ||
|
|
668ab68b8b | ||
|
|
bb41db0f76 | ||
|
|
c3b554ffc3 | ||
|
|
b3cda75c60 | ||
|
|
d1e30cfa5c | ||
|
|
d7b6040c38 | ||
|
|
39c15ef86c | ||
|
|
8f283ae097 | ||
|
|
bd64cab371 | ||
|
|
c6e0de57ec | ||
|
|
e8deef86a6 | ||
|
|
4d41635f19 | ||
|
|
d7a1ee94e6 | ||
|
|
bd90e641cf | ||
|
|
25b57a30fe | ||
|
|
ed9601c6aa | ||
|
|
d7c023950b | ||
|
|
a6ba2eeec5 | ||
|
|
904ec64a52 | ||
|
|
4f1f4ca77b | ||
|
|
67136eeedf | ||
|
|
3d90300b81 | ||
|
|
f6b662274c | ||
|
|
b2230a8afb | ||
|
|
2ca53be113 | ||
|
|
89b2cdc6f9 | ||
|
|
43085119b7 | ||
|
|
19d5dc19d6 | ||
|
|
6118008f77 | ||
|
|
aede06ea9e | ||
|
|
6746955337 | ||
|
|
34de6ae03e | ||
|
|
2989bb688f | ||
|
|
38a95c85dd | ||
|
|
03cbf45996 | ||
|
|
7fd7987056 | ||
|
|
08e85b7e8f | ||
|
|
7c6a19b078 | ||
|
|
f602a4baa7 | ||
|
|
c0291407fe | ||
|
|
ebdb4e1e2c | ||
|
|
0554714b52 | ||
|
|
e8b6c8efdb | ||
|
|
832c1c8a33 | ||
|
|
3b014c19ca | ||
|
|
80f57311e4 | ||
|
|
2978ddd09a | ||
|
|
869a0bd0ef | ||
|
|
d99d8e2b44 | ||
|
|
4057a7ba43 | ||
|
|
737df176f1 | ||
|
|
cd285df8e8 | ||
|
|
c3c2cdfe2b | ||
|
|
84fa08326f | ||
|
|
433676de7d | ||
|
|
8960bc52e7 | ||
|
|
88bd1e16d9 | ||
|
|
10a5d17015 | ||
|
|
5f29361ee4 | ||
|
|
a799fffaa7 | ||
|
|
1e2700f265 | ||
|
|
421c961df5 | ||
|
|
6ce6b1e4bc | ||
|
|
6409d43d38 | ||
|
|
e84c9c287e | ||
|
|
d9f3628dd7 | ||
|
|
afcfc8c13a | ||
|
|
2369919996 | ||
|
|
47e15b9feb | ||
|
|
1a4f894996 | ||
|
|
fcce3dcf32 | ||
|
|
db662f411f | ||
|
|
191af92d47 | ||
|
|
ab41a4f80f | ||
|
|
9ac3c738db | ||
|
|
8750901468 | ||
|
|
ed483b2e03 | ||
|
|
8971cdc872 | ||
|
|
0a601d2dd2 | ||
|
|
ce9ff6339d | ||
|
|
e27c0f791a | ||
|
|
874df39347 | ||
|
|
d5922c8f0d | ||
|
|
4ab67a5eab | ||
|
|
b6219e970b | ||
|
|
8dafff2722 | ||
|
|
f60ac9a09d | ||
|
|
90a8a33bb8 | ||
|
|
d820072d82 | ||
|
|
a73cc52a72 | ||
|
|
d30f067cee | ||
|
|
22024a75df | ||
|
|
818ede23e1 | ||
|
|
aad1f852b5 | ||
|
|
293699d051 | ||
|
|
28fc16da87 | ||
|
|
7c70fcb680 | ||
|
|
e6f39ee6b5 | ||
|
|
4f388d5c10 | ||
|
|
0499e58f4b | ||
|
|
a7c1d8fec7 | ||
|
|
56b6044320 | ||
|
|
041aeb7974 | ||
|
|
148c71d2b4 | ||
|
|
9bf3b46cf3 | ||
|
|
c6983bd768 | ||
|
|
e5f5e1d0e3 | ||
|
|
359869bc2d | ||
|
|
943e7e9388 | ||
|
|
daed8e12a0 | ||
|
|
60d59f2f07 | ||
|
|
28056fbdff | ||
|
|
3c3b5e76a7 | ||
|
|
651cd11ec0 | ||
|
|
5889dc2d4a | ||
|
|
819028cd9b | ||
|
|
e162dd8798 | ||
|
|
6136f02789 | ||
|
|
6b0327c702 | ||
|
|
fb96e23852 | ||
|
|
d185bd4aa1 | ||
|
|
d47fbfee09 | ||
|
|
6baab07e5a | ||
|
|
a3a85d2c98 | ||
|
|
80dbbd7024 | ||
|
|
b6dcc8cc48 | ||
|
|
810ae067bc | ||
|
|
c7fa54ce6b | ||
|
|
0c50e933f8 | ||
|
|
385aa5e008 | ||
|
|
f6be505eba | ||
|
|
06c9683eea | ||
|
|
823dd066c2 | ||
|
|
a1aa8dd969 | ||
|
|
ddbf6da277 | ||
|
|
023b7e42a3 | ||
|
|
c42c0ba5b8 | ||
|
|
e0e8566bec | ||
|
|
7f8a82d9ba | ||
|
|
fd84fecaec | ||
|
|
f42e562e14 | ||
|
|
149140cad7 | ||
|
|
4cfe77786b | ||
|
|
5dae6793f2 | ||
|
|
b8a69d571a | ||
|
|
010edebc97 | ||
|
|
13c772be6e | ||
|
|
f98a1c5fd3 | ||
|
|
4cd83ee40a | ||
|
|
f3c5702a67 | ||
|
|
4954924a4c | ||
|
|
98e7a547af | ||
|
|
56a734bb1a | ||
|
|
2e3f14ea17 | ||
|
|
0b403e7a58 | ||
|
|
c2c77faa8c | ||
|
|
c49d7464fd | ||
|
|
24490316aa | ||
|
|
dfb24f6270 | ||
|
|
2b488c8308 | ||
|
|
e10b69e4fe | ||
|
|
a8e50fa8cc | ||
|
|
8e56002a55 | ||
|
|
b9eda20be5 | ||
|
|
a356c98ef3 | ||
|
|
a352a5f9ad | ||
|
|
2379f58695 | ||
|
|
d3b5902e23 | ||
|
|
922ade83b7 | ||
|
|
a1d88baad4 | ||
|
|
9a3aa287fd | ||
|
|
ebf615967c | ||
|
|
7023fc8c69 | ||
|
|
836e446d8b | ||
|
|
bc956a5d36 | ||
|
|
94d1cca7d4 | ||
|
|
250b732037 | ||
|
|
f33f341adb | ||
|
|
58316c2141 | ||
|
|
1f387fdd75 | ||
|
|
21b41da6e2 | ||
|
|
3eef19bb28 | ||
|
|
c0592b8ef4 | ||
|
|
c752d0a463 | ||
|
|
cd8a49ad18 | ||
|
|
fc1a9e7b3d | ||
|
|
f8c39b3cd4 | ||
|
|
01739e1519 | ||
|
|
51f9d7849f | ||
|
|
4ff589039a | ||
|
|
80e3cad985 | ||
|
|
3157b3297b | ||
|
|
935645a97e | ||
|
|
717239c086 | ||
|
|
514f9e0f58 | ||
|
|
f7cbefef82 | ||
|
|
ffdc36ef4e | ||
|
|
196633c670 | ||
|
|
8982313c71 | ||
|
|
76baac4f8c | ||
|
|
a6129174e5 | ||
|
|
5d23284412 | ||
|
|
07a03b76f3 | ||
|
|
974b6bfb14 | ||
|
|
c30d40d42b | ||
|
|
9ba64d156f | ||
|
|
9b5fb2ad78 | ||
|
|
593390a93d | ||
|
|
576357a4d4 | ||
|
|
9253fd1df8 | ||
|
|
9975fbd6cc | ||
|
|
18c24e29f6 | ||
|
|
5fbb10f98d | ||
|
|
ec59074ba6 | ||
|
|
084ed1064a | ||
|
|
de99799f14 | ||
|
|
fd0896f374 | ||
|
|
f0ad8cc351 | ||
|
|
444e7530e1 | ||
|
|
618e8b54b0 | ||
|
|
fcfe1d1d79 | ||
|
|
c465b190a0 | ||
|
|
9413b8d798 | ||
|
|
100634f883 | ||
|
|
24d11d565e | ||
|
|
21fa0293d6 | ||
|
|
56b6095f3b | ||
|
|
e64f0709af | ||
|
|
da76ef5d48 | ||
|
|
1cd391f0bc | ||
|
|
570b03bca4 | ||
|
|
19f258f351 | ||
|
|
04c4f04452 | ||
|
|
a9b4edf095 | ||
|
|
f5cfe810ef | ||
|
|
4a5d55bd7e | ||
|
|
9adba48b45 | ||
|
|
e9ce7f666a | ||
|
|
edcba93a3a | ||
|
|
877ad05014 | ||
|
|
012623b603 | ||
|
|
646e49e5b9 | ||
|
|
256301db76 | ||
|
|
df6d009bee | ||
|
|
33f61f3007 | ||
|
|
f9d1fc4945 | ||
|
|
9158fc6655 | ||
|
|
d8517c136e | ||
|
|
c9ba66b646 | ||
|
|
84b52da6e1 | ||
|
|
35c1a5973d | ||
|
|
0e3e910804 | ||
|
|
dd24468d48 | ||
|
|
4a1eafc312 | ||
|
|
85779bda74 | ||
|
|
9485906877 | ||
|
|
85ca2bc0dd | ||
|
|
2ab1b93e51 | ||
|
|
381e7cc659 | ||
|
|
7a4dff1301 | ||
|
|
6e1e0e1cd2 | ||
|
|
c33943f991 | ||
|
|
3065e22f8f | ||
|
|
57efb02eb6 | ||
|
|
05a24f5fda | ||
|
|
61919ba257 | ||
|
|
86e6050f60 | ||
|
|
bf4d61bb10 | ||
|
|
1843d4de60 | ||
|
|
a3904fef4c | ||
|
|
643a506496 | ||
|
|
bfed7a6680 | ||
|
|
054d232b6c | ||
|
|
b4be8c7433 | ||
|
|
06fccfd7af | ||
|
|
c418244065 | ||
|
|
fb119f08dd | ||
|
|
738004f6ec | ||
|
|
7cdf99b1f5 | ||
|
|
0c716c1cde | ||
|
|
b15b435913 | ||
|
|
e0f0157686 | ||
|
|
2894ed417a | ||
|
|
d908ae0e9e | ||
|
|
88d3bd6607 | ||
|
|
ee04924d42 | ||
|
|
6f27bf0c89 | ||
|
|
76ef050e55 | ||
|
|
eaa359df6b | ||
|
|
04e357869f | ||
|
|
915d700d67 | ||
|
|
77d214b705 | ||
|
|
0bd204d435 | ||
|
|
2db39f4504 | ||
|
|
d37afef047 | ||
|
|
a38101e448 | ||
|
|
e85aded32a | ||
|
|
d5254aa0d7 | ||
|
|
989fe72ddb | ||
|
|
9ad3c6cd4e | ||
|
|
41067b50fc | ||
|
|
a6490e8007 | ||
|
|
ba2264ed97 | ||
|
|
3072e46951 | ||
|
|
19fe5c9005 | ||
|
|
d9f9c66962 | ||
|
|
ec8a4254a9 | ||
|
|
8ee78f468d | ||
|
|
00234a1efd | ||
|
|
a3d54edf64 | ||
|
|
9ea208eaf0 | ||
|
|
6ab6c0632c | ||
|
|
6da937fe58 | ||
|
|
1d72b92b46 | ||
|
|
2d45364d7e | ||
|
|
b56a35171a | ||
|
|
194eacd637 | ||
|
|
8aa77da2b1 | ||
|
|
034f28a4f6 | ||
|
|
9cdec8e722 | ||
|
|
efa1c33c13 | ||
|
|
ecb22dfeee | ||
|
|
5ecfef0595 | ||
|
|
0b8624c6ac | ||
|
|
3709ffcefe | ||
|
|
8b49c6197c | ||
|
|
c8306cafc4 | ||
|
|
4a5178da93 | ||
|
|
5d7fed1259 | ||
|
|
116defca80 | ||
|
|
ddeccf3a34 | ||
|
|
65404dbba8 | ||
|
|
6130b4c260 | ||
|
|
08f122c910 | ||
|
|
97453f606e | ||
|
|
fe950520b4 | ||
|
|
a07b596168 | ||
|
|
d8083946f3 | ||
|
|
44b4412d53 | ||
|
|
55ef215f63 | ||
|
|
774fe348b5 | ||
|
|
584ac47a8a | ||
|
|
8159135dfd | ||
|
|
6ac97e7bf3 | ||
|
|
51ea254c82 | ||
|
|
eafadbfa05 | ||
|
|
a6cf47015c | ||
|
|
730714620d | ||
|
|
73dcae8d35 | ||
|
|
abb030f663 | ||
|
|
749c8a6144 | ||
|
|
9a1a5579bf | ||
|
|
47c0a1b682 | ||
|
|
5b743dea38 | ||
|
|
38b70b722c | ||
|
|
a6b19c1621 | ||
|
|
45d8f099ca | ||
|
|
15d9de633c | ||
|
|
b288e8ee43 | ||
|
|
4b25be2021 | ||
|
|
8549615cd0 | ||
|
|
822059724f | ||
|
|
c104a7b916 | ||
|
|
3a8641003e | ||
|
|
2424f52409 | ||
|
|
237fc3d163 | ||
|
|
21f33a1768 | ||
|
|
f706de00bb | ||
|
|
f3d4b8bdb3 | ||
|
|
48da5e410e | ||
|
|
e7b85e0138 | ||
|
|
c5027772aa | ||
|
|
63b60eee52 | ||
|
|
830f840b83 | ||
|
|
3d02793488 | ||
|
|
27d59cb442 | ||
|
|
1e0fc89d3a | ||
|
|
2316880678 | ||
|
|
e2da4a5108 | ||
|
|
331590cc36 | ||
|
|
874ed6f824 | ||
|
|
bea098d743 | ||
|
|
1fe9a2c398 | ||
|
|
6449f3fa78 | ||
|
|
1884f3158c | ||
|
|
9794a67ba6 | ||
|
|
6f74cd1662 | ||
|
|
f046307aa9 | ||
|
|
0edf614e5e | ||
|
|
eabf73aa4f | ||
|
|
3de1c312bb | ||
|
|
1c17d74ae1 | ||
|
|
134119db33 | ||
|
|
f6ce6d39e7 | ||
|
|
fc342f5734 | ||
|
|
52a8946996 | ||
|
|
22149e3dfd | ||
|
|
b9bdef1e30 | ||
|
|
efa56c97f2 | ||
|
|
a2a17fd24a | ||
|
|
66984e5b25 | ||
|
|
b5e1d45b20 | ||
|
|
4c309f1eef | ||
|
|
20dc046c75 | ||
|
|
d97c9dd6ec | ||
|
|
cd867dad7d | ||
|
|
2e57a02355 | ||
|
|
ef6b247b01 | ||
|
|
68429fd3b0 | ||
|
|
917ceced01 | ||
|
|
69a654f218 | ||
|
|
83d260fc0d | ||
|
|
79de05d54c | ||
|
|
be038f16ba | ||
|
|
4452820f09 | ||
|
|
133df33e35 | ||
|
|
47d5b9ac7f | ||
|
|
1be58489b0 | ||
|
|
cf72d81cd3 | ||
|
|
0b1cd9b7b1 | ||
|
|
f3ee78329b | ||
|
|
842553943a | ||
|
|
a00c0c1a0d | ||
|
|
30340bd6cf | ||
|
|
4372265ee2 | ||
|
|
e19528b20f | ||
|
|
893e93530d | ||
|
|
2fb198d941 | ||
|
|
b8890b0132 | ||
|
|
d3c322ca48 | ||
|
|
a3c4ba6e82 | ||
|
|
1c5db27de0 | ||
|
|
f34847adb1 | ||
|
|
b5b15b90e2 | ||
|
|
d3e486b6d5 | ||
|
|
ae50048039 | ||
|
|
a94fb20d4f | ||
|
|
5b9f651efe | ||
|
|
68ba887854 | ||
|
|
6983e7ebec | ||
|
|
2e1850c19b | ||
|
|
599380bd10 | ||
|
|
eb22574d20 | ||
|
|
1cbfc94fde | ||
|
|
4dc562bfe5 | ||
|
|
e89e61291a | ||
|
|
ad0284bd10 | ||
|
|
962cffac1d | ||
|
|
7892b38128 | ||
|
|
2761d5926b | ||
|
|
5a3f3d4cbe | ||
|
|
241658d3ba | ||
|
|
8054aedcb5 | ||
|
|
dbff927a63 | ||
|
|
52e9decf78 | ||
|
|
2dfce691ce | ||
|
|
c97b7cdf39 | ||
|
|
7225dcfa87 | ||
|
|
1a0e8f08f5 | ||
|
|
b201db2193 | ||
|
|
5140d7a6fa | ||
|
|
9cb7ef5930 | ||
|
|
4bf6b28c71 | ||
|
|
e2c40b91a1 | ||
|
|
8d6a5af6c8 | ||
|
|
4f99ce0c87 | ||
|
|
81c8bf1897 | ||
|
|
e465dc860b | ||
|
|
180dad1fe3 | ||
|
|
c1d14214ac | ||
|
|
4f19324605 | ||
|
|
ae421c7a15 | ||
|
|
b44d2ba1f9 | ||
|
|
a332b172b3 | ||
|
|
cd8b53c3f3 | ||
|
|
8282389078 | ||
|
|
2a5dd91588 | ||
|
|
09d21bef97 | ||
|
|
ac89acfbeb | ||
|
|
58f704112c | ||
|
|
5f24a7e1dc | ||
|
|
f643864e54 | ||
|
|
bd19ea587b | ||
|
|
538c115367 | ||
|
|
ea356d50e3 | ||
|
|
2c9f747259 | ||
|
|
15ba5e691f | ||
|
|
6b4a578ccc | ||
|
|
c3b72ca3a9 | ||
|
|
32d5cf7674 | ||
|
|
7cad6e874d | ||
|
|
a7387810b9 | ||
|
|
c5394b8b22 | ||
|
|
548c2b4e94 | ||
|
|
92a1179fee | ||
|
|
0f52e03f7b | ||
|
|
62e35386a5 | ||
|
|
15651ad162 | ||
|
|
cae7d9eb39 | ||
|
|
6ce723794d | ||
|
|
8018a94936 | ||
|
|
08466372b2 | ||
|
|
2667c79d70 | ||
|
|
4ade970e3f | ||
|
|
6afb5d9c2e | ||
|
|
ea7e05ba30 | ||
|
|
c3c42386d8 | ||
|
|
e874bfa228 | ||
|
|
3057cdd154 | ||
|
|
2e7765311c | ||
|
|
d06519bd49 | ||
|
|
1c1eae6e8e | ||
|
|
e32cecbfe4 | ||
|
|
200cc27da2 | ||
|
|
b656379683 | ||
|
|
7d818d0db4 | ||
|
|
2987754b98 | ||
|
|
1597bc6240 | ||
|
|
44ef835b7a | ||
|
|
905094be8b | ||
|
|
3def04d376 | ||
|
|
e159dd917b | ||
|
|
1861ea2a60 | ||
|
|
99c1ef6686 | ||
|
|
95596c23ff | ||
|
|
4baea1c92c | ||
|
|
e333f6ca2a | ||
|
|
295d996216 | ||
|
|
6ff7294c1e | ||
|
|
fed261182c | ||
|
|
9bff7ff2ae | ||
|
|
0e825a1df5 | ||
|
|
5226b0bb0a | ||
|
|
a1afb1e9c5 | ||
|
|
5ce761ead5 | ||
|
|
4f6b9e2082 | ||
|
|
397eb46e02 | ||
|
|
d74ba76649 | ||
|
|
2895aa265a | ||
|
|
b9f89bb7f2 | ||
|
|
2e6aed7e91 | ||
|
|
8476888778 | ||
|
|
856f335db3 | ||
|
|
ec84f598aa | ||
|
|
9e43596a76 | ||
|
|
eebb15e773 | ||
|
|
4282eb6221 | ||
|
|
f2ea795156 | ||
|
|
3e6b68932f | ||
|
|
1c754e35ab | ||
|
|
1cce8b6526 | ||
|
|
0ee9f8f3fa | ||
|
|
94b90d1fef | ||
|
|
30cfa326f2 | ||
|
|
cc122dd696 | ||
|
|
f0636b8805 | ||
|
|
917db4cc8b | ||
|
|
f3d47b0bb9 | ||
|
|
5ed37017b5 | ||
|
|
b3da8c3d7b | ||
|
|
c605a19368 | ||
|
|
70a8763f3b | ||
|
|
e0504e7320 | ||
|
|
aacedf75a9 | ||
|
|
f2faffb88f | ||
|
|
4d5f821e7a | ||
|
|
538a55d1a2 | ||
|
|
0b7f09d0d9 | ||
|
|
342de5f159 | ||
|
|
2c59e2959f | ||
|
|
3970467a7d | ||
|
|
464eb37a7d | ||
|
|
2151b77ef3 | ||
|
|
a691c0b7fa | ||
|
|
c0985f0f53 | ||
|
|
5aff9e1b93 | ||
|
|
c3507638c1 | ||
|
|
4a79ecce80 | ||
|
|
68b045848e | ||
|
|
f681936a59 | ||
|
|
cfe818b87b | ||
|
|
9d43d91da8 | ||
|
|
8867efa451 |
Vendored
+100
@@ -0,0 +1,100 @@
|
|||||||
|
-----------------------------------------------------------------
|
||||||
|
Changes in release 13
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
- mips_biu.vhd: added asynchronous BUS-FIFOs to support different clocks for CPU and BUS
|
||||||
|
- mips_dcache.vhd: improved instant-RAW stall behavior (faster execution)
|
||||||
|
- uart_WB.vhd: added simulate_TX generic for plain TX output in simulation log
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Changes in release 12
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
- reworked GCC-toolchain: Valid mips*-elf-binaries are now compiled and linked
|
||||||
|
using a single mips*-elf-gcc command.
|
||||||
|
To use: Copy $THIS_RELEASE/bsp/toolchain/specs to $MIPS_GCC_PREFIX/lib/gcc/mipsel-elf/$GCC_VERSION/,
|
||||||
|
and see bsp/examples/Makefile gcc usage
|
||||||
|
GCC-provided crt*-functions are now called without problems.
|
||||||
|
In summary: The toolchain is now more compliant to the intentional use of GCC.
|
||||||
|
- mips_biu.vhd: Addresses 0xA0000000..0xBFFFFFFF are now un-dcached for memory-mapped I/O,
|
||||||
|
which is now compliant to literature.
|
||||||
|
- gpio_wb.vhd: Timer hard-reset is now removed. This helps to keep current time in case of CPU hard-reset.
|
||||||
|
- new bsp-example source: gunzip
|
||||||
|
- updated drawing 'mips_jbus_timing.pdf'
|
||||||
|
- added drawing 'memory_map.pdf'
|
||||||
|
- moved COP0 from mips_pipeline.vhd to mips_top.vhd. Created new cop-interface for later COPz connection.
|
||||||
|
- added I/D-cache info (size and linesize) to upper 16 bits of PrID-Register.
|
||||||
|
Example of reading cache info is done in bsp/examples/testbench::PrintCPUinfo()
|
||||||
|
- simplified instruction decoder in mips_instr.vhd. Now there are less warnings during synthesis.
|
||||||
|
Removed idecode_rom.vhd from project as consequence.
|
||||||
|
- added cop0 instructions to invalidate I-cache and D-Cache
|
||||||
|
- added copz instructions lwcz and swcz
|
||||||
|
- gpio_wb.vhd: added 32 bit timer with interrupt and auto reload
|
||||||
|
- added debugger in libsys. New files are mipsdis.c/h and dbg.c/h
|
||||||
|
- exception handlers can now be registered to any exception type
|
||||||
|
- bugfix mips_pipeline/mips_cop: cop0 registers were not written during exception commit. Cop registers now behave like general registers.
|
||||||
|
- added pin 'eb' to mips_top.vhd to select CPU-endianess at reset time (eb = 0 : little-endian, eb = 1 : big-endian)
|
||||||
|
- Status register bit 'RE'= 1 (bit 25) reverses endianess in user-mode
|
||||||
|
- Status register bit 'TS' (TLB Shutdown, bit 21) is tied high to indicate the absence of an MMU.
|
||||||
|
- uart_wb.vhd: added interrupt enable
|
||||||
|
- Interrupt pending flags (IP) are not anymore masked by Interrupt mask flags (IM) in H/W.
|
||||||
|
Masking has to be done in S/W. H/W masking was removed because it isn't MIPS-compliant.
|
||||||
|
- added NMI/RST pin (more MIPS compliant). Transition Asserting/Deasserting causes exception.
|
||||||
|
Exception vector is reset (0xBFC00000). It's a soft-reset, which can help debugging. NMI/RST is not maskable.
|
||||||
|
Using NMI/RST as reset is dangerous because periphery may not be reseted. Has to be done in S/W.
|
||||||
|
Drawback of using NMI/RST: Unitialized/unreseted periphery may cause trouble (e.g. firing unwanted interrupts), but I think you know that already.
|
||||||
|
- Bootloader: Startup.S now invalidates I/D-Caches at boot.
|
||||||
|
- uart_wb.vhd: fixed crappy tx-empty interrupt, Added Tx-IRQ acknowledge.
|
||||||
|
- Bugfix in mips_pipeline: register bypass with same target register, used for unaligned loads (LWL, LWR), was incorrect.
|
||||||
|
Newlib's MIPS-optimized version of memcpy() uses this for unaligned copy which revealed the bug.
|
||||||
|
Symptom: Consecutive load instructions without nops using same target register (which is legal) like
|
||||||
|
lw $1, 0(mem)
|
||||||
|
lwl $1, 1(mem)
|
||||||
|
or
|
||||||
|
lwl $1, 0(mem)
|
||||||
|
lwr $1, 1(mem)
|
||||||
|
or similar, lead to incorrect result. Now it's fixed.
|
||||||
|
- Bugfix mips_biu: instructions uncached LW => cached LW (with cache-miss) was buggy.
|
||||||
|
Symptom:
|
||||||
|
...
|
||||||
|
1.: lw $a0, 32($s0) # Uncached load from memory mapped I/O
|
||||||
|
2.: lw $a2, 4($v0) # Cached load and cache-miss.
|
||||||
|
# $a0 receives same value as $a2.
|
||||||
|
# CPU skips writing $a0 due to busy flag of D-Cache,
|
||||||
|
# which is already active in the previous cycle
|
||||||
|
...
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Changes in release 11
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
- bugfix in mips_pipeline: pc_is_branch is now initialized at reset
|
||||||
|
(fixes CPU unrecoverable state after reset)
|
||||||
|
- reverted "optimization" in mips_dcache, which behaved buggy during exceptions
|
||||||
|
- new example source: test_exception
|
||||||
|
- minor changes in libsys
|
||||||
|
- added async_port_timing in doc
|
||||||
|
- examples/testbench: date set now really works
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Changes in release 10b
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
- bugfix: fixed compiler bug (missing nop after lw) in bootloader,
|
||||||
|
which caused exception during boot
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Changes in release 10a
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
async_port_wb:
|
||||||
|
- added byte enable for async_port
|
||||||
|
|
||||||
|
bootloader.c
|
||||||
|
- bugfix: fixed compiler bug (missing nop after lw)
|
||||||
|
|
||||||
|
mips-core
|
||||||
|
- bugfix: SEL_O lines are also asserted correctly during reads
|
||||||
|
|
||||||
|
tools/romgen
|
||||||
|
- TCL-Jtag now compatible with Chipscope 10.1
|
||||||
|
|
||||||
|
mips_sys.c
|
||||||
|
- use byte enable for sram and flash
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
-----------------------------------------------------------------
|
||||||
|
J-MIPS Features
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
|
||||||
|
- Synchrones Design
|
||||||
|
- Portable Beschreibung in VHDL
|
||||||
|
- Kompatible zur GNU Toolchain (Binutils, GCC, Newlib)
|
||||||
|
- Befehle kompatibel mit MIPS-1 ISA (z.B. MIPS R3000)
|
||||||
|
- 5-Stufige Pipeline und Hazardvermeidung durch Forwarding
|
||||||
|
- 64Bit Multiplier (32Bit Operanden), 12 Cycles Latenz
|
||||||
|
- 64Bit Divider (32Bit Operanden), 36 Cycles Latenz
|
||||||
|
- Coprocessor 0 (COP0) für Exceptionhandling
|
||||||
|
- Direct-mapped Instruction Cache mit variabler Größe, 8-words per Line
|
||||||
|
- Direct-mapped Data Cache mit variabler Größe, 8-words per Line
|
||||||
|
- J-Bus kompatible Bus Interface Unit (J-Bus ist im wesentlichen FIFO interface mit 'wichtigen' Signalnamen)
|
||||||
|
- 1,2 DMIPS/MHz mit 16Kbyte I/D-Cache (Dhrystone 2.1, GCC 4.3)
|
||||||
|
- Endianness umschaltbar zur Hard-reset Zeit
|
||||||
|
- Unterschiedliche Frequenzen für CPU und BUS möglich
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Known Limitations
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
- keine MMU
|
||||||
|
- keine Unterstützung für Bus exceptions IBE und DBE
|
||||||
|
- kein externes Coprocessor interface (COP1..3) für z.B. FPU
|
||||||
|
- Befehle für Cop1..3 nicht implementiert:
|
||||||
|
CFCz, CTCz, COPz, MFCz, MTCz, LWCz, SWCz
|
||||||
|
Benutzung dieser Befehle führt zur Exception 'RI' (Reserved Instruction)
|
||||||
|
- nicht alle COP0 Register/Bits vorhanden.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Known Bugs
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
- es gibt bestimmt noch nicht entdeckte Bugs
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Known Optimizations
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
- Area: Multiplier als technologieabhängiges Primitive instanzieren
|
||||||
|
- Area: Auf Divider verzichten
|
||||||
|
- Area: Auf Multiplier verzichten
|
||||||
|
- Area vs. Speed: Bei Hazards Pipeline-stall statt Forwarding.
|
||||||
|
Durch Stalling geringerer Befehlsdurchsatz dafür weniger Logik.
|
||||||
|
Weniger Logik bedeutet vielleicht wieder auch größere Taktfrequenz.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Known ToDos
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
- Unterstützung für Bus exceptions IBE und DBE
|
||||||
|
- Externes COP1..3 interface, fehlende COP-Befehle implementieren
|
||||||
|
- Optimierungen evaluieren und ggf. durchführen
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Synthesis results
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Virtex-4 XC4VSX35-10
|
||||||
|
|
||||||
|
Config: 16Kbyte I/D-Cache
|
||||||
|
|
||||||
|
Number of Slices 2387 15360 15%
|
||||||
|
Number of Slice Flip Flops 1784 30720 5%
|
||||||
|
Number of 4 input LUTs 3962 30720 12%
|
||||||
|
Number of FIFO16/RAMB16s 18 192 9%
|
||||||
|
|
||||||
|
Speed: 110MHz nach Synthesis
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Virtex-1 XCV1000-4
|
||||||
|
|
||||||
|
Config: 4Kbyte I/D-Cache
|
||||||
|
|
||||||
|
Number of Slices 2045 13824 16%
|
||||||
|
Number of Slice Flip Flops 1783 27648 7%
|
||||||
|
Number of 4 input LUTs 3923 27648 15%
|
||||||
|
Number of FIFO16/RAMB16s 20 32 62%
|
||||||
|
|
||||||
|
Speed: 30MHz nach Synthesis
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Performance bei 100MHz
|
||||||
|
- GCC ohne Small-data section
|
||||||
|
- MIPS Rev. 9
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
I/D-Cache Dhrystone-2.1 RipeMD-160 Whetstone Stanford Queens(12x12)
|
||||||
|
1k 32 DMIPS 5 Mbit/s 345 kwhets/s 47/767 2,135s
|
||||||
|
2k 51 DMIPS 5 Mbit/s 534 kwhets/s 38/561 2,134s
|
||||||
|
4k 72 DMIPS 5 Mbit/s 623 kwhets/s 36/259 2,121s
|
||||||
|
8k 98 DMIPS 10 Mbit/s 1149 kwhets/s 31/228 1,938s
|
||||||
|
16k 115 DMIPS 17 Mbit/s 1234 kwhets/s 23/225 1,938s
|
||||||
|
32k 115 DMIPS 17 Mbit/s 1285 kwhets/s 24/218 1,938s
|
||||||
|
64k 115 DMIPS 17 Mbit/s 1285 kwhets/s 20/221 1,938s
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Performance bei 100MHz
|
||||||
|
- GCC mit Small-data section
|
||||||
|
- MIPS Rev. 9
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
I/D-Cache Dhrystone-2.1 RipeMD-160 Whetstone Stanford Queens(12x12)
|
||||||
|
16k 117 DMIPS 17 Mbit/s 1236 kwhets/s 24/230 1,811s
|
||||||
|
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
Performance bei 100MHz
|
||||||
|
- GCC mit Small-data section
|
||||||
|
- MIPS Rev. 10
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
I/D-Cache Dhrystone-2.1 RipeMD-160 Whetstone Stanford Queens(12x12)
|
||||||
|
16k 120 DMIPS 17 Mbit/s 1242 kwhets/s 25/219 1,803s
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,46 @@
|
|||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 1. Binutils bauen und installieren
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
> tar -xzf binutils-2.19.tar.gz
|
||||||
|
> mkdir binutils-2.19_build
|
||||||
|
> cd binutils-2.19_build
|
||||||
|
|
||||||
|
> ../binutils-2.19/configure --target=mipsel-elf --prefix=/usr/local
|
||||||
|
> make
|
||||||
|
> make install
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 2. GCC bootstrapping
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
> tar -xzf gcc-4.3.2.tar.gz
|
||||||
|
> mkdir gcc-4.3.2_build
|
||||||
|
> cd gcc-4.3.2_build
|
||||||
|
> ../gcc-4.3.2/configure --target=mipsel-elf --prefix=/usr/local --enable-languages="c,c++" --without-headers --with-newlib --with-float=soft --disable-multilib
|
||||||
|
> CFLAGS_FOR_TARGET="-mno-gpopt" make all-gcc
|
||||||
|
> make info-gcc
|
||||||
|
> make install-gcc
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 3. Newlib bauen und installieren
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
> tar -xzf newlib-1.16.0.tar.gz
|
||||||
|
! Bug in newlib-1.16.0/newlib/libc/machine/mips/strlen.c.
|
||||||
|
Newlib von Hand patchen (32-bit MIPS targets):
|
||||||
|
"lbu $3,0($4)\n"
|
||||||
|
"nop\n" <= nop einfügen
|
||||||
|
"bnez $3,1b\n"
|
||||||
|
|
||||||
|
> mkdir newlib-1.16.0_build
|
||||||
|
> cd newlib-1.16.0_build
|
||||||
|
> ../newlib-1.16.0/configure --target=mipsel-elf --prefix=/usr/local --with-float=soft --disable-multilib
|
||||||
|
> TARGET_CFLAGS="-mno-gpopt" make all
|
||||||
|
> make install
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 4. GCC bauen und installieren
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
> cd gcc-4.3.2_build
|
||||||
|
> ../gcc-4.3.2/configure --target=mipsel-elf --prefix=/usr/local --enable-languages="c,c++" --disable-shared --with-newlib --with-float=soft --disable-multilib
|
||||||
|
> CFLAGS_FOR_TARGET="-mno-gpopt" make all
|
||||||
|
> make info
|
||||||
|
> make install
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
TARGET=mipsel-elf
|
||||||
|
PREFIX=/usr/local
|
||||||
|
|
||||||
|
SRC_BINUTILS=binutils-2.19
|
||||||
|
SRC_GCC=gcc-4.3.3
|
||||||
|
SRC_NEWLIB=newlib-1.16.0
|
||||||
|
SRC_GMP=gmp-4.2.4
|
||||||
|
SRC_MPFR=mpfr-2.4.0
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 1. Binutils bauen und installieren
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
if [ ! -e $SRC_BINUTILS.tar.bz2 ]; then
|
||||||
|
echo Downloading $SRC_BINUTILS
|
||||||
|
wget ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/binutils/$SRC_BINUTILS.tar.bz2 || exit 1
|
||||||
|
else
|
||||||
|
echo Skipped downloading $SRC_BINUTILS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ./$SRC_BINUTILS ]; then
|
||||||
|
echo Unpacking $SRC_BINUTILS
|
||||||
|
tar -xjf $SRC_BINUTILS.tar.bz2 || exit 1
|
||||||
|
else
|
||||||
|
echo Skipped unpacking $SRC_BINUTILS
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ./$SRC_BINUTILS-build ]; then
|
||||||
|
echo Building $SRC_BINUTILS
|
||||||
|
mkdir -p $SRC_BINUTILS-build
|
||||||
|
cd $SRC_BINUTILS-build
|
||||||
|
../$SRC_BINUTILS/configure --target=$TARGET --prefix=$PREFIX || exit 1
|
||||||
|
make || exit 1
|
||||||
|
make install || exit 1
|
||||||
|
cd ..
|
||||||
|
else
|
||||||
|
echo $SRC_BINUTILS is already built.
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 2. GMP bauen und installieren
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
if [ ! -e $SRC_GMP.tar.bz2 ]; then
|
||||||
|
echo Downloading $SRC_GMP
|
||||||
|
wget http://ftp.sunet.se/pub/gnu/gmp/$SRC_GMP.tar.bz2 || exit 1
|
||||||
|
else
|
||||||
|
echo Skipped downloading $SRC_GMP
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ./$SRC_GMP ]; then
|
||||||
|
echo Unpacking $SRC_GMP
|
||||||
|
tar -xjf $SRC_GMP.tar.bz2 || exit 1
|
||||||
|
else
|
||||||
|
echo Skipped unpacking $SRC_GMP
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ./$SRC_GMP-build ]; then
|
||||||
|
echo Building $SRC_GMP
|
||||||
|
mkdir -p $SRC_GMP-build
|
||||||
|
cd $SRC_GMP-build
|
||||||
|
../$SRC_GMP/configure --prefix=$PREFIX || exit 1
|
||||||
|
make || exit 1
|
||||||
|
make check || exit 1
|
||||||
|
make install || exit 1
|
||||||
|
cd ..
|
||||||
|
else
|
||||||
|
echo $SRC_GMP is already built.
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 3. MPFR bauen und installieren
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
if [ ! -e $SRC_MPFR.tar.bz2 ]; then
|
||||||
|
echo Downloading $SRC_MPFR
|
||||||
|
wget http://www.mpfr.org/mpfr-current/$SRC_MPFR.tar.bz2 || exit 1
|
||||||
|
else
|
||||||
|
echo Skipped downloading $SRC_MPFR
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ./$SRC_MPFR ]; then
|
||||||
|
echo Unpacking $SRC_MPFR
|
||||||
|
tar -xjf $SRC_MPFR.tar.bz2 || exit 1
|
||||||
|
else
|
||||||
|
echo Skipped unpacking $SRC_MPFR
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ./$SRC_MPFR-build ]; then
|
||||||
|
echo Building $SRC_MPFR
|
||||||
|
mkdir -p $SRC_MPFR-build
|
||||||
|
cd $SRC_MPFR-build
|
||||||
|
../$SRC_MPFR/configure --prefix=$PREFIX || exit 1
|
||||||
|
make || exit 1
|
||||||
|
make check || exit 1
|
||||||
|
make install || exit 1
|
||||||
|
cd ..
|
||||||
|
else
|
||||||
|
echo $SRC_MPFR is already built.
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# 4. GCC & newlib bauen und installieren
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
if [ ! -e $SRC_NEWLIB.tar.gz ]; then
|
||||||
|
echo Downloading $SRC_NEWLIB
|
||||||
|
wget ftp://sources.redhat.com/pub/newlib/$SRC_NEWLIB.tar.gz || exit 1
|
||||||
|
else
|
||||||
|
echo Skipped downloading $SRC_NEWLIB
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ./$SRC_NEWLIB ]; then
|
||||||
|
echo Unpacking $SRC_NEWLIB
|
||||||
|
tar -xzf $SRC_NEWLIB.tar.gz || exit 1
|
||||||
|
if [ -e $SRC_NEWLIB-jens.patch ]; then
|
||||||
|
echo Patching $SRC_NEWLIB
|
||||||
|
patch -p0 < $SRC_NEWLIB-jens.patch || exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo Skipped unpacking $SRC_NEWLIB
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e $SRC_GCC.tar.bz2 ]; then
|
||||||
|
echo Downloading $SRC_GCC
|
||||||
|
wget ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/gcc/$SRC_GCC/$SRC_GCC.tar.bz2 || exit 1
|
||||||
|
else
|
||||||
|
echo Skipped downloading $SRC_GCC
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ./$SRC_GCC ]; then
|
||||||
|
echo Unpacking $SRC_GCC
|
||||||
|
tar -xjf $SRC_GCC.tar.bz2 || exit 1
|
||||||
|
cd ./$SRC_GCC
|
||||||
|
ln -sf ../$SRC_NEWLIB/newlib/ .
|
||||||
|
cd ..
|
||||||
|
else
|
||||||
|
echo Skipped unpacking $SRC_GCC
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ./$SRC_GCC-build ]; then
|
||||||
|
echo Building $SRC_GCC
|
||||||
|
mkdir -p $SRC_GCC-build
|
||||||
|
cd $SRC_GCC-build
|
||||||
|
../$SRC_GCC/configure --target=$TARGET --prefix=$PREFIX --with-float=soft --with-newlib --verbose --enable-languages="c,c++" || exit 1
|
||||||
|
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PREFIX/lib make all || exit 1
|
||||||
|
make info || exit 1
|
||||||
|
make install || exit 1
|
||||||
|
cd ..
|
||||||
|
echo $PREFIX/lib >/etc/ld.so.conf.d/local.conf
|
||||||
|
ldconfig
|
||||||
|
else
|
||||||
|
echo $SRC_GCC is already built.
|
||||||
|
fi
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
diff -Naur newlib-1.16.0/newlib/libc/machine/mips/strlen.c newlib-1.16.0-fixed/newlib/libc/machine/mips/strlen.c
|
||||||
|
--- newlib-1.16.0/newlib/libc/machine/mips/strlen.c 2002-03-14 03:41:43.000000000 +0100
|
||||||
|
+++ newlib-1.16.0-fixed/newlib/libc/machine/mips/strlen.c 2009-02-14 15:52:58.000000000 +0100
|
||||||
|
@@ -60,6 +60,7 @@
|
||||||
|
" addiu $2,$4,1\n"
|
||||||
|
"\n"
|
||||||
|
"1: lbu $3,0($4)\n"
|
||||||
|
+ " nop\n"
|
||||||
|
" bnez $3,1b\n"
|
||||||
|
" addiu $4,$4,1\n"
|
||||||
|
"\n"
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
diff -Naur newlib-1.17.0/newlib/libc/machine/mips/strlen.c newlib-1.17.0-fixed/newlib/libc/machine/mips/strlen.c
|
||||||
|
--- newlib-1.17.0/newlib/libc/machine/mips/strlen.c 2002-03-14 03:41:43.000000000 +0100
|
||||||
|
+++ newlib-1.17.0-fixed/newlib/libc/machine/mips/strlen.c 2009-02-14 15:45:19.000000000 +0100
|
||||||
|
@@ -60,6 +60,7 @@
|
||||||
|
" addiu $2,$4,1\n"
|
||||||
|
"\n"
|
||||||
|
"1: lbu $3,0($4)\n"
|
||||||
|
+ " nop\n"
|
||||||
|
" bnez $3,1b\n"
|
||||||
|
" addiu $4,$4,1\n"
|
||||||
|
"\n"
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,15 +0,0 @@
|
|||||||
## NOTE: Do not edit this file.
|
|
||||||
##
|
|
||||||
vlib work
|
|
||||||
vcom -explicit -93 "../../../PCK_FIO-1.16/PCK_FIO.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_types.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_instr.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_muldiv.vhd"
|
|
||||||
vcom -explicit -93 "../src/tb_mips_muldiv.vhd"
|
|
||||||
vsim -t 1ps -lib work tb_mips_muldiv
|
|
||||||
do {tb_mips_muldiv.wdo}
|
|
||||||
view wave
|
|
||||||
|
|
||||||
view structure
|
|
||||||
view signals
|
|
||||||
run 8ms
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
onerror {resume}
|
|
||||||
quietly WaveActivateNextPane {} 0
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/rst
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/clk
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/mul_divn
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/start
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/busy
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/s_un
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/ref_hi
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/din_hi
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/din_lo
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/hilo_sel
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/hilo_we
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/dout
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/ref_result
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/md_result
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/check
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/uut/pre_sum_vld
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/uut/mul_en
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/uut/sum_en
|
|
||||||
add wave -noupdate -divider FSM
|
|
||||||
add wave -noupdate -format Literal /tb_mips_muldiv/uut/cycle_cnt
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/uut/cycle_cnt_load
|
|
||||||
add wave -noupdate -format Literal /tb_mips_muldiv/uut/cycle_cnt_preset
|
|
||||||
add wave -noupdate -format Literal /tb_mips_muldiv/uut/s
|
|
||||||
add wave -noupdate -format Literal /tb_mips_muldiv/uut/sn
|
|
||||||
add wave -noupdate -divider {Multiplier internals}
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_mips_muldiv/uut/pprod
|
|
||||||
add wave -noupdate -format Literal /tb_mips_muldiv/uut/ppadd_cyi
|
|
||||||
add wave -noupdate -format Literal /tb_mips_muldiv/uut/ppadd_cyo
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/ppadd_op1
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/ppadd_op2
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/ppadd_res
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/pp_op2
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/pp_op2_r
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/add_op1
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/add_op2
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/add_res
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/pp_reg
|
|
||||||
add wave -noupdate -divider {Divider internals}
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/busy
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/s_un
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/uut/div_start
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/din_hi
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/din_lo
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/result
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/uut/div_add_cyi
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_add_op1
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_add_op2
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_add_res
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_m
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_m_n
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_a
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_muldiv/uut/div_q
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/uut/div_qbit
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/uut/div_en
|
|
||||||
add wave -noupdate -divider FSM
|
|
||||||
add wave -noupdate -format Literal /tb_mips_muldiv/uut/cycle_cnt
|
|
||||||
add wave -noupdate -format Logic /tb_mips_muldiv/uut/cycle_cnt_load
|
|
||||||
add wave -noupdate -format Literal /tb_mips_muldiv/uut/cycle_cnt_preset
|
|
||||||
add wave -noupdate -format Literal /tb_mips_muldiv/uut/s
|
|
||||||
add wave -noupdate -format Literal /tb_mips_muldiv/uut/sn
|
|
||||||
TreeUpdate [SetDefaultTree]
|
|
||||||
WaveRestoreCursors {{Cursor 1} {7735999838 ps} 0} {{Cursor 2} {512321 ps} 0}
|
|
||||||
configure wave -namecolwidth 149
|
|
||||||
configure wave -valuecolwidth 171
|
|
||||||
configure wave -justifyvalue left
|
|
||||||
configure wave -signalnamewidth 1
|
|
||||||
configure wave -snapdistance 10
|
|
||||||
configure wave -datasetprefix 0
|
|
||||||
configure wave -rowmargin 4
|
|
||||||
configure wave -childrowmargin 2
|
|
||||||
configure wave -gridoffset 0
|
|
||||||
configure wave -gridperiod 100
|
|
||||||
configure wave -griddelta 40
|
|
||||||
configure wave -timeline 1
|
|
||||||
update
|
|
||||||
WaveRestoreZoom {0 ps} {8400 us}
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
vlib work
|
||||||
|
vcom -explicit -93 "../src/dpram_2w2r.vhd"
|
||||||
|
vcom -explicit -93 "../src/dpram_1w1r.vhd"
|
||||||
|
vcom -explicit -93 "../src/fifo_ctrl_pkg.vhd"
|
||||||
|
vcom -explicit -93 "../src/gray_counter.vhd"
|
||||||
|
vcom -explicit -93 "../src/fifo_sync_ctrl.vhd"
|
||||||
|
vcom -explicit -93 "../src/fifo_sync.vhd"
|
||||||
|
vcom -explicit -93 "../src/fifo_async_ctrl.vhd"
|
||||||
|
vcom -explicit -93 "../src/fifo_async.vhd"
|
||||||
|
vcom -explicit -93 "../src/bbfifo_16x8.vhd"
|
||||||
|
vcom -explicit -93 "../src/kcuart_rx.vhd"
|
||||||
|
vcom -explicit -93 "../src/kcuart_tx.vhd"
|
||||||
|
vcom -explicit -93 "../src/uart_rx.vhd"
|
||||||
|
vcom -explicit -93 "../src/uart_tx.vhd"
|
||||||
|
vcom -explicit -93 "../src/uart_wb.vhd"
|
||||||
|
vcom -explicit -93 "../src/gpio_wb.vhd"
|
||||||
|
vcom -explicit -93 "../src/async_types.vhd"
|
||||||
|
vcom -explicit -93 "../src/async_port_wb.vhd"
|
||||||
|
vcom -explicit -93 "../src/async_defs.vhd"
|
||||||
|
vcom -explicit -93 "../src/bootloader.ROM.vhd"
|
||||||
|
vcom -explicit -93 "../src/rom_wb.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_types.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_instr.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_reg.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_shifter.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_alu.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_muldiv.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_cop.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_icache.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_dcache.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_biu.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_bcu.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_pipeline.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_top.vhd"
|
||||||
|
vcom -explicit -93 "../src/mips_sys.vhd"
|
||||||
|
vcom -explicit -93 "../src/tb_mips_sys.vhd"
|
||||||
|
vsim -t 1ps -lib work tb_mips_sys
|
||||||
|
do {tb_mips_sys.wdo}
|
||||||
|
view wave
|
||||||
|
view structure
|
||||||
|
view signals
|
||||||
|
run 3000us
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
onerror {resume}
|
||||||
|
quietly WaveActivateNextPane {} 0
|
||||||
|
add wave -noupdate -divider {MIPS top}
|
||||||
|
add wave -noupdate -format Literal /tb_mips_sys/debug
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/rst
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/clk
|
||||||
|
add wave -noupdate -divider Flash
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/clk
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/flash_cs_n
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/flash_oe_n
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/flash_a
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/flash_d
|
||||||
|
add wave -noupdate -divider SRAM
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/clk
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/sram_cs_n
|
||||||
|
add wave -noupdate -format Literal /tb_mips_sys/sram_wr_n
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/sram_oe_n
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/sram_a
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/sram_d
|
||||||
|
add wave -noupdate -divider GPIO
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/clk
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/gpo0
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/gpo1
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/gpi0
|
||||||
|
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_sys/gpi1
|
||||||
|
add wave -noupdate -divider UART
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/clk
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/rx
|
||||||
|
add wave -noupdate -format Logic /tb_mips_sys/tx
|
||||||
|
TreeUpdate [SetDefaultTree]
|
||||||
|
WaveRestoreCursors {{Cursor 1} {1165707237 ps} 0}
|
||||||
|
configure wave -namecolwidth 150
|
||||||
|
configure wave -valuecolwidth 100
|
||||||
|
configure wave -justifyvalue left
|
||||||
|
configure wave -signalnamewidth 1
|
||||||
|
configure wave -snapdistance 10
|
||||||
|
configure wave -datasetprefix 0
|
||||||
|
configure wave -rowmargin 4
|
||||||
|
configure wave -childrowmargin 2
|
||||||
|
configure wave -gridoffset 0
|
||||||
|
configure wave -gridperiod 100
|
||||||
|
configure wave -griddelta 40
|
||||||
|
configure wave -timeline 1
|
||||||
|
update
|
||||||
|
WaveRestoreZoom {0 ps} {3150 us}
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
## NOTE: Do not edit this file.
|
|
||||||
##
|
|
||||||
vlib work
|
|
||||||
|
|
||||||
# RAMS
|
|
||||||
vcom -explicit -93 "../../../misc/dpram_2w2r.vhd"
|
|
||||||
vcom -explicit -93 "../../../misc/dpram_1w1r.vhd"
|
|
||||||
vcom -explicit -93 "../../../misc/dpram_1w1r_dist.vhd"
|
|
||||||
|
|
||||||
# FIFOS
|
|
||||||
vcom -explicit -93 "../../../FIFO/src/fifo_ctrl_pkg.vhd"
|
|
||||||
vcom -explicit -93 "../../../FIFO/src/sync_fifo_ctrl.vhd"
|
|
||||||
vcom -explicit -93 "../../../FIFO/src/fifo_sync_dist.vhd"
|
|
||||||
|
|
||||||
# UART
|
|
||||||
vcom -explicit -93 "../../../uart/bbfifo_16x8.vhd"
|
|
||||||
vcom -explicit -93 "../../../uart/kcuart_rx.vhd"
|
|
||||||
vcom -explicit -93 "../../../uart/kcuart_tx.vhd"
|
|
||||||
vcom -explicit -93 "../../../uart/uart_rx.vhd"
|
|
||||||
vcom -explicit -93 "../../../uart/uart_tx.vhd"
|
|
||||||
vcom -explicit -93 "../../../uart/uart_wb.vhd"
|
|
||||||
|
|
||||||
# GPIO
|
|
||||||
vcom -explicit -93 "../../../misc/gpio_wb.vhd"
|
|
||||||
|
|
||||||
# Async port
|
|
||||||
vcom -explicit -93 "../../../misc/async_types.vhd"
|
|
||||||
vcom -explicit -93 "../../../misc/async_port_wb.vhd"
|
|
||||||
vcom -explicit -93 "../src/async_defs.vhd"
|
|
||||||
|
|
||||||
# ROM
|
|
||||||
vcom -explicit -93 "../src/bootloader.ROM.vhd"
|
|
||||||
vcom -explicit -93 "../../../misc/rom_wb.vhd"
|
|
||||||
|
|
||||||
# MIPS
|
|
||||||
vcom -explicit -93 "../src/core/mips_types.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_instr.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_idecode_rom.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_reg.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_shifter.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_alu.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_muldiv.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_cop.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_icache.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_dcache.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_biu.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_bcu.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_pipeline.vhd"
|
|
||||||
vcom -explicit -93 "../src/core/mips_top.vhd"
|
|
||||||
|
|
||||||
vcom -explicit -93 "../src/tb_mips_top.vhd"
|
|
||||||
vsim -t 1ps -lib work tb_mips_top
|
|
||||||
do {tb_mips_top.wdo}
|
|
||||||
view wave
|
|
||||||
view structure
|
|
||||||
view signals
|
|
||||||
run 1600us
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
onerror {resume}
|
|
||||||
quietly WaveActivateNextPane {} 0
|
|
||||||
add wave -noupdate -divider {TOP interface}
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/clk
|
|
||||||
add wave -noupdate -format Literal /tb_mips_top/debug
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/stb_o
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/ack_i
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/srdy_i
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/addr_o
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/dat_i
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/dat_o
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/we_o
|
|
||||||
add wave -noupdate -format Literal /tb_mips_top/sel_o
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/cyc_o
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/mrdy_o
|
|
||||||
add wave -noupdate -format Literal /tb_mips_top/int
|
|
||||||
add wave -noupdate -divider {External components}
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/clk
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/gpo0
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/gpo1
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/gpi0
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/gpi1
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/clk
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/rx
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/tx
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/clk
|
|
||||||
add wave -noupdate -format Literal /tb_mips_top/mem_area
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/sram_a
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/sram_d
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/flash_a
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/flash_d
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/flash_cs_n
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/flash_oe_n
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/sram_cs_n
|
|
||||||
add wave -noupdate -format Literal /tb_mips_top/sram_wr_n
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/sram_oe_n
|
|
||||||
add wave -noupdate -divider ALU
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/clk
|
|
||||||
add wave -noupdate -format Literal /tb_mips_top/uut/inst_pipeline/hdu
|
|
||||||
add wave -noupdate -divider PC
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/clk
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal /tb_mips_top/uut/inst_pipeline/pc
|
|
||||||
add wave -noupdate -divider PC
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/clk
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_mips_top/uut/inst_pipeline/id_stage
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/clk
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_mips_top/uut/inst_pipeline/ex_stage
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/clk
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_mips_top/uut/inst_pipeline/mem_stage
|
|
||||||
add wave -noupdate -format Logic /tb_mips_top/clk
|
|
||||||
add wave -noupdate -format Literal -radix hexadecimal -expand /tb_mips_top/uut/inst_pipeline/wb_stage
|
|
||||||
TreeUpdate [SetDefaultTree]
|
|
||||||
WaveRestoreCursors {{Cursor 1} {1199854590 ps} 0}
|
|
||||||
configure wave -namecolwidth 188
|
|
||||||
configure wave -valuecolwidth 100
|
|
||||||
configure wave -justifyvalue left
|
|
||||||
configure wave -signalnamewidth 1
|
|
||||||
configure wave -snapdistance 10
|
|
||||||
configure wave -datasetprefix 0
|
|
||||||
configure wave -rowmargin 4
|
|
||||||
configure wave -childrowmargin 2
|
|
||||||
configure wave -gridoffset 0
|
|
||||||
configure wave -gridperiod 100
|
|
||||||
configure wave -griddelta 40
|
|
||||||
configure wave -timeline 1
|
|
||||||
update
|
|
||||||
WaveRestoreZoom {0 ps} {1260 us}
|
|
||||||
@@ -31,29 +31,37 @@ package async_defs is
|
|||||||
|
|
||||||
constant ts_flash : async_timespec_t :=
|
constant ts_flash : async_timespec_t :=
|
||||||
(
|
(
|
||||||
ncyc_access => 1,
|
T_leadin => 00.0,
|
||||||
ncyc_pulse_rd => 12,
|
T_pulse_rd => 120.0,
|
||||||
ncyc_pulse_wr => 7,
|
T_pulse_wr => 70.0,
|
||||||
ncyc_cs_hold => 1,
|
T_leadout => 00.0,
|
||||||
ncyc_release => 1,
|
T_release => 40.0,
|
||||||
ncyc_pulse_rst => 8,
|
T_pulse_rst => 80.0,
|
||||||
|
T_pulse_page_rd => 30.0,
|
||||||
|
can_page_rd => true,
|
||||||
|
nbits_page_rd => 4,
|
||||||
pol_cs => '0',
|
pol_cs => '0',
|
||||||
pol_oe => '0',
|
pol_oe => '0',
|
||||||
pol_we => '0',
|
pol_we => '0',
|
||||||
|
pol_be => '0',
|
||||||
pol_rst => '0'
|
pol_rst => '0'
|
||||||
);
|
);
|
||||||
|
|
||||||
constant ts_sram : async_timespec_t :=
|
constant ts_sram : async_timespec_t :=
|
||||||
(
|
(
|
||||||
ncyc_access => 1,
|
T_leadin => 00.0,
|
||||||
ncyc_pulse_rd => 12,
|
T_pulse_rd => 10.0,
|
||||||
ncyc_pulse_wr => 7,
|
T_pulse_wr => 10.0,
|
||||||
ncyc_cs_hold => 1,
|
T_leadout => 00.0,
|
||||||
ncyc_release => 1,
|
T_release => 00.0,
|
||||||
ncyc_pulse_rst => 8,
|
T_pulse_rst => 80.0,
|
||||||
|
T_pulse_page_rd => 20.0,
|
||||||
|
can_page_rd => false,
|
||||||
|
nbits_page_rd => 5,
|
||||||
pol_cs => '0',
|
pol_cs => '0',
|
||||||
pol_oe => '0',
|
pol_oe => '0',
|
||||||
pol_we => '0',
|
pol_we => '0',
|
||||||
|
pol_be => '0',
|
||||||
pol_rst => '0'
|
pol_rst => '0'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+1444
-1444
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
|||||||
|
VHDL/lib/CPUs/MIPS/src/core/dcache.vhd
|
||||||
|
VHDL/lib/CPUs/MIPS/src/core/mips_dcache.vhd
|
||||||
|
VHDL/lib/CPUs/MIPS/src/core/icache.vhd
|
||||||
|
VHDL/lib/CPUs/MIPS/src/core/mips_icache.vhd
|
||||||
|
VHDL/lib/CPUs/MIPS/src/core/mips_biu.vhd
|
||||||
|
|
||||||
|
VHDL/lib/CPUs/MIPS/src/core/mips_bui.vhd
|
||||||
|
VHDL/lib/CPUs/MIPS/src/core/mips_biu.vhd
|
||||||
|
VHDL/lib/CPUs/MIPS/src/core/mips_dcache.vhd
|
||||||
|
|
||||||
|
VHDL/lib/CPUs/MIPS/src/core/mips_icache.vhd
|
||||||
|
|
||||||
+281
-181
@@ -1,7 +1,29 @@
|
|||||||
|
--------------------------------------------------------------------------
|
||||||
|
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||||
|
-- This file: JIPS top file
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2008 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
LIBRARY IEEE;
|
LIBRARY IEEE;
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
use IEEE.MATH_REAL.ALL;
|
|
||||||
|
|
||||||
library work;
|
library work;
|
||||||
use work.mips_types.all;
|
use work.mips_types.all;
|
||||||
@@ -18,11 +40,12 @@ ENTITY dcache IS
|
|||||||
CLK_I : in STD_LOGIC;
|
CLK_I : in STD_LOGIC;
|
||||||
ACK_I : in STD_LOGIC;
|
ACK_I : in STD_LOGIC;
|
||||||
SRDY_I : in STD_LOGIC;
|
SRDY_I : in STD_LOGIC;
|
||||||
|
MRDY_O : out STD_LOGIC;
|
||||||
ADDR_O : out word_t;
|
ADDR_O : out word_t;
|
||||||
DAT_I : in word_t;
|
DAT_I : in word_t;
|
||||||
STB_O : out STD_LOGIC;
|
STB_O : out STD_LOGIC;
|
||||||
CYC_O : out STD_LOGIC;
|
CYC_O : out STD_LOGIC;
|
||||||
en : in STD_LOGIC;
|
ctrl : in cache_ctrl_t;
|
||||||
cpu_en : in STD_LOGIC;
|
cpu_en : in STD_LOGIC;
|
||||||
cpu_we : in STD_LOGIC;
|
cpu_we : in STD_LOGIC;
|
||||||
cpu_be : in unsigned(3 downto 0);
|
cpu_be : in unsigned(3 downto 0);
|
||||||
@@ -77,25 +100,15 @@ COMPONENT dpram_2w2r is
|
|||||||
);
|
);
|
||||||
END COMPONENT;
|
END COMPONENT;
|
||||||
|
|
||||||
function lg2(x : natural) return natural is
|
constant addr_width : natural := 32;
|
||||||
begin
|
|
||||||
return natural(ceil(log2(real(x))));
|
|
||||||
end lg2;
|
|
||||||
|
|
||||||
function po2(x : natural) return natural is
|
|
||||||
begin
|
|
||||||
|
|
||||||
return 2**lg2(x);
|
|
||||||
end po2;
|
|
||||||
|
|
||||||
constant word_index_width : natural := lg2(line_size);
|
constant word_index_width : natural := lg2(line_size);
|
||||||
constant cache_index_width : natural := lg2(cache_size) - word_index_width;
|
constant cache_index_width : natural := lg2(cache_size) - word_index_width;
|
||||||
constant tag_width : natural := 32 - word_index_width - cache_index_width - 2;
|
constant tag_width : natural := addr_width - word_index_width - cache_index_width - 2;
|
||||||
constant tag_parity_width : natural := 3;
|
constant tag_parity_width : natural := 3;
|
||||||
constant tram_data_width : natural := 1 + tag_parity_width + tag_width;
|
constant tag_ram_data_width : natural := 1 + tag_parity_width + tag_width;
|
||||||
constant tram_addr_width : natural := cache_index_width;
|
constant tag_ram_addr_width : natural := cache_index_width;
|
||||||
|
|
||||||
subtype tram_data_t is unsigned (tram_data_width-1 downto 0);
|
subtype tag_ram_data_t is unsigned (tag_ram_data_width-1 downto 0);
|
||||||
|
|
||||||
type dcache_entry_t is record
|
type dcache_entry_t is record
|
||||||
valid : std_logic;
|
valid : std_logic;
|
||||||
@@ -103,11 +116,7 @@ END COMPONENT;
|
|||||||
tag : unsigned(tag_width-1 downto 0);
|
tag : unsigned(tag_width-1 downto 0);
|
||||||
end record;
|
end record;
|
||||||
|
|
||||||
alias cpu_word_index is cpu_addr(word_index_width+1 downto 2);
|
function to_dcache_entry(x : tag_ram_data_t) return dcache_entry_t is
|
||||||
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
|
||||||
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
|
||||||
|
|
||||||
function to_dcache_entry(x : tram_data_t) return dcache_entry_t is
|
|
||||||
variable result : dcache_entry_t;
|
variable result : dcache_entry_t;
|
||||||
begin
|
begin
|
||||||
result.valid := x(0);
|
result.valid := x(0);
|
||||||
@@ -117,106 +126,141 @@ END COMPONENT;
|
|||||||
return result;
|
return result;
|
||||||
end to_dcache_entry;
|
end to_dcache_entry;
|
||||||
|
|
||||||
function to_tram_data(x : dcache_entry_t) return tram_data_t is
|
function to_tag_ram_data(x : dcache_entry_t) return tag_ram_data_t is
|
||||||
variable result : tram_data_t;
|
variable result : tag_ram_data_t;
|
||||||
begin
|
begin
|
||||||
result(0) := x.valid;
|
result(0) := x.valid;
|
||||||
result(3 downto 1) := x.tv_p;
|
result(3 downto 1) := x.tv_p;
|
||||||
result(tag_width+3 downto 4) := x.tag;
|
result(tag_width+3 downto 4) := x.tag;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
end to_tram_data;
|
end to_tag_ram_data;
|
||||||
|
|
||||||
type cache_state_t is (init, ready, flush, mem_request, mem_access, mem_wait, mem_data, upd_cache, rd_cache);
|
type cache_state_t is (init, ready, invalidate, flush, mem_request, mem_access, mem_data, rd_cache);
|
||||||
signal s, sn : cache_state_t;
|
signal s, sn : cache_state_t;
|
||||||
|
|
||||||
|
signal cache_req : std_logic;
|
||||||
|
signal cache_ack : std_logic;
|
||||||
signal cache_busy : std_logic;
|
signal cache_busy : std_logic;
|
||||||
signal cache_hit : std_logic;
|
signal cache_hit : std_logic;
|
||||||
signal tag_match : std_logic;
|
signal tag_match : std_logic;
|
||||||
signal word_index_reg : unsigned(word_index_width-1 downto 0);
|
signal cache_hit_inv : std_logic;
|
||||||
signal cache_index_reg : unsigned(cache_index_width-1 downto 0);
|
signal tag_match_inv : std_logic;
|
||||||
signal tag_index_reg : unsigned(tag_width-1 downto 0);
|
|
||||||
|
signal request_addr : unsigned(addr_width-1 downto 0);
|
||||||
|
signal fill_addr : unsigned(addr_width-1 downto 0);
|
||||||
|
|
||||||
|
signal cache_index_inv : unsigned(cache_index_width-1 downto 0);
|
||||||
|
signal tag_inv : unsigned(tag_width-1 downto 0);
|
||||||
|
signal tag_reg_inv : unsigned(tag_width-1 downto 0);
|
||||||
|
|
||||||
signal cache_entry_in : dcache_entry_t;
|
signal cache_entry_in : dcache_entry_t;
|
||||||
signal cache_entry_out : dcache_entry_t;
|
signal cache_entry_out : dcache_entry_t;
|
||||||
signal cpu_dram_addr : unsigned(lg2(cache_size)-1 downto 0);
|
signal cache_entry_out_inv : dcache_entry_t;
|
||||||
signal cpu_dram_dout : word_t;
|
signal cpu_data_ram_addr : unsigned(lg2(cache_size)-1 downto 0);
|
||||||
signal cpu_dram_din : word_t;
|
signal cpu_data_ram_dout : word_t;
|
||||||
signal cpu_data_reg : word_t;
|
signal cpu_data_reg : word_t;
|
||||||
signal cpu_be_reg : unsigned(3 downto 0);
|
signal cpu_be_reg : unsigned(3 downto 0);
|
||||||
signal cpu_we_reg : std_logic;
|
signal cpu_we_reg : std_logic;
|
||||||
signal ctrl_dram_en : std_logic;
|
signal ctrl_data_ram_addr : unsigned(lg2(cache_size)-1 downto 0);
|
||||||
signal ctrl_dram_addr : unsigned(lg2(cache_size)-1 downto 0);
|
signal ctrl_data_ram_we : unsigned(3 downto 0);
|
||||||
signal ctrl_dram_din : word_t;
|
signal cpu_data_ram_we : unsigned(3 downto 0);
|
||||||
signal ctrl_dram_we : unsigned(3 downto 0);
|
|
||||||
signal cpu_dram_we : unsigned(3 downto 0);
|
|
||||||
signal cpu_dram_en : std_logic;
|
|
||||||
signal cpu_en2 : std_logic;
|
|
||||||
signal cpu_we2 : std_logic;
|
signal cpu_we2 : std_logic;
|
||||||
|
|
||||||
signal tram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
||||||
signal tram_dout : tram_data_t;
|
signal tag_ram_dout : tag_ram_data_t;
|
||||||
signal tram_addr_wr : unsigned(cache_index_width-1 downto 0);
|
signal tag_ram_dout_inv : tag_ram_data_t;
|
||||||
signal tram_din : tram_data_t;
|
signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
|
||||||
signal tram_re : std_logic;
|
signal tag_ram_din : tag_ram_data_t;
|
||||||
signal tram_we : std_logic;
|
signal tag_ram_we : std_logic;
|
||||||
|
|
||||||
signal ram_index_count : natural range 0 to 2**word_index_width-1;
|
signal fill_count : natural range 0 to 2**word_index_width-1;
|
||||||
signal ram_index_count_rst : std_logic;
|
signal fill_count_en : std_logic;
|
||||||
signal cache_index_count : natural range 0 to 2**cache_index_width-1;
|
signal fill_count_rdy : std_logic;
|
||||||
signal cache_index_count_en : std_logic;
|
signal flush_count : natural range 0 to 2**cache_index_width-1;
|
||||||
signal mem_index_count : natural range 0 to 2**word_index_width-1;
|
signal flush_count_rst : std_logic;
|
||||||
signal mem_index_count_en : std_logic;
|
signal flush_count_en : std_logic;
|
||||||
signal mem_index_count_rst : std_logic;
|
signal flush_count_rdy : std_logic;
|
||||||
signal cpu_reg_en : std_logic;
|
signal request_count : natural range 0 to 2**word_index_width-1;
|
||||||
|
signal request_count_en : std_logic;
|
||||||
|
signal request_count_rdy : std_logic;
|
||||||
signal was_miss : std_logic;
|
signal was_miss : std_logic;
|
||||||
signal data_write : std_logic;
|
signal invalidate_all : std_logic;
|
||||||
|
signal invalidate_ack : std_logic;
|
||||||
|
signal invalidate_en : std_logic;
|
||||||
|
signal invalidate_req : std_logic;
|
||||||
signal cpu_hit_we : std_logic;
|
signal cpu_hit_we : std_logic;
|
||||||
signal instant_raw : std_logic;
|
signal instant_raw : std_logic;
|
||||||
|
signal hit_cache_index : unsigned(cache_index_width-1 downto 0);
|
||||||
|
|
||||||
|
alias cpu_word_index is cpu_addr(word_index_width+1 downto 2);
|
||||||
|
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||||
|
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||||
|
|
||||||
|
alias fill_word_index is fill_addr(word_index_width+1 downto 2);
|
||||||
|
alias fill_cache_index is fill_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||||
|
alias fill_tag is fill_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||||
|
|
||||||
|
alias req_word_index is request_addr(word_index_width+1 downto 2);
|
||||||
|
alias req_cache_index is request_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||||
|
alias req_tag is request_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
|
cache_index_inv <= ctrl.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||||
|
tag_inv <= ctrl.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||||
|
|
||||||
cpu_hit_we <= cpu_we2 and cache_hit;
|
cpu_hit_we <= cpu_we2 and cache_hit;
|
||||||
|
|
||||||
cpu_index_register:
|
fill_address_register:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if RST_I = '1' then
|
if fill_count_en = '1' then
|
||||||
cache_index_reg <= (others => '0');
|
if ACK_I = '1' then
|
||||||
tag_index_reg <= (others => '0');
|
fill_word_index <= fill_word_index + 1;
|
||||||
elsif cpu_reg_en = '1' and en = '1' and instant_raw = '0' then
|
end if;
|
||||||
word_index_reg <= cpu_word_index;
|
elsif cache_busy = '0' then
|
||||||
cache_index_reg <= cpu_cache_index;
|
fill_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||||
tag_index_reg <= cpu_tag;
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
cpu_data_register:
|
request_address_register:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if request_count_en = '1'then
|
||||||
|
if SRDY_I = '1' then
|
||||||
|
req_word_index <= req_word_index + 1;
|
||||||
|
end if;
|
||||||
|
elsif cache_busy = '0' then
|
||||||
|
request_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
cpu_request_register:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if RST_I = '1' then
|
if RST_I = '1' then
|
||||||
cpu_we_reg <= '0';
|
cpu_we_reg <= '0';
|
||||||
elsif cpu_reg_en = '1' and en = '1' then
|
cache_req <= '0';
|
||||||
|
elsif cpu_en = '1' then
|
||||||
|
if cache_busy = '0' then
|
||||||
|
cpu_we2 <= cpu_we;
|
||||||
|
cache_req <= '1';
|
||||||
cpu_data_reg <= cpu_din;
|
cpu_data_reg <= cpu_din;
|
||||||
cpu_be_reg <= cpu_be;
|
cpu_be_reg <= cpu_be;
|
||||||
cpu_we_reg <= cpu_we;
|
cpu_we_reg <= cpu_we;
|
||||||
|
if cpu_we = '1' then
|
||||||
|
hit_cache_index <= cpu_cache_index;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
elsif cache_ack = '1' then
|
||||||
|
cache_req <= '0';
|
||||||
cpu_was_wr_register:
|
|
||||||
process(CLK_I)
|
|
||||||
begin
|
|
||||||
if rising_edge(CLK_I) then
|
|
||||||
cpu_en2 <= '0';
|
|
||||||
cpu_we2 <= '0';
|
cpu_we2 <= '0';
|
||||||
if cpu_en = '1' and en = '1' then
|
|
||||||
cpu_we2 <= cpu_we;
|
|
||||||
cpu_en2 <= '1';
|
|
||||||
cpu_dram_din <= cpu_din;
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
@@ -225,25 +269,33 @@ instant_raw_logic:
|
|||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
instant_raw <= cpu_hit_we and cpu_en and en and not cpu_we;
|
instant_raw <= '0';
|
||||||
|
if cpu_word_index = fill_word_index and cpu_cache_index = hit_cache_index then
|
||||||
|
instant_raw <= cpu_hit_we and cpu_en and not cpu_we;
|
||||||
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
inst_tag_ram : dpram_1w1r
|
inst_tag_ram : dpram_2w2r
|
||||||
GENERIC MAP (
|
GENERIC MAP
|
||||||
addr_width => tram_addr_width,
|
(
|
||||||
data_width => tram_data_width
|
addr_width => tag_ram_addr_width,
|
||||||
|
data_width => tag_ram_data_width
|
||||||
)
|
)
|
||||||
PORT MAP (
|
PORT MAP
|
||||||
clka => CLK_I,
|
(
|
||||||
clkb => CLK_I,
|
clk_a => CLK_I,
|
||||||
|
clk_b => CLK_I,
|
||||||
en_a => '1',
|
en_a => '1',
|
||||||
en_b => tram_re,
|
en_b => '1',
|
||||||
we_a => tram_we,
|
we_a => tag_ram_we,
|
||||||
addr_a => tram_addr_wr,
|
we_b => '0',
|
||||||
addr_b => tram_addr_rd,
|
addr_a => tag_ram_addr_wr,
|
||||||
din_a => tram_din,
|
addr_b => tag_ram_addr_rd,
|
||||||
dout_b => tram_dout
|
din_a => tag_ram_din,
|
||||||
|
din_b => tag_ram_din,
|
||||||
|
dout_a => tag_ram_dout_inv,
|
||||||
|
dout_b => tag_ram_dout
|
||||||
);
|
);
|
||||||
|
|
||||||
gen_data_ram:
|
gen_data_ram:
|
||||||
@@ -251,26 +303,45 @@ gen_data_ram:
|
|||||||
begin
|
begin
|
||||||
|
|
||||||
inst_data_ram : dpram_2w2r
|
inst_data_ram : dpram_2w2r
|
||||||
GENERIC MAP (
|
GENERIC MAP
|
||||||
|
(
|
||||||
addr_width => lg2(cache_size),
|
addr_width => lg2(cache_size),
|
||||||
data_width => word_t'length/4
|
data_width => word_t'length/4
|
||||||
)
|
)
|
||||||
PORT MAP (
|
PORT MAP
|
||||||
|
(
|
||||||
clk_a => CLK_I,
|
clk_a => CLK_I,
|
||||||
clk_b => CLK_I,
|
clk_b => CLK_I,
|
||||||
en_a => ctrl_dram_en,
|
en_a => '1',
|
||||||
en_b => '1',
|
en_b => '1',
|
||||||
we_a => ctrl_dram_we(i),
|
we_a => cpu_data_ram_we(i),
|
||||||
we_b => cpu_dram_we(i),
|
we_b => ctrl_data_ram_we(i),
|
||||||
addr_a => ctrl_dram_addr,
|
addr_a => ctrl_data_ram_addr,
|
||||||
addr_b => cpu_dram_addr,
|
addr_b => cpu_data_ram_addr,
|
||||||
din_a => ctrl_dram_din(8*(i+1)-1 downto 8*i),
|
din_a => cpu_data_reg(8*(i+1)-1 downto 8*i),
|
||||||
din_b => cpu_dram_din(8*(i+1)-1 downto 8*i),
|
din_b => DAT_I(8*(i+1)-1 downto 8*i),
|
||||||
dout_a => open,
|
dout_a => open,
|
||||||
dout_b => cpu_dram_dout(8*(i+1)-1 downto 8*i)
|
dout_b => cpu_data_ram_dout(8*(i+1)-1 downto 8*i)
|
||||||
);
|
);
|
||||||
end generate;
|
end generate;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cache_invalidate_request:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' or ctrl.inv_all = '1' or ctrl.inv_at = '1' then
|
||||||
|
invalidate_req <= '1';
|
||||||
|
invalidate_all <= ctrl.inv_all or RST_I;
|
||||||
|
tag_reg_inv <= tag_inv;
|
||||||
|
elsif invalidate_ack = '1' then
|
||||||
|
invalidate_req <= '0';
|
||||||
|
invalidate_all <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
cache_state_next:
|
cache_state_next:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
@@ -283,146 +354,175 @@ cache_state_next:
|
|||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
cpu_busy <= cache_busy or instant_raw;
|
MRDY_O <= fill_count_en;
|
||||||
cpu_dout <= cpu_dram_dout;
|
ADDR_O <= request_addr;
|
||||||
|
|
||||||
tag_match <= '1' when tag_index_reg = cache_entry_out.tag else '0';
|
cpu_busy <= cache_busy;
|
||||||
|
cpu_dout <= cpu_data_ram_dout;
|
||||||
|
|
||||||
|
tag_match <= '1' when fill_tag = cache_entry_out.tag else '0';
|
||||||
cache_hit <= tag_match and cache_entry_out.valid;
|
cache_hit <= tag_match and cache_entry_out.valid;
|
||||||
tram_din <= to_tram_data(cache_entry_in);
|
tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0';
|
||||||
tram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg;
|
cache_hit_inv <= tag_match_inv and cache_entry_out_inv.valid;
|
||||||
cache_entry_out <= to_dcache_entry(tram_dout);
|
tag_ram_din <= to_tag_ram_data(cache_entry_in);
|
||||||
cpu_dram_addr <= (cpu_cache_index & cpu_word_index) when (was_miss = '0' and cpu_hit_we = '0' and instant_raw = '0') else (cache_index_reg & word_index_reg);
|
tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when invalidate_en = '1' else fill_cache_index;
|
||||||
ADDR_O <= tag_index_reg & cache_index_reg & to_unsigned(mem_index_count, word_index_width) & "00";
|
tag_ram_addr_rd <= cpu_cache_index when (was_miss = '0' and instant_raw = '0') else fill_cache_index;
|
||||||
ctrl_dram_addr <= cache_index_reg & to_unsigned(ram_index_count, word_index_width);
|
|
||||||
ctrl_dram_din <= DAT_I;
|
cache_entry_out <= to_dcache_entry(tag_ram_dout);
|
||||||
ctrl_dram_we <= (others => '1');
|
cache_entry_out_inv <= to_dcache_entry(tag_ram_dout_inv);
|
||||||
ctrl_dram_en <= data_write and ACK_I;
|
|
||||||
cpu_dram_we <= cpu_be_reg when (cpu_hit_we = '1') else (others => '0');
|
cpu_data_ram_addr <= (cpu_cache_index & cpu_word_index) when (was_miss = '0' and instant_raw = '0' and fill_count_en = '0') else (fill_cache_index & fill_word_index);
|
||||||
|
ctrl_data_ram_addr <= fill_cache_index & fill_word_index;
|
||||||
|
ctrl_data_ram_we <= (others => fill_count_en and ACK_I);
|
||||||
|
cpu_data_ram_we <= cpu_be_reg when (cpu_hit_we = '1') else (others => '0');
|
||||||
|
|
||||||
cache_state:
|
cache_state:
|
||||||
process(s, instant_raw, cache_hit, cache_index_count, ram_index_count, mem_index_count, cache_index_reg, ACK_I, tag_index_reg, cpu_en, SRDY_I, cpu_en2, cpu_we_reg)
|
process(s, cache_req, instant_raw, cache_hit, cache_hit_inv, flush_count_rdy, fill_count_rdy, request_count_rdy, fill_tag, SRDY_I, cpu_we_reg, invalidate_req, invalidate_all)
|
||||||
begin
|
begin
|
||||||
cpu_reg_en <= '0';
|
cache_busy <= cache_req;
|
||||||
cache_busy <= '1';
|
cache_ack <= '0';
|
||||||
tram_we <= '0';
|
tag_ram_we <= '0';
|
||||||
cache_index_count_en <= '0';
|
flush_count_en <= '0';
|
||||||
ram_index_count_rst <= '0';
|
flush_count_rst <= '0';
|
||||||
mem_index_count_en <= '0';
|
invalidate_en <= '0';
|
||||||
mem_index_count_rst <= '0';
|
request_count_en <= '0';
|
||||||
|
fill_count_en <= '0';
|
||||||
CYC_O <= '0';
|
CYC_O <= '0';
|
||||||
STB_O <= '0';
|
STB_O <= '0';
|
||||||
tram_re <= '0';
|
|
||||||
was_miss <= '0';
|
was_miss <= '0';
|
||||||
data_write <= '0';
|
invalidate_ack <= '0';
|
||||||
tram_addr_wr <= to_unsigned(cache_index_count, cache_index_width);
|
|
||||||
cache_entry_in.tv_p <= (others => '0');
|
cache_entry_in.tv_p <= (others => '0');
|
||||||
cache_entry_in.tag <= tag_index_reg;
|
cache_entry_in.tag <= fill_tag;
|
||||||
cache_entry_in.valid <= '0';
|
cache_entry_in.valid <= '0';
|
||||||
sn <= s;
|
sn <= s;
|
||||||
|
|
||||||
case s is
|
case s is
|
||||||
when init =>
|
when init =>
|
||||||
sn <= flush;
|
sn <= ready;
|
||||||
when ready =>
|
when ready =>
|
||||||
cache_busy <= '0';
|
if invalidate_req = '1' then
|
||||||
cpu_reg_en <= '1';
|
sn <= invalidate;
|
||||||
tram_re <= cpu_en;
|
invalidate_en <= '1';
|
||||||
if cpu_en2 = '1' then
|
else
|
||||||
|
if cache_req = '1' then
|
||||||
if cache_hit = '0' and cpu_we_reg = '0' then
|
if cache_hit = '0' and cpu_we_reg = '0' then
|
||||||
sn <= mem_request;
|
sn <= mem_request;
|
||||||
cpu_reg_en <= '0';
|
|
||||||
cache_busy <= '1';
|
|
||||||
CYC_O <= '1';
|
CYC_O <= '1';
|
||||||
|
else
|
||||||
|
cache_busy <= instant_raw;
|
||||||
|
cache_ack <= not instant_raw;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
when flush =>
|
end if;
|
||||||
cache_index_count_en <= '1';
|
when invalidate =>
|
||||||
tram_addr_wr <= to_unsigned(cache_index_count, cache_index_width);
|
sn <= rd_cache;
|
||||||
tram_we <= '1';
|
invalidate_en <= '1';
|
||||||
|
invalidate_ack <= '1';
|
||||||
|
if invalidate_all = '1' then
|
||||||
|
sn <= flush;
|
||||||
|
flush_count_rst <= '1';
|
||||||
|
elsif cache_hit_inv = '1' then
|
||||||
|
tag_ram_we <= '1';
|
||||||
cache_entry_in.valid <= '0';
|
cache_entry_in.valid <= '0';
|
||||||
cache_entry_in.tag <= (others => '0');
|
cache_entry_in.tag <= (others => '0');
|
||||||
if cache_index_count = 0 then
|
sn <= rd_cache;
|
||||||
sn <= ready;
|
|
||||||
if cpu_en = '1' then
|
|
||||||
cpu_reg_en <= '1';
|
|
||||||
tram_re <= '1';
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
when flush =>
|
||||||
|
flush_count_en <= '1';
|
||||||
|
invalidate_en <= '1';
|
||||||
|
tag_ram_we <= '1';
|
||||||
|
cache_entry_in.valid <= '0';
|
||||||
|
cache_entry_in.tag <= (others => '0');
|
||||||
|
if flush_count_rdy = '1' then
|
||||||
|
tag_ram_we <= '0';
|
||||||
|
sn <= rd_cache;
|
||||||
end if;
|
end if;
|
||||||
when mem_request =>
|
when mem_request =>
|
||||||
ram_index_count_rst <= '1';
|
|
||||||
mem_index_count_rst <= '1';
|
|
||||||
CYC_O <= '1';
|
CYC_O <= '1';
|
||||||
if SRDY_I = '1' then
|
if SRDY_I = '1' then
|
||||||
sn <= mem_access;
|
sn <= mem_access;
|
||||||
end if;
|
end if;
|
||||||
when mem_access =>
|
when mem_access =>
|
||||||
data_write <= '1';
|
fill_count_en <= '1';
|
||||||
mem_index_count_en <= '1';
|
request_count_en <= '1';
|
||||||
CYC_O <= '1';
|
CYC_O <= '1';
|
||||||
STB_O <= '1';
|
STB_O <= '1';
|
||||||
if mem_index_count = 2**word_index_width-1 then
|
if request_count_rdy = '1' then
|
||||||
if SRDY_I = '1' then
|
STB_O <= '0';
|
||||||
sn <= mem_data;
|
sn <= mem_data;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
|
||||||
when mem_data =>
|
when mem_data =>
|
||||||
CYC_O <= '1';
|
CYC_O <= '1';
|
||||||
data_write <= '1';
|
fill_count_en <= '1';
|
||||||
if ram_index_count = 2**word_index_width-1 then
|
if fill_count_rdy = '1' then
|
||||||
if ACK_I = '1' then
|
tag_ram_we <= '1';
|
||||||
sn <= upd_cache;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
when upd_cache =>
|
|
||||||
tram_addr_wr <= cache_index_reg;
|
|
||||||
tram_we <= '1';
|
|
||||||
cache_entry_in.valid <= '1';
|
cache_entry_in.valid <= '1';
|
||||||
sn <= rd_cache;
|
sn <= rd_cache;
|
||||||
|
end if;
|
||||||
when rd_cache =>
|
when rd_cache =>
|
||||||
tram_re <= '1';
|
|
||||||
was_miss <= '1';
|
was_miss <= '1';
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
|
|
||||||
when others =>
|
when others =>
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
end case;
|
end case;
|
||||||
|
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
cache_index_counter:
|
flush_counter:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if cache_index_count_en = '0' then
|
if ctrl.inv_at = '1' then
|
||||||
cache_index_count <= 2**cache_index_width-1;
|
flush_count <= to_integer(cache_index_inv);
|
||||||
elsif cache_index_count /= 0 then
|
elsif flush_count_rst = '1' then
|
||||||
cache_index_count <= cache_index_count - 1;
|
flush_count_rdy <= '0';
|
||||||
end if;
|
flush_count <= 2**cache_index_width-1;
|
||||||
end if;
|
elsif flush_count_en = '1' then
|
||||||
end process;
|
if flush_count /= 0 then
|
||||||
|
flush_count <= flush_count - 1;
|
||||||
ram_index_counter:
|
else
|
||||||
process(CLK_I)
|
flush_count_rdy <= '1';
|
||||||
begin
|
|
||||||
if rising_edge(CLK_I) then
|
|
||||||
if ram_index_count_rst = '1' then
|
|
||||||
ram_index_count <= 0;
|
|
||||||
elsif data_write = '1' and ACK_I = '1' then
|
|
||||||
if ram_index_count /= 2**word_index_width-1 then
|
|
||||||
ram_index_count <= ram_index_count + 1;
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
mem_index_counter:
|
request_counter:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if mem_index_count_rst = '1' then
|
if request_count_en = '0' then
|
||||||
mem_index_count <= 0;
|
request_count_rdy <= '0';
|
||||||
elsif mem_index_count_en = '1' and SRDY_I = '1' then
|
request_count <= 2**word_index_width-1;
|
||||||
if mem_index_count /= 2**word_index_width-1 then
|
else
|
||||||
mem_index_count <= mem_index_count + 1;
|
if SRDY_I = '1' then
|
||||||
|
if request_count /= 0 then
|
||||||
|
request_count <= request_count - 1;
|
||||||
|
else
|
||||||
|
request_count_rdy <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
fill_counter:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if fill_count_en = '0' then
|
||||||
|
fill_count_rdy <= '0';
|
||||||
|
fill_count <= 2**word_index_width-1;
|
||||||
|
else
|
||||||
|
if ACK_I = '1' then
|
||||||
|
if fill_count /= 0 then
|
||||||
|
fill_count <= fill_count - 1;
|
||||||
|
else
|
||||||
|
fill_count_rdy <= '1';
|
||||||
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
|
|||||||
+264
-130
@@ -1,7 +1,29 @@
|
|||||||
|
--------------------------------------------------------------------------
|
||||||
|
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||||
|
-- This file: JIPS top file
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2008 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
LIBRARY IEEE;
|
LIBRARY IEEE;
|
||||||
USE IEEE.STD_LOGIC_1164.ALL;
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
USE IEEE.NUMERIC_STD.ALL;
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
use IEEE.MATH_REAL.ALL;
|
|
||||||
|
|
||||||
library work;
|
library work;
|
||||||
use work.mips_types.all;
|
use work.mips_types.all;
|
||||||
@@ -18,11 +40,12 @@ ENTITY icache IS
|
|||||||
CLK_I : in STD_LOGIC;
|
CLK_I : in STD_LOGIC;
|
||||||
ACK_I : in STD_LOGIC;
|
ACK_I : in STD_LOGIC;
|
||||||
SRDY_I : in STD_LOGIC;
|
SRDY_I : in STD_LOGIC;
|
||||||
|
MRDY_O : out STD_LOGIC;
|
||||||
ADDR_O : out word_t;
|
ADDR_O : out word_t;
|
||||||
DAT_I : in word_t;
|
DAT_I : in word_t;
|
||||||
STB_O : out STD_LOGIC;
|
STB_O : out STD_LOGIC;
|
||||||
CYC_O : out STD_LOGIC;
|
CYC_O : out STD_LOGIC;
|
||||||
en : in STD_LOGIC;
|
ctrl : in cache_ctrl_t;
|
||||||
cpu_en : in STD_LOGIC;
|
cpu_en : in STD_LOGIC;
|
||||||
cpu_addr : in word_t;
|
cpu_addr : in word_t;
|
||||||
cpu_dout : out word_t;
|
cpu_dout : out word_t;
|
||||||
@@ -51,20 +74,33 @@ COMPONENT dpram_1w1r
|
|||||||
);
|
);
|
||||||
END COMPONENT;
|
END COMPONENT;
|
||||||
|
|
||||||
function lg2(x : natural) return natural is
|
COMPONENT dpram_2w2r is
|
||||||
begin
|
GENERIC
|
||||||
return natural(ceil(log2(real(x))));
|
(
|
||||||
end lg2;
|
addr_width : integer := 3;
|
||||||
|
data_width : integer := 8
|
||||||
function po2(x : natural) return natural is
|
);
|
||||||
begin
|
PORT
|
||||||
|
(
|
||||||
return 2**lg2(x);
|
clk_a : in STD_LOGIC;
|
||||||
end po2;
|
clk_b : in STD_LOGIC;
|
||||||
|
en_a : in STD_LOGIC;
|
||||||
|
en_b : in STD_LOGIC;
|
||||||
|
we_a : in STD_LOGIC;
|
||||||
|
we_b : in STD_LOGIC;
|
||||||
|
addr_a : in unsigned (addr_width-1 downto 0);
|
||||||
|
addr_b : in unsigned (addr_width-1 downto 0);
|
||||||
|
din_a : in unsigned (data_width-1 downto 0);
|
||||||
|
din_b : in unsigned (data_width-1 downto 0);
|
||||||
|
dout_a : out unsigned (data_width-1 downto 0);
|
||||||
|
dout_b : out unsigned (data_width-1 downto 0)
|
||||||
|
);
|
||||||
|
END COMPONENT;
|
||||||
|
|
||||||
|
constant addr_width : natural := 32;
|
||||||
constant word_index_width : natural := lg2(line_size);
|
constant word_index_width : natural := lg2(line_size);
|
||||||
constant cache_index_width : natural := lg2(cache_size) - word_index_width;
|
constant cache_index_width : natural := lg2(cache_size) - word_index_width;
|
||||||
constant tag_width : natural := 32 - word_index_width - cache_index_width - 2;
|
constant tag_width : natural := addr_width - word_index_width - cache_index_width - 2;
|
||||||
constant tag_parity_width : natural := 3;
|
constant tag_parity_width : natural := 3;
|
||||||
constant tag_ram_data_width : natural := 1 + tag_parity_width + tag_width;
|
constant tag_ram_data_width : natural := 1 + tag_parity_width + tag_width;
|
||||||
constant tag_ram_addr_width : natural := cache_index_width;
|
constant tag_ram_addr_width : natural := cache_index_width;
|
||||||
@@ -77,10 +113,6 @@ END COMPONENT;
|
|||||||
tag : unsigned(tag_width-1 downto 0);
|
tag : unsigned(tag_width-1 downto 0);
|
||||||
end record;
|
end record;
|
||||||
|
|
||||||
alias cpu_word_index is cpu_addr(word_index_width+1 downto 2);
|
|
||||||
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
|
||||||
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
|
||||||
|
|
||||||
function to_icache_entry(x : tag_ram_data_t) return icache_entry_t is
|
function to_icache_entry(x : tag_ram_data_t) return icache_entry_t is
|
||||||
variable result : icache_entry_t;
|
variable result : icache_entry_t;
|
||||||
begin
|
begin
|
||||||
@@ -101,88 +133,168 @@ END COMPONENT;
|
|||||||
return result;
|
return result;
|
||||||
end to_tag_ram_data;
|
end to_tag_ram_data;
|
||||||
|
|
||||||
type cache_state_t is (init, ready, flush, mem_request, mem_access, mem_wait, mem_data, upd_cache, rd_cache);
|
type cache_state_t is (init, ready, invalidate, flush, mem_request, mem_access, mem_data, rd_cache, upd_cache);
|
||||||
signal s, sn : cache_state_t;
|
signal s, sn : cache_state_t;
|
||||||
|
|
||||||
|
signal cache_req : std_logic;
|
||||||
|
signal cache_ack : std_logic;
|
||||||
signal cache_busy : std_logic;
|
signal cache_busy : std_logic;
|
||||||
signal cache_miss : std_logic;
|
signal cache_miss : std_logic;
|
||||||
signal tag_match : std_logic;
|
signal tag_match : std_logic;
|
||||||
signal word_index_reg : unsigned(word_index_width-1 downto 0);
|
signal cache_miss_inv : std_logic;
|
||||||
signal cache_index_reg : unsigned(cache_index_width-1 downto 0);
|
signal tag_match_inv : std_logic;
|
||||||
signal tag_index_reg : unsigned(tag_width-1 downto 0);
|
signal request_addr : unsigned(addr_width-1 downto 0);
|
||||||
|
signal fill_addr : unsigned(addr_width-1 downto 0);
|
||||||
|
|
||||||
|
signal cache_index_inv : unsigned(cache_index_width-1 downto 0);
|
||||||
|
signal tag_inv : unsigned(tag_width-1 downto 0);
|
||||||
|
signal tag_reg_inv : unsigned(tag_width-1 downto 0);
|
||||||
|
|
||||||
signal cache_entry_in : icache_entry_t;
|
signal cache_entry_in : icache_entry_t;
|
||||||
signal cache_entry_out : icache_entry_t;
|
signal cache_entry_out : icache_entry_t;
|
||||||
|
signal cache_entry_out_inv : icache_entry_t;
|
||||||
signal data_ram_addr_rd : unsigned(lg2(cache_size)-1 downto 0);
|
signal data_ram_addr_rd : unsigned(lg2(cache_size)-1 downto 0);
|
||||||
signal data_ram_data_rd : word_t;
|
signal data_ram_data_rd : word_t;
|
||||||
signal data_ram_addr_wr : unsigned(lg2(cache_size)-1 downto 0);
|
signal data_ram_addr_wr : unsigned(lg2(cache_size)-1 downto 0);
|
||||||
signal data_ram_data_wr : word_t;
|
signal data_ram_data_wr : word_t;
|
||||||
signal data_ram_we : std_logic;
|
signal data_ram_we : std_logic;
|
||||||
signal data_ram_re : std_logic;
|
|
||||||
|
|
||||||
signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
|
||||||
signal tag_ram_data_rd : tag_ram_data_t;
|
signal tag_ram_data_rd : tag_ram_data_t;
|
||||||
|
signal tag_ram_data_rd_inv : tag_ram_data_t;
|
||||||
signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
|
signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
|
||||||
signal tag_ram_data_wr : tag_ram_data_t;
|
signal tag_ram_data_wr : tag_ram_data_t;
|
||||||
signal tag_ram_re : std_logic;
|
|
||||||
signal tag_ram_we : std_logic;
|
signal tag_ram_we : std_logic;
|
||||||
|
|
||||||
signal ram_index_count : natural range 0 to 2**word_index_width-1;
|
signal fill_count : natural range 0 to 2**word_index_width-1;
|
||||||
signal ram_index_count_rst : std_logic;
|
signal fill_count_en : std_logic;
|
||||||
signal cache_index_count : natural range 0 to 2**cache_index_width-1;
|
signal fill_count_rdy : std_logic;
|
||||||
signal cache_index_count_en : std_logic;
|
signal flush_count : natural range 0 to 2**cache_index_width-1;
|
||||||
signal mem_index_count : natural range 0 to 2**word_index_width-1;
|
signal flush_count_rst : std_logic;
|
||||||
signal mem_index_count_en : std_logic;
|
signal flush_count_en : std_logic;
|
||||||
signal mem_index_count_rst : std_logic;
|
signal flush_count_rdy : std_logic;
|
||||||
signal cpu_reg_en : std_logic;
|
signal request_count : natural range 0 to 2**word_index_width-1;
|
||||||
|
signal request_count_en : std_logic;
|
||||||
|
signal request_count_rdy : std_logic;
|
||||||
|
signal ram_read_en : std_logic;
|
||||||
signal was_miss : std_logic;
|
signal was_miss : std_logic;
|
||||||
signal data_write : std_logic;
|
signal invalidate_all : std_logic;
|
||||||
|
signal invalidate_ack : std_logic;
|
||||||
|
signal invalidate_en : std_logic;
|
||||||
|
signal invalidate_req : std_logic;
|
||||||
|
|
||||||
|
alias cpu_word_index is cpu_addr(word_index_width+1 downto 2);
|
||||||
|
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||||
|
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||||
|
|
||||||
|
alias fill_word_index is fill_addr(word_index_width+1 downto 2);
|
||||||
|
alias fill_cache_index is fill_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||||
|
alias fill_tag is fill_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||||
|
|
||||||
|
alias req_word_index is request_addr(word_index_width+1 downto 2);
|
||||||
|
alias req_cache_index is request_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||||
|
alias req_tag is request_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
|
ram_read_en <= cpu_en or was_miss;
|
||||||
|
cache_index_inv <= ctrl.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
|
||||||
|
tag_inv <= ctrl.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
|
||||||
|
|
||||||
cpu_index_reg:
|
|
||||||
|
fill_address_register:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if RST_I = '1' then
|
if fill_count_en = '1' then
|
||||||
cache_index_reg <= (others => '0');
|
if ACK_I = '1' then
|
||||||
tag_index_reg <= (others => '0');
|
fill_word_index <= fill_word_index + 1;
|
||||||
elsif cpu_reg_en = '1' then
|
end if;
|
||||||
word_index_reg <= cpu_word_index;
|
elsif cache_busy = '0' then
|
||||||
cache_index_reg <= cpu_cache_index;
|
fill_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||||
tag_index_reg <= cpu_tag;
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
inst_tag_ram : dpram_1w1r
|
request_address_register:
|
||||||
GENERIC MAP (
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if request_count_en = '1'then
|
||||||
|
if SRDY_I = '1' then
|
||||||
|
req_word_index <= req_word_index + 1;
|
||||||
|
end if;
|
||||||
|
elsif cache_busy = '0' then
|
||||||
|
request_addr <= cpu_addr(addr_width-1 downto 2) & "00";
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
cpu_request_register:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' then
|
||||||
|
cache_req <= '0';
|
||||||
|
elsif cpu_en = '1' then
|
||||||
|
if cache_busy = '0' then
|
||||||
|
cache_req <= '1';
|
||||||
|
end if;
|
||||||
|
elsif cache_ack = '1' then
|
||||||
|
cache_req <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
cache_invalidate_request:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' or ctrl.inv_all = '1' or ctrl.inv_at = '1' then
|
||||||
|
invalidate_req <= '1';
|
||||||
|
invalidate_all <= ctrl.inv_all or RST_I;
|
||||||
|
tag_reg_inv <= tag_inv;
|
||||||
|
elsif invalidate_ack = '1' then
|
||||||
|
invalidate_req <= '0';
|
||||||
|
invalidate_all <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
inst_tag_ram : dpram_2w2r
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
addr_width => tag_ram_addr_width,
|
addr_width => tag_ram_addr_width,
|
||||||
data_width => tag_ram_data_width
|
data_width => tag_ram_data_width
|
||||||
)
|
)
|
||||||
PORT MAP (
|
PORT MAP
|
||||||
clka => CLK_I,
|
(
|
||||||
clkb => CLK_I,
|
clk_a => CLK_I,
|
||||||
|
clk_b => CLK_I,
|
||||||
en_a => '1',
|
en_a => '1',
|
||||||
en_b => tag_ram_re,
|
en_b => ram_read_en,
|
||||||
we_a => tag_ram_we,
|
we_a => tag_ram_we,
|
||||||
|
we_b => '0',
|
||||||
addr_a => tag_ram_addr_wr,
|
addr_a => tag_ram_addr_wr,
|
||||||
addr_b => tag_ram_addr_rd,
|
addr_b => tag_ram_addr_rd,
|
||||||
din_a => tag_ram_data_wr,
|
din_a => tag_ram_data_wr,
|
||||||
|
din_b => tag_ram_data_wr,
|
||||||
|
dout_a => tag_ram_data_rd_inv,
|
||||||
dout_b => tag_ram_data_rd
|
dout_b => tag_ram_data_rd
|
||||||
);
|
);
|
||||||
|
|
||||||
inst_data_ram : dpram_1w1r
|
inst_data_ram : dpram_1w1r
|
||||||
GENERIC MAP (
|
GENERIC MAP
|
||||||
|
(
|
||||||
addr_width => lg2(cache_size),
|
addr_width => lg2(cache_size),
|
||||||
data_width => word_t'length
|
data_width => word_t'length
|
||||||
)
|
)
|
||||||
PORT MAP (
|
PORT MAP
|
||||||
|
(
|
||||||
clka => CLK_I,
|
clka => CLK_I,
|
||||||
clkb => CLK_I,
|
clkb => CLK_I,
|
||||||
en_a => '1',
|
en_a => '1',
|
||||||
en_b => data_ram_re,
|
en_b => ram_read_en,
|
||||||
we_a => data_ram_we,
|
we_a => data_ram_we,
|
||||||
addr_a => data_ram_addr_wr,
|
addr_a => data_ram_addr_wr,
|
||||||
addr_b => data_ram_addr_rd,
|
addr_b => data_ram_addr_rd,
|
||||||
@@ -190,7 +302,6 @@ inst_data_ram : dpram_1w1r
|
|||||||
dout_b => data_ram_data_rd
|
dout_b => data_ram_data_rd
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
cache_state_next:
|
cache_state_next:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
@@ -203,149 +314,172 @@ cache_state_next:
|
|||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
MRDY_O <= fill_count_en;
|
||||||
|
ADDR_O <= fill_tag & fill_cache_index & req_word_index & "00";
|
||||||
|
|
||||||
cpu_busy <= cache_busy;
|
cpu_busy <= cache_busy;
|
||||||
cpu_dout <= data_ram_data_rd;
|
cpu_dout <= data_ram_data_rd;
|
||||||
|
|
||||||
tag_match <= '1' when tag_index_reg = cache_entry_out.tag else '0';
|
|
||||||
cache_miss <= not (tag_match and cache_entry_out.valid);
|
|
||||||
tag_ram_data_wr <= to_tag_ram_data(cache_entry_in);
|
|
||||||
tag_ram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg;
|
|
||||||
cache_entry_out <= to_icache_entry(tag_ram_data_rd);
|
cache_entry_out <= to_icache_entry(tag_ram_data_rd);
|
||||||
data_ram_addr_rd <= (cpu_cache_index & cpu_word_index) when was_miss = '0' else (cache_index_reg & word_index_reg);
|
tag_match <= '1' when fill_tag = cache_entry_out.tag else '0';
|
||||||
ADDR_O <= tag_index_reg & cache_index_reg & to_unsigned(mem_index_count, word_index_width) & "00";
|
cache_miss <= not (tag_match and cache_entry_out.valid);
|
||||||
data_ram_addr_wr <= cache_index_reg & to_unsigned(ram_index_count, word_index_width);
|
|
||||||
|
cache_entry_out_inv <= to_icache_entry(tag_ram_data_rd_inv);
|
||||||
|
tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0';
|
||||||
|
cache_miss_inv <= not (tag_match_inv and cache_entry_out_inv.valid);
|
||||||
|
|
||||||
|
tag_ram_data_wr <= to_tag_ram_data(cache_entry_in);
|
||||||
|
tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when invalidate_en = '1' else fill_cache_index;
|
||||||
|
tag_ram_addr_rd <= cpu_cache_index when was_miss = '0' else fill_cache_index;
|
||||||
|
data_ram_addr_rd <= (cpu_cache_index & cpu_word_index) when was_miss = '0' else (fill_cache_index & fill_word_index);
|
||||||
|
data_ram_addr_wr <= fill_cache_index & fill_word_index;
|
||||||
data_ram_data_wr <= DAT_I;
|
data_ram_data_wr <= DAT_I;
|
||||||
data_ram_we <= data_write and ACK_I;
|
data_ram_we <= fill_count_en and ACK_I;
|
||||||
|
|
||||||
cache_state:
|
cache_state:
|
||||||
process(s, cache_miss, cache_index_count, ram_index_count, mem_index_count, cache_index_reg, ACK_I, tag_index_reg, cpu_en, SRDY_I, en)
|
process(s, cache_req, cache_miss, cache_miss_inv, flush_count_rdy, fill_count_rdy, request_count_rdy, fill_tag, SRDY_I, invalidate_req, invalidate_all)
|
||||||
begin
|
begin
|
||||||
cpu_reg_en <= '0';
|
cache_busy <= cache_req;
|
||||||
cache_busy <= '1';
|
cache_ack <= '0';
|
||||||
tag_ram_we <= '0';
|
tag_ram_we <= '0';
|
||||||
cache_index_count_en <= '0';
|
flush_count_en <= '0';
|
||||||
ram_index_count_rst <= '0';
|
flush_count_rst <= '0';
|
||||||
mem_index_count_en <= '0';
|
invalidate_en <= '0';
|
||||||
mem_index_count_rst <= '0';
|
request_count_en <= '0';
|
||||||
|
fill_count_en <= '0';
|
||||||
CYC_O <= '0';
|
CYC_O <= '0';
|
||||||
STB_O <= '0';
|
STB_O <= '0';
|
||||||
data_ram_re <= '0';
|
|
||||||
tag_ram_re <= '0';
|
|
||||||
was_miss <= '0';
|
was_miss <= '0';
|
||||||
data_write <= '0';
|
invalidate_ack <= '0';
|
||||||
tag_ram_addr_wr <= to_unsigned(cache_index_count, cache_index_width);
|
|
||||||
cache_entry_in.tv_p <= (others => '0');
|
cache_entry_in.tv_p <= (others => '0');
|
||||||
cache_entry_in.tag <= tag_index_reg;
|
cache_entry_in.tag <= fill_tag;
|
||||||
cache_entry_in.valid <= '0';
|
cache_entry_in.valid <= '0';
|
||||||
sn <= s;
|
sn <= s;
|
||||||
|
|
||||||
case s is
|
case s is
|
||||||
when init =>
|
when init =>
|
||||||
sn <= flush;
|
sn <= ready;
|
||||||
when ready =>
|
when ready =>
|
||||||
if en = '1' then
|
if invalidate_req = '1' then
|
||||||
cache_busy <= '0';
|
sn <= invalidate;
|
||||||
|
invalidate_en <= '1';
|
||||||
|
elsif cache_req = '1' then
|
||||||
if cache_miss = '1' then
|
if cache_miss = '1' then
|
||||||
sn <= mem_request;
|
sn <= mem_request;
|
||||||
cpu_reg_en <= '0';
|
|
||||||
cache_busy <= '1';
|
|
||||||
CYC_O <= '1';
|
CYC_O <= '1';
|
||||||
elsif cpu_en = '1' then
|
else
|
||||||
cpu_reg_en <= '1';
|
cache_busy <= '0';
|
||||||
data_ram_re <= '1';
|
cache_ack <= '1';
|
||||||
tag_ram_re <= '1';
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
when flush =>
|
when invalidate =>
|
||||||
cache_index_count_en <= '1';
|
sn <= rd_cache;
|
||||||
tag_ram_addr_wr <= to_unsigned(cache_index_count, cache_index_width);
|
invalidate_en <= '1';
|
||||||
|
invalidate_ack <= '1';
|
||||||
|
if invalidate_all = '1' then
|
||||||
|
sn <= flush;
|
||||||
|
flush_count_rst <= '1';
|
||||||
|
elsif cache_miss_inv = '0' then
|
||||||
tag_ram_we <= '1';
|
tag_ram_we <= '1';
|
||||||
cache_entry_in.valid <= '0';
|
cache_entry_in.valid <= '0';
|
||||||
cache_entry_in.tag <= (others => '0');
|
cache_entry_in.tag <= (others => '0');
|
||||||
if cache_index_count = 0 then
|
sn <= rd_cache;
|
||||||
sn <= ready;
|
|
||||||
if cpu_en = '1' then
|
|
||||||
cpu_reg_en <= '1';
|
|
||||||
data_ram_re <= '1';
|
|
||||||
tag_ram_re <= '1';
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
when flush =>
|
||||||
|
flush_count_en <= '1';
|
||||||
|
invalidate_en <= '1';
|
||||||
|
tag_ram_we <= '1';
|
||||||
|
cache_entry_in.valid <= '0';
|
||||||
|
cache_entry_in.tag <= (others => '0');
|
||||||
|
if flush_count_rdy = '1' then
|
||||||
|
tag_ram_we <= '0';
|
||||||
|
sn <= rd_cache;
|
||||||
end if;
|
end if;
|
||||||
when mem_request =>
|
when mem_request =>
|
||||||
ram_index_count_rst <= '1';
|
|
||||||
mem_index_count_rst <= '1';
|
|
||||||
CYC_O <= '1';
|
CYC_O <= '1';
|
||||||
if SRDY_I = '1' then
|
if SRDY_I = '1' then
|
||||||
sn <= mem_access;
|
sn <= mem_access;
|
||||||
end if;
|
end if;
|
||||||
when mem_access =>
|
when mem_access =>
|
||||||
mem_index_count_en <= '1';
|
request_count_en <= '1';
|
||||||
data_write <= '1';
|
fill_count_en <= '1';
|
||||||
CYC_O <= '1';
|
CYC_O <= '1';
|
||||||
STB_O <= '1';
|
STB_O <= '1';
|
||||||
if mem_index_count = 2**word_index_width-1 then
|
if request_count_rdy = '1' then
|
||||||
if SRDY_I = '1' then
|
STB_O <= '0';
|
||||||
sn <= mem_data;
|
sn <= mem_data;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
|
||||||
when mem_data =>
|
when mem_data =>
|
||||||
CYC_O <= '1';
|
CYC_O <= '1';
|
||||||
data_write <= '1';
|
fill_count_en <= '1';
|
||||||
if ram_index_count = 2**word_index_width-1 then
|
if fill_count_rdy = '1' then
|
||||||
if ACK_I = '1' then
|
|
||||||
sn <= upd_cache;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
when upd_cache =>
|
|
||||||
tag_ram_addr_wr <= cache_index_reg;
|
|
||||||
tag_ram_we <= '1';
|
tag_ram_we <= '1';
|
||||||
cache_entry_in.valid <= '1';
|
cache_entry_in.valid <= '1';
|
||||||
sn <= rd_cache;
|
sn <= rd_cache;
|
||||||
|
end if;
|
||||||
when rd_cache =>
|
when rd_cache =>
|
||||||
tag_ram_re <= '1';
|
|
||||||
data_ram_re <= '1';
|
|
||||||
was_miss <= '1';
|
was_miss <= '1';
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
when others =>
|
when others =>
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
end case;
|
end case;
|
||||||
|
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
cache_index_counter:
|
flush_counter:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if cache_index_count_en = '0' then
|
if ctrl.inv_at = '1' then
|
||||||
cache_index_count <= 2**cache_index_width-1;
|
flush_count <= to_integer(cache_index_inv);
|
||||||
elsif cache_index_count /= 0 then
|
elsif flush_count_rst = '1' then
|
||||||
cache_index_count <= cache_index_count - 1;
|
flush_count_rdy <= '0';
|
||||||
end if;
|
flush_count <= 2**cache_index_width-1;
|
||||||
end if;
|
elsif flush_count_en = '1' then
|
||||||
end process;
|
if flush_count /= 0 then
|
||||||
|
flush_count <= flush_count - 1;
|
||||||
ram_index_counter:
|
else
|
||||||
process(CLK_I)
|
flush_count_rdy <= '1';
|
||||||
begin
|
|
||||||
if rising_edge(CLK_I) then
|
|
||||||
if ram_index_count_rst = '1' then
|
|
||||||
ram_index_count <= 0;
|
|
||||||
elsif data_write = '1' and ACK_I = '1' then
|
|
||||||
if ram_index_count /= 2**word_index_width-1 then
|
|
||||||
ram_index_count <= ram_index_count + 1;
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
mem_index_counter:
|
request_counter:
|
||||||
process(CLK_I)
|
process(CLK_I)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(CLK_I) then
|
||||||
if mem_index_count_rst = '1' then
|
if request_count_en = '0' then
|
||||||
mem_index_count <= 0;
|
request_count_rdy <= '0';
|
||||||
elsif mem_index_count_en = '1' and SRDY_I = '1' then
|
request_count <= 2**word_index_width-1;
|
||||||
if mem_index_count /= 2**word_index_width-1 then
|
else
|
||||||
mem_index_count <= mem_index_count + 1;
|
if SRDY_I = '1' then
|
||||||
|
if request_count /= 0 then
|
||||||
|
request_count <= request_count - 1;
|
||||||
|
else
|
||||||
|
request_count_rdy <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
fill_counter:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if fill_count_en = '0' then
|
||||||
|
fill_count_rdy <= '0';
|
||||||
|
fill_count <= 2**word_index_width-1;
|
||||||
|
else
|
||||||
|
if ACK_I = '1' then
|
||||||
|
if fill_count /= 0 then
|
||||||
|
fill_count <= fill_count - 1;
|
||||||
|
else
|
||||||
|
fill_count_rdy <= '1';
|
||||||
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ entity biu is
|
|||||||
Generic
|
Generic
|
||||||
(
|
(
|
||||||
icache_size : natural := 2048; -- words
|
icache_size : natural := 2048; -- words
|
||||||
dcache_size : natural := 2048 -- words
|
icache_line : natural := 8; -- words
|
||||||
|
dcache_size : natural := 2048; -- words
|
||||||
|
dcache_line : natural := 8 -- words
|
||||||
);
|
);
|
||||||
Port
|
Port
|
||||||
(
|
(
|
||||||
@@ -40,14 +42,16 @@ entity biu is
|
|||||||
CLK_I : in STD_LOGIC;
|
CLK_I : in STD_LOGIC;
|
||||||
ACK_I : in STD_LOGIC;
|
ACK_I : in STD_LOGIC;
|
||||||
SRDY_I : in STD_LOGIC;
|
SRDY_I : in STD_LOGIC;
|
||||||
ADDR_O : out word_t;
|
ADDR_O : out unsigned(31 downto 0);
|
||||||
DAT_I : in word_t;
|
DAT_I : in unsigned(31 downto 0);
|
||||||
DAT_O : out word_t;
|
DAT_O : out unsigned(31 downto 0);
|
||||||
WE_O : out STD_LOGIC;
|
WE_O : out STD_LOGIC;
|
||||||
SEL_O : out unsigned(3 downto 0);
|
SEL_O : out unsigned(3 downto 0);
|
||||||
CYC_O : out STD_LOGIC;
|
CYC_O : out STD_LOGIC;
|
||||||
STB_O : out STD_LOGIC;
|
STB_O : out STD_LOGIC;
|
||||||
MRDY_O : out STD_LOGIC;
|
MRDY_O : out STD_LOGIC;
|
||||||
|
cop0_ctrl_in : in cop0_ctrl_out_t;
|
||||||
|
cpu_clk : in STD_LOGIC;
|
||||||
cpu_imem_err : out STD_LOGIC;
|
cpu_imem_err : out STD_LOGIC;
|
||||||
cpu_imem_rdy : out STD_LOGIC;
|
cpu_imem_rdy : out STD_LOGIC;
|
||||||
cpu_imem_en : in STD_LOGIC;
|
cpu_imem_en : in STD_LOGIC;
|
||||||
@@ -78,11 +82,12 @@ architecture behavior of biu is
|
|||||||
CLK_I : in STD_LOGIC;
|
CLK_I : in STD_LOGIC;
|
||||||
ACK_I : in STD_LOGIC;
|
ACK_I : in STD_LOGIC;
|
||||||
SRDY_I : in STD_LOGIC;
|
SRDY_I : in STD_LOGIC;
|
||||||
|
MRDY_O : out STD_LOGIC;
|
||||||
ADDR_O : out word_t;
|
ADDR_O : out word_t;
|
||||||
DAT_I : in word_t;
|
DAT_I : in word_t;
|
||||||
STB_O : out STD_LOGIC;
|
STB_O : out STD_LOGIC;
|
||||||
CYC_O : out STD_LOGIC;
|
CYC_O : out STD_LOGIC;
|
||||||
en : in STD_LOGIC;
|
ctrl : in cache_ctrl_t;
|
||||||
cpu_en : in STD_LOGIC;
|
cpu_en : in STD_LOGIC;
|
||||||
cpu_addr : in word_t;
|
cpu_addr : in word_t;
|
||||||
cpu_dout : out word_t;
|
cpu_dout : out word_t;
|
||||||
@@ -102,11 +107,12 @@ architecture behavior of biu is
|
|||||||
CLK_I : in STD_LOGIC;
|
CLK_I : in STD_LOGIC;
|
||||||
ACK_I : in STD_LOGIC;
|
ACK_I : in STD_LOGIC;
|
||||||
SRDY_I : in STD_LOGIC;
|
SRDY_I : in STD_LOGIC;
|
||||||
|
MRDY_O : out STD_LOGIC;
|
||||||
ADDR_O : out word_t;
|
ADDR_O : out word_t;
|
||||||
DAT_I : in word_t;
|
DAT_I : in word_t;
|
||||||
STB_O : out STD_LOGIC;
|
STB_O : out STD_LOGIC;
|
||||||
CYC_O : out STD_LOGIC;
|
CYC_O : out STD_LOGIC;
|
||||||
en : in STD_LOGIC;
|
ctrl : in cache_ctrl_t;
|
||||||
cpu_en : in STD_LOGIC;
|
cpu_en : in STD_LOGIC;
|
||||||
cpu_we : in STD_LOGIC;
|
cpu_we : in STD_LOGIC;
|
||||||
cpu_be : in unsigned(3 downto 0);
|
cpu_be : in unsigned(3 downto 0);
|
||||||
@@ -136,6 +142,8 @@ architecture behavior of biu is
|
|||||||
signal CYC_O_dmem_wr : std_logic;
|
signal CYC_O_dmem_wr : std_logic;
|
||||||
signal SRDY_I_icache : std_logic;
|
signal SRDY_I_icache : std_logic;
|
||||||
signal SRDY_I_dcache : std_logic;
|
signal SRDY_I_dcache : std_logic;
|
||||||
|
signal MRDY_O_icache : std_logic;
|
||||||
|
signal MRDY_O_dcache : std_logic;
|
||||||
signal ADDR_O_icache : word_t;
|
signal ADDR_O_icache : word_t;
|
||||||
signal ADDR_O_dcache : word_t;
|
signal ADDR_O_dcache : word_t;
|
||||||
signal ADDR_O_dmem_rd : word_t;
|
signal ADDR_O_dmem_rd : word_t;
|
||||||
@@ -147,9 +155,13 @@ architecture behavior of biu is
|
|||||||
signal DAT_I_dmem_rd : word_t;
|
signal DAT_I_dmem_rd : word_t;
|
||||||
signal DAT_O_dmem_wr : word_t;
|
signal DAT_O_dmem_wr : word_t;
|
||||||
signal SEL_O_dmem_wr : unsigned(3 downto 0);
|
signal SEL_O_dmem_wr : unsigned(3 downto 0);
|
||||||
|
signal SEL_O_dmem_rd : unsigned(3 downto 0);
|
||||||
signal dcached : std_logic;
|
signal dcached : std_logic;
|
||||||
|
signal dcache_en2 : std_logic;
|
||||||
signal dcache_en : std_logic;
|
signal dcache_en : std_logic;
|
||||||
signal uncached_access : std_logic;
|
signal uncached_access : std_logic;
|
||||||
|
signal ACK : std_logic;
|
||||||
|
signal DAT : unsigned(31 downto 0);
|
||||||
|
|
||||||
type timeout_cnt_t is range 0 to 1E5-1;
|
type timeout_cnt_t is range 0 to 1E5-1;
|
||||||
signal bus_timeout_cnt : timeout_cnt_t;
|
signal bus_timeout_cnt : timeout_cnt_t;
|
||||||
@@ -163,6 +175,13 @@ architecture behavior of biu is
|
|||||||
signal bout_fifo_empty : std_logic;
|
signal bout_fifo_empty : std_logic;
|
||||||
signal bout_rdy : std_logic;
|
signal bout_rdy : std_logic;
|
||||||
|
|
||||||
|
signal bin_fifo_din : unsigned(31 downto 0);
|
||||||
|
signal bin_fifo_dout : unsigned(31 downto 0);
|
||||||
|
signal bin_fifo_re : std_logic;
|
||||||
|
signal bin_fifo_we : std_logic;
|
||||||
|
signal bin_fifo_full : std_logic;
|
||||||
|
signal bin_fifo_empty : std_logic;
|
||||||
|
|
||||||
alias bout_fifo_addr_in is bout_fifo_din(31 downto 0);
|
alias bout_fifo_addr_in is bout_fifo_din(31 downto 0);
|
||||||
alias bout_fifo_data_in is bout_fifo_din(63 downto 32);
|
alias bout_fifo_data_in is bout_fifo_din(63 downto 32);
|
||||||
alias bout_fifo_sel_in is bout_fifo_din(67 downto 64);
|
alias bout_fifo_sel_in is bout_fifo_din(67 downto 64);
|
||||||
@@ -178,7 +197,6 @@ architecture behavior of biu is
|
|||||||
signal write_fifo_we : std_logic;
|
signal write_fifo_we : std_logic;
|
||||||
signal write_fifo_full : std_logic;
|
signal write_fifo_full : std_logic;
|
||||||
signal write_fifo_empty : std_logic;
|
signal write_fifo_empty : std_logic;
|
||||||
signal write_busy : std_logic;
|
|
||||||
|
|
||||||
alias write_fifo_addr_in is write_fifo_din(31 downto 0);
|
alias write_fifo_addr_in is write_fifo_din(31 downto 0);
|
||||||
alias write_fifo_data_in is write_fifo_din(63 downto 32);
|
alias write_fifo_data_in is write_fifo_din(63 downto 32);
|
||||||
@@ -191,13 +209,10 @@ architecture behavior of biu is
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
|
|
||||||
MRDY_O <= '1';
|
|
||||||
|
|
||||||
read_cyc_register:
|
read_cyc_register:
|
||||||
process(CLK_I)
|
process(cpu_clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(cpu_clk) then
|
||||||
if RST_I = '1' then
|
if RST_I = '1' then
|
||||||
read_cycle <= '0';
|
read_cycle <= '0';
|
||||||
else
|
else
|
||||||
@@ -208,6 +223,7 @@ read_cyc_register:
|
|||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
MRDY_O <= not bin_fifo_full;
|
||||||
CYC_O <= not bout_fifo_empty or read_cycle;
|
CYC_O <= not bout_fifo_empty or read_cycle;
|
||||||
STB_O <= not bout_fifo_empty;
|
STB_O <= not bout_fifo_empty;
|
||||||
ADDR_O <= bout_fifo_addr_out;
|
ADDR_O <= bout_fifo_addr_out;
|
||||||
@@ -216,26 +232,27 @@ read_cyc_register:
|
|||||||
WE_O <= bout_fifo_we_out;
|
WE_O <= bout_fifo_we_out;
|
||||||
|
|
||||||
cpu_imem_rdy <= not icache_busy after 4.5 ns;
|
cpu_imem_rdy <= not icache_busy after 4.5 ns;
|
||||||
busy <= CYC_O_dmem_rd or dcache_busy or (write_busy);
|
busy <= CYC_O_dmem_rd or dcache_busy or (write_fifo_full);
|
||||||
cpu_dmem_rdy <= not busy after 4.5 ns;
|
cpu_dmem_rdy <= not busy after 4.5 ns;
|
||||||
|
|
||||||
inst_icache : icache
|
inst_icache : icache
|
||||||
GENERIC MAP
|
GENERIC MAP
|
||||||
(
|
(
|
||||||
cache_size => icache_size, -- words
|
cache_size => icache_size, -- words
|
||||||
line_size => 8
|
line_size => icache_line -- words
|
||||||
)
|
)
|
||||||
PORT MAP
|
PORT MAP
|
||||||
(
|
(
|
||||||
CLK_I => CLK_I,
|
CLK_I => cpu_clk,
|
||||||
RST_I => RST_I,
|
RST_I => RST_I,
|
||||||
STB_O => STB_O_icache,
|
STB_O => STB_O_icache,
|
||||||
CYC_O => CYC_O_icache,
|
CYC_O => CYC_O_icache,
|
||||||
ADDR_O => ADDR_O_icache,
|
ADDR_O => ADDR_O_icache,
|
||||||
DAT_I => DAT_I,
|
MRDY_O => MRDY_O_icache,
|
||||||
ACK_I => ACK_I,
|
DAT_I => DAT,
|
||||||
|
ACK_I => ACK,
|
||||||
SRDY_I => SRDY_I_icache,
|
SRDY_I => SRDY_I_icache,
|
||||||
en => '1',
|
ctrl => cop0_ctrl_in.icache,
|
||||||
cpu_en => cpu_imem_en,
|
cpu_en => cpu_imem_en,
|
||||||
cpu_addr => cpu_imem_addr,
|
cpu_addr => cpu_imem_addr,
|
||||||
cpu_dout => cpu_imem_din,
|
cpu_dout => cpu_imem_din,
|
||||||
@@ -248,19 +265,20 @@ inst_dcache : dcache
|
|||||||
GENERIC MAP
|
GENERIC MAP
|
||||||
(
|
(
|
||||||
cache_size => dcache_size, -- words
|
cache_size => dcache_size, -- words
|
||||||
line_size => 8
|
line_size => dcache_line -- words
|
||||||
)
|
)
|
||||||
PORT MAP
|
PORT MAP
|
||||||
(
|
(
|
||||||
CLK_I => CLK_I,
|
CLK_I => cpu_clk,
|
||||||
RST_I => RST_I,
|
RST_I => RST_I,
|
||||||
CYC_O => CYC_O_dcache,
|
CYC_O => CYC_O_dcache,
|
||||||
STB_O => STB_O_dcache,
|
STB_O => STB_O_dcache,
|
||||||
ADDR_O => ADDR_O_dcache,
|
ADDR_O => ADDR_O_dcache,
|
||||||
DAT_I => DAT_I,
|
MRDY_O => MRDY_O_dcache,
|
||||||
ACK_I => ACK_I,
|
DAT_I => DAT,
|
||||||
|
ACK_I => ACK,
|
||||||
SRDY_I => SRDY_I_dcache,
|
SRDY_I => SRDY_I_dcache,
|
||||||
en => dcached,
|
ctrl => cop0_ctrl_in.dcache,
|
||||||
cpu_en => dcache_en,
|
cpu_en => dcache_en,
|
||||||
cpu_we => cpu_dmem_we,
|
cpu_we => cpu_dmem_we,
|
||||||
cpu_be => cpu_dmem_be,
|
cpu_be => cpu_dmem_be,
|
||||||
@@ -272,21 +290,52 @@ inst_dcache : dcache
|
|||||||
|
|
||||||
SRDY_I_dcache <= bout_rdy and dcache_mem_gnt;
|
SRDY_I_dcache <= bout_rdy and dcache_mem_gnt;
|
||||||
|
|
||||||
dcached <= '1' when cpu_dmem_addr(31 downto 28) /= X"A" else '0';
|
dcached <= '1' when cpu_dmem_addr(31 downto 29) /= "101" else '0';
|
||||||
cpu_dmem_din <= dcache_dout when uncached_access = '0' else DAT_I_dmem_rd;
|
cpu_dmem_din <= dcache_dout when uncached_access = '0' else DAT_I_dmem_rd;
|
||||||
dcache_en <= cpu_dmem_en and not busy;
|
dcache_en <= dcached and cpu_dmem_en and dcache_en2; -- or write_fifo_full);
|
||||||
|
|
||||||
-- Instantiate synchronous FIFO
|
-- Instantiate synchronous FIFO
|
||||||
inst_bout_fifo: entity work.fifo_sync_dist
|
inst_bin_fifo: entity work.fifo_async
|
||||||
GENERIC MAP
|
GENERIC MAP
|
||||||
(
|
(
|
||||||
addr_width => 4,
|
addr_width => 4,
|
||||||
data_width => 69
|
data_width => 32,
|
||||||
|
do_last_read_update => true
|
||||||
)
|
)
|
||||||
PORT MAP
|
PORT MAP
|
||||||
(
|
(
|
||||||
rst => RST_I,
|
rst => RST_I,
|
||||||
clk => CLK_I,
|
clk_w => CLK_I,
|
||||||
|
clk_r => cpu_clk,
|
||||||
|
we => bin_fifo_we,
|
||||||
|
re => bin_fifo_re,
|
||||||
|
fifo_full => bin_fifo_full,
|
||||||
|
fifo_empty => bin_fifo_empty,
|
||||||
|
fifo_afull => open,
|
||||||
|
fifo_aempty => open,
|
||||||
|
data_w => bin_fifo_din,
|
||||||
|
data_r => bin_fifo_dout
|
||||||
|
);
|
||||||
|
|
||||||
|
bin_fifo_din <= DAT_I;
|
||||||
|
DAT <= bin_fifo_dout;
|
||||||
|
ACK <= not bin_fifo_empty;
|
||||||
|
bin_fifo_we <= ACK_I;
|
||||||
|
bin_fifo_re <= dmem_mem_rd_gnt or MRDY_O_icache or MRDY_O_dcache;
|
||||||
|
|
||||||
|
-- Instantiate synchronous FIFO
|
||||||
|
inst_bout_fifo: entity work.fifo_async
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
addr_width => 4,
|
||||||
|
data_width => 69,
|
||||||
|
do_last_read_update => false
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => RST_I,
|
||||||
|
clk_w => cpu_clk,
|
||||||
|
clk_r => CLK_I,
|
||||||
we => bout_fifo_we,
|
we => bout_fifo_we,
|
||||||
re => bout_fifo_re,
|
re => bout_fifo_re,
|
||||||
fifo_full => bout_fifo_full,
|
fifo_full => bout_fifo_full,
|
||||||
@@ -297,7 +346,7 @@ inst_bout_fifo: entity work.fifo_sync_dist
|
|||||||
data_r => bout_fifo_dout
|
data_r => bout_fifo_dout
|
||||||
);
|
);
|
||||||
bout_rdy <= not bout_fifo_full;
|
bout_rdy <= not bout_fifo_full;
|
||||||
bout_fifo_re <= not bout_fifo_empty and SRDY_I;
|
bout_fifo_re <= SRDY_I and not bin_fifo_full;
|
||||||
|
|
||||||
bout_fifo_we <= STB_O_dmem_wr or STB_O_dmem_rd or STB_O_dcache or STB_O_icache;
|
bout_fifo_we <= STB_O_dmem_wr or STB_O_dmem_rd or STB_O_dcache or STB_O_icache;
|
||||||
|
|
||||||
@@ -308,23 +357,26 @@ inst_bout_fifo: entity work.fifo_sync_dist
|
|||||||
ADDR_O_dcache when dcache_mem_gnt = '1' else
|
ADDR_O_dcache when dcache_mem_gnt = '1' else
|
||||||
ADDR_O_icache when icache_mem_gnt = '1' else (others => '-');
|
ADDR_O_icache when icache_mem_gnt = '1' else (others => '-');
|
||||||
|
|
||||||
bout_fifo_sel_in <= SEL_O_dmem_wr when dmem_mem_wr_gnt = '1' else (others => '0');
|
bout_fifo_sel_in <= SEL_O_dmem_wr when dmem_mem_wr_gnt = '1' else
|
||||||
|
SEL_O_dmem_rd when dmem_mem_rd_gnt = '1' else (others => '1');
|
||||||
|
|
||||||
bout_fifo_we_in <= '1' when dmem_mem_wr_gnt = '1' else '0';
|
bout_fifo_we_in <= '1' when dmem_mem_wr_gnt = '1' else '0';
|
||||||
|
|
||||||
-- Instantiate synchronous FIFO
|
-- Instantiate synchronous FIFO
|
||||||
inst_write_fifo: entity work.fifo_sync_dist
|
inst_write_fifo: entity work.fifo_sync
|
||||||
GENERIC MAP
|
GENERIC MAP
|
||||||
(
|
(
|
||||||
addr_width => 4,
|
addr_width => 4,
|
||||||
data_width => 68
|
data_width => 68,
|
||||||
|
do_last_read_update => true
|
||||||
)
|
)
|
||||||
PORT MAP
|
PORT MAP
|
||||||
(
|
(
|
||||||
rst => RST_I,
|
rst => RST_I,
|
||||||
clk => CLK_I,
|
clk => cpu_clk,
|
||||||
we => write_fifo_we,
|
we => write_fifo_we,
|
||||||
re => write_fifo_re,
|
re => write_fifo_re,
|
||||||
fifo_full => write_busy,
|
fifo_full => write_fifo_full,
|
||||||
fifo_empty => write_fifo_empty,
|
fifo_empty => write_fifo_empty,
|
||||||
fifo_afull => open,
|
fifo_afull => open,
|
||||||
fifo_aempty => open,
|
fifo_aempty => open,
|
||||||
@@ -344,20 +396,23 @@ inst_write_fifo: entity work.fifo_sync_dist
|
|||||||
write_fifo_we <= cpu_dmem_en and not busy and cpu_dmem_we;
|
write_fifo_we <= cpu_dmem_en and not busy and cpu_dmem_we;
|
||||||
|
|
||||||
dmem_rd_flags:
|
dmem_rd_flags:
|
||||||
process(CLK_I)
|
process(cpu_clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(cpu_clk) then
|
||||||
uncached_access <= '0';
|
uncached_access <= '0';
|
||||||
if RST_I = '1' then
|
if RST_I = '1' then
|
||||||
CYC_O_dmem_rd <= '0';
|
CYC_O_dmem_rd <= '0';
|
||||||
|
dcache_en2 <= '1';
|
||||||
else
|
else
|
||||||
if ACK_I = '1' and dmem_mem_rd_gnt = '1' then
|
if ACK = '1' and dmem_mem_rd_gnt = '1' then
|
||||||
uncached_access <= '1';
|
uncached_access <= '1';
|
||||||
CYC_O_dmem_rd <= '0';
|
CYC_O_dmem_rd <= '0';
|
||||||
|
dcache_en2 <= '1';
|
||||||
end if;
|
end if;
|
||||||
if cpu_dmem_en = '1' and busy = '0' and cpu_dmem_we = '0' then
|
if cpu_dmem_en = '1' and busy = '0' and cpu_dmem_we = '0' then
|
||||||
if dcached = '0' then
|
if dcached = '0' then
|
||||||
CYC_O_dmem_rd <= '1';
|
CYC_O_dmem_rd <= '1';
|
||||||
|
dcache_en2 <= '0';
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
@@ -365,31 +420,32 @@ dmem_rd_flags:
|
|||||||
end process;
|
end process;
|
||||||
|
|
||||||
dmem_rd_data:
|
dmem_rd_data:
|
||||||
process(CLK_I)
|
process(cpu_clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(cpu_clk) then
|
||||||
if RST_I = '1' then
|
if RST_I = '1' then
|
||||||
DAT_I_dmem_rd <= (others => '0');
|
DAT_I_dmem_rd <= (others => '0');
|
||||||
elsif ACK_I = '1' and CYC_O_dmem_rd = '1' then
|
elsif ACK = '1' and CYC_O_dmem_rd = '1' then
|
||||||
DAT_I_dmem_rd <= DAT_I;
|
DAT_I_dmem_rd <= DAT;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
dmem_rd_regs:
|
dmem_rd_regs:
|
||||||
process(CLK_I)
|
process(cpu_clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(cpu_clk) then
|
||||||
if cpu_dmem_en = '1' and busy = '0' then
|
if cpu_dmem_en = '1' and busy = '0' then
|
||||||
ADDR_O_dmem_rd <= cpu_dmem_addr;
|
ADDR_O_dmem_rd <= cpu_dmem_addr;
|
||||||
|
SEL_O_dmem_rd <= cpu_dmem_be;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
bus_state_next:
|
bus_state_next:
|
||||||
process(CLK_I)
|
process(cpu_clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(cpu_clk) then
|
||||||
if RST_I = '1' then
|
if RST_I = '1' then
|
||||||
s <= init;
|
s <= init;
|
||||||
else
|
else
|
||||||
@@ -399,7 +455,7 @@ bus_state_next:
|
|||||||
end process;
|
end process;
|
||||||
|
|
||||||
bus_state:
|
bus_state:
|
||||||
process(s, CYC_O_icache, CYC_O_dcache, CYC_O_dmem_wr, CYC_O_dmem_rd, bout_rdy, ACK_I)
|
process(s, CYC_O_icache, CYC_O_dcache, CYC_O_dmem_wr, CYC_O_dmem_rd, bout_rdy, ACK)
|
||||||
begin
|
begin
|
||||||
|
|
||||||
icache_mem_gnt <= '0';
|
icache_mem_gnt <= '0';
|
||||||
@@ -451,7 +507,7 @@ bus_state:
|
|||||||
end if;
|
end if;
|
||||||
when read_finish =>
|
when read_finish =>
|
||||||
dmem_mem_rd_gnt <= '1';
|
dmem_mem_rd_gnt <= '1';
|
||||||
if ACK_I = '1' then
|
if ACK = '1' then
|
||||||
sn <= ready;
|
sn <= ready;
|
||||||
end if;
|
end if;
|
||||||
when others =>
|
when others =>
|
||||||
@@ -461,9 +517,9 @@ bus_state:
|
|||||||
end process;
|
end process;
|
||||||
|
|
||||||
bus_timeout_counter:
|
bus_timeout_counter:
|
||||||
process(CLK_I)
|
process(cpu_clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(cpu_clk) then
|
||||||
if bus_idle = '0' then
|
if bus_idle = '0' then
|
||||||
if bus_timeout_cnt /= 0 then
|
if bus_timeout_cnt /= 0 then
|
||||||
bus_timeout_cnt <= bus_timeout_cnt - 1;
|
bus_timeout_cnt <= bus_timeout_cnt - 1;
|
||||||
@@ -478,9 +534,9 @@ bus_timeout_counter:
|
|||||||
end process;
|
end process;
|
||||||
|
|
||||||
bus_err:
|
bus_err:
|
||||||
process(CLK_I)
|
process(cpu_clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(CLK_I) then
|
if rising_edge(cpu_clk) then
|
||||||
if RST_I = '1' then
|
if RST_I = '1' then
|
||||||
cpu_imem_err <= '0';
|
cpu_imem_err <= '0';
|
||||||
cpu_dmem_err <= '0';
|
cpu_dmem_err <= '0';
|
||||||
|
|||||||
+244
-113
@@ -29,16 +29,24 @@ use work.mips_types.all;
|
|||||||
use work.mips_instr.all;
|
use work.mips_instr.all;
|
||||||
|
|
||||||
entity cop is
|
entity cop is
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
icache_size : natural := 2048; -- words
|
||||||
|
icache_line : natural := 8; -- words
|
||||||
|
dcache_size : natural := 2048; -- words
|
||||||
|
dcache_line : natural := 8 -- words
|
||||||
|
);
|
||||||
Port
|
Port
|
||||||
(
|
(
|
||||||
rst : in STD_LOGIC;
|
rst : in STD_LOGIC;
|
||||||
clk : in STD_LOGIC;
|
clk : in STD_LOGIC;
|
||||||
sdu : in sdu_t;
|
eb : in STD_LOGIC;
|
||||||
IR_valid : in STD_LOGIC;
|
int : in unsigned(5 downto 0);
|
||||||
IR : in word_t;
|
nmi : in STD_LOGIC;
|
||||||
events : in event_t;
|
ir_en : in STD_LOGIC;
|
||||||
ctrl_in : in cop_ctrl_in_t;
|
ir : in word_t;
|
||||||
ctrl_out : out cop_ctrl_out_t;
|
ctrl_in : in cop0_ctrl_in_t;
|
||||||
|
ctrl_out : out cop0_ctrl_out_t;
|
||||||
din : in word_t;
|
din : in word_t;
|
||||||
dout : out word_t
|
dout : out word_t
|
||||||
);
|
);
|
||||||
@@ -49,6 +57,8 @@ architecture Behavioral of cop is
|
|||||||
signal epc : word_t;
|
signal epc : word_t;
|
||||||
signal cause : word_t;
|
signal cause : word_t;
|
||||||
signal status : word_t;
|
signal status : word_t;
|
||||||
|
signal imem_addr : word_t;
|
||||||
|
signal imem_addr_we : STD_LOGIC;
|
||||||
signal BadVAddr : word_t;
|
signal BadVAddr : word_t;
|
||||||
signal exc_code : unsigned(4 downto 0);
|
signal exc_code : unsigned(4 downto 0);
|
||||||
signal test_reg : word_t;
|
signal test_reg : word_t;
|
||||||
@@ -59,20 +69,30 @@ architecture Behavioral of cop is
|
|||||||
signal code_reg_we : STD_LOGIC;
|
signal code_reg_we : STD_LOGIC;
|
||||||
signal ip_reg_we : STD_LOGIC;
|
signal ip_reg_we : STD_LOGIC;
|
||||||
signal bd : STD_LOGIC;
|
signal bd : STD_LOGIC;
|
||||||
|
signal sw_int : unsigned(1 downto 0);
|
||||||
signal ip : unsigned(7 downto 0);
|
signal ip : unsigned(7 downto 0);
|
||||||
signal im : unsigned(7 downto 0);
|
signal im : unsigned(7 downto 0);
|
||||||
signal status_save : STD_LOGIC;
|
signal status_save : STD_LOGIC;
|
||||||
signal status_rest : STD_LOGIC;
|
signal status_rest : STD_LOGIC;
|
||||||
signal exception : STD_LOGIC;
|
|
||||||
signal exception_end : STD_LOGIC;
|
|
||||||
signal eflags : exc_flags_t;
|
signal eflags : exc_flags_t;
|
||||||
signal exc_enable : STD_LOGIC;
|
signal EB_reg : STD_LOGIC;
|
||||||
signal cop_EX_en : STD_LOGIC;
|
signal icache_info : unsigned(7 downto 0);
|
||||||
|
signal dcache_info : unsigned(7 downto 0);
|
||||||
|
signal reg_rptr : reg_ptr_t;
|
||||||
|
signal reg_wptr : reg_ptr_t;
|
||||||
|
signal inject_exc : STD_LOGIC;
|
||||||
|
signal latch_vect_en : STD_LOGIC;
|
||||||
|
signal int_nmi : STD_LOGIC;
|
||||||
|
signal nmi_asserted : std_logic;
|
||||||
|
|
||||||
type cop_pipe_t is record
|
type cop_pipe_t is record
|
||||||
din : word_t;
|
opc : opcode_t;
|
||||||
|
RFE : std_logic;
|
||||||
|
CO : std_logic;
|
||||||
|
reg_ptr : reg_ptr_t;
|
||||||
rs : reg_ptr_t;
|
rs : reg_ptr_t;
|
||||||
rd : reg_ptr_t;
|
rd : reg_ptr_t;
|
||||||
|
rt : reg_ptr_t;
|
||||||
func : func_t;
|
func : func_t;
|
||||||
we : std_logic;
|
we : std_logic;
|
||||||
re : std_logic;
|
re : std_logic;
|
||||||
@@ -93,93 +113,130 @@ architecture Behavioral of cop is
|
|||||||
return result;
|
return result;
|
||||||
end eval_int;
|
end eval_int;
|
||||||
|
|
||||||
type exc_state_t is (exc_init, exc_idle, exc_commit_ID, exc_commit_EX, exc_commit_MEM);
|
type exc_state_t is (exc_idle, exc_pipe_flush, exc_commit, exc_inject, exc_enter, exc_leave, exc_left);
|
||||||
signal exc_state, exc_staten : exc_state_t;
|
signal exc_state, exc_staten : exc_state_t;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
begin
|
begin
|
||||||
|
|
||||||
cop_pipe_ID.din <= din;
|
icache_info <= "00" & to_unsigned(lg2(icache_line), 3) & to_unsigned(lg2(icache_size)-8, 3);
|
||||||
cop_pipe_ID.cs <= IR_valid;
|
dcache_info <= "00" & to_unsigned(lg2(dcache_line), 3) & to_unsigned(lg2(dcache_size)-8, 3);
|
||||||
cop_pipe_ID.rs <= extract_rs(IR);
|
cop_pipe_ID.cs <= ir_en;
|
||||||
cop_pipe_ID.rd <= extract_rd(IR);
|
cop_pipe_ID.opc <= extract_opc(ir);
|
||||||
cop_pipe_ID.func <= extract_func(IR);
|
cop_pipe_ID.rs <= extract_rs(ir);
|
||||||
cop_pipe_ID.re <= cop_pipe_ID.cs when cop_pipe_ID.rs = "00000" else '0';
|
cop_pipe_ID.rd <= extract_rd(ir);
|
||||||
cop_pipe_ID.we <= cop_pipe_ID.cs when cop_pipe_ID.rs = "00100" else '0';
|
cop_pipe_ID.rt <= extract_rt(ir);
|
||||||
cop_EX_en <= exc_enable and not status_save;
|
cop_pipe_ID.func <= extract_func(ir);
|
||||||
|
cop_pipe_ID.CO <= ir(25);
|
||||||
ctrl_out.ee <= exc_enable;
|
cop_pipe_ID.re <= cop_pipe_ID.cs when (cop_pipe_ID.opc = "111000" or (cop_pipe_ID.opc = "010000" and cop_pipe_ID.rs = "00000")) else '0';
|
||||||
ctrl_out.ec <= status_save;
|
cop_pipe_ID.we <= cop_pipe_ID.cs when (cop_pipe_ID.opc = "110000" or (cop_pipe_ID.opc = "010000" and cop_pipe_ID.rs = "00100")) else '0';
|
||||||
ctrl_out.RE <= status(25);
|
cop_pipe_ID.RFE <= cop_pipe_ID.cs when (cop_pipe_ID.CO = '1' and cop_pipe_ID.func = "010000") else '0';
|
||||||
|
ctrl_out.EB <= EB_reg xor (status(25) and status(1));
|
||||||
ctrl_out.user_mode <= status(1);
|
ctrl_out.user_mode <= status(1);
|
||||||
ctrl_out.int <= eflags.Int;
|
ctrl_out.exc_inject <= inject_exc or rst;
|
||||||
|
cop_pipe_ID.reg_ptr <= cop_pipe_ID.rd when cop_pipe_ID.opc = "010000" else cop_pipe_ID.rt;
|
||||||
ctrl_out.cop_read <= cop_pipe_EX.cs and cop_pipe_EX.re after 1 ns;
|
|
||||||
ctrl_out.reg_write <= cop_pipe_ID.re after 1 ns;
|
|
||||||
|
|
||||||
im <= status(15 downto 8);
|
im <= status(15 downto 8);
|
||||||
cause <= bd & (30 downto 16 => '0') & ip & '0' & exc_code & "00";
|
cause <= bd & (30 downto 16 => '0') & ip & '0' & exc_code & "00";
|
||||||
|
|
||||||
eflags.Ov <= events.alu_ovf or events.alu_uvf;
|
eflags.Ov <= ctrl_in.events.alu_ovf or ctrl_in.events.alu_uvf;
|
||||||
eflags.DAdEL <= events.data_load_err;
|
eflags.DAdEL <= ctrl_in.events.data_load_err;
|
||||||
eflags.DAdES <= events.data_store_err;
|
eflags.DAdES <= ctrl_in.events.data_store_err;
|
||||||
eflags.IAdEL <= events.inst_load_err;
|
eflags.IAdEL <= ctrl_in.events.inst_load_err;
|
||||||
eflags.IAdEK <= events.inst_priv_addr and status(1);
|
eflags.IAdEK <= ctrl_in.events.inst_priv_addr and status(1);
|
||||||
eflags.Sys <= events.syscall;
|
eflags.Sys <= ctrl_in.events.syscall;
|
||||||
eflags.Bp <= events.break;
|
eflags.Bp <= ctrl_in.events.break;
|
||||||
eflags.RI <= events.illegal;
|
eflags.RI <= ctrl_in.events.illegal;
|
||||||
eflags.Int <= eval_int(ip) and status(0);
|
eflags.Int <= ctrl_in.events.int;
|
||||||
|
|
||||||
exception <= eflags.Ov or eflags.Sys or eflags.Bp or eflags.RI or eflags.IAdEL or eflags.IAdEK or eflags.DAdEL or eflags.DAdES or eflags.Int after 1 ns;
|
-- NMI/RST transition detector
|
||||||
|
proc_nmi_transition:
|
||||||
|
process(clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if rst = '1' then
|
||||||
|
int_nmi <= '0';
|
||||||
|
nmi_asserted <= '0';
|
||||||
|
elsif latch_vect_en = '1' then
|
||||||
|
int_nmi <= '0';
|
||||||
|
elsif nmi_asserted = '1' then
|
||||||
|
if nmi = '0' then
|
||||||
|
nmi_asserted <= '0';
|
||||||
|
int_nmi <= '1';
|
||||||
|
end if;
|
||||||
|
elsif nmi = '1' then
|
||||||
|
nmi_asserted <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
exception_state:
|
|
||||||
process(exc_state, ctrl_in, exception, sdu)
|
-- Main exception FSM
|
||||||
|
proc_exc_state:
|
||||||
|
process(exc_state, ctrl_in, cop_pipe_ID)
|
||||||
begin
|
begin
|
||||||
|
|
||||||
exc_enable <= '0';
|
|
||||||
ctrl_out.exc_commit <= '0';
|
ctrl_out.exc_commit <= '0';
|
||||||
ctrl_out.exc_pending <= '0';
|
ctrl_out.exc_pending <= '0';
|
||||||
|
ctrl_out.exc_exit <= '0';
|
||||||
epc_reg_we <= '0';
|
epc_reg_we <= '0';
|
||||||
code_reg_we <= '0';
|
code_reg_we <= '0';
|
||||||
status_save <= '0';
|
status_save <= '0';
|
||||||
eflags_reg_we <= '0';
|
status_rest <= '0';
|
||||||
|
inject_exc <= '0';
|
||||||
|
imem_addr_we <= '0';
|
||||||
|
latch_vect_en <= '0';
|
||||||
|
|
||||||
exc_staten <= exc_state;
|
exc_staten <= exc_state;
|
||||||
|
|
||||||
case exc_state is
|
case exc_state is
|
||||||
|
|
||||||
when exc_init =>
|
|
||||||
exc_staten <= exc_idle;
|
|
||||||
|
|
||||||
when exc_idle =>
|
when exc_idle =>
|
||||||
exc_enable <= '1';
|
if cop_pipe_ID.RFE = '1' then
|
||||||
if exception = '1' then
|
exc_staten <= exc_leave;
|
||||||
status_save <= '1';
|
ctrl_out.exc_exit <= '1';
|
||||||
eflags_reg_we <= '1';
|
ctrl_out.exc_commit <= '1';
|
||||||
|
elsif ctrl_in.exc_req = '1' then
|
||||||
|
exc_staten <= exc_pipe_flush;
|
||||||
|
imem_addr_we <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when exc_pipe_flush =>
|
||||||
|
ctrl_out.exc_pending <= '1';
|
||||||
|
ctrl_out.exc_commit <= '1';
|
||||||
|
if ctrl_in.exc_ack = '1' then
|
||||||
|
exc_staten <= exc_commit;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when exc_commit =>
|
||||||
|
latch_vect_en <= '1';
|
||||||
|
ctrl_out.exc_pending <= '1';
|
||||||
|
ctrl_out.exc_commit <= '1';
|
||||||
|
if ctrl_in.sdu.ID_stall = '0' then
|
||||||
|
exc_staten <= exc_inject;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when exc_inject =>
|
||||||
|
ctrl_out.exc_pending <= '1';
|
||||||
|
ctrl_out.exc_commit <= '1';
|
||||||
code_reg_we <= '1';
|
code_reg_we <= '1';
|
||||||
exc_staten <= exc_commit_ID;
|
status_save <= '1';
|
||||||
end if;
|
|
||||||
|
|
||||||
when exc_commit_ID =>
|
|
||||||
ctrl_out.exc_pending <= '1';
|
|
||||||
ctrl_out.exc_commit <= '1';
|
|
||||||
if sdu.ID_stall = '0' then
|
|
||||||
exc_staten <= exc_commit_EX;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when exc_commit_EX =>
|
|
||||||
ctrl_out.exc_pending <= '1';
|
|
||||||
ctrl_out.exc_commit <= '1';
|
|
||||||
if sdu.EX_stall = '0' then
|
|
||||||
exc_staten <= exc_commit_MEM;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when exc_commit_MEM =>
|
|
||||||
ctrl_out.exc_pending <= '1';
|
|
||||||
if sdu.MEM_stall = '0' then
|
|
||||||
epc_reg_we <= '1';
|
epc_reg_we <= '1';
|
||||||
|
inject_exc <= '1';
|
||||||
|
exc_staten <= exc_enter;
|
||||||
|
|
||||||
|
when exc_enter =>
|
||||||
|
ctrl_out.exc_pending <= '1';
|
||||||
|
exc_staten <= exc_idle;
|
||||||
|
|
||||||
|
when exc_leave =>
|
||||||
|
exc_staten <= exc_left;
|
||||||
|
status_rest <= '1';
|
||||||
|
ctrl_out.exc_exit <= '1';
|
||||||
|
ctrl_out.exc_commit <= '1';
|
||||||
|
|
||||||
|
when exc_left =>
|
||||||
exc_staten <= exc_idle;
|
exc_staten <= exc_idle;
|
||||||
end if;
|
|
||||||
|
|
||||||
when others =>
|
when others =>
|
||||||
exc_staten <= exc_idle;
|
exc_staten <= exc_idle;
|
||||||
@@ -187,18 +244,41 @@ exception_state:
|
|||||||
end case;
|
end case;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
exception_state_next:
|
proc_exc_state_next:
|
||||||
process(clk)
|
process(clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk) then
|
if rising_edge(clk) then
|
||||||
if rst = '1' then
|
if rst = '1' then
|
||||||
exc_state <= exc_init;
|
exc_state <= exc_idle;
|
||||||
else
|
else
|
||||||
exc_state <= exc_staten;
|
exc_state <= exc_staten;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
-- Endian switch sampled at hard reset
|
||||||
|
sample_endian:
|
||||||
|
process(clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if rst = '1' then
|
||||||
|
EB_reg <= eb;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Sample imem_addr for later use
|
||||||
|
exception_last_imem_addr:
|
||||||
|
process(clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if imem_addr_we = '1' then
|
||||||
|
imem_addr <= ctrl_in.imem_addr;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- EPC reg and BD-bit write
|
||||||
cop_exception_epc_write:
|
cop_exception_epc_write:
|
||||||
process(clk)
|
process(clk)
|
||||||
begin
|
begin
|
||||||
@@ -217,6 +297,7 @@ cop_exception_epc_write:
|
|||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
-- BadVaddr and exception code write
|
||||||
cop_exception_map:
|
cop_exception_map:
|
||||||
process(clk)
|
process(clk)
|
||||||
begin
|
begin
|
||||||
@@ -235,10 +316,10 @@ cop_exception_map:
|
|||||||
exc_code <= "01010";
|
exc_code <= "01010";
|
||||||
elsif eflags.IAdEL = '1' then
|
elsif eflags.IAdEL = '1' then
|
||||||
exc_code <= "00100";
|
exc_code <= "00100";
|
||||||
BadVAddr <= ctrl_in.imem_addr;
|
BadVAddr <= imem_addr;
|
||||||
elsif eflags.IAdEK = '1' then
|
elsif eflags.IAdEK = '1' then
|
||||||
exc_code <= "00100";
|
exc_code <= "00100";
|
||||||
BadVAddr <= ctrl_in.imem_addr;
|
BadVAddr <= imem_addr;
|
||||||
elsif eflags.DAdEL = '1' then
|
elsif eflags.DAdEL = '1' then
|
||||||
exc_code <= "00100";
|
exc_code <= "00100";
|
||||||
BadVAddr <= ctrl_in.dmem_addr;
|
BadVAddr <= ctrl_in.dmem_addr;
|
||||||
@@ -252,51 +333,78 @@ cop_exception_map:
|
|||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
status_rest <= exception_end and ctrl_in.exc_left;
|
ctrl_out.icache.inv_addr <= test_reg;
|
||||||
|
ctrl_out.dcache.inv_addr <= test_reg;
|
||||||
|
|
||||||
cop_status_restore:
|
-- Custom I/D-Cache operations: invalidate all/line
|
||||||
|
cop_cache_op:
|
||||||
process(clk)
|
process(clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk) then
|
if rising_edge(clk) then
|
||||||
if rst = '1' then
|
ctrl_out.icache.inv_at <= '0';
|
||||||
exception_end <= '0';
|
ctrl_out.icache.inv_all <= '0';
|
||||||
ctrl_out.exc_exit <= '0';
|
ctrl_out.dcache.inv_at <= '0';
|
||||||
else
|
ctrl_out.dcache.inv_all <= '0';
|
||||||
if cop_pipe_ID.func = "10000" and exception_end = '0' then -- RFE
|
if cop_pipe_ID.cs = '1' and cop_pipe_ID.CO = '1' then
|
||||||
exception_end <= cop_pipe_ID.cs;
|
case cop_pipe_ID.func is
|
||||||
ctrl_out.exc_exit <= cop_pipe_ID.cs;
|
when "100000" =>
|
||||||
elsif exception_end = '1' and ctrl_in.exc_left = '1' then
|
ctrl_out.icache.inv_all <= '1';
|
||||||
exception_end <= '0';
|
when "100001" =>
|
||||||
ctrl_out.exc_exit <= '0';
|
ctrl_out.icache.inv_at <= '1';
|
||||||
end if;
|
when "100010" =>
|
||||||
|
ctrl_out.dcache.inv_all <= '1';
|
||||||
|
when "100011" =>
|
||||||
|
ctrl_out.dcache.inv_at <= '1';
|
||||||
|
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
-- IP register write and signalling Int to pipeline
|
||||||
cop_ip_reg_write:
|
cop_ip_reg_write:
|
||||||
process(clk)
|
process(clk)
|
||||||
|
variable ip_v : unsigned(7 downto 0);
|
||||||
|
variable ipm_v : unsigned(7 downto 0);
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk) then
|
if rising_edge(clk) then
|
||||||
if rst = '1' then
|
if rst = '1' then
|
||||||
ip(1 downto 0) <= (others => '0');
|
sw_int <= (others => '0');
|
||||||
elsif ip_reg_we = '1' then
|
elsif ctrl_in.sdu.WB_nop = '0' then
|
||||||
ip(1 downto 0) <= cop_pipe_EX.din(9 downto 8) and im(1 downto 0);
|
if ip_reg_we = '1' then
|
||||||
|
sw_int <= din(9 downto 8);
|
||||||
end if;
|
end if;
|
||||||
ip(7 downto 2) <= events.Int and im(7 downto 2);
|
end if;
|
||||||
|
ip_v := (int & sw_int);
|
||||||
|
ipm_v := ip_v and im;
|
||||||
|
ip <= ip_v;
|
||||||
|
ctrl_out.int <= (eval_int(ipm_v) and status(0));
|
||||||
|
ctrl_out.NMI <= int_nmi;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
-- Exception vector dispatch
|
||||||
cop_exc_vector:
|
cop_exc_vector:
|
||||||
process(clk)
|
process(clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk) then
|
if rising_edge(clk) then
|
||||||
ctrl_out.exc_vec <= X"80000180";
|
if rst = '1' then
|
||||||
|
ctrl_out.exc_vec <= X"BFC00000";
|
||||||
|
elsif latch_vect_en = '1' then
|
||||||
|
if ctrl_in.events.nmi = '1' then
|
||||||
|
ctrl_out.exc_vec <= X"BFC00000";
|
||||||
|
else
|
||||||
|
ctrl_out.exc_vec <= X"80000080";
|
||||||
if status(22) = '1' then
|
if status(22) = '1' then
|
||||||
ctrl_out.exc_vec <= X"BFC00180";
|
ctrl_out.exc_vec <= X"BFC00180";
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
-- Cop pipeline
|
||||||
cop_pipe:
|
cop_pipe:
|
||||||
process(clk)
|
process(clk)
|
||||||
begin
|
begin
|
||||||
@@ -305,20 +413,25 @@ cop_pipe:
|
|||||||
cop_pipe_EX.cs <= '0';
|
cop_pipe_EX.cs <= '0';
|
||||||
cop_pipe_EX.we <= '0';
|
cop_pipe_EX.we <= '0';
|
||||||
cop_pipe_EX.re <= '0';
|
cop_pipe_EX.re <= '0';
|
||||||
else
|
elsif ctrl_in.sdu.stall_all = '0' then
|
||||||
if sdu.EX_stall = '0' then
|
|
||||||
cop_pipe_EX <= cop_pipe_ID;
|
cop_pipe_EX <= cop_pipe_ID;
|
||||||
|
if cop_pipe_ID.we = '1' then
|
||||||
|
reg_wptr <= cop_pipe_ID.reg_ptr;
|
||||||
|
end if;
|
||||||
|
if cop_pipe_ID.re = '1' then
|
||||||
|
reg_rptr <= cop_pipe_ID.reg_ptr;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
-- COP Register read
|
||||||
cop_register_read:
|
cop_register_read:
|
||||||
process(clk)
|
process(reg_rptr, BadVAddr, status, cause, epc, dcache_info, icache_info, test_reg)
|
||||||
variable reg : word_t;
|
variable reg : word_t;
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk) and cop_pipe_ID.re = '1' and sdu.ID_stall = '0' then
|
|
||||||
case cop_pipe_ID.rd is
|
case reg_rptr is
|
||||||
when "01000" => -- BadVAddr
|
when "01000" => -- BadVAddr
|
||||||
reg := BadVAddr;
|
reg := BadVAddr;
|
||||||
|
|
||||||
@@ -332,7 +445,7 @@ cop_register_read:
|
|||||||
reg := epc;
|
reg := epc;
|
||||||
|
|
||||||
when "01111" => -- PRId (Processor Revision Register)
|
when "01111" => -- PRId (Processor Revision Register)
|
||||||
reg := X"000002" & to_unsigned(REVISION ,8);
|
reg := dcache_info & icache_info & X"02" & to_unsigned(REVISION ,8);
|
||||||
|
|
||||||
when "11111" => -- test_reg
|
when "11111" => -- test_reg
|
||||||
reg := test_reg;
|
reg := test_reg;
|
||||||
@@ -341,10 +454,12 @@ cop_register_read:
|
|||||||
reg := (others => '-');
|
reg := (others => '-');
|
||||||
|
|
||||||
end case;
|
end case;
|
||||||
dout <= reg after 1 ns;
|
|
||||||
end if;
|
dout <= reg after 2 ns;
|
||||||
|
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
-- COP Register write strobe generation
|
||||||
cop_we_gen:
|
cop_we_gen:
|
||||||
process(clk)
|
process(clk)
|
||||||
begin
|
begin
|
||||||
@@ -353,20 +468,20 @@ cop_we_gen:
|
|||||||
test_reg_we <= '0';
|
test_reg_we <= '0';
|
||||||
stat_reg_we <= '0';
|
stat_reg_we <= '0';
|
||||||
ip_reg_we <= '0';
|
ip_reg_we <= '0';
|
||||||
else
|
elsif ctrl_in.sdu.stall_all = '0' then
|
||||||
test_reg_we <= '0';
|
test_reg_we <= '0';
|
||||||
stat_reg_we <= '0';
|
stat_reg_we <= '0';
|
||||||
ip_reg_we <= '0';
|
ip_reg_we <= '0';
|
||||||
if (cop_EX_en and cop_pipe_EX.we) = '1' then
|
if cop_pipe_EX.we = '1' then
|
||||||
|
|
||||||
case cop_pipe_EX.rd is
|
case reg_wptr is
|
||||||
|
|
||||||
when "01100" =>
|
when "01100" =>
|
||||||
stat_reg_we <= not status(1) or status(28);
|
stat_reg_we <= '1'; -- not status(1) or status(28);
|
||||||
when "01101" =>
|
when "01101" =>
|
||||||
ip_reg_we <= not status(1) or status(28);
|
ip_reg_we <= '1'; -- not status(1) or status(28);
|
||||||
when "11111" =>
|
when "11111" =>
|
||||||
test_reg_we <= not status(1) or status(28);
|
test_reg_we <= '1'; -- not status(1) or status(28);
|
||||||
when others => null;
|
when others => null;
|
||||||
|
|
||||||
end case;
|
end case;
|
||||||
@@ -376,36 +491,52 @@ cop_we_gen:
|
|||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
-- COP Test Register
|
||||||
cop_test_reg_write:
|
cop_test_reg_write:
|
||||||
process(clk)
|
process(clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk) then
|
if rising_edge(clk) then
|
||||||
if rst = '1' then
|
if rst = '1' then
|
||||||
test_reg <= (others => '0');
|
test_reg <= (others => '0');
|
||||||
else --if ce = '1' then
|
elsif ctrl_in.sdu.WB_nop = '0' then
|
||||||
if test_reg_we = '1' then
|
if test_reg_we = '1' then
|
||||||
test_reg <= cop_pipe_EX.din;
|
test_reg <= din;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
-- COP Status Register
|
||||||
cop_status_reg_write:
|
cop_status_reg_write:
|
||||||
process(clk)
|
process(clk)
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk) then
|
if rising_edge(clk) then
|
||||||
if rst = '1' then
|
if rst = '1' then
|
||||||
status <= X"00400000";
|
status <= X"00600000";
|
||||||
else
|
elsif status_save = '1' then
|
||||||
if status_save = '1' then
|
if ctrl_in.events.nmi = '0' then
|
||||||
status(5 downto 4) <= status(3 downto 2);
|
status(5 downto 4) <= status(3 downto 2);
|
||||||
status(3 downto 2) <= status(1 downto 0);
|
status(3 downto 2) <= status(1 downto 0);
|
||||||
|
else
|
||||||
|
status(22) <= '1';
|
||||||
|
end if;
|
||||||
status(1 downto 0) <= "00";
|
status(1 downto 0) <= "00";
|
||||||
elsif status_rest = '1' then
|
elsif status_rest = '1' then
|
||||||
status(1 downto 0) <= status(3 downto 2);
|
status(1 downto 0) <= status(3 downto 2);
|
||||||
status(3 downto 2) <= status(5 downto 4);
|
status(3 downto 2) <= status(5 downto 4);
|
||||||
elsif stat_reg_we = '1' then
|
elsif ctrl_in.sdu.WB_nop = '0' then
|
||||||
status <= cop_pipe_EX.din;
|
if stat_reg_we = '1' then
|
||||||
|
if status(1) = '0' then
|
||||||
|
status(0) <= din(0); -- IEc
|
||||||
|
status(1) <= din(1); -- KUc
|
||||||
|
status(2) <= din(2); -- IEp
|
||||||
|
status(3) <= din(3); -- KUp
|
||||||
|
status(4) <= din(4); -- IEo
|
||||||
|
status(5) <= din(5); -- KUo
|
||||||
|
end if;
|
||||||
|
status(15 downto 8) <= din(15 downto 8); -- IM
|
||||||
|
status(22) <= din(22); -- BEV
|
||||||
|
status(25) <= din(25); -- RE
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
--------------------------------------------------------------------------
|
|
||||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
|
||||||
-- This file: The datapath controller
|
|
||||||
--
|
|
||||||
-- Copyright (C) 2008 J. Ahrensfeld
|
|
||||||
--
|
|
||||||
-- This program is free software: you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation, either version 3 of the License, or
|
|
||||||
-- (at your option) any later version.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
--
|
|
||||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
||||||
--
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
library IEEE;
|
|
||||||
use IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
use IEEE.numeric_std.ALL;
|
|
||||||
|
|
||||||
library work;
|
|
||||||
use work.mips_types.all;
|
|
||||||
use work.mips_instr.all;
|
|
||||||
|
|
||||||
entity idecode_rom is
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
nop : in std_logic;
|
|
||||||
inst_in : in word_t;
|
|
||||||
ctrl_out : out ctrl_lines_t
|
|
||||||
);
|
|
||||||
end idecode_rom;
|
|
||||||
|
|
||||||
architecture Behavioral of idecode_rom is
|
|
||||||
|
|
||||||
signal ctrl_special : ctrl_lines_t;
|
|
||||||
signal ctrl_regimm : ctrl_lines_t;
|
|
||||||
signal ctrl_opcode : ctrl_lines_t;
|
|
||||||
|
|
||||||
signal rom_special : rom_special_t := gen_rom_special;
|
|
||||||
signal rom_regimm : rom_regimm_t := gen_rom_regimm;
|
|
||||||
signal rom_opcode : rom_opcode_t := gen_rom_opcode;
|
|
||||||
|
|
||||||
attribute rom_style : string;
|
|
||||||
|
|
||||||
attribute rom_style of rom_special: signal is "distributed";
|
|
||||||
attribute rom_style of rom_regimm: signal is "distributed";
|
|
||||||
attribute rom_style of rom_opcode: signal is "distributed";
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
i_dec_special:
|
|
||||||
process(inst_in, rom_special)
|
|
||||||
variable func : func_t;
|
|
||||||
begin
|
|
||||||
func := extract_func(inst_in);
|
|
||||||
ctrl_special <= rom_special(to_integer(func));
|
|
||||||
end process;
|
|
||||||
|
|
||||||
i_dec_regimm:
|
|
||||||
process(inst_in, rom_regimm)
|
|
||||||
variable rt : reg_ptr_t;
|
|
||||||
begin
|
|
||||||
rt := extract_rt(inst_in);
|
|
||||||
ctrl_regimm <= rom_regimm(to_integer(rt));
|
|
||||||
end process;
|
|
||||||
|
|
||||||
i_dec_opcode:
|
|
||||||
process(inst_in, rom_opcode)
|
|
||||||
variable opc : opcode_t;
|
|
||||||
begin
|
|
||||||
opc := extract_opc(inst_in);
|
|
||||||
ctrl_opcode <= rom_opcode(to_integer(opc));
|
|
||||||
end process;
|
|
||||||
|
|
||||||
proc_decode:
|
|
||||||
process(inst_in, ctrl_special, ctrl_regimm, ctrl_opcode, nop)
|
|
||||||
variable opclass : opcode_t;
|
|
||||||
begin
|
|
||||||
opclass := extract_opc(inst_in);
|
|
||||||
ctrl_out <= ctrl_lines_default after 2 ns;
|
|
||||||
if nop = '0' then
|
|
||||||
case opclass is
|
|
||||||
when "000000" =>
|
|
||||||
ctrl_out <= ctrl_special after 2 ns;
|
|
||||||
when "000001" =>
|
|
||||||
ctrl_out <= ctrl_regimm after 2 ns;
|
|
||||||
when others =>
|
|
||||||
ctrl_out <= ctrl_opcode after 2 ns;
|
|
||||||
end case;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
end Behavioral;
|
|
||||||
@@ -43,12 +43,7 @@ package mips_instr is
|
|||||||
function extract_bimm18(instr, pc : word_t) return word_t;
|
function extract_bimm18(instr, pc : word_t) return word_t;
|
||||||
function decode_op(instr : word_t) return op_t;
|
function decode_op(instr : word_t) return op_t;
|
||||||
function ctrl_lines_default return ctrl_lines_t;
|
function ctrl_lines_default return ctrl_lines_t;
|
||||||
function special_ctrl_lines(func : func_t) return ctrl_lines_t;
|
function opcode_ctrl_lines(instr : word_t) return ctrl_lines_t;
|
||||||
function regimm_ctrl_lines(rt : reg_ptr_t) return ctrl_lines_t;
|
|
||||||
function opcode_ctrl_lines(opc : opcode_t) return ctrl_lines_t;
|
|
||||||
function gen_rom_opcode return rom_opcode_t;
|
|
||||||
function gen_rom_regimm return rom_regimm_t;
|
|
||||||
function gen_rom_special return rom_special_t;
|
|
||||||
|
|
||||||
end mips_instr;
|
end mips_instr;
|
||||||
|
|
||||||
@@ -153,14 +148,16 @@ package body mips_instr is
|
|||||||
variable opc : natural range 0 to 63;
|
variable opc : natural range 0 to 63;
|
||||||
variable func : natural range 0 to 63;
|
variable func : natural range 0 to 63;
|
||||||
variable rt : natural range 0 to 31;
|
variable rt : natural range 0 to 31;
|
||||||
|
variable rs : natural range 0 to 31;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
opc := to_integer(extract_opc(instr));
|
opc := to_integer(extract_opc(instr));
|
||||||
func := to_integer(extract_func(instr));
|
func := to_integer(extract_func(instr));
|
||||||
rt := to_integer(extract_rt(instr));
|
rt := to_integer(extract_rt(instr));
|
||||||
|
rs := to_integer(extract_rs(instr));
|
||||||
|
|
||||||
result := op_sll;
|
result := reserved;
|
||||||
|
|
||||||
case opc is
|
case opc is
|
||||||
|
|
||||||
@@ -318,15 +315,103 @@ package body mips_instr is
|
|||||||
|
|
||||||
when 16 =>
|
when 16 =>
|
||||||
result := op_cop0;
|
result := op_cop0;
|
||||||
|
case rs is
|
||||||
|
when 0 =>
|
||||||
|
result := op_mfc0;
|
||||||
|
when 2 =>
|
||||||
|
result := op_cfc0; -- illegal
|
||||||
|
when 4 =>
|
||||||
|
result := op_mtc0;
|
||||||
|
when 6 =>
|
||||||
|
result := op_ctc0; -- illegal
|
||||||
|
when 8 =>
|
||||||
|
case rt is
|
||||||
|
when 0 =>
|
||||||
|
result := op_bcf0; -- illegal
|
||||||
|
when 1 =>
|
||||||
|
result := op_bct0; -- illegal
|
||||||
|
|
||||||
|
when others => null; -- undef
|
||||||
|
end case;
|
||||||
|
|
||||||
|
when others => null; -- undef
|
||||||
|
|
||||||
|
end case;
|
||||||
|
|
||||||
when 17 =>
|
when 17 =>
|
||||||
result := op_cop1;
|
result := op_cop1;
|
||||||
|
case rs is
|
||||||
|
when 0 =>
|
||||||
|
result := op_mfc1;
|
||||||
|
when 2 =>
|
||||||
|
result := op_cfc1;
|
||||||
|
when 4 =>
|
||||||
|
result := op_mtc1;
|
||||||
|
when 6 =>
|
||||||
|
result := op_ctc1;
|
||||||
|
when 8 =>
|
||||||
|
case rt is
|
||||||
|
when 0 =>
|
||||||
|
result := op_bcf1;
|
||||||
|
when 1 =>
|
||||||
|
result := op_bct1;
|
||||||
|
|
||||||
|
when others => null; -- undef
|
||||||
|
end case;
|
||||||
|
|
||||||
|
when others => null; -- undef
|
||||||
|
|
||||||
|
end case;
|
||||||
|
|
||||||
when 18 =>
|
when 18 =>
|
||||||
result := op_cop2;
|
result := op_cop2;
|
||||||
|
case rs is
|
||||||
|
when 0 =>
|
||||||
|
result := op_mfc2;
|
||||||
|
when 2 =>
|
||||||
|
result := op_cfc2;
|
||||||
|
when 4 =>
|
||||||
|
result := op_mtc2;
|
||||||
|
when 6 =>
|
||||||
|
result := op_ctc2;
|
||||||
|
when 8 =>
|
||||||
|
case rt is
|
||||||
|
when 0 =>
|
||||||
|
result := op_bcf2;
|
||||||
|
when 1 =>
|
||||||
|
result := op_bct2;
|
||||||
|
|
||||||
|
when others => null; -- undef
|
||||||
|
end case;
|
||||||
|
|
||||||
|
when others => null; -- undef
|
||||||
|
|
||||||
|
end case;
|
||||||
|
|
||||||
when 19 =>
|
when 19 =>
|
||||||
result := op_cop3;
|
result := op_cop3;
|
||||||
|
case rs is
|
||||||
|
when 0 =>
|
||||||
|
result := op_mfc3;
|
||||||
|
when 2 =>
|
||||||
|
result := op_cfc3;
|
||||||
|
when 4 =>
|
||||||
|
result := op_mtc3;
|
||||||
|
when 6 =>
|
||||||
|
result := op_ctc3;
|
||||||
|
when 8 =>
|
||||||
|
case rt is
|
||||||
|
when 0 =>
|
||||||
|
result := op_bcf3;
|
||||||
|
when 1 =>
|
||||||
|
result := op_bct3;
|
||||||
|
|
||||||
|
when others => null; -- undef
|
||||||
|
end case;
|
||||||
|
|
||||||
|
when others => null; -- undef
|
||||||
|
|
||||||
|
end case;
|
||||||
|
|
||||||
when 32 =>
|
when 32 =>
|
||||||
result := op_lb;
|
result := op_lb;
|
||||||
@@ -364,6 +449,9 @@ package body mips_instr is
|
|||||||
when 46 =>
|
when 46 =>
|
||||||
result := op_swr;
|
result := op_swr;
|
||||||
|
|
||||||
|
when 48 =>
|
||||||
|
result := op_lwc0; -- illegal
|
||||||
|
|
||||||
when 49 =>
|
when 49 =>
|
||||||
result := op_lwc1;
|
result := op_lwc1;
|
||||||
|
|
||||||
@@ -373,6 +461,9 @@ package body mips_instr is
|
|||||||
when 51 =>
|
when 51 =>
|
||||||
result := op_lwc3;
|
result := op_lwc3;
|
||||||
|
|
||||||
|
when 56 =>
|
||||||
|
result := op_swc0; -- illegal
|
||||||
|
|
||||||
when 57 =>
|
when 57 =>
|
||||||
result := op_swc1;
|
result := op_swc1;
|
||||||
|
|
||||||
@@ -394,6 +485,7 @@ package body mips_instr is
|
|||||||
variable result : ctrl_lines_t;
|
variable result : ctrl_lines_t;
|
||||||
begin
|
begin
|
||||||
result.cop_instr_en := '0';
|
result.cop_instr_en := '0';
|
||||||
|
result.cop_read := '0';
|
||||||
result.jump := '0';
|
result.jump := '0';
|
||||||
result.jump_long := '0';
|
result.jump_long := '0';
|
||||||
result.branch := '0';
|
result.branch := '0';
|
||||||
@@ -436,16 +528,24 @@ package body mips_instr is
|
|||||||
|
|
||||||
end ctrl_lines_default;
|
end ctrl_lines_default;
|
||||||
|
|
||||||
|
function opcode_ctrl_lines(instr : word_t) return ctrl_lines_t is
|
||||||
function special_ctrl_lines(func : func_t) return ctrl_lines_t is
|
|
||||||
variable result : ctrl_lines_t;
|
variable result : ctrl_lines_t;
|
||||||
variable op : integer range 0 to 2**func_t'length-1;
|
variable opc : integer range 0 to 2**opcode_t'length-1;
|
||||||
|
variable func : integer range 0 to 2**func_t'length-1;
|
||||||
|
variable rt : integer range 0 to 2**reg_ptr_t'length-1;
|
||||||
|
variable rs : integer range 0 to 2**reg_ptr_t'length-1;
|
||||||
begin
|
begin
|
||||||
|
|
||||||
result := ctrl_lines_default;
|
result := ctrl_lines_default;
|
||||||
|
opc := to_integer(extract_opc(instr));
|
||||||
|
func := to_integer(extract_func(instr));
|
||||||
|
rt := to_integer(extract_rt(instr));
|
||||||
|
rs := to_integer(extract_rs(instr));
|
||||||
|
|
||||||
op := to_integer(func);
|
case opc is
|
||||||
case op is
|
-- SPECIAL
|
||||||
|
when 0 =>
|
||||||
|
case func is
|
||||||
|
|
||||||
-- when op_add =>
|
-- when op_add =>
|
||||||
when 32 =>
|
when 32 =>
|
||||||
@@ -653,32 +753,9 @@ package body mips_instr is
|
|||||||
|
|
||||||
end case;
|
end case;
|
||||||
|
|
||||||
return result;
|
-- REGIMM
|
||||||
|
when 1 =>
|
||||||
end special_ctrl_lines;
|
case rt is
|
||||||
|
|
||||||
function gen_rom_special return rom_special_t is
|
|
||||||
variable result : rom_special_t;
|
|
||||||
variable func : func_t;
|
|
||||||
begin
|
|
||||||
|
|
||||||
for i in 0 to 2**func_t'length-1 loop
|
|
||||||
func := to_unsigned(i, func_t'length);
|
|
||||||
result(i) := special_ctrl_lines(func);
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
end gen_rom_special;
|
|
||||||
|
|
||||||
function regimm_ctrl_lines(rt : reg_ptr_t) return ctrl_lines_t is
|
|
||||||
variable result : ctrl_lines_t;
|
|
||||||
variable op : integer range 0 to 2**reg_ptr_t'length-1;
|
|
||||||
begin
|
|
||||||
|
|
||||||
result := ctrl_lines_default;
|
|
||||||
|
|
||||||
op := to_integer(rt);
|
|
||||||
case op is
|
|
||||||
|
|
||||||
-- when op_bgez =>
|
-- when op_bgez =>
|
||||||
when 1 =>
|
when 1 =>
|
||||||
@@ -715,32 +792,21 @@ package body mips_instr is
|
|||||||
|
|
||||||
end case;
|
end case;
|
||||||
|
|
||||||
return result;
|
-- when COPz =>
|
||||||
|
when 16 | 17 | 18 | 19 =>
|
||||||
|
result.cop_instr_en := '1';
|
||||||
|
case rs is
|
||||||
|
when 0 => -- MFCz
|
||||||
|
result.cop_read := '1';
|
||||||
|
result.reg_write := '1';
|
||||||
|
when 2 => -- CFCz
|
||||||
|
result.cop_read := '1';
|
||||||
|
result.reg_write := '1';
|
||||||
|
|
||||||
end regimm_ctrl_lines;
|
when others => null; -- undef
|
||||||
|
|
||||||
function gen_rom_regimm return rom_regimm_t is
|
end case;
|
||||||
variable result : rom_regimm_t;
|
|
||||||
variable rt : reg_ptr_t;
|
|
||||||
begin
|
|
||||||
|
|
||||||
for i in 0 to 2**reg_ptr_t'length-1 loop
|
|
||||||
rt := to_unsigned(i, reg_ptr_t'length);
|
|
||||||
result(i) := regimm_ctrl_lines(rt);
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
end gen_rom_regimm;
|
|
||||||
|
|
||||||
function opcode_ctrl_lines(opc : opcode_t) return ctrl_lines_t is
|
|
||||||
variable result : ctrl_lines_t;
|
|
||||||
variable op : integer range 0 to 2**opcode_t'length-1;
|
|
||||||
begin
|
|
||||||
|
|
||||||
result := ctrl_lines_default;
|
|
||||||
|
|
||||||
op := to_integer(opc);
|
|
||||||
case op is
|
|
||||||
|
|
||||||
-- when op_addi =>
|
-- when op_addi =>
|
||||||
when 8 =>
|
when 8 =>
|
||||||
@@ -793,10 +859,6 @@ package body mips_instr is
|
|||||||
result.bc_src := bc_eq_ne;
|
result.bc_src := bc_eq_ne;
|
||||||
result.bc_not := '1';
|
result.bc_not := '1';
|
||||||
|
|
||||||
-- when op_cop =>
|
|
||||||
when 16 | 17 | 18 | 19 =>
|
|
||||||
result.cop_instr_en := '1';
|
|
||||||
|
|
||||||
-- when op_j =>
|
-- when op_j =>
|
||||||
when 2 =>
|
when 2 =>
|
||||||
result.jump := '1';
|
result.jump := '1';
|
||||||
@@ -870,6 +932,13 @@ package body mips_instr is
|
|||||||
result.reg_write := '1';
|
result.reg_write := '1';
|
||||||
result.except_en := '1';
|
result.except_en := '1';
|
||||||
|
|
||||||
|
-- when op_lwcz =>
|
||||||
|
when 48 | 49 | 50 | 51 =>
|
||||||
|
-- result.imm_src := src_imm32;
|
||||||
|
result.dmem_en := '1';
|
||||||
|
result.except_en := '1';
|
||||||
|
result.cop_instr_en := '1';
|
||||||
|
|
||||||
-- when op_lwl =>
|
-- when op_lwl =>
|
||||||
when 34 =>
|
when 34 =>
|
||||||
-- result.imm_src := src_imm32;
|
-- result.imm_src := src_imm32;
|
||||||
@@ -942,6 +1011,15 @@ package body mips_instr is
|
|||||||
-- result.imm_src := src_imm32;
|
-- result.imm_src := src_imm32;
|
||||||
result.except_en := '1';
|
result.except_en := '1';
|
||||||
|
|
||||||
|
-- when op_swcz =>
|
||||||
|
when 56 | 57 | 58 | 59 =>
|
||||||
|
result.dmem_en := '1';
|
||||||
|
result.dmem_we := '1';
|
||||||
|
-- result.imm_src := src_imm32;
|
||||||
|
result.except_en := '1';
|
||||||
|
result.cop_instr_en := '1';
|
||||||
|
result.cop_read := '1';
|
||||||
|
|
||||||
-- when op_swl =>
|
-- when op_swl =>
|
||||||
when 42 =>
|
when 42 =>
|
||||||
result.dmem_en := '1';
|
result.dmem_en := '1';
|
||||||
@@ -977,19 +1055,6 @@ package body mips_instr is
|
|||||||
|
|
||||||
end opcode_ctrl_lines;
|
end opcode_ctrl_lines;
|
||||||
|
|
||||||
function gen_rom_opcode return rom_opcode_t is
|
|
||||||
variable result : rom_opcode_t;
|
|
||||||
variable opc : opcode_t;
|
|
||||||
begin
|
|
||||||
|
|
||||||
for i in 0 to 2**opcode_t'length-1 loop
|
|
||||||
opc := to_unsigned(i, opcode_t'length);
|
|
||||||
result(i) := opcode_ctrl_lines(opc);
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
end gen_rom_opcode;
|
|
||||||
|
|
||||||
end mips_instr;
|
end mips_instr;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ entity pipeline is
|
|||||||
(
|
(
|
||||||
rst : in STD_LOGIC;
|
rst : in STD_LOGIC;
|
||||||
clk : in STD_LOGIC;
|
clk : in STD_LOGIC;
|
||||||
halt : in STD_LOGIC;
|
ce : in STD_LOGIC;
|
||||||
int : in unsigned(5 downto 0);
|
|
||||||
imem_err : in STD_LOGIC;
|
imem_err : in STD_LOGIC;
|
||||||
imem_rdy : in STD_LOGIC;
|
imem_rdy : in STD_LOGIC;
|
||||||
imem_en : out STD_LOGIC;
|
imem_en : out STD_LOGIC;
|
||||||
@@ -47,7 +46,14 @@ entity pipeline is
|
|||||||
dmem_be : out unsigned(3 downto 0);
|
dmem_be : out unsigned(3 downto 0);
|
||||||
dmem_addr : out word_t;
|
dmem_addr : out word_t;
|
||||||
dmem_din : in word_t;
|
dmem_din : in word_t;
|
||||||
dmem_dout : out word_t
|
dmem_dout : out word_t;
|
||||||
|
cop_ir : out word_t;
|
||||||
|
cop_ir_en : out STD_LOGIC;
|
||||||
|
cop_din : in word_t;
|
||||||
|
cop_dout : out word_t;
|
||||||
|
c0_ctrl_out : out cop0_ctrl_in_t;
|
||||||
|
c0_ctrl_in : in cop0_ctrl_out_t
|
||||||
|
|
||||||
);
|
);
|
||||||
end pipeline;
|
end pipeline;
|
||||||
|
|
||||||
@@ -74,16 +80,6 @@ architecture Behavioral of pipeline is
|
|||||||
);
|
);
|
||||||
END COMPONENT;
|
END COMPONENT;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
COMPONENT idecode_rom is
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
nop : in std_logic;
|
|
||||||
inst_in : in word_t;
|
|
||||||
ctrl_out : out ctrl_lines_t
|
|
||||||
);
|
|
||||||
END COMPONENT;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
COMPONENT shifter is
|
COMPONENT shifter is
|
||||||
Generic
|
Generic
|
||||||
@@ -129,23 +125,6 @@ architecture Behavioral of pipeline is
|
|||||||
);
|
);
|
||||||
END COMPONENT;
|
END COMPONENT;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
COMPONENT cop is
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
rst : in STD_LOGIC;
|
|
||||||
clk : in STD_LOGIC;
|
|
||||||
sdu : in sdu_t;
|
|
||||||
IR_valid : in STD_LOGIC;
|
|
||||||
IR : in word_t;
|
|
||||||
events : in event_t;
|
|
||||||
ctrl_in : in cop_ctrl_in_t;
|
|
||||||
ctrl_out : out cop_ctrl_out_t;
|
|
||||||
din : in word_t;
|
|
||||||
dout : out word_t
|
|
||||||
);
|
|
||||||
END COMPONENT;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
COMPONENT muldiv is
|
COMPONENT muldiv is
|
||||||
Port
|
Port
|
||||||
@@ -165,8 +144,6 @@ architecture Behavioral of pipeline is
|
|||||||
END COMPONENT;
|
END COMPONENT;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
constant RESET_VECTOR : word_t := X"BFC00000";
|
|
||||||
|
|
||||||
signal ID_stage : ID_t;
|
signal ID_stage : ID_t;
|
||||||
signal EX_stage : EX_t;
|
signal EX_stage : EX_t;
|
||||||
signal MEM_stage : MEM_t;
|
signal MEM_stage : MEM_t;
|
||||||
@@ -174,20 +151,10 @@ architecture Behavioral of pipeline is
|
|||||||
signal clk_2, clk_1 : STD_LOGIC;
|
signal clk_2, clk_1 : STD_LOGIC;
|
||||||
signal hdu : hdu_t;
|
signal hdu : hdu_t;
|
||||||
signal sdu : sdu_t;
|
signal sdu : sdu_t;
|
||||||
signal cpu_rst : STD_LOGIC;
|
|
||||||
signal reg_a : word_t;
|
signal reg_a : word_t;
|
||||||
signal reg_b : word_t;
|
signal reg_b : word_t;
|
||||||
signal ctrl_lines : ctrl_lines_t;
|
|
||||||
signal cpu_run : STD_LOGIC;
|
|
||||||
signal branch_ce : STD_LOGIC;
|
signal branch_ce : STD_LOGIC;
|
||||||
signal run_en : STD_LOGIC;
|
signal cpu_run : STD_LOGIC;
|
||||||
signal mul_dep : STD_LOGIC;
|
|
||||||
signal imem_dep : STD_LOGIC;
|
|
||||||
signal dmem_dep : STD_LOGIC;
|
|
||||||
signal cop_ctrl : cop_ctrl_in_t;
|
|
||||||
signal cop_stat : cop_ctrl_out_t;
|
|
||||||
signal cop_din : word_t;
|
|
||||||
signal cop_dout : word_t;
|
|
||||||
signal alu_result : word_t;
|
signal alu_result : word_t;
|
||||||
signal mul_result : word_t;
|
signal mul_result : word_t;
|
||||||
signal mul_busy : STD_LOGIC;
|
signal mul_busy : STD_LOGIC;
|
||||||
@@ -200,11 +167,9 @@ architecture Behavioral of pipeline is
|
|||||||
signal bcu_op_b : word_t;
|
signal bcu_op_b : word_t;
|
||||||
signal bcu_flags : bcu_flags_t;
|
signal bcu_flags : bcu_flags_t;
|
||||||
signal vaddr : word_t;
|
signal vaddr : word_t;
|
||||||
|
signal dmem_src : word_t;
|
||||||
attribute ram_style : string;
|
signal stage_rst : unsigned(3 downto 0);
|
||||||
|
signal pipe_rst : STD_LOGIC;
|
||||||
attribute ram_style of reg_a: signal is "distributed";
|
|
||||||
attribute ram_style of reg_b: signal is "distributed";
|
|
||||||
|
|
||||||
signal pc : pc_t;
|
signal pc : pc_t;
|
||||||
|
|
||||||
@@ -213,24 +178,41 @@ begin
|
|||||||
|
|
||||||
clk_1 <= clk;
|
clk_1 <= clk;
|
||||||
clk_2 <= not clk;
|
clk_2 <= not clk;
|
||||||
cpu_run <= run_en;
|
cpu_run <= ce;
|
||||||
|
|
||||||
-- Stall Detection Unit ---------------------------------------------------
|
-- Stall Detection Unit ---------------------------------------------------
|
||||||
sdu.ID_nop <= imem_dep or cop_stat.exc_pending or EX_stage.exc or MEM_stage.exc;
|
sdu.ID_nop <= sdu.imem_dep or c0_ctrl_in.exc_pending or ID_stage.exc or EX_stage.exc or MEM_stage.exc;
|
||||||
sdu.EX_nop <= mul_dep or ID_stage.nop or ID_stage.exc;
|
sdu.EX_nop <= sdu.mul_dep or ID_stage.nop or ID_stage.exc;
|
||||||
sdu.MEM_nop <= EX_stage.nop or EX_stage.exc;
|
sdu.MEM_nop <= EX_stage.nop or EX_stage.exc;
|
||||||
sdu.WB_nop <= dmem_dep or MEM_stage.nop;
|
sdu.WB_nop <= sdu.dmem_dep or MEM_stage.nop;
|
||||||
|
|
||||||
sdu.ID_stall <= dmem_dep or imem_dep or mul_dep or ID_stage.exc;
|
sdu.stall_all <= sdu.dmem_dep;
|
||||||
sdu.EX_stall <= dmem_dep;
|
sdu.ID_stall <= sdu.stall_all or sdu.imem_dep or sdu.mul_dep or c0_ctrl_in.exc_exit;
|
||||||
sdu.MEM_stall <= dmem_dep;
|
sdu.EX_stall <= sdu.stall_all;
|
||||||
|
sdu.MEM_stall <= sdu.stall_all;
|
||||||
sdu.WB_stall <= '0';
|
sdu.WB_stall <= '0';
|
||||||
|
|
||||||
mul_dep <= ID_stage.ctrl.mul_access and (EX_stage.ctrl.mul_start or mul_busy);
|
sdu.mul_dep <= ID_stage.ctrl.mul_access and (EX_stage.ctrl.mul_start or mul_busy);
|
||||||
imem_dep <= not imem_rdy;
|
sdu.imem_dep <= not imem_rdy;
|
||||||
dmem_dep <= not dmem_rdy and MEM_stage.ctrl.dmem_en;
|
sdu.dmem_dep <= not dmem_rdy and MEM_stage.ctrl.dmem_en;
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
imem_en <= cpu_run and not (mul_dep or dmem_dep or cop_stat.exc_commit);
|
imem_en <= cpu_run and not (sdu.mul_dep or sdu.dmem_dep or c0_ctrl_in.exc_commit);
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
-- Coprocessor assignments
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
c0_ctrl_out.bd_wb <= WB_stage.bd;
|
||||||
|
c0_ctrl_out.epc_mem <= MEM_stage.pcn;
|
||||||
|
c0_ctrl_out.epc_wb <= MEM_stage.epc;
|
||||||
|
c0_ctrl_out.imem_addr <= EX_stage.epc;
|
||||||
|
c0_ctrl_out.dmem_addr <= MEM_stage.va;
|
||||||
|
c0_ctrl_out.sdu <= sdu;
|
||||||
|
c0_ctrl_out.events <= WB_stage.events;
|
||||||
|
c0_ctrl_out.exc_req <= MEM_stage.exc;
|
||||||
|
c0_ctrl_out.exc_ack <= WB_stage.exc;
|
||||||
|
cop_ir <= ID_stage.IR;
|
||||||
|
cop_ir_en <= ID_stage.ctrl.cop_instr_en;
|
||||||
|
cop_dout <= dmem_din when MEM_stage.ctrl.dmem_en = '1' else MEM_stage.ex_result;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
-- Muldiv
|
-- Muldiv
|
||||||
@@ -238,7 +220,7 @@ begin
|
|||||||
inst_muldiv: muldiv
|
inst_muldiv: muldiv
|
||||||
PORT MAP
|
PORT MAP
|
||||||
(
|
(
|
||||||
rst => cpu_rst,
|
rst => rst,
|
||||||
clk => clk,
|
clk => clk,
|
||||||
hilo_we => EX_stage.ctrl.mul_hilo_we,
|
hilo_we => EX_stage.ctrl.mul_hilo_we,
|
||||||
din_hi => EX_stage.reg_a,
|
din_hi => EX_stage.reg_a,
|
||||||
@@ -251,47 +233,33 @@ inst_muldiv: muldiv
|
|||||||
dout => mul_result
|
dout => mul_result
|
||||||
);
|
);
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
-- Coprocessor
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
inst_cop: cop
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
rst => cpu_rst,
|
|
||||||
clk => clk,
|
|
||||||
sdu => sdu,
|
|
||||||
events => MEM_stage.events,
|
|
||||||
IR_valid => ID_stage.ctrl.cop_instr_en,
|
|
||||||
IR => ID_stage.IR,
|
|
||||||
ctrl_in => cop_ctrl,
|
|
||||||
ctrl_out => cop_stat,
|
|
||||||
dout => cop_dout,
|
|
||||||
din => cop_din
|
|
||||||
);
|
|
||||||
|
|
||||||
cop_ctrl.bd_wb <= WB_stage.bd;
|
|
||||||
cop_ctrl.epc_mem <= MEM_stage.pcn;
|
|
||||||
cop_ctrl.epc_wb <= MEM_stage.epc;
|
|
||||||
cop_ctrl.imem_addr <= pc.nxt;
|
|
||||||
cop_ctrl.dmem_addr <= MEM_stage.va;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
-- IF stage
|
-- IF stage
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
imem_addr <= pc.curr;
|
imem_addr <= pc.curr;
|
||||||
|
|
||||||
proc_stage_pc:
|
pipe_rst <= stage_rst(0);
|
||||||
process(pc, rst, cop_stat)
|
|
||||||
|
proc_stage_reset:
|
||||||
|
process(clk_1)
|
||||||
begin
|
begin
|
||||||
|
if rising_edge(clk_1) then
|
||||||
if rst = '1' then
|
if rst = '1' then
|
||||||
pc.curr <= RESET_VECTOR after 2 ns;
|
stage_rst <= (others => '1');
|
||||||
else
|
else
|
||||||
if pc.is_branch and cop_stat.exc_pending = '0' then
|
stage_rst <= stage_rst(stage_rst'left-1 downto 0) & '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_stage_pc:
|
||||||
|
process(pc)
|
||||||
|
begin
|
||||||
|
if pc.branch_take = '1' then
|
||||||
pc.curr <= pc.pc_branch after 2 ns;
|
pc.curr <= pc.pc_branch after 2 ns;
|
||||||
else
|
else
|
||||||
pc.curr <= pc.nxt after 2 ns;
|
pc.curr <= pc.nxt after 2 ns;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
proc_stage_pc_branch:
|
proc_stage_pc_branch:
|
||||||
@@ -304,21 +272,28 @@ proc_stage_pc_branch:
|
|||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
proc_stage_branch_ce:
|
||||||
|
process(clk_1)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk_1) then
|
||||||
|
if pipe_rst = '1' then
|
||||||
|
branch_ce <= '1';
|
||||||
|
else
|
||||||
|
branch_ce <= c0_ctrl_in.exc_pending;
|
||||||
|
if sdu.ID_stall = '0' and c0_ctrl_in.exc_inject = '0' then
|
||||||
|
branch_ce <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
proc_stage_pc_next:
|
proc_stage_pc_next:
|
||||||
process(clk_1)
|
process(clk_1)
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk_1) then
|
if rising_edge(clk_1) then
|
||||||
branch_ce <= '0';
|
if c0_ctrl_in.exc_inject = '1' then
|
||||||
cop_ctrl.exc_left <= '0';
|
pc.nxt <= c0_ctrl_in.exc_vec;
|
||||||
if rst = '1' then
|
|
||||||
pc.nxt <= pc.curr;
|
|
||||||
pc.last <= pc.curr;
|
|
||||||
else
|
|
||||||
if cop_stat.exc_commit = '1' then
|
|
||||||
pc.nxt <= cop_stat.exc_vec;
|
|
||||||
elsif sdu.ID_stall = '0' then
|
elsif sdu.ID_stall = '0' then
|
||||||
cop_ctrl.exc_left <= cop_stat.exc_exit;
|
|
||||||
branch_ce <= '1';
|
|
||||||
pc.last <= pc.curr;
|
pc.last <= pc.curr;
|
||||||
if ID_stage.ctrl.jump = '1' then
|
if ID_stage.ctrl.jump = '1' then
|
||||||
pc.nxt <= ID_stage.jimm32;
|
pc.nxt <= ID_stage.jimm32;
|
||||||
@@ -329,32 +304,25 @@ proc_stage_pc_next:
|
|||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
proc_stage_branch:
|
proc_stage_branch:
|
||||||
process(clk_2)
|
process(clk_2)
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk_2) and branch_ce = '1' then
|
if rising_edge(clk_2) and branch_ce = '1' then
|
||||||
pc.is_branch <= false;
|
pc.branch_take <= '0';
|
||||||
if EX_stage.ctrl.branch = '1' then
|
if EX_stage.ctrl.branch = '1' then
|
||||||
|
|
||||||
case EX_stage.ctrl.bc_src is
|
case EX_stage.ctrl.bc_src is
|
||||||
|
|
||||||
when bc_eq_ne =>
|
when bc_eq_ne =>
|
||||||
if (EX_stage.ctrl.bc_not xor bcu_flags.eq) = '1' then
|
pc.branch_take <= EX_stage.ctrl.bc_not xor bcu_flags.eq;
|
||||||
pc.is_branch <= true;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when bc_lez_gtz =>
|
when bc_lez_gtz =>
|
||||||
if (EX_stage.ctrl.bc_not xor (bcu_flags.eq or bcu_flags.ltz)) = '1' then
|
pc.branch_take <= EX_stage.ctrl.bc_not xor (bcu_flags.eq or bcu_flags.ltz);
|
||||||
pc.is_branch <= true;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when bc_ltz_gez =>
|
when bc_ltz_gez =>
|
||||||
if (EX_stage.ctrl.bc_not xor bcu_flags.ltz) = '1' then
|
pc.branch_take <= EX_stage.ctrl.bc_not xor bcu_flags.ltz;
|
||||||
pc.is_branch <= true;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
when others => null;
|
when others => null;
|
||||||
end case;
|
end case;
|
||||||
@@ -362,25 +330,6 @@ proc_stage_branch:
|
|||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
process(rst, clk_1)
|
|
||||||
variable reset_delay : unsigned (5 downto 0);
|
|
||||||
begin
|
|
||||||
if rising_edge(clk_1) then
|
|
||||||
if rst = '1' then
|
|
||||||
reset_delay := (others => '1');
|
|
||||||
cpu_rst <= '1';
|
|
||||||
run_en <= '0';
|
|
||||||
elsif reset_delay /= (5 downto 0 => '0') then
|
|
||||||
reset_delay := reset_delay - 1;
|
|
||||||
else
|
|
||||||
cpu_rst <= '0';
|
|
||||||
end if;
|
|
||||||
if reset_delay(reset_delay'left-1) = '0' then
|
|
||||||
run_en <= '1';
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
-- ID stage
|
-- ID stage
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
@@ -392,18 +341,18 @@ proc_stage_branch:
|
|||||||
ID_stage.shamt <= extract_shamt(ID_stage.IR);
|
ID_stage.shamt <= extract_shamt(ID_stage.IR);
|
||||||
ID_stage.reg_a_rptr <= extract_rs(ID_stage.IR);
|
ID_stage.reg_a_rptr <= extract_rs(ID_stage.IR);
|
||||||
ID_stage.reg_b_rptr <= extract_rt(ID_stage.IR);
|
ID_stage.reg_b_rptr <= extract_rt(ID_stage.IR);
|
||||||
ID_stage.ctrl <= ctrl_lines;
|
ID_stage.ctrl <= opcode_ctrl_lines(ID_stage.IR) when sdu.ID_nop = '0' else ctrl_lines_default;
|
||||||
ID_stage.reg_write <= ID_stage.ctrl.reg_write or cop_stat.reg_write;
|
ID_stage.reg_write <= ID_stage.ctrl.reg_write;
|
||||||
ID_stage.epc <= pc.last;
|
ID_stage.epc <= pc.last;
|
||||||
ID_stage.exc <= event_is_active(ID_stage.events); -- Todo: works
|
ID_stage.exc <= event_is_active(ID_stage.events); -- Todo: works
|
||||||
ID_stage.nop <= sdu.ID_nop;
|
ID_stage.nop <= sdu.ID_nop;
|
||||||
|
|
||||||
proc_ID_except:
|
proc_ID_except:
|
||||||
process(ID_stage, cop_stat, pc)
|
process(ID_stage, c0_ctrl_in, pc)
|
||||||
begin
|
begin
|
||||||
ID_stage.events <= events_clr;
|
ID_stage.events <= events_clr;
|
||||||
ID_stage.events.inst_load_err <= pc.nxt(1) or pc.nxt(0);
|
ID_stage.events.inst_load_err <= not c0_ctrl_in.exc_pending and (pc.nxt(1) or pc.nxt(0));
|
||||||
ID_stage.events.inst_priv_addr <= pc.nxt(word_t'left) and cop_stat.user_mode;
|
ID_stage.events.inst_priv_addr <= not c0_ctrl_in.exc_pending and (pc.nxt(word_t'left) and c0_ctrl_in.user_mode);
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
proc_stage_hdu:
|
proc_stage_hdu:
|
||||||
@@ -489,14 +438,6 @@ proc_imm_mux:
|
|||||||
end process;
|
end process;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
inst_idecode_rom: idecode_rom
|
|
||||||
PORT MAP
|
|
||||||
(
|
|
||||||
nop => sdu.ID_nop,
|
|
||||||
inst_in => ID_stage.IR,
|
|
||||||
ctrl_out => ctrl_lines
|
|
||||||
);
|
|
||||||
|
|
||||||
inst_reg_dual: reg_dual
|
inst_reg_dual: reg_dual
|
||||||
GENERIC MAP
|
GENERIC MAP
|
||||||
(
|
(
|
||||||
@@ -527,7 +468,7 @@ proc_stage_ID_EX_1:
|
|||||||
process(clk_1)
|
process(clk_1)
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk_1) then
|
if rising_edge(clk_1) then
|
||||||
if rst = '1' then
|
if stage_rst(1) = '1' then
|
||||||
EX_stage.op <= NOP;
|
EX_stage.op <= NOP;
|
||||||
EX_stage.IR <= (others => '0');
|
EX_stage.IR <= (others => '0');
|
||||||
EX_stage.ctrl <= ctrl_lines_default;
|
EX_stage.ctrl <= ctrl_lines_default;
|
||||||
@@ -545,13 +486,12 @@ proc_stage_ID_EX_1:
|
|||||||
EX_stage.nop <= sdu.EX_nop;
|
EX_stage.nop <= sdu.EX_nop;
|
||||||
EX_stage.IR <= ID_stage.IR;
|
EX_stage.IR <= ID_stage.IR;
|
||||||
EX_stage.pcn <= ID_stage.pcn;
|
EX_stage.pcn <= ID_stage.pcn;
|
||||||
|
EX_stage.epc <= ID_stage.epc;
|
||||||
if sdu.EX_nop = '1' then
|
if sdu.EX_nop = '1' then
|
||||||
EX_stage.op <= NOP;
|
EX_stage.op <= NOP;
|
||||||
EX_stage.IR <= (others => '0');
|
EX_stage.IR <= (others => '0');
|
||||||
EX_stage.ctrl <= ctrl_lines_default;
|
EX_stage.ctrl <= ctrl_lines_default;
|
||||||
EX_stage.reg_write <= '0';
|
EX_stage.reg_write <= '0';
|
||||||
else
|
|
||||||
EX_stage.epc <= ID_stage.epc;
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
@@ -586,7 +526,7 @@ proc_stage_EX_mem_except:
|
|||||||
process(clk_1)
|
process(clk_1)
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk_1) then
|
if rising_edge(clk_1) then
|
||||||
if rst = '1' then
|
if pipe_rst = '1' then
|
||||||
dmem_en <= '0';
|
dmem_en <= '0';
|
||||||
elsif sdu.EX_stall = '0' then
|
elsif sdu.EX_stall = '0' then
|
||||||
EX_events_mem <= events_clr;
|
EX_events_mem <= events_clr;
|
||||||
@@ -617,19 +557,23 @@ proc_stage_DMEM_ADDR:
|
|||||||
if rising_edge(clk_1) then
|
if rising_edge(clk_1) then
|
||||||
if sdu.EX_stall = '0' then
|
if sdu.EX_stall = '0' then
|
||||||
EX_stage.va <= vaddr;
|
EX_stage.va <= vaddr;
|
||||||
if cop_stat.RE = '1' then
|
if c0_ctrl_in.EB = '1' then
|
||||||
|
if ID_stage.ctrl.word2_en = '0' then
|
||||||
EX_stage.pa_off <= not vaddr(1 downto 0);
|
EX_stage.pa_off <= not vaddr(1 downto 0);
|
||||||
|
else
|
||||||
|
EX_stage.pa_off <= not vaddr(1) & vaddr(0);
|
||||||
|
end if;
|
||||||
else
|
else
|
||||||
EX_stage.pa_off <= vaddr(1 downto 0);
|
EX_stage.pa_off <= vaddr(1 downto 0);
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
dmem_be <= store_be(EX_stage.pa_off, EX_stage.ctrl.dmem_we, EX_stage.ctrl.word2_en, EX_stage.ctrl.word4_en, EX_stage.ctrl.align_left, EX_stage.ctrl.byte_en_byp) after 1 ns;
|
dmem_src <= cop_din when EX_stage.ctrl.cop_instr_en = '1' else EX_stage.reg_b;
|
||||||
|
dmem_be <= store_be(EX_stage.pa_off, EX_stage.ctrl.dmem_en, EX_stage.ctrl.word2_en, EX_stage.ctrl.word4_en, EX_stage.ctrl.align_left, EX_stage.ctrl.shift_byp) after 1 ns;
|
||||||
dmem_we <= EX_stage.ctrl.dmem_we;
|
dmem_we <= EX_stage.ctrl.dmem_we;
|
||||||
dmem_dout <= store_shift(EX_stage.reg_b, EX_stage.pa_off, EX_stage.ctrl.shift_offset, EX_stage.ctrl.shift_byp) after 1ns;
|
dmem_dout <= store_shift(dmem_src, EX_stage.pa_off, EX_stage.ctrl.shift_offset, EX_stage.ctrl.shift_byp) after 1ns;
|
||||||
dmem_addr <= EX_stage.va;
|
dmem_addr <= EX_stage.va;
|
||||||
cop_din <= EX_stage.reg_b;
|
|
||||||
EX_stage.events <= EX_events_instr or EX_events_mem or EX_events_alu or EX_stage.events_in;
|
EX_stage.events <= EX_events_instr or EX_events_mem or EX_events_alu or EX_stage.events_in;
|
||||||
EX_stage.exc <= event_is_active(EX_stage.events);
|
EX_stage.exc <= event_is_active(EX_stage.events);
|
||||||
|
|
||||||
@@ -783,7 +727,7 @@ proc_stage_MEM_n:
|
|||||||
process(clk_1)
|
process(clk_1)
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk_1) then
|
if rising_edge(clk_1) then
|
||||||
if rst = '1' then
|
if stage_rst(2) = '1' then
|
||||||
MEM_stage.op <= NOP;
|
MEM_stage.op <= NOP;
|
||||||
MEM_stage.wreg_we <= '0';
|
MEM_stage.wreg_we <= '0';
|
||||||
MEM_stage.ctrl <= ctrl_lines_default;
|
MEM_stage.ctrl <= ctrl_lines_default;
|
||||||
@@ -794,17 +738,25 @@ proc_stage_MEM_n:
|
|||||||
MEM_stage.op <= EX_stage.op;
|
MEM_stage.op <= EX_stage.op;
|
||||||
MEM_stage.wreg_we <= EX_stage.wreg_we;
|
MEM_stage.wreg_we <= EX_stage.wreg_we;
|
||||||
MEM_stage.ctrl <= EX_stage.ctrl;
|
MEM_stage.ctrl <= EX_stage.ctrl;
|
||||||
|
if EX_stage.ctrl.dmem_en = '1' then
|
||||||
MEM_stage.va <= EX_stage.va;
|
MEM_stage.va <= EX_stage.va;
|
||||||
|
end if;
|
||||||
MEM_stage.pa_off <= EX_stage.pa_off;
|
MEM_stage.pa_off <= EX_stage.pa_off;
|
||||||
MEM_stage.reg_wptr <= EX_stage.reg_wptr;
|
MEM_stage.reg_wptr <= EX_stage.reg_wptr;
|
||||||
MEM_stage.nop <= sdu.MEM_nop;
|
MEM_stage.nop <= sdu.MEM_nop;
|
||||||
if EX_stage.ctrl.dmem_en = '1' then
|
if MEM_stage.reg_wptr = EX_stage.reg_wptr then
|
||||||
MEM_stage.ex_result <= EX_stage.reg_b;
|
if (EX_stage.ctrl.dmem_en and MEM_stage.ctrl.dmem_en) = '1' then
|
||||||
else
|
MEM_stage.ex_result <= MEM_stage.data;
|
||||||
MEM_stage.ex_result <= EX_stage.result;
|
|
||||||
if cop_stat.cop_read = '1' then
|
|
||||||
MEM_stage.ex_result <= cop_dout;
|
|
||||||
end if;
|
end if;
|
||||||
|
else
|
||||||
|
MEM_stage.ex_result <= EX_stage.reg_b;
|
||||||
|
end if;
|
||||||
|
if EX_stage.ctrl.cop_instr_en = '1' then
|
||||||
|
if EX_stage.ctrl.cop_read = '1' then
|
||||||
|
MEM_stage.ex_result <= cop_din;
|
||||||
|
end if;
|
||||||
|
elsif EX_stage.ctrl.dmem_en = '0' then
|
||||||
|
MEM_stage.ex_result <= EX_stage.result;
|
||||||
end if;
|
end if;
|
||||||
if sdu.MEM_nop = '1' then
|
if sdu.MEM_nop = '1' then
|
||||||
MEM_stage.op <= NOP;
|
MEM_stage.op <= NOP;
|
||||||
@@ -826,12 +778,12 @@ proc_stage_MEM_mux:
|
|||||||
variable be : unsigned(3 downto 0);
|
variable be : unsigned(3 downto 0);
|
||||||
begin
|
begin
|
||||||
data := MEM_stage.ex_result;
|
data := MEM_stage.ex_result;
|
||||||
be := load_be(MEM_stage.pa_off, MEM_stage.ctrl.align_left, MEM_stage.ctrl.byte_en_byp);
|
|
||||||
if MEM_stage.ctrl.reg_link = '1' then
|
if MEM_stage.ctrl.reg_link = '1' then
|
||||||
data := MEM_stage.pcn + 4;
|
data := MEM_stage.epc + 8;
|
||||||
elsif MEM_stage.ctrl.dmem_en = '1' then
|
elsif MEM_stage.ctrl.dmem_en = '1' then
|
||||||
temp1 := load_shift(dmem_din, MEM_stage.pa_off, MEM_stage.ctrl.shift_offset, MEM_stage.ctrl.shift_byp);
|
temp1 := load_shift(dmem_din, MEM_stage.pa_off, MEM_stage.ctrl.shift_offset, MEM_stage.ctrl.shift_byp);
|
||||||
temp2 := load_sign_ext(temp1, MEM_stage.ctrl.sign_ext_byp, MEM_stage.ctrl.load_signed, MEM_stage.ctrl.word2_en, MEM_stage.ctrl.word4_en);
|
temp2 := load_sign_ext(temp1, MEM_stage.ctrl.sign_ext_byp, MEM_stage.ctrl.load_signed, MEM_stage.ctrl.word2_en, MEM_stage.ctrl.word4_en);
|
||||||
|
be := load_be(MEM_stage.pa_off, MEM_stage.ctrl.align_left, MEM_stage.ctrl.byte_en_byp);
|
||||||
if be(0) = '1' then
|
if be(0) = '1' then
|
||||||
data(7 downto 0) := temp2(7 downto 0);
|
data(7 downto 0) := temp2(7 downto 0);
|
||||||
end if;
|
end if;
|
||||||
@@ -850,13 +802,14 @@ proc_stage_MEM_mux:
|
|||||||
end process;
|
end process;
|
||||||
|
|
||||||
proc_stage_MEM_except:
|
proc_stage_MEM_except:
|
||||||
process(MEM_stage, int)
|
process(MEM_stage, c0_ctrl_in)
|
||||||
begin
|
begin
|
||||||
MEM_stage.events <= MEM_stage.events_in;
|
MEM_stage.events <= MEM_stage.events_in;
|
||||||
MEM_stage.events.Int <= int;
|
MEM_stage.events.Int <= c0_ctrl_in.int;
|
||||||
|
MEM_stage.events.NMI <= c0_ctrl_in.NMI;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
MEM_stage.exc <= cop_stat.int or event_is_active(MEM_stage.events_in);
|
MEM_stage.exc <= event_is_active(MEM_stage.events);
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
-- WB stage
|
-- WB stage
|
||||||
@@ -865,20 +818,29 @@ proc_stage_WB_p:
|
|||||||
process(clk_1)
|
process(clk_1)
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk_1) then
|
if rising_edge(clk_1) then
|
||||||
if rst = '1' then
|
if stage_rst(3) = '1' then
|
||||||
WB_stage.op <= NOP;
|
WB_stage.op <= NOP;
|
||||||
WB_stage.wreg_we <= '0';
|
WB_stage.wreg_we <= '1';
|
||||||
|
WB_stage.reg_wptr <= (others => '0');
|
||||||
|
WB_stage.data <= (others => '0');
|
||||||
|
WB_stage.events <= events_clr;
|
||||||
elsif sdu.WB_stall = '0' then
|
elsif sdu.WB_stall = '0' then
|
||||||
WB_stage.op <= MEM_stage.op;
|
WB_stage.op <= MEM_stage.op;
|
||||||
WB_stage.wreg_we <= MEM_stage.wreg_we;
|
WB_stage.wreg_we <= MEM_stage.wreg_we;
|
||||||
WB_stage.reg_wptr <= MEM_stage.reg_wptr;
|
WB_stage.reg_wptr <= MEM_stage.reg_wptr;
|
||||||
WB_stage.data <= MEM_stage.data;
|
WB_stage.data <= MEM_stage.data;
|
||||||
|
WB_stage.exc <= '0';
|
||||||
|
if sdu.stall_all = '0' then
|
||||||
|
WB_stage.exc <= MEM_stage.exc;
|
||||||
|
if MEM_stage.exc = '1' then
|
||||||
|
WB_stage.events <= MEM_stage.events;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
WB_stage.nop <= sdu.WB_nop;
|
WB_stage.nop <= sdu.WB_nop;
|
||||||
if sdu.WB_nop = '1' then
|
if sdu.WB_nop = '1' then
|
||||||
WB_stage.op <= NOP;
|
WB_stage.op <= NOP;
|
||||||
WB_stage.wreg_we <= '0';
|
WB_stage.wreg_we <= '0';
|
||||||
else
|
else
|
||||||
WB_stage.epc <= MEM_stage.epc;
|
|
||||||
WB_stage.bd <= MEM_stage.ctrl.branch or MEM_stage.ctrl.jump or MEM_stage.ctrl.jump_long; -- Todo: works
|
WB_stage.bd <= MEM_stage.ctrl.branch or MEM_stage.ctrl.jump or MEM_stage.ctrl.jump_long; -- Todo: works
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
|
|||||||
@@ -51,16 +51,7 @@ architecture Behavioral of reg_dual is
|
|||||||
constant depth : integer := 2**addr_width;
|
constant depth : integer := 2**addr_width;
|
||||||
type mem_t is array (0 to depth-1) of unsigned (data_width-1 downto 0);
|
type mem_t is array (0 to depth-1) of unsigned (data_width-1 downto 0);
|
||||||
|
|
||||||
function mem_clear(depth : natural) return mem_t is
|
signal reg_mem : mem_t;
|
||||||
variable result : mem_t;
|
|
||||||
begin
|
|
||||||
for i in 0 to depth-1 loop
|
|
||||||
result(i) := (others => '0');
|
|
||||||
end loop;
|
|
||||||
return result;
|
|
||||||
end mem_clear;
|
|
||||||
|
|
||||||
signal reg_mem : mem_t := mem_clear(depth);
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,23 @@ architecture Behavioral of shifter is
|
|||||||
signal sa_rnd : unsigned (4 downto 0);
|
signal sa_rnd : unsigned (4 downto 0);
|
||||||
signal fill : std_logic;
|
signal fill : std_logic;
|
||||||
|
|
||||||
|
type fill_mask_rom_t is array (0 to 2*data_width-1) of unsigned(data_width-1 downto 0);
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
function gen_fill_mask_rom(data_width : natural) return fill_mask_rom_t is
|
||||||
|
variable result : fill_mask_rom_t;
|
||||||
|
begin
|
||||||
|
result(0) := (data_width-1 downto 0 => '0');
|
||||||
|
for i in 1 to data_width-1 loop
|
||||||
|
result(i) := (data_width-1-i downto 0 => '0') & (i-1 downto 0 => '1');
|
||||||
|
end loop;
|
||||||
|
result(data_width) := (data_width-1 downto 0 => '0');
|
||||||
|
for i in 1 to data_width-1 loop
|
||||||
|
result(data_width+i) := (i-1 downto 0 => '1') & (data_width-1-i downto 0 => '0');
|
||||||
|
end loop;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
end gen_fill_mask_rom;
|
||||||
|
|
||||||
function rot_stage(x : unsigned; en : std_logic; stage_num : natural) return unsigned is
|
function rot_stage(x : unsigned; en : std_logic; stage_num : natural) return unsigned is
|
||||||
variable result : unsigned(x'range);
|
variable result : unsigned(x'range);
|
||||||
constant sa : natural := 2**stage_num;
|
constant sa : natural := 2**stage_num;
|
||||||
@@ -63,33 +79,10 @@ function rot_stage(x : unsigned; en : std_logic; stage_num : natural) return uns
|
|||||||
|
|
||||||
end rot_stage;
|
end rot_stage;
|
||||||
|
|
||||||
function rot_fill(x : unsigned; fill : std_logic; shift_right : std_logic; sa : natural) return unsigned is
|
constant fill_mask_rom : fill_mask_rom_t := gen_fill_mask_rom(data_width);
|
||||||
variable result : unsigned(x'range) := (others => '0');
|
signal fill_mask : unsigned(data_width-1 downto 0);
|
||||||
variable j : integer;
|
signal fill_mask_addr : unsigned(5 downto 0);
|
||||||
begin
|
signal dout_filled : unsigned (data_width-1 downto 0);
|
||||||
|
|
||||||
if shift_right = '0' then
|
|
||||||
for i in 0 to x'left loop
|
|
||||||
if i >= sa then
|
|
||||||
result(i) := x(i);
|
|
||||||
else
|
|
||||||
result(i) := fill;
|
|
||||||
end if;
|
|
||||||
end loop;
|
|
||||||
else
|
|
||||||
j := x'left;
|
|
||||||
for i in 0 to x'left loop
|
|
||||||
if i < sa then
|
|
||||||
result(j) := fill;
|
|
||||||
else
|
|
||||||
result(j) := x(j);
|
|
||||||
end if;
|
|
||||||
j := j - 1;
|
|
||||||
end loop;
|
|
||||||
end if;
|
|
||||||
return result;
|
|
||||||
|
|
||||||
end rot_fill;
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
begin
|
begin
|
||||||
@@ -104,10 +97,20 @@ gen_rotate_right:
|
|||||||
|
|
||||||
sa_rnd <= shift_ctrl.shamt_rnd;
|
sa_rnd <= shift_ctrl.shamt_rnd;
|
||||||
fill <= shift_ctrl.shift_arith and din(data_width-1);
|
fill <= shift_ctrl.shift_arith and din(data_width-1);
|
||||||
dout <= rot_fill(rot_data(5), fill, shift_ctrl.shift_right, to_integer(shift_ctrl.shamt_nrm)) after 5 ns;
|
fill_mask_addr <= shift_ctrl.shift_right & shift_ctrl.shamt_nrm;
|
||||||
-- dout <= rot_data(5);
|
fill_mask <= fill_mask_rom(to_integer(fill_mask_addr));
|
||||||
|
|
||||||
|
proc_fill_neu:
|
||||||
|
process(fill_mask, fill, rot_data(5))
|
||||||
|
begin
|
||||||
|
if fill = '1' then
|
||||||
|
dout_filled <= rot_data(5) or fill_mask;
|
||||||
|
else
|
||||||
|
dout_filled <= rot_data(5) and not fill_mask;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
dout <= dout_filled after 5 ns;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
end Behavioral;
|
end Behavioral;
|
||||||
|
|||||||
@@ -29,16 +29,26 @@ library work;
|
|||||||
use work.mips_types.all;
|
use work.mips_types.all;
|
||||||
|
|
||||||
entity mips_top is
|
entity mips_top is
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
icache_size : natural := 8192; -- words
|
||||||
|
icache_line : natural := 8; -- words
|
||||||
|
dcache_size : natural := 4096; -- words
|
||||||
|
dcache_line : natural := 8 -- words
|
||||||
|
);
|
||||||
Port
|
Port
|
||||||
(
|
(
|
||||||
debug : out unsigned(1 downto 0);
|
debug : out unsigned(1 downto 0);
|
||||||
|
eb : in STD_LOGIC;
|
||||||
|
nmi : in STD_LOGIC;
|
||||||
|
cpu_clk : in STD_LOGIC;
|
||||||
RST_I : in STD_LOGIC;
|
RST_I : in STD_LOGIC;
|
||||||
CLK_I : in STD_LOGIC;
|
CLK_I : in STD_LOGIC;
|
||||||
ACK_I : in STD_LOGIC;
|
ACK_I : in STD_LOGIC;
|
||||||
SRDY_I : in STD_LOGIC;
|
SRDY_I : in STD_LOGIC;
|
||||||
ADDR_O : out word_t;
|
ADDR_O : out unsigned(31 downto 0);
|
||||||
DAT_I : in word_t;
|
DAT_I : in unsigned(31 downto 0);
|
||||||
DAT_O : out word_t;
|
DAT_O : out unsigned(31 downto 0);
|
||||||
WE_O : out STD_LOGIC;
|
WE_O : out STD_LOGIC;
|
||||||
SEL_O : out unsigned(3 downto 0);
|
SEL_O : out unsigned(3 downto 0);
|
||||||
CYC_O : out STD_LOGIC;
|
CYC_O : out STD_LOGIC;
|
||||||
@@ -51,13 +61,15 @@ end mips_top;
|
|||||||
|
|
||||||
architecture rtl of mips_top is
|
architecture rtl of mips_top is
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
-- Pipeline
|
||||||
|
--------------------------------------------------------------------------
|
||||||
COMPONENT pipeline is
|
COMPONENT pipeline is
|
||||||
Port
|
Port
|
||||||
(
|
(
|
||||||
rst : in STD_LOGIC;
|
rst : in STD_LOGIC;
|
||||||
clk : in STD_LOGIC;
|
clk : in STD_LOGIC;
|
||||||
halt : in STD_LOGIC;
|
ce : in STD_LOGIC;
|
||||||
int : in unsigned (5 downto 0);
|
|
||||||
imem_err : in STD_LOGIC;
|
imem_err : in STD_LOGIC;
|
||||||
imem_rdy : in STD_LOGIC;
|
imem_rdy : in STD_LOGIC;
|
||||||
imem_en : out STD_LOGIC;
|
imem_en : out STD_LOGIC;
|
||||||
@@ -70,7 +82,13 @@ architecture rtl of mips_top is
|
|||||||
dmem_be : out unsigned(3 downto 0);
|
dmem_be : out unsigned(3 downto 0);
|
||||||
dmem_addr : out word_t;
|
dmem_addr : out word_t;
|
||||||
dmem_din : in word_t;
|
dmem_din : in word_t;
|
||||||
dmem_dout : out word_t
|
dmem_dout : out word_t;
|
||||||
|
cop_ir : out word_t;
|
||||||
|
cop_ir_en : out STD_LOGIC;
|
||||||
|
cop_din : in word_t;
|
||||||
|
cop_dout : out word_t;
|
||||||
|
c0_ctrl_out : out cop0_ctrl_in_t;
|
||||||
|
c0_ctrl_in : in cop0_ctrl_out_t
|
||||||
);
|
);
|
||||||
END COMPONENT;
|
END COMPONENT;
|
||||||
signal imem_err : std_logic;
|
signal imem_err : std_logic;
|
||||||
@@ -87,12 +105,54 @@ architecture rtl of mips_top is
|
|||||||
signal dmem_din : word_t;
|
signal dmem_din : word_t;
|
||||||
signal dmem_be : unsigned(3 downto 0);
|
signal dmem_be : unsigned(3 downto 0);
|
||||||
|
|
||||||
|
signal biu_rst : STD_LOGIC;
|
||||||
|
signal cpu_rst : STD_LOGIC;
|
||||||
|
signal cpu_run : STD_LOGIC;
|
||||||
|
|
||||||
|
signal pipe_cop_ir : word_t;
|
||||||
|
signal pipe_cop_ir_en : STD_LOGIC;
|
||||||
|
signal pipe_cop_din : word_t;
|
||||||
|
signal pipe_cop_dout : word_t;
|
||||||
|
signal pipe_c0_ctrl_out : cop0_ctrl_in_t;
|
||||||
|
signal pipe_c0_ctrl_in : cop0_ctrl_out_t;
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
-- Coprocessor
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
COMPONENT cop is
|
||||||
|
GENERIC
|
||||||
|
(
|
||||||
|
icache_size : natural;
|
||||||
|
icache_line : natural;
|
||||||
|
dcache_size : natural;
|
||||||
|
dcache_line : natural
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
rst : in STD_LOGIC;
|
||||||
|
clk : in STD_LOGIC;
|
||||||
|
nmi : in STD_LOGIC;
|
||||||
|
eb : in STD_LOGIC;
|
||||||
|
int : in unsigned (5 downto 0);
|
||||||
|
ir_en : in STD_LOGIC;
|
||||||
|
ir : in word_t;
|
||||||
|
ctrl_in : in cop0_ctrl_in_t;
|
||||||
|
ctrl_out : out cop0_ctrl_out_t;
|
||||||
|
din : in word_t;
|
||||||
|
dout : out word_t
|
||||||
|
);
|
||||||
|
END COMPONENT;
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
-- Bus Interface Unit
|
||||||
|
--------------------------------------------------------------------------
|
||||||
COMPONENT biu
|
COMPONENT biu
|
||||||
GENERIC
|
GENERIC
|
||||||
(
|
(
|
||||||
icache_size : natural;
|
icache_size : natural;
|
||||||
dcache_size : natural
|
icache_line : natural;
|
||||||
|
dcache_size : natural;
|
||||||
|
dcache_line : natural
|
||||||
);
|
);
|
||||||
PORT
|
PORT
|
||||||
(
|
(
|
||||||
@@ -100,14 +160,16 @@ architecture rtl of mips_top is
|
|||||||
CLK_I : in STD_LOGIC;
|
CLK_I : in STD_LOGIC;
|
||||||
ACK_I : in STD_LOGIC;
|
ACK_I : in STD_LOGIC;
|
||||||
SRDY_I : in STD_LOGIC;
|
SRDY_I : in STD_LOGIC;
|
||||||
ADDR_O : out word_t;
|
ADDR_O : out unsigned(31 downto 0);
|
||||||
DAT_I : in word_t;
|
DAT_I : in unsigned(31 downto 0);
|
||||||
DAT_O : out word_t;
|
DAT_O : out unsigned(31 downto 0);
|
||||||
WE_O : out STD_LOGIC;
|
WE_O : out STD_LOGIC;
|
||||||
SEL_O : out unsigned(3 downto 0);
|
SEL_O : out unsigned(3 downto 0);
|
||||||
CYC_O : out STD_LOGIC;
|
CYC_O : out STD_LOGIC;
|
||||||
STB_O : out STD_LOGIC;
|
STB_O : out STD_LOGIC;
|
||||||
MRDY_O : out STD_LOGIC;
|
MRDY_O : out STD_LOGIC;
|
||||||
|
cop0_ctrl_in : in cop0_ctrl_out_t;
|
||||||
|
cpu_clk : in STD_LOGIC;
|
||||||
cpu_imem_err : out STD_LOGIC;
|
cpu_imem_err : out STD_LOGIC;
|
||||||
cpu_imem_rdy : out STD_LOGIC;
|
cpu_imem_rdy : out STD_LOGIC;
|
||||||
cpu_imem_en : in STD_LOGIC;
|
cpu_imem_en : in STD_LOGIC;
|
||||||
@@ -130,13 +192,36 @@ begin
|
|||||||
debug(0) <= imem_err;
|
debug(0) <= imem_err;
|
||||||
debug(1) <= dmem_err;
|
debug(1) <= dmem_err;
|
||||||
|
|
||||||
|
process(CLK_I)
|
||||||
|
variable reset_delay : unsigned (31 downto 0);
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' then
|
||||||
|
reset_delay := (others => '0');
|
||||||
|
biu_rst <= '1';
|
||||||
|
cpu_rst <= '1';
|
||||||
|
cpu_run <= '0';
|
||||||
|
else
|
||||||
|
reset_delay := reset_delay(reset_delay'left-1 downto 0) & '1';
|
||||||
|
if reset_delay(20) = '1' then
|
||||||
|
biu_rst <= '0';
|
||||||
|
end if;
|
||||||
|
if reset_delay(31) = '1' then
|
||||||
|
cpu_rst <= '0';
|
||||||
|
end if;
|
||||||
|
if reset_delay(16) = '1' then
|
||||||
|
cpu_run <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
inst_pipeline: pipeline
|
inst_pipeline: pipeline
|
||||||
PORT MAP
|
PORT MAP
|
||||||
(
|
(
|
||||||
rst => RST_I,
|
rst => cpu_rst,
|
||||||
clk => CLK_I,
|
clk => cpu_clk,
|
||||||
halt => '0',
|
ce => cpu_run,
|
||||||
int => INT,
|
|
||||||
imem_err => imem_err,
|
imem_err => imem_err,
|
||||||
imem_rdy => imem_rdy,
|
imem_rdy => imem_rdy,
|
||||||
imem_en => imem_en,
|
imem_en => imem_en,
|
||||||
@@ -149,18 +234,49 @@ inst_pipeline: pipeline
|
|||||||
dmem_be => dmem_be,
|
dmem_be => dmem_be,
|
||||||
dmem_addr => dmem_addr,
|
dmem_addr => dmem_addr,
|
||||||
dmem_din => dmem_din,
|
dmem_din => dmem_din,
|
||||||
dmem_dout => dmem_dout
|
dmem_dout => dmem_dout,
|
||||||
|
cop_ir => pipe_cop_ir,
|
||||||
|
cop_ir_en => pipe_cop_ir_en,
|
||||||
|
cop_din => pipe_cop_din,
|
||||||
|
cop_dout => pipe_cop_dout,
|
||||||
|
c0_ctrl_out => pipe_c0_ctrl_out,
|
||||||
|
c0_ctrl_in => pipe_c0_ctrl_in
|
||||||
|
);
|
||||||
|
|
||||||
|
inst_cop: cop
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
icache_size => icache_size, -- words
|
||||||
|
icache_line => icache_line, -- words
|
||||||
|
dcache_size => dcache_size, -- words
|
||||||
|
dcache_line => dcache_line -- words
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => cpu_rst,
|
||||||
|
clk => cpu_clk,
|
||||||
|
nmi => nmi,
|
||||||
|
eb => eb,
|
||||||
|
int => INT,
|
||||||
|
ir_en => pipe_cop_ir_en,
|
||||||
|
ir => pipe_cop_ir,
|
||||||
|
ctrl_in => pipe_c0_ctrl_out,
|
||||||
|
ctrl_out => pipe_c0_ctrl_in,
|
||||||
|
dout => pipe_cop_din,
|
||||||
|
din => pipe_cop_dout
|
||||||
);
|
);
|
||||||
|
|
||||||
inst_biu: biu
|
inst_biu: biu
|
||||||
GENERIC MAP
|
GENERIC MAP
|
||||||
(
|
(
|
||||||
icache_size => 4096, -- words
|
icache_size => icache_size, -- words
|
||||||
dcache_size => 4096 -- words
|
icache_line => icache_line, -- words
|
||||||
|
dcache_size => dcache_size, -- words
|
||||||
|
dcache_line => dcache_line -- words
|
||||||
)
|
)
|
||||||
PORT MAP
|
PORT MAP
|
||||||
(
|
(
|
||||||
RST_I => RST_I,
|
RST_I => biu_rst,
|
||||||
CLK_I => CLK_I,
|
CLK_I => CLK_I,
|
||||||
ACK_I => ACK_I,
|
ACK_I => ACK_I,
|
||||||
SRDY_I => SRDY_I,
|
SRDY_I => SRDY_I,
|
||||||
@@ -172,6 +288,8 @@ inst_biu: biu
|
|||||||
CYC_O => CYC_O,
|
CYC_O => CYC_O,
|
||||||
STB_O => STB_O,
|
STB_O => STB_O,
|
||||||
MRDY_O => MRDY_O,
|
MRDY_O => MRDY_O,
|
||||||
|
cop0_ctrl_in => pipe_c0_ctrl_in,
|
||||||
|
cpu_clk => cpu_clk,
|
||||||
cpu_imem_err => imem_err,
|
cpu_imem_err => imem_err,
|
||||||
cpu_imem_rdy => imem_rdy,
|
cpu_imem_rdy => imem_rdy,
|
||||||
cpu_imem_en => imem_en,
|
cpu_imem_en => imem_en,
|
||||||
|
|||||||
@@ -23,14 +23,14 @@
|
|||||||
|
|
||||||
library IEEE;
|
library IEEE;
|
||||||
use IEEE.STD_LOGIC_1164.ALL;
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
use IEEE.numeric_std.ALL;
|
use IEEE.NUMERIC_STD.ALL;
|
||||||
|
use IEEE.MATH_REAL.ALL;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
package mips_types is
|
package mips_types is
|
||||||
|
|
||||||
-- Revision of the CPU
|
-- Revision of the CPU
|
||||||
constant REVISION : integer := 9;
|
constant REVISION : integer := 13;
|
||||||
constant WORD_WIDTH : integer := 32;
|
constant WORD_WIDTH : integer := 32;
|
||||||
|
|
||||||
--Types
|
--Types
|
||||||
@@ -43,10 +43,9 @@ package mips_types is
|
|||||||
subtype sa_t is natural range 0 to 63;
|
subtype sa_t is natural range 0 to 63;
|
||||||
subtype func_t is unsigned(5 downto 0);
|
subtype func_t is unsigned(5 downto 0);
|
||||||
|
|
||||||
type opclass_t is (special, regimm, opcode);
|
|
||||||
|
|
||||||
type op_t is
|
type op_t is
|
||||||
(
|
(
|
||||||
|
reserved,
|
||||||
nop,
|
nop,
|
||||||
op_sll,
|
op_sll,
|
||||||
op_srl,
|
op_srl,
|
||||||
@@ -110,9 +109,35 @@ package mips_types is
|
|||||||
op_cop1,
|
op_cop1,
|
||||||
op_cop2,
|
op_cop2,
|
||||||
op_cop3,
|
op_cop3,
|
||||||
|
op_mfc0,
|
||||||
|
op_cfc0,
|
||||||
|
op_mtc0,
|
||||||
|
op_ctc0,
|
||||||
|
op_bcf0,
|
||||||
|
op_bct0,
|
||||||
|
op_mfc1,
|
||||||
|
op_cfc1,
|
||||||
|
op_mtc1,
|
||||||
|
op_ctc1,
|
||||||
|
op_bcf1,
|
||||||
|
op_bct1,
|
||||||
|
op_mfc2,
|
||||||
|
op_cfc2,
|
||||||
|
op_mtc2,
|
||||||
|
op_ctc2,
|
||||||
|
op_bcf2,
|
||||||
|
op_bct2,
|
||||||
|
op_mfc3,
|
||||||
|
op_cfc3,
|
||||||
|
op_mtc3,
|
||||||
|
op_ctc3,
|
||||||
|
op_bcf3,
|
||||||
|
op_bct3,
|
||||||
|
op_lwc0,
|
||||||
op_lwc1,
|
op_lwc1,
|
||||||
op_lwc2,
|
op_lwc2,
|
||||||
op_lwc3,
|
op_lwc3,
|
||||||
|
op_swc0,
|
||||||
op_swc1,
|
op_swc1,
|
||||||
op_swc2,
|
op_swc2,
|
||||||
op_swc3
|
op_swc3
|
||||||
@@ -135,7 +160,7 @@ package mips_types is
|
|||||||
last : word_t;
|
last : word_t;
|
||||||
nxt : word_t;
|
nxt : word_t;
|
||||||
pc_branch : word_t;
|
pc_branch : word_t;
|
||||||
is_branch : boolean;
|
branch_take : std_logic;
|
||||||
end record;
|
end record;
|
||||||
|
|
||||||
type alu_outsel_t is
|
type alu_outsel_t is
|
||||||
@@ -150,6 +175,30 @@ package mips_types is
|
|||||||
alu_lts
|
alu_lts
|
||||||
);
|
);
|
||||||
|
|
||||||
|
type sdu_t is record
|
||||||
|
imem_dep : STD_LOGIC;
|
||||||
|
dmem_dep : STD_LOGIC;
|
||||||
|
mul_dep : STD_LOGIC;
|
||||||
|
ID_nop : STD_LOGIC;
|
||||||
|
EX_nop : STD_LOGIC;
|
||||||
|
MEM_nop : STD_LOGIC;
|
||||||
|
WB_nop : STD_LOGIC;
|
||||||
|
ID_stall : STD_LOGIC;
|
||||||
|
EX_stall : STD_LOGIC;
|
||||||
|
MEM_stall : STD_LOGIC;
|
||||||
|
WB_stall : STD_LOGIC;
|
||||||
|
stall_all : STD_LOGIC;
|
||||||
|
end record;
|
||||||
|
|
||||||
|
type hdu_t is record
|
||||||
|
alu_fwd_a_ex : boolean;
|
||||||
|
alu_fwd_a_mem : boolean;
|
||||||
|
alu_fwd_a_wb : boolean;
|
||||||
|
alu_fwd_b_ex : boolean;
|
||||||
|
alu_fwd_b_mem : boolean;
|
||||||
|
alu_fwd_b_wb : boolean;
|
||||||
|
end record;
|
||||||
|
|
||||||
type alu_flags_t is record
|
type alu_flags_t is record
|
||||||
c : STD_LOGIC;
|
c : STD_LOGIC;
|
||||||
uvf : STD_LOGIC;
|
uvf : STD_LOGIC;
|
||||||
@@ -164,7 +213,8 @@ package mips_types is
|
|||||||
end record;
|
end record;
|
||||||
|
|
||||||
type event_t is record
|
type event_t is record
|
||||||
Int : unsigned(5 downto 0);
|
NMI : STD_LOGIC;
|
||||||
|
Int : STD_LOGIC;
|
||||||
data_load_err : STD_LOGIC;
|
data_load_err : STD_LOGIC;
|
||||||
data_store_err : STD_LOGIC;
|
data_store_err : STD_LOGIC;
|
||||||
inst_load_err : STD_LOGIC;
|
inst_load_err : STD_LOGIC;
|
||||||
@@ -196,47 +246,36 @@ package mips_types is
|
|||||||
cause : word_t;
|
cause : word_t;
|
||||||
end record;
|
end record;
|
||||||
|
|
||||||
type cop_ctrl_in_t is record
|
type cache_ctrl_t is record
|
||||||
|
inv_addr : word_t;
|
||||||
|
inv_at : STD_LOGIC;
|
||||||
|
inv_all : STD_LOGIC;
|
||||||
|
end record;
|
||||||
|
|
||||||
|
type cop0_ctrl_in_t is record
|
||||||
|
sdu : sdu_t;
|
||||||
|
events : event_t;
|
||||||
bd_wb : STD_LOGIC;
|
bd_wb : STD_LOGIC;
|
||||||
epc_mem : word_t;
|
epc_mem : word_t;
|
||||||
epc_wb : word_t;
|
epc_wb : word_t;
|
||||||
imem_addr : word_t;
|
imem_addr : word_t;
|
||||||
dmem_addr : word_t;
|
dmem_addr : word_t;
|
||||||
exc_left : STD_LOGIC;
|
exc_req : STD_LOGIC;
|
||||||
|
exc_ack : STD_LOGIC;
|
||||||
end record;
|
end record;
|
||||||
|
|
||||||
type cop_ctrl_out_t is record
|
type cop0_ctrl_out_t is record
|
||||||
RE : STD_LOGIC;
|
EB : STD_LOGIC;
|
||||||
ee : STD_LOGIC;
|
exc_inject : STD_LOGIC;
|
||||||
ec : STD_LOGIC;
|
|
||||||
exc_commit : STD_LOGIC;
|
exc_commit : STD_LOGIC;
|
||||||
exc_pending : STD_LOGIC;
|
exc_pending : STD_LOGIC;
|
||||||
exc_exit : STD_LOGIC;
|
exc_exit : STD_LOGIC;
|
||||||
reg_write : STD_LOGIC;
|
|
||||||
cop_read : STD_LOGIC;
|
|
||||||
user_mode : STD_LOGIC;
|
user_mode : STD_LOGIC;
|
||||||
|
NMI : STD_LOGIC;
|
||||||
int : STD_LOGIC;
|
int : STD_LOGIC;
|
||||||
exc_vec : word_t;
|
exc_vec : word_t;
|
||||||
end record;
|
icache : cache_ctrl_t;
|
||||||
|
dcache : cache_ctrl_t;
|
||||||
type sdu_t is record
|
|
||||||
ID_nop : STD_LOGIC;
|
|
||||||
EX_nop : STD_LOGIC;
|
|
||||||
MEM_nop : STD_LOGIC;
|
|
||||||
WB_nop : STD_LOGIC;
|
|
||||||
ID_stall : STD_LOGIC;
|
|
||||||
EX_stall : STD_LOGIC;
|
|
||||||
MEM_stall : STD_LOGIC;
|
|
||||||
WB_stall : STD_LOGIC;
|
|
||||||
end record;
|
|
||||||
|
|
||||||
type hdu_t is record
|
|
||||||
alu_fwd_a_ex : boolean;
|
|
||||||
alu_fwd_a_mem : boolean;
|
|
||||||
alu_fwd_a_wb : boolean;
|
|
||||||
alu_fwd_b_ex : boolean;
|
|
||||||
alu_fwd_b_mem : boolean;
|
|
||||||
alu_fwd_b_wb : boolean;
|
|
||||||
end record;
|
end record;
|
||||||
|
|
||||||
type alu_ctrl_t is record
|
type alu_ctrl_t is record
|
||||||
@@ -270,6 +309,7 @@ package mips_types is
|
|||||||
shamt2_srcsel : sa_src_t;
|
shamt2_srcsel : sa_src_t;
|
||||||
wptr_srcsel : wptr_src_t;
|
wptr_srcsel : wptr_src_t;
|
||||||
cop_instr_en : STD_LOGIC;
|
cop_instr_en : STD_LOGIC;
|
||||||
|
cop_read : STD_LOGIC;
|
||||||
shift_offset : unsigned(1 downto 0);
|
shift_offset : unsigned(1 downto 0);
|
||||||
shift_byp : STD_LOGIC;
|
shift_byp : STD_LOGIC;
|
||||||
byte_en_byp : STD_LOGIC;
|
byte_en_byp : STD_LOGIC;
|
||||||
@@ -357,8 +397,9 @@ package mips_types is
|
|||||||
|
|
||||||
type WB_t is record
|
type WB_t is record
|
||||||
nop : STD_LOGIC;
|
nop : STD_LOGIC;
|
||||||
|
exc : std_logic;
|
||||||
|
events : event_t;
|
||||||
op : op_t;
|
op : op_t;
|
||||||
epc : word_t;
|
|
||||||
reg_wptr : reg_ptr_t;
|
reg_wptr : reg_ptr_t;
|
||||||
wreg_we : STD_LOGIC;
|
wreg_we : STD_LOGIC;
|
||||||
data : word_t;
|
data : word_t;
|
||||||
@@ -379,6 +420,9 @@ package mips_types is
|
|||||||
function event_is_active(e : event_t) return std_logic;
|
function event_is_active(e : event_t) return std_logic;
|
||||||
function "or" (a, b : event_t) return event_t;
|
function "or" (a, b : event_t) return event_t;
|
||||||
|
|
||||||
|
function lg2(x : natural) return natural;
|
||||||
|
function po2(x : natural) return natural;
|
||||||
|
|
||||||
end mips_types;
|
end mips_types;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
@@ -412,16 +456,15 @@ package body mips_types is
|
|||||||
function store_be(va : unsigned(1 downto 0); be_src, word2_en, word4_en, align_left, bypass : std_logic) return unsigned is
|
function store_be(va : unsigned(1 downto 0); be_src, word2_en, word4_en, align_left, bypass : std_logic) return unsigned is
|
||||||
variable result : unsigned(3 downto 0);
|
variable result : unsigned(3 downto 0);
|
||||||
begin
|
begin
|
||||||
if bypass = '1' then
|
|
||||||
result := (3 downto 0 => be_src);
|
result := (3 downto 0 => be_src);
|
||||||
elsif word2_en = '1' then
|
if bypass = '0' then
|
||||||
|
if word2_en = '1' then
|
||||||
case va is
|
case va is
|
||||||
when "00" | "01" =>
|
when "00" =>
|
||||||
result := "00" & be_src & be_src;
|
result := "00" & be_src & be_src;
|
||||||
when "10" | "11" =>
|
when "10" =>
|
||||||
result := be_src & be_src & "00";
|
result := be_src & be_src & "00";
|
||||||
when others =>
|
when others => null;
|
||||||
result := "0000";
|
|
||||||
end case;
|
end case;
|
||||||
elsif word4_en = '1' then
|
elsif word4_en = '1' then
|
||||||
case va is
|
case va is
|
||||||
@@ -433,8 +476,7 @@ package body mips_types is
|
|||||||
result := '0' & be_src & "00";
|
result := '0' & be_src & "00";
|
||||||
when "11" =>
|
when "11" =>
|
||||||
result := be_src & "000";
|
result := be_src & "000";
|
||||||
when others =>
|
when others => null;
|
||||||
result := "0000";
|
|
||||||
end case;
|
end case;
|
||||||
elsif align_left = '1' then
|
elsif align_left = '1' then
|
||||||
case va is
|
case va is
|
||||||
@@ -446,8 +488,7 @@ package body mips_types is
|
|||||||
result := be_src & be_src & "00";
|
result := be_src & be_src & "00";
|
||||||
when "11" =>
|
when "11" =>
|
||||||
result := be_src & "000";
|
result := be_src & "000";
|
||||||
when others =>
|
when others => null;
|
||||||
result := "0000";
|
|
||||||
end case;
|
end case;
|
||||||
else
|
else
|
||||||
case va is
|
case va is
|
||||||
@@ -459,10 +500,10 @@ package body mips_types is
|
|||||||
result := '0' & be_src & be_src & be_src;
|
result := '0' & be_src & be_src & be_src;
|
||||||
when "11" =>
|
when "11" =>
|
||||||
result := be_src & be_src & be_src & be_src;
|
result := be_src & be_src & be_src & be_src;
|
||||||
when others =>
|
when others => null;
|
||||||
result := "0000";
|
|
||||||
end case;
|
end case;
|
||||||
end if;
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -497,9 +538,9 @@ package body mips_types is
|
|||||||
function load_be(va : unsigned(1 downto 0); align_left, bypass : std_logic) return unsigned is
|
function load_be(va : unsigned(1 downto 0); align_left, bypass : std_logic) return unsigned is
|
||||||
variable result : unsigned(3 downto 0);
|
variable result : unsigned(3 downto 0);
|
||||||
begin
|
begin
|
||||||
if bypass = '1' then
|
|
||||||
result := (3 downto 0 => '1');
|
result := (3 downto 0 => '1');
|
||||||
elsif align_left = '1' then
|
if bypass = '0' then
|
||||||
|
if align_left = '1' then
|
||||||
case va is
|
case va is
|
||||||
when "00" =>
|
when "00" =>
|
||||||
result := "1000";
|
result := "1000";
|
||||||
@@ -509,8 +550,7 @@ package body mips_types is
|
|||||||
result := "1110";
|
result := "1110";
|
||||||
when "11" =>
|
when "11" =>
|
||||||
result := "1111";
|
result := "1111";
|
||||||
when others =>
|
when others => null;
|
||||||
result := "0000";
|
|
||||||
end case;
|
end case;
|
||||||
else
|
else
|
||||||
case va is
|
case va is
|
||||||
@@ -522,10 +562,10 @@ package body mips_types is
|
|||||||
result := "0011";
|
result := "0011";
|
||||||
when "11" =>
|
when "11" =>
|
||||||
result := "0001";
|
result := "0001";
|
||||||
when others =>
|
when others => null;
|
||||||
result := "0000";
|
|
||||||
end case;
|
end case;
|
||||||
end if;
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@@ -554,7 +594,8 @@ package body mips_types is
|
|||||||
function events_clr return event_t is
|
function events_clr return event_t is
|
||||||
variable result : event_t;
|
variable result : event_t;
|
||||||
begin
|
begin
|
||||||
result.Int := (others => '0');
|
result.NMI := '0';
|
||||||
|
result.Int := '0';
|
||||||
result.data_load_err := '0';
|
result.data_load_err := '0';
|
||||||
result.data_store_err := '0';
|
result.data_store_err := '0';
|
||||||
result.inst_load_err := '0';
|
result.inst_load_err := '0';
|
||||||
@@ -569,15 +610,14 @@ package body mips_types is
|
|||||||
|
|
||||||
end events_clr;
|
end events_clr;
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------
|
||||||
function event_is_active(e : event_t) return std_logic is
|
function event_is_active(e : event_t) return std_logic is
|
||||||
variable result : std_logic;
|
variable result : std_logic;
|
||||||
begin
|
begin
|
||||||
result := '0';
|
result := '0';
|
||||||
|
|
||||||
for i in e.Int'range loop
|
result := result or e.NMI;
|
||||||
result := result or e.Int(i);
|
result := result or e.Int;
|
||||||
end loop;
|
|
||||||
|
|
||||||
result := result or e.data_load_err;
|
result := result or e.data_load_err;
|
||||||
result := result or e.data_store_err;
|
result := result or e.data_store_err;
|
||||||
result := result or e.inst_load_err;
|
result := result or e.inst_load_err;
|
||||||
@@ -592,12 +632,12 @@ package body mips_types is
|
|||||||
|
|
||||||
end event_is_active;
|
end event_is_active;
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------
|
||||||
function "or" (a, b : event_t) return event_t is
|
function "or" (a, b : event_t) return event_t is
|
||||||
variable result : event_t;
|
variable result : event_t;
|
||||||
begin
|
begin
|
||||||
for i in a.Int'range loop
|
result.NMI := a.NMI or b.NMI;
|
||||||
result.Int(i) := a.Int(i) or b.Int(i);
|
result.Int := a.Int or b.Int;
|
||||||
end loop;
|
|
||||||
result.data_load_err := a.data_load_err or b.data_load_err;
|
result.data_load_err := a.data_load_err or b.data_load_err;
|
||||||
result.data_store_err := a.data_store_err or b.data_store_err;
|
result.data_store_err := a.data_store_err or b.data_store_err;
|
||||||
result.inst_load_err := a.inst_load_err or b.inst_load_err;
|
result.inst_load_err := a.inst_load_err or b.inst_load_err;
|
||||||
@@ -613,7 +653,18 @@ package body mips_types is
|
|||||||
end "or";
|
end "or";
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
end mips_types;
|
function lg2(x : natural) return natural is
|
||||||
|
begin
|
||||||
|
return natural(ceil(log2(real(x))));
|
||||||
|
end lg2;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
function po2(x : natural) return natural is
|
||||||
|
begin
|
||||||
|
|
||||||
|
return 2**lg2(x);
|
||||||
|
end po2;
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
end mips_types;
|
||||||
|
|
||||||
|
|||||||
@@ -32,25 +32,53 @@ use work.mips_instr.all;
|
|||||||
use work.async_types.all;
|
use work.async_types.all;
|
||||||
use work.async_defs.all;
|
use work.async_defs.all;
|
||||||
|
|
||||||
ENTITY tb_mips_top IS
|
ENTITY mips_sys IS
|
||||||
END tb_mips_top;
|
GENERIC
|
||||||
|
(
|
||||||
|
ICACHE_SIZE : natural := 512; -- words
|
||||||
|
DCACHE_SIZE : natural := 512; -- words
|
||||||
|
SRAM_ADDR_WIDTH : integer := 14;
|
||||||
|
FLASH_ADDR_WIDTH : integer := 14
|
||||||
|
);
|
||||||
|
PORT
|
||||||
|
(
|
||||||
|
eb : in std_logic;
|
||||||
|
nmi : in std_logic;
|
||||||
|
rst : in std_logic;
|
||||||
|
clk : in std_logic;
|
||||||
|
flash_cs_n : out std_logic;
|
||||||
|
flash_oe_n : out std_logic;
|
||||||
|
flash_we_n : out std_logic;
|
||||||
|
flash_be_n : out unsigned(3 downto 0);
|
||||||
|
sram_cs_n : out std_logic;
|
||||||
|
sram_we_n : out std_logic;
|
||||||
|
sram_oe_n : out std_logic;
|
||||||
|
sram_be_n : out unsigned(3 downto 0);
|
||||||
|
sram_a : out unsigned(SRAM_ADDR_WIDTH-1 downto 0);
|
||||||
|
sram_d : inout unsigned(31 downto 0);
|
||||||
|
flash_a : out unsigned(FLASH_ADDR_WIDTH-1 downto 0);
|
||||||
|
flash_d : inout unsigned(31 downto 0);
|
||||||
|
|
||||||
ARCHITECTURE behavior OF tb_mips_top IS
|
gpo0 : out unsigned(31 downto 0);
|
||||||
|
gpo1 : out unsigned(31 downto 0);
|
||||||
|
gpi0 : in unsigned(31 downto 0);
|
||||||
|
gpi1 : in unsigned(31 downto 0);
|
||||||
|
|
||||||
constant CLK_PERIOD : time := 10 ns;
|
rx : in std_logic;
|
||||||
constant SRAM_ADDR_WIDTH : integer := 14; -- bits
|
tx : out std_logic;
|
||||||
constant FLASH_ADDR_WIDTH : integer := 14; -- bits
|
|
||||||
|
|
||||||
signal debug : unsigned(1 downto 0);
|
debug : out unsigned(1 downto 0)
|
||||||
|
);
|
||||||
|
END mips_sys;
|
||||||
|
|
||||||
|
ARCHITECTURE behavior OF mips_sys IS
|
||||||
|
|
||||||
-- Master
|
-- Master
|
||||||
signal rst : STD_LOGIC := '1';
|
|
||||||
signal clk : STD_LOGIC := '0';
|
|
||||||
signal ACK_I : STD_LOGIC := '0';
|
signal ACK_I : STD_LOGIC := '0';
|
||||||
signal SRDY_I : STD_LOGIC := '0';
|
signal SRDY_I : STD_LOGIC := '0';
|
||||||
signal ADDR_O : word_t;
|
signal ADDR_O : unsigned(31 downto 0);
|
||||||
signal DAT_I : word_t := (others => '0');
|
signal DAT_I : unsigned(31 downto 0) := (others => '0');
|
||||||
signal DAT_O : word_t;
|
signal DAT_O : unsigned(31 downto 0);
|
||||||
signal WE_O : STD_LOGIC;
|
signal WE_O : STD_LOGIC;
|
||||||
signal SEL_O : unsigned(3 downto 0);
|
signal SEL_O : unsigned(3 downto 0);
|
||||||
signal CYC_O : STD_LOGIC;
|
signal CYC_O : STD_LOGIC;
|
||||||
@@ -84,41 +112,14 @@ ARCHITECTURE behavior OF tb_mips_top IS
|
|||||||
signal SRDY_O_uart : std_logic;
|
signal SRDY_O_uart : std_logic;
|
||||||
signal DAT_O_uart : unsigned(31 downto 0);
|
signal DAT_O_uart : unsigned(31 downto 0);
|
||||||
|
|
||||||
signal flash_cs_n : std_logic;
|
signal int_timer : std_logic;
|
||||||
signal flash_oe_n : std_logic;
|
signal int_uart : std_logic;
|
||||||
signal sram_cs_n : std_logic;
|
|
||||||
signal sram_wr_n : unsigned(3 downto 0);
|
|
||||||
signal sram_oe_n : std_logic;
|
|
||||||
signal sram_a : unsigned(SRAM_ADDR_WIDTH-1 downto 0);
|
|
||||||
signal sram_d : unsigned(31 downto 0);
|
|
||||||
signal flash_a : unsigned(FLASH_ADDR_WIDTH-1 downto 0);
|
|
||||||
signal flash_d : unsigned(31 downto 0);
|
|
||||||
|
|
||||||
signal gpo0 : unsigned(31 downto 0);
|
|
||||||
signal gpo1 : unsigned(31 downto 0);
|
|
||||||
signal gpi0 : unsigned(31 downto 0) := (others => '0');
|
|
||||||
signal gpi1 : unsigned(31 downto 0) := (others => '0');
|
|
||||||
|
|
||||||
signal int_uart_rx : std_logic;
|
|
||||||
signal rx : std_logic := '1';
|
|
||||||
signal tx : std_logic;
|
|
||||||
|
|
||||||
type mem_area_t is (mem_dead, mem_flash, mem_sram, mem_rom, mem_gpio, mem_uart);
|
type mem_area_t is (mem_dead, mem_flash, mem_sram, mem_rom, mem_gpio, mem_uart);
|
||||||
signal mem_area : mem_area_t;
|
signal mem_area : mem_area_t;
|
||||||
|
|
||||||
type word_array_t is array (natural range <>) of word_t;
|
|
||||||
signal sram_data : word_array_t(0 to 2**SRAM_ADDR_WIDTH-1);
|
|
||||||
signal flash_data : word_array_t(0 to 2**FLASH_ADDR_WIDTH-1);
|
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
CLK_GEN: process
|
|
||||||
begin
|
|
||||||
wait for CLK_PERIOD/2;
|
|
||||||
clk <= not clk;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
-- Memory mux
|
-- Memory mux
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
@@ -188,10 +189,18 @@ signal_mux:
|
|||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
------------------------------------------------------------------
|
||||||
uut: entity work.mips_top
|
inst_mips_top: entity work.mips_top
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
icache_size => ICACHE_SIZE, -- words
|
||||||
|
dcache_size => DCACHE_SIZE -- words
|
||||||
|
)
|
||||||
PORT MAP
|
PORT MAP
|
||||||
(
|
(
|
||||||
debug => debug,
|
debug => debug,
|
||||||
|
nmi => nmi,
|
||||||
|
eb => eb,
|
||||||
|
cpu_clk => clk,
|
||||||
RST_I => rst,
|
RST_I => rst,
|
||||||
CLK_I => clk,
|
CLK_I => clk,
|
||||||
ACK_I => ACK_I,
|
ACK_I => ACK_I,
|
||||||
@@ -206,7 +215,8 @@ uut: entity work.mips_top
|
|||||||
MRDY_O => MRDY_O,
|
MRDY_O => MRDY_O,
|
||||||
INT => INT
|
INT => INT
|
||||||
);
|
);
|
||||||
INT(1) <= int_uart_rx;
|
INT(1) <= int_uart;
|
||||||
|
INT(5) <= int_timer;
|
||||||
|
|
||||||
inst_rom : entity work.rom_wb
|
inst_rom : entity work.rom_wb
|
||||||
PORT MAP
|
PORT MAP
|
||||||
@@ -237,7 +247,7 @@ inst_gpio : entity work.gpio_wb
|
|||||||
ADDR_I => ADDR_O,
|
ADDR_I => ADDR_O,
|
||||||
DAT_I => DAT_O,
|
DAT_I => DAT_O,
|
||||||
DAT_O => DAT_O_gpio,
|
DAT_O => DAT_O_gpio,
|
||||||
|
INT_TIM_O => int_timer,
|
||||||
sys_gpo0 => gpo0,
|
sys_gpo0 => gpo0,
|
||||||
sys_gpo1 => gpo1,
|
sys_gpo1 => gpo1,
|
||||||
sys_gpi0 => gpi0,
|
sys_gpi0 => gpi0,
|
||||||
@@ -249,7 +259,7 @@ inst_flash_port : entity work.async_port_wb
|
|||||||
(
|
(
|
||||||
addr_width => FLASH_ADDR_WIDTH,
|
addr_width => FLASH_ADDR_WIDTH,
|
||||||
data_width => 32,
|
data_width => 32,
|
||||||
byte_sel_width => 1,
|
byte_sel_width => 4,
|
||||||
async_timespec => ts_flash
|
async_timespec => ts_flash
|
||||||
)
|
)
|
||||||
PORT MAP
|
PORT MAP
|
||||||
@@ -266,11 +276,13 @@ inst_flash_port : entity work.async_port_wb
|
|||||||
ADDR_I => ADDR_O,
|
ADDR_I => ADDR_O,
|
||||||
DAT_I => DAT_O,
|
DAT_I => DAT_O,
|
||||||
DAT_O => DAT_O_flash,
|
DAT_O => DAT_O_flash,
|
||||||
|
page_mode_en => '0',
|
||||||
async_a => flash_a,
|
async_a => flash_a,
|
||||||
async_d => flash_d,
|
async_d => flash_d,
|
||||||
async_cs => flash_cs_n,
|
async_cs => flash_cs_n,
|
||||||
async_wr => open,
|
async_wr => flash_we_n,
|
||||||
async_rd => flash_oe_n,
|
async_rd => flash_oe_n,
|
||||||
|
async_be => flash_be_n,
|
||||||
async_rst => open
|
async_rst => open
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -296,11 +308,13 @@ inst_sram_port : entity work.async_port_wb
|
|||||||
ADDR_I => ADDR_O,
|
ADDR_I => ADDR_O,
|
||||||
DAT_I => DAT_O,
|
DAT_I => DAT_O,
|
||||||
DAT_O => DAT_O_sram,
|
DAT_O => DAT_O_sram,
|
||||||
|
page_mode_en => '0',
|
||||||
async_a => sram_a,
|
async_a => sram_a,
|
||||||
async_d => sram_d,
|
async_d => sram_d,
|
||||||
async_cs => sram_cs_n,
|
async_cs => sram_cs_n,
|
||||||
async_wr => sram_wr_n,
|
async_wr => sram_we_n,
|
||||||
async_rd => sram_oe_n,
|
async_rd => sram_oe_n,
|
||||||
|
async_be => sram_be_n,
|
||||||
async_rst => open
|
async_rst => open
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -319,87 +333,9 @@ inst_uart : entity work.uart_wb
|
|||||||
ADDR_I => ADDR_O,
|
ADDR_I => ADDR_O,
|
||||||
DAT_I => DAT_O,
|
DAT_I => DAT_O,
|
||||||
DAT_O => DAT_O_uart,
|
DAT_O => DAT_O_uart,
|
||||||
INT_RX_O => int_uart_rx,
|
INT_O => int_uart,
|
||||||
INT_TX_O => open,
|
|
||||||
ser_rx => rx,
|
ser_rx => rx,
|
||||||
ser_tx => tx
|
ser_tx => tx
|
||||||
);
|
);
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
SRAM_READ:
|
|
||||||
process(sram_a, sram_cs_n, sram_oe_n)
|
|
||||||
begin
|
|
||||||
sram_d <= (others => 'Z');
|
|
||||||
if sram_oe_n = '0' then
|
|
||||||
if sram_cs_n = '0' then
|
|
||||||
sram_d <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)));
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
SRAM_WRITE:
|
|
||||||
process(sram_a, sram_cs_n, sram_wr_n)
|
|
||||||
begin
|
|
||||||
if rising_edge(sram_wr_n(0)) then
|
|
||||||
if sram_cs_n = '0' then
|
|
||||||
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(7 downto 0) <= sram_d(7 downto 0);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
if rising_edge(sram_wr_n(1)) then
|
|
||||||
if sram_cs_n = '0' then
|
|
||||||
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(15 downto 8) <= sram_d(15 downto 8);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
if rising_edge(sram_wr_n(2)) then
|
|
||||||
if sram_cs_n = '0' then
|
|
||||||
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(23 downto 16) <= sram_d(23 downto 16);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
if rising_edge(sram_wr_n(3)) then
|
|
||||||
if sram_cs_n = '0' then
|
|
||||||
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(31 downto 24) <= sram_d(31 downto 24);
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
FLASH_READ:
|
|
||||||
process(rst, flash_cs_n, flash_oe_n, flash_a)
|
|
||||||
type file_t is file of integer;
|
|
||||||
file load_flash : file_t open read_mode is "hello.flash.bin";
|
|
||||||
variable instr : integer;
|
|
||||||
variable index : natural;
|
|
||||||
variable temp : signed(31 downto 0);
|
|
||||||
begin
|
|
||||||
if rst = '1' then
|
|
||||||
index := 0;
|
|
||||||
while not endfile(load_flash) loop
|
|
||||||
read(load_flash, instr);
|
|
||||||
temp := to_signed(instr, word_t'length);
|
|
||||||
flash_data(index) <= unsigned(temp);
|
|
||||||
index := index + 1;
|
|
||||||
end loop;
|
|
||||||
else
|
|
||||||
flash_d <= (others => 'Z') after 10 ns;
|
|
||||||
if flash_oe_n = '0' and flash_cs_n = '0' then
|
|
||||||
index := to_integer(flash_a(FLASH_ADDR_WIDTH-1 downto 2));
|
|
||||||
flash_d <= flash_data(index) after 10 ns;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
------------------------------------------------------------------
|
|
||||||
STIMULUS: process
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
|
|
||||||
wait for 3*CLK_PERIOD;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
rst <= '0';
|
|
||||||
|
|
||||||
wait;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
END;
|
END;
|
||||||
@@ -1,332 +0,0 @@
|
|||||||
-------------------------------------------------------------------------
|
|
||||||
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
|
||||||
-- This file: Testbench for JCPU
|
|
||||||
-- also writes 'opc.lst' for JASM-assembler
|
|
||||||
--
|
|
||||||
-- Copyright (C) 2007 J. Ahrensfeld
|
|
||||||
--
|
|
||||||
-- This program is free software: you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation, either version 3 of the License, or
|
|
||||||
-- (at your option) any later version.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
--
|
|
||||||
-- For questions and ideas, please contact the author at jens@jayfield.org
|
|
||||||
--
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
LIBRARY ieee;
|
|
||||||
use IEEE.STD_LOGIC_1164.ALL;
|
|
||||||
USE ieee.numeric_std.ALL;
|
|
||||||
|
|
||||||
library work;
|
|
||||||
use work.mips_types.all;
|
|
||||||
use work.mips_instr.all;
|
|
||||||
|
|
||||||
ENTITY tb_mips_muldiv IS
|
|
||||||
END tb_mips_muldiv;
|
|
||||||
|
|
||||||
ARCHITECTURE behavior OF tb_mips_muldiv IS
|
|
||||||
|
|
||||||
COMPONENT muldiv is
|
|
||||||
Port
|
|
||||||
(
|
|
||||||
rst : in std_logic;
|
|
||||||
clk : in std_logic;
|
|
||||||
hilo_we : in std_logic;
|
|
||||||
din_hi : in word_t;
|
|
||||||
din_lo : in word_t;
|
|
||||||
mul_divn : in std_logic;
|
|
||||||
s_un : in std_logic;
|
|
||||||
start : in std_logic;
|
|
||||||
hilo_sel : in std_logic;
|
|
||||||
busy : out std_logic;
|
|
||||||
dout : out word_t
|
|
||||||
);
|
|
||||||
END COMPONENT;
|
|
||||||
|
|
||||||
constant CLK_PERIOD : time := 10 ns;
|
|
||||||
signal ENABLE_FAIL_REPORT : boolean := true;
|
|
||||||
signal rst : std_logic := '1';
|
|
||||||
signal clk : std_logic := '1';
|
|
||||||
signal busy : std_logic;
|
|
||||||
signal mul_divn : std_logic := '0';
|
|
||||||
signal s_un : std_logic := '1';
|
|
||||||
signal hilo_we : std_logic := '0';
|
|
||||||
signal start : std_logic := '0';
|
|
||||||
signal din_hi : word_t := (others => '-');
|
|
||||||
signal din_lo : word_t := (others => '-');
|
|
||||||
signal dout : word_t;
|
|
||||||
signal hilo_sel : std_logic := '0';
|
|
||||||
signal md_result : unsigned (2*word_t'length-1 downto 0) := (others => '0');
|
|
||||||
signal ref_result : unsigned (2*word_t'length-1 downto 0);
|
|
||||||
signal ref_hi : unsigned (word_t'length-1 downto 0);
|
|
||||||
signal rtmp : unsigned (2*word_t'length-1 downto 0);
|
|
||||||
signal tmp2 : unsigned (word_t'length-1 downto 0);
|
|
||||||
signal check : std_logic;
|
|
||||||
|
|
||||||
type word_array_t is array (natural range <>) of word_t;
|
|
||||||
|
|
||||||
constant operands : word_array_t(0 to 63) :=
|
|
||||||
(
|
|
||||||
X"00000000",
|
|
||||||
X"00000001",
|
|
||||||
X"00000010",
|
|
||||||
X"00000100",
|
|
||||||
X"00001000",
|
|
||||||
X"00010000",
|
|
||||||
X"00100000",
|
|
||||||
X"01000000",
|
|
||||||
X"10000000",
|
|
||||||
X"0000000F",
|
|
||||||
X"000000FF",
|
|
||||||
X"00000FFF",
|
|
||||||
X"0000FFFF",
|
|
||||||
X"000FFFFF",
|
|
||||||
X"00FFFFFF",
|
|
||||||
X"0FFFFFFF",
|
|
||||||
X"12345678",
|
|
||||||
X"23456789",
|
|
||||||
X"7FFFFFFF",
|
|
||||||
X"80000000",
|
|
||||||
X"A541B3B9",
|
|
||||||
X"80000001",
|
|
||||||
X"80000010",
|
|
||||||
X"80000100",
|
|
||||||
X"80001000",
|
|
||||||
X"80010000",
|
|
||||||
X"80100000",
|
|
||||||
X"81000000",
|
|
||||||
X"87654321",
|
|
||||||
X"98765432",
|
|
||||||
X"FFFFFFFF",
|
|
||||||
X"FFFFFFFE",
|
|
||||||
X"FFFFFFFD",
|
|
||||||
X"FFFFFFFB",
|
|
||||||
X"FFFFFFF7",
|
|
||||||
X"FFFFFFEF",
|
|
||||||
X"FFFFFFDF",
|
|
||||||
X"FFFFFFBF",
|
|
||||||
X"FFFFFF7F",
|
|
||||||
X"FFFFFEFF",
|
|
||||||
X"FFFFFDFF",
|
|
||||||
X"FFFFFBFF",
|
|
||||||
X"FFFFF7FF",
|
|
||||||
X"FFFFEFFF",
|
|
||||||
X"FFFFDFFF",
|
|
||||||
X"FFFFBFFF",
|
|
||||||
X"FFFF7FFF",
|
|
||||||
X"FFFEFFFF",
|
|
||||||
X"FFFDFFFF",
|
|
||||||
X"FFFBFFFF",
|
|
||||||
X"FFF7FFFF",
|
|
||||||
X"FFEFFFFF",
|
|
||||||
X"FFDFFFFF",
|
|
||||||
X"FFBFFFFF",
|
|
||||||
X"FF7FFFFF",
|
|
||||||
X"FEFFFFFF",
|
|
||||||
X"FDFFFFFF",
|
|
||||||
X"FBFFFFFF",
|
|
||||||
X"F7FFFFFF",
|
|
||||||
X"EFFFFFFF",
|
|
||||||
X"DFFFFFFF",
|
|
||||||
X"BFFFFFFF",
|
|
||||||
X"CFFFFFFF",
|
|
||||||
X"7FFFFFFF"
|
|
||||||
);
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
|
|
||||||
uut: muldiv
|
|
||||||
PORT MAP(
|
|
||||||
rst => rst,
|
|
||||||
clk => clk,
|
|
||||||
hilo_we => hilo_we,
|
|
||||||
din_hi => din_hi,
|
|
||||||
din_lo => din_lo,
|
|
||||||
mul_divn => mul_divn,
|
|
||||||
s_un => s_un,
|
|
||||||
start => start,
|
|
||||||
hilo_sel => hilo_sel,
|
|
||||||
busy => busy,
|
|
||||||
dout => dout
|
|
||||||
);
|
|
||||||
|
|
||||||
CLK_GEN: process
|
|
||||||
begin
|
|
||||||
wait for CLK_PERIOD/2;
|
|
||||||
clk <= not clk;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
REF_GEN: process
|
|
||||||
begin
|
|
||||||
if mul_divn = '0' then
|
|
||||||
wait until rising_edge(clk) and check = '1';
|
|
||||||
if s_un = '1' then
|
|
||||||
rtmp <= unsigned(signed(md_result(31 downto 0)) * signed(din_lo));
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
tmp2 <= unsigned(signed(rtmp(31 downto 0)) + signed(md_result(63 downto 32)));
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
ref_hi <= tmp2(31 downto 0);
|
|
||||||
else
|
|
||||||
rtmp <= md_result(31 downto 0) * din_lo;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
tmp2 <= rtmp(31 downto 0) + md_result(63 downto 32);
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
ref_hi <= tmp2(31 downto 0);
|
|
||||||
end if;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
|
|
||||||
if din_lo /= X"00000000" then
|
|
||||||
if ENABLE_FAIL_REPORT then
|
|
||||||
assert din_hi = ref_hi report "Error on divison" severity failure;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
wait until rising_edge(clk) and check = '1';
|
|
||||||
if s_un = '1' then
|
|
||||||
ref_result <= unsigned(signed(din_hi) * signed(din_lo));
|
|
||||||
else
|
|
||||||
ref_result <= unsigned(din_hi) * unsigned(din_lo);
|
|
||||||
end if;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
if ENABLE_FAIL_REPORT then
|
|
||||||
assert ref_result = md_result report "Error on multiplication" severity failure;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
STIMULUS: process
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
wait for 3*CLK_PERIOD;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
rst <= '0';
|
|
||||||
wait for 2*CLK_PERIOD;
|
|
||||||
|
|
||||||
mul_divn <= '0';
|
|
||||||
s_un <= '0';
|
|
||||||
for i in 0 to operands'length-1 loop
|
|
||||||
for j in 0 to operands'length-1 loop
|
|
||||||
check <= '0';
|
|
||||||
wait until rising_edge(clk) and busy = '0';
|
|
||||||
din_hi <= operands(i);
|
|
||||||
din_lo <= operands(j);
|
|
||||||
start <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
start <= '0';
|
|
||||||
hilo_sel <= '0';
|
|
||||||
|
|
||||||
-- Read result
|
|
||||||
wait until rising_edge(clk) and busy = '0';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
md_result(31 downto 0) <= dout;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
hilo_sel <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
md_result(63 downto 32) <= dout;
|
|
||||||
check <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
check <= '0';
|
|
||||||
wait for 8*CLK_PERIOD;
|
|
||||||
end loop;
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
s_un <= '1';
|
|
||||||
for i in 0 to operands'length-1 loop
|
|
||||||
for j in 0 to operands'length-1 loop
|
|
||||||
check <= '0';
|
|
||||||
wait until rising_edge(clk) and busy = '0';
|
|
||||||
din_hi <= operands(i);
|
|
||||||
din_lo <= operands(j);
|
|
||||||
start <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
start <= '0';
|
|
||||||
hilo_sel <= '0';
|
|
||||||
|
|
||||||
-- Read result
|
|
||||||
wait until rising_edge(clk) and busy = '0';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
md_result(31 downto 0) <= dout;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
hilo_sel <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
md_result(63 downto 32) <= dout;
|
|
||||||
check <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
check <= '0';
|
|
||||||
wait for 8*CLK_PERIOD;
|
|
||||||
end loop;
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
mul_divn <= '1';
|
|
||||||
s_un <= '0';
|
|
||||||
for i in 0 to operands'length-1 loop
|
|
||||||
for j in 0 to operands'length-1 loop
|
|
||||||
check <= '0';
|
|
||||||
wait until rising_edge(clk) and busy = '0';
|
|
||||||
din_hi <= operands(i);
|
|
||||||
din_lo <= operands(j);
|
|
||||||
start <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
start <= '0';
|
|
||||||
hilo_sel <= '0';
|
|
||||||
|
|
||||||
-- Read result
|
|
||||||
wait until rising_edge(clk) and busy = '0';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
md_result(31 downto 0) <= dout;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
hilo_sel <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
md_result(63 downto 32) <= dout;
|
|
||||||
check <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
check <= '0';
|
|
||||||
wait for 8*CLK_PERIOD;
|
|
||||||
end loop;
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
s_un <= '1';
|
|
||||||
for i in 0 to operands'length-1 loop
|
|
||||||
for j in 0 to operands'length-1 loop
|
|
||||||
check <= '0';
|
|
||||||
wait until rising_edge(clk) and busy = '0';
|
|
||||||
din_hi <= operands(i);
|
|
||||||
din_lo <= operands(j);
|
|
||||||
start <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
start <= '0';
|
|
||||||
hilo_sel <= '0';
|
|
||||||
|
|
||||||
-- Read result
|
|
||||||
wait until rising_edge(clk) and busy = '0';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
md_result(31 downto 0) <= dout;
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
hilo_sel <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
md_result(63 downto 32) <= dout;
|
|
||||||
check <= '1';
|
|
||||||
wait until rising_edge(clk);
|
|
||||||
check <= '0';
|
|
||||||
wait for 8*CLK_PERIOD;
|
|
||||||
end loop;
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
wait;
|
|
||||||
|
|
||||||
end process;
|
|
||||||
|
|
||||||
END;
|
|
||||||
@@ -0,0 +1,233 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
|
||||||
|
-- This file: Testbench for JCPU
|
||||||
|
-- also writes 'opc.lst' for JASM-assembler
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
LIBRARY ieee;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE ieee.numeric_std.ALL;
|
||||||
|
|
||||||
|
library work;
|
||||||
|
use work.mips_types.all;
|
||||||
|
use work.mips_instr.all;
|
||||||
|
use work.async_types.all;
|
||||||
|
use work.async_defs.all;
|
||||||
|
|
||||||
|
ENTITY tb_mips_sys IS
|
||||||
|
END tb_mips_sys;
|
||||||
|
|
||||||
|
ARCHITECTURE behavior OF tb_mips_sys IS
|
||||||
|
|
||||||
|
constant CLK_PERIOD : time := 10 ns;
|
||||||
|
constant ICACHE_SIZE : natural := 512; -- words
|
||||||
|
constant DCACHE_SIZE : natural := 512; -- words
|
||||||
|
constant SRAM_ADDR_WIDTH : integer := 17; -- bits
|
||||||
|
constant FLASH_ADDR_WIDTH : integer := 17; -- bits
|
||||||
|
|
||||||
|
signal debug : unsigned(1 downto 0);
|
||||||
|
|
||||||
|
-- Master
|
||||||
|
signal nmi : STD_LOGIC := '0';
|
||||||
|
signal rst : STD_LOGIC := '1';
|
||||||
|
signal clk : STD_LOGIC := '0';
|
||||||
|
signal eb : STD_LOGIC := '1';
|
||||||
|
|
||||||
|
signal flash_cs_n : std_logic;
|
||||||
|
signal flash_we_n : std_logic;
|
||||||
|
signal flash_oe_n : std_logic;
|
||||||
|
signal flash_be_n : unsigned(3 downto 0);
|
||||||
|
signal sram_cs_n : std_logic;
|
||||||
|
signal sram_be_n : unsigned(3 downto 0);
|
||||||
|
signal sram_wr_n : std_logic;
|
||||||
|
signal sram_oe_n : std_logic;
|
||||||
|
signal sram_a : unsigned(SRAM_ADDR_WIDTH-1 downto 0);
|
||||||
|
signal sram_d : unsigned(31 downto 0);
|
||||||
|
signal flash_a : unsigned(FLASH_ADDR_WIDTH-1 downto 0);
|
||||||
|
signal flash_d : unsigned(31 downto 0);
|
||||||
|
|
||||||
|
signal gpo0 : unsigned(31 downto 0);
|
||||||
|
signal gpo1 : unsigned(31 downto 0);
|
||||||
|
signal gpi0 : unsigned(31 downto 0) := (others => '0');
|
||||||
|
signal gpi1 : unsigned(31 downto 0) := (others => '0');
|
||||||
|
|
||||||
|
signal int_timer : std_logic;
|
||||||
|
signal int_uart : std_logic;
|
||||||
|
signal rx : std_logic := '1';
|
||||||
|
signal tx : std_logic;
|
||||||
|
|
||||||
|
type word_array_t is array (natural range <>) of unsigned(31 downto 0);
|
||||||
|
signal sram_data : word_array_t(0 to 2**SRAM_ADDR_WIDTH-1);
|
||||||
|
signal flash_data : word_array_t(0 to 2**FLASH_ADDR_WIDTH-1);
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
CLK_GEN: process
|
||||||
|
begin
|
||||||
|
wait for CLK_PERIOD/2;
|
||||||
|
clk <= not clk;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
uut : entity work.mips_sys
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
ICACHE_SIZE => ICACHE_SIZE, -- words
|
||||||
|
DCACHE_SIZE => DCACHE_SIZE, -- words
|
||||||
|
SRAM_ADDR_WIDTH => SRAM_ADDR_WIDTH,
|
||||||
|
FLASH_ADDR_WIDTH => FLASH_ADDR_WIDTH
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
eb => eb,
|
||||||
|
nmi => nmi,
|
||||||
|
rst => rst,
|
||||||
|
clk => clk,
|
||||||
|
flash_cs_n => flash_cs_n,
|
||||||
|
flash_oe_n => flash_oe_n,
|
||||||
|
flash_we_n => flash_we_n,
|
||||||
|
flash_be_n => flash_be_n,
|
||||||
|
sram_cs_n => sram_cs_n,
|
||||||
|
sram_we_n => sram_wr_n,
|
||||||
|
sram_oe_n => sram_oe_n,
|
||||||
|
sram_be_n => sram_be_n,
|
||||||
|
sram_a => sram_a,
|
||||||
|
sram_d => sram_d,
|
||||||
|
flash_a => flash_a,
|
||||||
|
flash_d => flash_d,
|
||||||
|
|
||||||
|
gpo0 => gpo0,
|
||||||
|
gpo1 => gpo1,
|
||||||
|
gpi0 => gpi0,
|
||||||
|
gpi1 => gpi1,
|
||||||
|
|
||||||
|
rx => rx,
|
||||||
|
tx => tx,
|
||||||
|
|
||||||
|
debug => debug
|
||||||
|
);
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
SRAM_READ:
|
||||||
|
process(sram_a, sram_cs_n, sram_oe_n, sram_be_n)
|
||||||
|
begin
|
||||||
|
sram_d <= (others => 'Z') after 10 ns;
|
||||||
|
if sram_oe_n = '0' then
|
||||||
|
if sram_cs_n = '0' then
|
||||||
|
if sram_be_n(0) = '0' then
|
||||||
|
sram_d(7 downto 0) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(7 downto 0) after 10 ns;
|
||||||
|
end if;
|
||||||
|
if sram_be_n(1) = '0' then
|
||||||
|
sram_d(15 downto 8) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(15 downto 8) after 10 ns;
|
||||||
|
end if;
|
||||||
|
if sram_be_n(2) = '0' then
|
||||||
|
sram_d(23 downto 16) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(23 downto 16) after 10 ns;
|
||||||
|
end if;
|
||||||
|
if sram_be_n(3) = '0' then
|
||||||
|
sram_d(31 downto 24) <= sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(31 downto 24) after 10 ns;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
SRAM_WRITE:
|
||||||
|
process(sram_wr_n)
|
||||||
|
begin
|
||||||
|
if rising_edge(sram_wr_n) then
|
||||||
|
if sram_cs_n = '0' then
|
||||||
|
if sram_be_n(0) = '0' then
|
||||||
|
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(7 downto 0) <= sram_d(7 downto 0);
|
||||||
|
end if;
|
||||||
|
if sram_be_n(1) = '0' then
|
||||||
|
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(15 downto 8) <= sram_d(15 downto 8);
|
||||||
|
end if;
|
||||||
|
if sram_be_n(2) = '0' then
|
||||||
|
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(23 downto 16) <= sram_d(23 downto 16);
|
||||||
|
end if;
|
||||||
|
if sram_be_n(3) = '0' then
|
||||||
|
sram_data(to_integer(sram_a(SRAM_ADDR_WIDTH-1 downto 2)))(31 downto 24) <= sram_d(31 downto 24);
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
FLASH_READ:
|
||||||
|
process(rst, flash_cs_n, flash_oe_n, flash_a)
|
||||||
|
type file_t is file of integer;
|
||||||
|
file load_flash : file_t open read_mode is "hello.flash.bin";
|
||||||
|
variable instr : integer;
|
||||||
|
variable index : natural;
|
||||||
|
variable temp : signed(31 downto 0);
|
||||||
|
constant tpd : time := 25 ns;
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
index := 0;
|
||||||
|
while not endfile(load_flash) loop
|
||||||
|
read(load_flash, instr);
|
||||||
|
temp := to_signed(instr, word_t'length);
|
||||||
|
flash_data(index) <= unsigned(temp);
|
||||||
|
index := index + 1;
|
||||||
|
end loop;
|
||||||
|
else
|
||||||
|
flash_d <= (others => 'Z') after tpd;
|
||||||
|
index := to_integer(flash_a(FLASH_ADDR_WIDTH-1 downto 2));
|
||||||
|
if flash_oe_n = '0' then
|
||||||
|
if flash_cs_n = '0' then
|
||||||
|
if flash_be_n(0) = '0' then
|
||||||
|
flash_d(7 downto 0) <= flash_data(index)(7 downto 0) after tpd;
|
||||||
|
end if;
|
||||||
|
if flash_be_n(1) = '0' then
|
||||||
|
flash_d(15 downto 8) <= flash_data(index)(15 downto 8) after tpd;
|
||||||
|
end if;
|
||||||
|
if flash_be_n(2) = '0' then
|
||||||
|
flash_d(23 downto 16) <= flash_data(index)(23 downto 16) after tpd;
|
||||||
|
end if;
|
||||||
|
if flash_be_n(3) = '0' then
|
||||||
|
flash_d(31 downto 24) <= flash_data(index)(31 downto 24) after tpd;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
STIMULUS: process
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
|
||||||
|
wait for 3*CLK_PERIOD;
|
||||||
|
wait until rising_edge(clk);
|
||||||
|
rst <= '0';
|
||||||
|
wait for 778254*CLK_PERIOD;
|
||||||
|
wait until rising_edge(clk);
|
||||||
|
nmi <= '0';
|
||||||
|
wait for 3000*CLK_PERIOD;
|
||||||
|
wait until rising_edge(clk);
|
||||||
|
nmi <= '0';
|
||||||
|
|
||||||
|
wait;
|
||||||
|
|
||||||
|
end process;
|
||||||
|
|
||||||
|
END;
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
vhdl work "../../src/core/mips_types.vhd"
|
|
||||||
vhdl work "../../../../misc/dpram_2w2r.vhd"
|
|
||||||
vhdl work "../../../../misc/dpram_1w1r_dist.vhd"
|
|
||||||
vhdl work "../../../../misc/dpram_1w1r.vhd"
|
|
||||||
vhdl work "../../../../FIFO/src/sync_fifo_ctrl.vhd"
|
|
||||||
vhdl work "../../../../FIFO/src/fifo_ctrl_pkg.vhd"
|
|
||||||
vhdl work "../../src/core/mips_instr.vhd"
|
|
||||||
vhdl work "../../../../FIFO/src/fifo_sync_dist.vhd"
|
|
||||||
vhdl work "../../src/core/mips_shifter.vhd"
|
|
||||||
vhdl work "../../src/core/mips_reg.vhd"
|
|
||||||
vhdl work "../../src/core/mips_muldiv.vhd"
|
|
||||||
vhdl work "../../src/core/mips_idecode_rom.vhd"
|
|
||||||
vhdl work "../../src/core/mips_icache.vhd"
|
|
||||||
vhdl work "../../src/core/mips_dcache.vhd"
|
|
||||||
vhdl work "../../src/core/mips_cop.vhd"
|
|
||||||
vhdl work "../../src/core/mips_bcu.vhd"
|
|
||||||
vhdl work "../../src/core/mips_alu.vhd"
|
|
||||||
vhdl work "../../src/core/mips_pipeline.vhd"
|
|
||||||
vhdl work "../../src/core/mips_biu.vhd"
|
|
||||||
vhdl work "../../src/core/mips_top.vhd"
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_types.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\misc\dpram_2w2r.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\misc\dpram_1w1r_dist.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\misc\dpram_1w1r.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\FIFO\src\sync_fifo_ctrl.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\FIFO\src\fifo_ctrl_pkg.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_instr.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\FIFO\src\fifo_sync_dist.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_shifter.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_reg.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_muldiv.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_idecode_rom.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_icache.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_dcache.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_cop.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_bcu.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_alu.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_pipeline.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_biu.vhd"
|
|
||||||
vhdl work "W:\vhdl\lib\CPUs\MIPS\src\core\mips_top.vhd"
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
2008-10-26
|
|
||||||
- Optimierung: MUL32x32 primitive für Virtex-4
|
|
||||||
- External COP 1..3 interface
|
|
||||||
- FPU (COP1)
|
|
||||||
- MMU
|
|
||||||
@@ -1,17 +1,20 @@
|
|||||||
CFLAGS=-O2
|
CFLAGS=-O2
|
||||||
|
|
||||||
CC=gcc
|
CC=gcc
|
||||||
|
PREFIX=/usr/local
|
||||||
all: romgen ramgen flashgen
|
all: romgen ramgen flashgen
|
||||||
|
|
||||||
romgen: ./src/romgen.c
|
romgen: ./src/romgen.c
|
||||||
$(CC) $(CFLAGS) ./src/romgen.c -o ./romgen
|
$(CC) $(CFLAGS) ./src/romgen.c -lm -o ./romgen
|
||||||
|
|
||||||
ramgen: ./src/ramgen.c
|
ramgen: ./src/ramgen.c
|
||||||
$(CC) $(CFLAGS) ./src/ramgen.c -o ./ramgen
|
$(CC) $(CFLAGS) ./src/ramgen.c -lm -o ./ramgen
|
||||||
|
|
||||||
flashgen: ./src/flashgen.c
|
flashgen: ./src/flashgen.c
|
||||||
$(CC) $(CFLAGS) ./src/flashgen.c -o ./flashgen
|
$(CC) $(CFLAGS) ./src/flashgen.c -lm -o ./flashgen
|
||||||
|
|
||||||
|
install:
|
||||||
|
cp romgen $(PREFIX)/bin
|
||||||
|
cp ramgen $(PREFIX)/bin
|
||||||
|
cp flashgen $(PREFIX)/bin
|
||||||
clean:
|
clean:
|
||||||
rm -rf romgen* ramgen* flashgen*
|
rm -rf romgen* ramgen* flashgen*
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -17,10 +17,25 @@
|
|||||||
#define SDRAM_BASE 0x40000000
|
#define SDRAM_BASE 0x40000000
|
||||||
#define FLASH_OFFSET 0x00000000
|
#define FLASH_OFFSET 0x00000000
|
||||||
|
|
||||||
|
#define MAGIC_EB 0x4A464931 // "JFI1" in big-endian;
|
||||||
|
#define MAGIC_EL 0x3149464A // "JFI1" in little-endian;
|
||||||
|
|
||||||
|
UINT32 conv_endian32(UINT32 src)
|
||||||
|
{
|
||||||
|
UINT32 dst;
|
||||||
|
|
||||||
|
dst = (0xFF000000 & (src << 24))
|
||||||
|
| (0x00FF0000 & (src << 8))
|
||||||
|
| (0x0000FF00 & (src >> 8))
|
||||||
|
| (0x000000FF & (src >> 24));
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
typedef struct _sflash_img_hdr_t
|
typedef struct _sflash_img_hdr_t
|
||||||
{
|
{
|
||||||
UINT8 magic[4];
|
UINT32 magic;
|
||||||
UINT32 target_addr;
|
UINT32 target_addr;
|
||||||
UINT32 img_offset;
|
UINT32 img_offset;
|
||||||
UINT32 img_size;
|
UINT32 img_size;
|
||||||
@@ -54,6 +69,7 @@ int main(int argc, char *argv[])
|
|||||||
char name_flash[1024];
|
char name_flash[1024];
|
||||||
char name_prj[1024];
|
char name_prj[1024];
|
||||||
char *pBuf;
|
char *pBuf;
|
||||||
|
UINT32 *pBuf32;
|
||||||
flash_img_hdr_t img_hdr = {0};
|
flash_img_hdr_t img_hdr = {0};
|
||||||
|
|
||||||
FILE *pFile;
|
FILE *pFile;
|
||||||
@@ -63,7 +79,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: flashgen <input file>\n");
|
fprintf(stderr, "Usage: flashgen <input file> [-{EL|EB}]\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,15 +114,22 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
img_hdr.magic[0] = 'J';
|
img_hdr.magic = MAGIC_EL;
|
||||||
img_hdr.magic[1] = 'F';
|
|
||||||
img_hdr.magic[2] = 'I';
|
|
||||||
img_hdr.magic[3] = '1';
|
|
||||||
img_hdr.target_addr = SDRAM_BASE;
|
img_hdr.target_addr = SDRAM_BASE;
|
||||||
img_hdr.img_size = filesize;
|
img_hdr.img_size = filesize;
|
||||||
img_hdr.img_offset = FLASH_OFFSET + sizeof(flash_img_hdr_t);
|
img_hdr.img_offset = FLASH_OFFSET + sizeof(flash_img_hdr_t);
|
||||||
img_hdr.hdr_next = FLASH_OFFSET;
|
img_hdr.hdr_next = FLASH_OFFSET;
|
||||||
|
|
||||||
|
if (argc == 3)
|
||||||
|
{
|
||||||
|
if ((argv[2][0] == '-') && (toupper(argv[2][1]) == 'E') && (toupper(argv[2][2]) == 'B'))
|
||||||
|
{
|
||||||
|
img_hdr.magic = MAGIC_EB;
|
||||||
|
pBuf32 = (UINT32*)pBuf;
|
||||||
|
for (i=0; i < filesize/4; i ++)
|
||||||
|
pBuf32[i] = conv_endian32(pBuf32[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
fwrite(&img_hdr, sizeof(flash_img_hdr_t), 1, pFile);
|
fwrite(&img_hdr, sizeof(flash_img_hdr_t), 1, pFile);
|
||||||
fwrite(pBuf, 1, filesize, pFile);
|
fwrite(pBuf, 1, filesize, pFile);
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,54 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#define INT8 char
|
||||||
|
#define INT16 short
|
||||||
|
#define INT32 long
|
||||||
|
#define UINT8 unsigned char
|
||||||
|
#define UINT16 unsigned short
|
||||||
|
#define UINT32 unsigned long
|
||||||
|
#define INT int
|
||||||
|
#define UINT unsigned int
|
||||||
|
#define FLOAT32 float
|
||||||
|
#define FLOAT64 double
|
||||||
|
|
||||||
#define ARCH_NAME "data"
|
#define ARCH_NAME "data"
|
||||||
#define ENT_NAME "rom"
|
#define ENT_NAME "rom"
|
||||||
#define JTAG_ADDR_WIDTH 16
|
#define JTAG_ADDR_WIDTH 16
|
||||||
|
|
||||||
|
UINT32 g_endianess_EB;
|
||||||
|
|
||||||
// --------------------------------------------------------------
|
// --------------------------------------------------------------
|
||||||
|
UINT32 conv_endian32(UINT32 src)
|
||||||
|
{
|
||||||
|
UINT32 dst;
|
||||||
|
|
||||||
|
dst = (0xFF000000 & (src << 24))
|
||||||
|
| (0x00FF0000 & (src << 8))
|
||||||
|
| (0x0000FF00 & (src >> 8))
|
||||||
|
| (0x000000FF & (src >> 24));
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
};
|
||||||
|
|
||||||
|
UINT32 to_big_endian32(UINT32 src)
|
||||||
|
{
|
||||||
|
#ifndef NATIVE_IS_BIG_ENDIAN
|
||||||
|
return conv_endian32(src);
|
||||||
|
#else
|
||||||
|
return src;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 from_big_endian32(UINT32 src)
|
||||||
|
{
|
||||||
|
#ifndef NATIVE_IS_BIG_ENDIAN
|
||||||
|
return conv_endian32(src);
|
||||||
|
#else
|
||||||
|
return src;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void basename(char *pSrc, char *pDst)
|
void basename(char *pSrc, char *pDst)
|
||||||
{
|
{
|
||||||
int i, size;
|
int i, size;
|
||||||
@@ -90,7 +133,11 @@ int SaveROM(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pEntNa
|
|||||||
for (i=0; i < filesize; i += sizeof(int))
|
for (i=0; i < filesize; i += sizeof(int))
|
||||||
{
|
{
|
||||||
fread(&word, 1, sizeof(int), pFileIn);
|
fread(&word, 1, sizeof(int), pFileIn);
|
||||||
|
if (g_endianess_EB)
|
||||||
|
fprintf(pFileOut, "\t\tX\"%8.8X\"", to_big_endian32(word));
|
||||||
|
else
|
||||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||||
|
|
||||||
if (i < (romsize-sizeof(int)))
|
if (i < (romsize-sizeof(int)))
|
||||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||||
else
|
else
|
||||||
@@ -208,7 +255,11 @@ int SaveROM_V4LD(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *p
|
|||||||
for (i=0; i < filesize; i += sizeof(int))
|
for (i=0; i < filesize; i += sizeof(int))
|
||||||
{
|
{
|
||||||
fread(&word, 1, sizeof(int), pFileIn);
|
fread(&word, 1, sizeof(int), pFileIn);
|
||||||
|
if (g_endianess_EB)
|
||||||
|
fprintf(pFileOut, "\t\tX\"%8.8X\"", to_big_endian32(word));
|
||||||
|
else
|
||||||
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
fprintf(pFileOut, "\t\tX\"%8.8X\"", word);
|
||||||
|
|
||||||
if (i < (romsize-sizeof(int)))
|
if (i < (romsize-sizeof(int)))
|
||||||
fprintf(pFileOut, ", -- %8.8X\n", i);
|
fprintf(pFileOut, ", -- %8.8X\n", i);
|
||||||
else
|
else
|
||||||
@@ -269,7 +320,8 @@ int SaveROM_TCL(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pE
|
|||||||
char binstr_addr[33];
|
char binstr_addr[33];
|
||||||
char binstr_data[33];
|
char binstr_data[33];
|
||||||
|
|
||||||
char tpl[] = {"# ---------------------------------------------------------------------\n# For Chipscope 9.1\n# ---------------------------------------------------------------------\n# Source JTAG/TCL frame work\ncd $env(CHIPSCOPE)\\\\bin\\\\nt\nsource csejtag.tcl\n\nnamespace import ::chipscope::*\n\n# Platform USB Cable\nset PLATFORM_USB_CABLE_ARGS [list \"port=USB2\" \"frequency=6000000\"]\n# frequency=\"24000000 | 12000000 | 6000000 | 3000000 | 1500000 | 750000\"\n\n# Create session\nset handle [::chipscope::csejtag_session create 0]\n\n# Open JTAG and lock\nset open_result [::chipscope::csejtag_target open $handle $CSEJTAG_TARGET_PLATFORMUSB 0 $PLATFORM_USB_CABLE_ARGS]\nset lock_result [::chipscope::csejtag_target lock $handle 1000]\n\nset devlist [::chipscope::csejtag_tap autodetect_chain $handle $CSEJTAG_SCAN_DEFAULT]\n\n# Get Device ID\nset devtype \"Virtex-4SX\"\nset devid 2\nset irlength [::chipscope::csejtag_tap get_irlength $handle $devid]\nset idcode [::chipscope::csejtag_tap get_device_idcode $handle $devid]\n\nset CSE_OP $CSEJTAG_SHIFT_READWRITE\nset CSE_ES $CSEJTAG_RUN_TEST_IDLE\n\n# Write Program\n"};
|
char tpl[] =
|
||||||
|
{"# ---------------------------------------------------------------------\n# For Chipscope 10.1\n# ---------------------------------------------------------------------\n# Source JTAG/TCL frame work\nsource $env(CS_PATH)\\\\csejtag.tcl\n\nnamespace import ::chipscope::*\n\n# Platform USB Cable\n# Create session\nset handle [::chipscope::csejtag_session create 0]\n\n# Open JTAG and lock\nset open_result [::chipscope::csejtag_target open $handle $CSEJTAG_TARGET_PLATFORMUSB 0 \"port=USB2\" \"frequency=6000000\"]\n# frequency=\"24000000 | 12000000 | 6000000 | 3000000 | 1500000 | 750000\"\n\nset lock_result [::chipscope::csejtag_target lock $handle 1000]\n\nset devlist [::chipscope::csejtag_tap autodetect_chain $handle $CSEJTAG_SCAN_DEFAULT]\n\n# Get Device ID\nset devtype \"Virtex-4SX\"\nset devid 2\nset irlength [::chipscope::csejtag_tap get_irlength $handle $devid]\nset idcode [::chipscope::csejtag_tap get_device_idcode $handle $devid]\n\nset CSE_OP $CSEJTAG_SHIFT_READWRITE\nset CSE_ES $CSEJTAG_RUN_TEST_IDLE\n\n# Write Program\n"};
|
||||||
|
|
||||||
pFileIn = fopen(pFilenameIn, "rb");
|
pFileIn = fopen(pFilenameIn, "rb");
|
||||||
if (!pFileIn)
|
if (!pFileIn)
|
||||||
@@ -313,6 +365,9 @@ int SaveROM_TCL(char *pFilenameIn, char *pFilenameOut, char *pArchName, char *pE
|
|||||||
for (i=0; i < filesize; i += sizeof(int))
|
for (i=0; i < filesize; i += sizeof(int))
|
||||||
{
|
{
|
||||||
fread(&word, 1, sizeof(int), pFileIn);
|
fread(&word, 1, sizeof(int), pFileIn);
|
||||||
|
if (g_endianess_EB)
|
||||||
|
fprintf(pFileOut, "::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%4.4X%8.8X\"\n", nbits_data + JTAG_ADDR_WIDTH, word_addr, to_big_endian32(word));
|
||||||
|
else
|
||||||
fprintf(pFileOut, "::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%4.4X%8.8X\"\n", nbits_data + JTAG_ADDR_WIDTH, word_addr, word);
|
fprintf(pFileOut, "::chipscope::csejtag_tap shift_device_dr $handle $devid $CSE_OP $CSE_ES 0 %d \"%4.4X%8.8X\"\n", nbits_data + JTAG_ADDR_WIDTH, word_addr, word);
|
||||||
word_addr++;
|
word_addr++;
|
||||||
}
|
}
|
||||||
@@ -344,14 +399,19 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: romgen <input file> <num. word address bits>\n");
|
fprintf(stderr, "Usage: romgen <input file> <num. word address bits> [-{EL|EB}]\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pFilenameIn = argv[1];
|
pFilenameIn = argv[1];
|
||||||
if (argc == 3)
|
|
||||||
nbits_addr = atoi(argv[2]);
|
nbits_addr = atoi(argv[2]);
|
||||||
|
|
||||||
|
g_endianess_EB = 0;
|
||||||
|
if (argc == 4)
|
||||||
|
{
|
||||||
|
if ((argv[3][0] == '-') && (toupper(argv[3][1]) == 'E') && (toupper(argv[3][2]) == 'B'))
|
||||||
|
g_endianess_EB = 1;
|
||||||
|
}
|
||||||
|
|
||||||
basename(pFilenameIn, name_prj);
|
basename(pFilenameIn, name_prj);
|
||||||
sprintf(name_rom, "%s.vhd", name_prj);
|
sprintf(name_rom, "%s.vhd", name_prj);
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
VHDL/lib/FIFO/src/async_fifo_ctrl.vhd
|
||||||
|
VHDL/lib/FIFO/src/fifo_async_ctrl.vhd
|
||||||
|
VHDL/lib/FIFO/src/fifo_async_ctrl.vhd
|
||||||
|
|
||||||
|
VHDL/lib/FIFO/src/fifo_sync_ctrl.vhd
|
||||||
|
|
||||||
|
VHDL/lib/FIFO/src/sync_fifo_ctrl.vhd
|
||||||
|
VHDL/lib/FIFO/src/fifo_sync_ctrl.vhd
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: FIFO, generic FIFOs written in VHDL
|
||||||
|
-- Release 1
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This library is free software; you can redistribute it and/or
|
||||||
|
-- modify it under the terms of the GNU Lesser General Public
|
||||||
|
-- License as published by the Free Software Foundation; either
|
||||||
|
-- version 2.1 of the License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This library is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
-- Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU Lesser General Public
|
||||||
|
-- License along with this library; if not, write to the Free Software
|
||||||
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.numeric_std.ALL;
|
||||||
|
|
||||||
|
LIBRARY WORK;
|
||||||
|
USE WORK.FIFO_CTRL_PKG.ALL;
|
||||||
|
|
||||||
|
entity fifo_async_ctrl is
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
addr_width : integer := 3;
|
||||||
|
almost_full_thresh : integer := 6;
|
||||||
|
almost_empty_thresh : integer := 2
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
rst : in STD_LOGIC;
|
||||||
|
clk_w : in STD_LOGIC;
|
||||||
|
clk_r : in STD_LOGIC;
|
||||||
|
winc : in STD_LOGIC;
|
||||||
|
rinc : in STD_LOGIC;
|
||||||
|
ptr_w : out unsigned (addr_width-1 downto 0);
|
||||||
|
ptr_r : out unsigned (addr_width-1 downto 0);
|
||||||
|
fifo_pre_full : out STD_LOGIC;
|
||||||
|
fifo_pre_empty : out STD_LOGIC;
|
||||||
|
fifo_full : out STD_LOGIC;
|
||||||
|
fifo_empty : out STD_LOGIC;
|
||||||
|
fifo_afull : out STD_LOGIC;
|
||||||
|
fifo_aempty : out STD_LOGIC
|
||||||
|
);
|
||||||
|
end fifo_async_ctrl;
|
||||||
|
|
||||||
|
architecture Behavioral of fifo_async_ctrl is
|
||||||
|
|
||||||
|
signal gcnt_w : unsigned (addr_width downto 0);
|
||||||
|
signal gcnt2_w : unsigned (addr_width downto 0);
|
||||||
|
signal bcnt2_aw : unsigned (addr_width downto 0);
|
||||||
|
signal bcnt_w : unsigned (addr_width downto 0);
|
||||||
|
signal gnxt_w : unsigned (addr_width downto 0);
|
||||||
|
signal bnxt_w : unsigned (addr_width downto 0);
|
||||||
|
signal gcnt_r : unsigned (addr_width downto 0);
|
||||||
|
signal gcnt2_r : unsigned (addr_width downto 0);
|
||||||
|
signal bcnt2_ar : unsigned (addr_width downto 0);
|
||||||
|
signal bcnt_r : unsigned (addr_width downto 0);
|
||||||
|
signal gnxt_r : unsigned (addr_width downto 0);
|
||||||
|
signal bnxt_r : unsigned (addr_width downto 0);
|
||||||
|
|
||||||
|
signal pre_empty, pre_full : std_logic;
|
||||||
|
signal full, empty : std_logic;
|
||||||
|
|
||||||
|
-- synthesis translate_off
|
||||||
|
signal diffw : signed (addr_width downto 0);
|
||||||
|
signal diffr : signed (addr_width downto 0);
|
||||||
|
-- synthesis translate_on
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
ptr_w <= bcnt_w(addr_width-1 downto 0);
|
||||||
|
ptr_r <= bnxt_r(addr_width-1 downto 0);
|
||||||
|
fifo_full <= full;
|
||||||
|
fifo_empty <= empty;
|
||||||
|
fifo_pre_full <= pre_full;
|
||||||
|
fifo_pre_empty <= pre_empty;
|
||||||
|
|
||||||
|
proc_write_inhibit:
|
||||||
|
process(rst, clk_w)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
full <= '0';
|
||||||
|
elsif rising_edge(clk_w) then
|
||||||
|
full <= pre_full;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_read_inhibit:
|
||||||
|
process(rst, clk_r)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
empty <= '1';
|
||||||
|
elsif rising_edge(clk_r) then
|
||||||
|
empty <= pre_empty;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_sync_grptr:
|
||||||
|
process(clk_w)
|
||||||
|
variable p1, p2 : unsigned (addr_width downto 0);
|
||||||
|
begin
|
||||||
|
if rising_edge(clk_w) then
|
||||||
|
gcnt2_r <= p2;
|
||||||
|
p2 := p1;
|
||||||
|
p1 := gcnt_r;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_ptr_gwptr:
|
||||||
|
process(clk_r)
|
||||||
|
variable p1, p2 : unsigned (addr_width downto 0);
|
||||||
|
begin
|
||||||
|
if rising_edge(clk_r) then
|
||||||
|
gcnt2_w <= p2;
|
||||||
|
p2 := p1;
|
||||||
|
p1 := gcnt_w;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_status_full:
|
||||||
|
process(gnxt_w, gcnt2_r)
|
||||||
|
begin
|
||||||
|
if (gnxt_w = (not gcnt2_r(gcnt2_r'left downto gcnt2_r'left-1) & gcnt2_r(gcnt2_r'left-2 downto 0))) then
|
||||||
|
pre_full <= '1';
|
||||||
|
else
|
||||||
|
pre_full <= '0';
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_status_empty:
|
||||||
|
process(gnxt_r, gcnt2_w)
|
||||||
|
begin
|
||||||
|
if (gnxt_r = gcnt2_w) then
|
||||||
|
pre_empty <= '1';
|
||||||
|
else
|
||||||
|
pre_empty <= '0';
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_sync_arptr:
|
||||||
|
process(clk_w)
|
||||||
|
variable p1, p2 : unsigned (addr_width downto 0);
|
||||||
|
begin
|
||||||
|
if rising_edge(clk_w) then
|
||||||
|
bcnt2_ar <= p2;
|
||||||
|
p2 := p1;
|
||||||
|
p1 := bcnt_r;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_ptr_awptr:
|
||||||
|
process(clk_r)
|
||||||
|
variable p1, p2 : unsigned (addr_width downto 0);
|
||||||
|
begin
|
||||||
|
if rising_edge(clk_r) then
|
||||||
|
bcnt2_aw <= p2;
|
||||||
|
p2 := p1;
|
||||||
|
p1 := bcnt_w;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_status_almost_full:
|
||||||
|
process(rst, clk_w)
|
||||||
|
variable diff : unsigned (addr_width downto 0);
|
||||||
|
begin
|
||||||
|
-- synthesis translate_off
|
||||||
|
diffw <= signed(diff);
|
||||||
|
-- synthesis translate_on
|
||||||
|
if rst = '1' then
|
||||||
|
fifo_afull <= '0';
|
||||||
|
diff := (others => '0');
|
||||||
|
elsif rising_edge(clk_w) then
|
||||||
|
if diff >= almost_full_thresh-1 then
|
||||||
|
fifo_afull <= '1';
|
||||||
|
else
|
||||||
|
fifo_afull <= '0';
|
||||||
|
end if;
|
||||||
|
diff := unsigned(abs(signed(bnxt_w) - signed(bcnt2_ar)));
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_status_almost_empty:
|
||||||
|
process(rst, clk_r)
|
||||||
|
variable diff : unsigned (addr_width downto 0);
|
||||||
|
begin
|
||||||
|
-- synthesis translate_off
|
||||||
|
diffr <= signed(diff);
|
||||||
|
-- synthesis translate_on
|
||||||
|
if rst = '1' then
|
||||||
|
fifo_aempty <= '1';
|
||||||
|
diff := (others => '0');
|
||||||
|
elsif rising_edge(clk_r) then
|
||||||
|
if diff <= almost_empty_thresh+1 then
|
||||||
|
fifo_aempty <= '1';
|
||||||
|
else
|
||||||
|
fifo_aempty <= '0';
|
||||||
|
end if;
|
||||||
|
diff := unsigned(abs(signed(bcnt2_aw) - signed(bnxt_r)));
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
inst_gray_counter_w : entity work.gray_counter
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
width => addr_width+1,
|
||||||
|
init_value => 0
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
rst => rst,
|
||||||
|
clk => clk_w,
|
||||||
|
ce => winc,
|
||||||
|
bcnt => bcnt_w,
|
||||||
|
bnxt => bnxt_w,
|
||||||
|
gcnt => gcnt_w,
|
||||||
|
gnxt => gnxt_w
|
||||||
|
);
|
||||||
|
|
||||||
|
inst_gray_counter_r : entity work.gray_counter
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
width => addr_width+1,
|
||||||
|
init_value => 0
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
rst => rst,
|
||||||
|
clk => clk_r,
|
||||||
|
ce => rinc,
|
||||||
|
bcnt => bcnt_r,
|
||||||
|
bnxt => bnxt_r,
|
||||||
|
gcnt => gcnt_r,
|
||||||
|
gnxt => gnxt_r
|
||||||
|
);
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
|
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: FIFO, generic FIFOs written in VHDL
|
||||||
|
-- Release 1
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This library is free software; you can redistribute it and/or
|
||||||
|
-- modify it under the terms of the GNU Lesser General Public
|
||||||
|
-- License as published by the Free Software Foundation; either
|
||||||
|
-- version 2.1 of the License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This library is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
-- Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU Lesser General Public
|
||||||
|
-- License along with this library; if not, write to the Free Software
|
||||||
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
LIBRARY IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
use work.fifo_ctrl_pkg.all;
|
||||||
|
|
||||||
|
entity fifo_async is
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
addr_width : natural := 4;
|
||||||
|
data_width : natural := 8;
|
||||||
|
almost_full_thresh : integer := 12;
|
||||||
|
almost_empty_thresh : integer := 4;
|
||||||
|
allow_full_writes : boolean := false;
|
||||||
|
allow_empty_reads : boolean := false;
|
||||||
|
do_last_read_update : boolean := true
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
rst : in STD_LOGIC;
|
||||||
|
clk_w : in STD_LOGIC;
|
||||||
|
clk_r : in STD_LOGIC;
|
||||||
|
we : in STD_LOGIC;
|
||||||
|
re : in STD_LOGIC;
|
||||||
|
fifo_full : out STD_LOGIC;
|
||||||
|
fifo_empty : out STD_LOGIC;
|
||||||
|
fifo_afull : out STD_LOGIC;
|
||||||
|
fifo_aempty : out STD_LOGIC;
|
||||||
|
data_w : in unsigned (data_width-1 downto 0);
|
||||||
|
data_r : out unsigned (data_width-1 downto 0)
|
||||||
|
);
|
||||||
|
end fifo_async;
|
||||||
|
|
||||||
|
architecture Behavioral of fifo_async is
|
||||||
|
|
||||||
|
signal mem_wr_en : STD_LOGIC;
|
||||||
|
signal mem_rd_en : STD_LOGIC;
|
||||||
|
signal ptr_w : unsigned (addr_width-1 downto 0);
|
||||||
|
signal ptr_r : unsigned (addr_width-1 downto 0);
|
||||||
|
signal full : std_logic;
|
||||||
|
signal empty : std_logic;
|
||||||
|
signal pre_full : STD_LOGIC;
|
||||||
|
signal pre_empty : STD_LOGIC;
|
||||||
|
signal rinc : std_logic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
fifo_full <= full;
|
||||||
|
fifo_empty <= empty;
|
||||||
|
|
||||||
|
mem_wr_en <= (we and not full) when allow_full_writes = false else we;
|
||||||
|
rinc <= (re and not empty) when allow_empty_reads = false else re;
|
||||||
|
mem_rd_en <= not pre_empty when do_last_read_update = false else '1';
|
||||||
|
|
||||||
|
|
||||||
|
inst_fifo_async_ctrl: entity work.fifo_async_ctrl
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
addr_width => addr_width,
|
||||||
|
almost_full_thresh => almost_full_thresh,
|
||||||
|
almost_empty_thresh => almost_empty_thresh
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => rst,
|
||||||
|
clk_w => clk_w,
|
||||||
|
clk_r => clk_r,
|
||||||
|
winc => mem_wr_en,
|
||||||
|
rinc => rinc,
|
||||||
|
ptr_w => ptr_w,
|
||||||
|
ptr_r => ptr_r,
|
||||||
|
fifo_full => full,
|
||||||
|
fifo_empty => empty,
|
||||||
|
fifo_pre_full => pre_full,
|
||||||
|
fifo_pre_empty => pre_empty,
|
||||||
|
fifo_afull => fifo_afull,
|
||||||
|
fifo_aempty => fifo_aempty
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
inst_dpram_1w1r: entity work.dpram_1w1r
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
addr_width => addr_width,
|
||||||
|
data_width => data_width
|
||||||
|
)
|
||||||
|
PORT MAP(
|
||||||
|
clka => clk_w,
|
||||||
|
clkb => clk_r,
|
||||||
|
en_a => '1',
|
||||||
|
en_b => mem_rd_en,
|
||||||
|
we_a => mem_wr_en,
|
||||||
|
addr_a => ptr_w,
|
||||||
|
addr_b => ptr_r,
|
||||||
|
din_a => data_w,
|
||||||
|
dout_b => data_r
|
||||||
|
);
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
|
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: FIFO, generic FIFOs written in VHDL
|
||||||
|
-- Release 1
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This library is free software; you can redistribute it and/or
|
||||||
|
-- modify it under the terms of the GNU Lesser General Public
|
||||||
|
-- License as published by the Free Software Foundation; either
|
||||||
|
-- version 2.1 of the License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This library is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
-- Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU Lesser General Public
|
||||||
|
-- License along with this library; if not, write to the Free Software
|
||||||
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
LIBRARY IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
package fifo_ctrl_pkg is
|
||||||
|
|
||||||
|
-- Constants
|
||||||
|
-- Types
|
||||||
|
|
||||||
|
-- Functions
|
||||||
|
function bin2gray(xb : unsigned) return unsigned;
|
||||||
|
function gray2bin(xg : unsigned) return unsigned;
|
||||||
|
|
||||||
|
end fifo_ctrl_pkg;
|
||||||
|
|
||||||
|
package body fifo_ctrl_pkg is
|
||||||
|
|
||||||
|
function bin2gray(xb : unsigned) return unsigned is
|
||||||
|
variable xg : unsigned(xb'left downto xb'right);
|
||||||
|
begin
|
||||||
|
|
||||||
|
xg(xg'left) := xb(xb'left);
|
||||||
|
for i in 1 to xb'left loop
|
||||||
|
xg(xg'left-i) := xb(xb'left-i+1) xor xb(xb'left-i);
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
return xg;
|
||||||
|
end bin2gray;
|
||||||
|
|
||||||
|
function gray2bin(xg : unsigned) return unsigned is
|
||||||
|
variable xb : unsigned(xg'left downto xg'right);
|
||||||
|
begin
|
||||||
|
|
||||||
|
xb(xb'left) := xg(xg'left);
|
||||||
|
for i in 1 to xg'left loop
|
||||||
|
xb(xb'left-i) := xb(xb'left-i+1) xor xg(xg'left-i);
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
return xb;
|
||||||
|
end gray2bin;
|
||||||
|
|
||||||
|
end fifo_ctrl_pkg;
|
||||||
|
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: FIFO, generic FIFOs written in VHDL
|
||||||
|
-- Release 1
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This library is free software; you can redistribute it and/or
|
||||||
|
-- modify it under the terms of the GNU Lesser General Public
|
||||||
|
-- License as published by the Free Software Foundation; either
|
||||||
|
-- version 2.1 of the License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This library is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
-- Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU Lesser General Public
|
||||||
|
-- License along with this library; if not, write to the Free Software
|
||||||
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
LIBRARY IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
use work.fifo_ctrl_pkg.all;
|
||||||
|
|
||||||
|
entity fifo_sync is
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
addr_width : natural := 4;
|
||||||
|
data_width : natural := 8;
|
||||||
|
almost_full_thresh : integer := 12;
|
||||||
|
almost_empty_thresh : integer := 4;
|
||||||
|
allow_full_writes : boolean := false;
|
||||||
|
allow_empty_reads : boolean := false;
|
||||||
|
do_last_read_update : boolean := true
|
||||||
|
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
rst : in STD_LOGIC;
|
||||||
|
clk : in STD_LOGIC;
|
||||||
|
we : in STD_LOGIC;
|
||||||
|
re : in STD_LOGIC;
|
||||||
|
fifo_full : out STD_LOGIC;
|
||||||
|
fifo_empty : out STD_LOGIC;
|
||||||
|
fifo_afull : out STD_LOGIC;
|
||||||
|
fifo_aempty : out STD_LOGIC;
|
||||||
|
data_w : in unsigned (data_width-1 downto 0);
|
||||||
|
data_r : out unsigned (data_width-1 downto 0)
|
||||||
|
);
|
||||||
|
end fifo_sync;
|
||||||
|
|
||||||
|
architecture Behavioral of fifo_sync is
|
||||||
|
|
||||||
|
signal mem_wr_en : STD_LOGIC;
|
||||||
|
signal mem_rd_en : STD_LOGIC;
|
||||||
|
signal ptr_w : unsigned (addr_width-1 downto 0);
|
||||||
|
signal ptr_r : unsigned (addr_width-1 downto 0);
|
||||||
|
signal full : STD_LOGIC;
|
||||||
|
signal empty : std_logic;
|
||||||
|
signal pre_full : STD_LOGIC;
|
||||||
|
signal pre_empty : STD_LOGIC;
|
||||||
|
signal rinc : std_logic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
fifo_full <= full;
|
||||||
|
fifo_empty <= empty;
|
||||||
|
|
||||||
|
mem_wr_en <= (we and not full) when allow_full_writes = false else we;
|
||||||
|
rinc <= (re and not empty) when allow_empty_reads = false else re;
|
||||||
|
mem_rd_en <= not pre_empty when do_last_read_update = false else '1';
|
||||||
|
|
||||||
|
|
||||||
|
inst_fifo_sync_ctrl: entity work.fifo_sync_ctrl
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
addr_width => addr_width,
|
||||||
|
almost_full_thresh => almost_full_thresh,
|
||||||
|
almost_empty_thresh => almost_empty_thresh
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => rst,
|
||||||
|
clk => clk,
|
||||||
|
winc => mem_wr_en,
|
||||||
|
rinc => rinc,
|
||||||
|
ptr_w => ptr_w,
|
||||||
|
ptr_r => ptr_r,
|
||||||
|
fifo_full => full,
|
||||||
|
fifo_empty => empty,
|
||||||
|
fifo_pre_full => pre_full,
|
||||||
|
fifo_pre_empty => pre_empty,
|
||||||
|
fifo_afull => fifo_afull,
|
||||||
|
fifo_aempty => fifo_aempty
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
inst_dpram_1w1r: entity work.dpram_1w1r
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
addr_width => addr_width,
|
||||||
|
data_width => data_width
|
||||||
|
)
|
||||||
|
PORT MAP(
|
||||||
|
clka => clk,
|
||||||
|
clkb => clk,
|
||||||
|
en_a => '1',
|
||||||
|
en_b => mem_rd_en,
|
||||||
|
we_a => mem_wr_en,
|
||||||
|
addr_a => ptr_w,
|
||||||
|
addr_b => ptr_r,
|
||||||
|
din_a => data_w,
|
||||||
|
dout_b => data_r
|
||||||
|
);
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
|
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: FIFO, generic FIFOs written in VHDL
|
||||||
|
-- Release 1
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This library is free software; you can redistribute it and/or
|
||||||
|
-- modify it under the terms of the GNU Lesser General Public
|
||||||
|
-- License as published by the Free Software Foundation; either
|
||||||
|
-- version 2.1 of the License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This library is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
-- Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU Lesser General Public
|
||||||
|
-- License along with this library; if not, write to the Free Software
|
||||||
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.numeric_std.ALL;
|
||||||
|
|
||||||
|
LIBRARY WORK;
|
||||||
|
USE WORK.FIFO_CTRL_PKG.ALL;
|
||||||
|
|
||||||
|
entity gray_counter is
|
||||||
|
Generic (
|
||||||
|
width : natural := 3;
|
||||||
|
init_value : natural := 0
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
rst : in STD_LOGIC;
|
||||||
|
clk : in STD_LOGIC;
|
||||||
|
ce : in STD_LOGIC;
|
||||||
|
bcnt : out unsigned (width-1 downto 0);
|
||||||
|
bnxt : out unsigned (width-1 downto 0);
|
||||||
|
gcnt : out unsigned (width-1 downto 0);
|
||||||
|
gnxt : out unsigned (width-1 downto 0)
|
||||||
|
);
|
||||||
|
end gray_counter;
|
||||||
|
|
||||||
|
architecture Behavioral of gray_counter is
|
||||||
|
|
||||||
|
signal cntg : unsigned (width-1 downto 0);
|
||||||
|
signal cntb : unsigned (width-1 downto 0);
|
||||||
|
signal nxtb : unsigned (width-1 downto 0);
|
||||||
|
signal nxtg : unsigned (width-1 downto 0);
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
bnxt <= nxtb;
|
||||||
|
gnxt <= nxtg;
|
||||||
|
bcnt <= cntb;
|
||||||
|
gcnt <= cntg;
|
||||||
|
|
||||||
|
process(rst, clk, ce, cntb, nxtb)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
cntb <= to_unsigned(init_value, width);
|
||||||
|
nxtb <= to_unsigned(init_value, width);
|
||||||
|
nxtg <= to_unsigned(init_value, width);
|
||||||
|
cntg <= to_unsigned(init_value, width);
|
||||||
|
else
|
||||||
|
if rising_edge(clk) then
|
||||||
|
cntg <= nxtg;
|
||||||
|
cntb <= nxtb;
|
||||||
|
end if;
|
||||||
|
nxtg <= bin2gray(nxtb);
|
||||||
|
nxtb <= cntb;
|
||||||
|
if ce = '1' then
|
||||||
|
nxtb <= cntb + 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
|
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: FIFO, generic FIFOs written in VHDL
|
||||||
|
-- Release 1
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This library is free software; you can redistribute it and/or
|
||||||
|
-- modify it under the terms of the GNU Lesser General Public
|
||||||
|
-- License as published by the Free Software Foundation; either
|
||||||
|
-- version 2.1 of the License, or (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This library is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
-- Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU Lesser General Public
|
||||||
|
-- License along with this library; if not, write to the Free Software
|
||||||
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.numeric_std.ALL;
|
||||||
|
|
||||||
|
entity fifo_sync_ctrl is
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
addr_width : integer := 3;
|
||||||
|
almost_full_thresh : integer := 6;
|
||||||
|
almost_empty_thresh : integer := 2
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
rst : in STD_LOGIC;
|
||||||
|
clk : in STD_LOGIC;
|
||||||
|
winc : in STD_LOGIC;
|
||||||
|
rinc : in STD_LOGIC;
|
||||||
|
ptr_w : out unsigned (addr_width-1 downto 0);
|
||||||
|
ptr_r : out unsigned (addr_width-1 downto 0);
|
||||||
|
fifo_pre_full : out STD_LOGIC;
|
||||||
|
fifo_pre_empty : out STD_LOGIC;
|
||||||
|
fifo_full : out STD_LOGIC;
|
||||||
|
fifo_empty : out STD_LOGIC;
|
||||||
|
fifo_afull : out STD_LOGIC;
|
||||||
|
fifo_aempty : out STD_LOGIC
|
||||||
|
);
|
||||||
|
end fifo_sync_ctrl;
|
||||||
|
|
||||||
|
architecture Behavioral of fifo_sync_ctrl is
|
||||||
|
|
||||||
|
signal pW, pW_cnt, pW_next : unsigned (addr_width-1 downto 0);
|
||||||
|
signal pR, pR_cnt, pR_next : unsigned (addr_width-1 downto 0);
|
||||||
|
signal empty, full : std_logic;
|
||||||
|
signal pre_empty, pre_full : std_logic;
|
||||||
|
signal was_write : std_logic;
|
||||||
|
signal diff : unsigned (addr_width downto 0);
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
fifo_full <= full;
|
||||||
|
fifo_empty <= empty;
|
||||||
|
fifo_pre_full <= pre_full;
|
||||||
|
fifo_pre_empty <= pre_empty;
|
||||||
|
|
||||||
|
|
||||||
|
proc_diff_gen:
|
||||||
|
process(rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
diff <= (others => '0');
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if winc = '1' and rinc = '0' then
|
||||||
|
diff <= diff + 1;
|
||||||
|
elsif winc = '0' and rinc = '1' then
|
||||||
|
diff <= diff - 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_status_almost_full:
|
||||||
|
process(rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
fifo_afull <= '0';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if diff >= almost_full_thresh-1 then
|
||||||
|
fifo_afull <= '1';
|
||||||
|
else
|
||||||
|
fifo_afull <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_status_almost_empty:
|
||||||
|
process(rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
fifo_aempty <= '1';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if diff <= almost_empty_thresh+1 then
|
||||||
|
fifo_aempty <= '1';
|
||||||
|
else
|
||||||
|
fifo_aempty <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_full_reg:
|
||||||
|
process(rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
full <= '0';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
full <= pre_full;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_empty_reg:
|
||||||
|
process(rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
empty <= '1';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
empty <= pre_empty;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_status_w:
|
||||||
|
process(was_write, pW_next, pR_next, pW, pR, winc, rinc)
|
||||||
|
begin
|
||||||
|
if (pW_next = pR) and (winc = '1' or was_write = '1') then
|
||||||
|
pre_full <= '1';
|
||||||
|
else
|
||||||
|
pre_full <= '0';
|
||||||
|
end if;
|
||||||
|
if (pR_next = pW) and (rinc = '1' or was_write = '0') then
|
||||||
|
pre_empty <= '1';
|
||||||
|
else
|
||||||
|
pre_empty <= '0';
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_flag_write:
|
||||||
|
process(rst, clk)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
was_write <= '0';
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if winc = '1' then
|
||||||
|
was_write <= '1';
|
||||||
|
elsif rinc = '1' then
|
||||||
|
was_write <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_ptr_w:
|
||||||
|
process(rst, clk, pW, winc)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
pW <= to_unsigned(0, addr_width);
|
||||||
|
pW_next <= to_unsigned(0, addr_width);
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if winc = '1' then
|
||||||
|
pW <= pW_next;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
pW_next <= pW;
|
||||||
|
if winc = '1' then
|
||||||
|
pW_next <= pW + 1;
|
||||||
|
end if;
|
||||||
|
ptr_w <= pW;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_ptr_r:
|
||||||
|
process(rst, clk, pR_next, pR, rinc)
|
||||||
|
begin
|
||||||
|
if rst = '1' then
|
||||||
|
pR <= to_unsigned(0, addr_width);
|
||||||
|
pR_next <= to_unsigned(0, addr_width);
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
if rinc = '1' then
|
||||||
|
pR <= pR_next;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
pR_next <= pR;
|
||||||
|
if rinc = '1' then
|
||||||
|
pR_next <= pR + 1;
|
||||||
|
end if;
|
||||||
|
ptr_r <= pR_next;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
|
|
||||||
@@ -0,0 +1,317 @@
|
|||||||
|
-----------------------------------------------------------------------
|
||||||
|
-- $Header: /tmp/cvsroot/VHDL/lib/misc/async_port_wb.vhd,v 1.16 2010-02-09 09:56:37 Jens Exp $
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.NUMERIC_STD.ALL;
|
||||||
|
use work.async_types.all;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
entity async_port_wb is
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
f_sysclk : real := 100.0;
|
||||||
|
addr_width : natural := 32;
|
||||||
|
data_width : natural := 32;
|
||||||
|
byte_sel_width : natural := 4;
|
||||||
|
async_timespec : async_timespec_t
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
CLK_I : in STD_LOGIC;
|
||||||
|
RST_I : in STD_LOGIC;
|
||||||
|
CYC_I : in STD_LOGIC;
|
||||||
|
STB_I : in STD_LOGIC;
|
||||||
|
WE_I : in STD_LOGIC;
|
||||||
|
ACK_O : out STD_LOGIC;
|
||||||
|
SRDY_O : out STD_LOGIC;
|
||||||
|
MRDY_I : in STD_LOGIC;
|
||||||
|
SEL_I : in unsigned(3 downto 0);
|
||||||
|
ADDR_I : in unsigned(31 downto 0);
|
||||||
|
DAT_I : in unsigned(31 downto 0);
|
||||||
|
DAT_O : out unsigned(31 downto 0);
|
||||||
|
page_mode_en : in STD_LOGIC;
|
||||||
|
async_a : out unsigned(addr_width-1 downto 0);
|
||||||
|
async_d : inout unsigned(data_width-1 downto 0);
|
||||||
|
async_cs : out std_logic;
|
||||||
|
async_wr : out std_logic;
|
||||||
|
async_rd : out std_logic;
|
||||||
|
async_be : out unsigned(byte_sel_width-1 downto 0);
|
||||||
|
async_rst : out std_logic
|
||||||
|
);
|
||||||
|
end async_port_wb;
|
||||||
|
|
||||||
|
architecture Behavioral of async_port_wb is
|
||||||
|
|
||||||
|
type async_t is record
|
||||||
|
cs : std_logic;
|
||||||
|
wr : std_logic;
|
||||||
|
rd : std_logic;
|
||||||
|
rst : std_logic;
|
||||||
|
drive_d : std_logic;
|
||||||
|
end record;
|
||||||
|
|
||||||
|
type async_state_t is (start, reset, idle, leadin, pulse, leadout, release);
|
||||||
|
|
||||||
|
signal s, sn : async_state_t;
|
||||||
|
signal as : async_t;
|
||||||
|
signal ack : std_logic;
|
||||||
|
signal cc_rst : std_logic;
|
||||||
|
signal cycle_cnt : natural range 0 to 31;
|
||||||
|
signal cycle_reload : natural range 0 to 31;
|
||||||
|
signal rdy : std_logic;
|
||||||
|
signal rdyo : std_logic;
|
||||||
|
signal en : std_logic;
|
||||||
|
signal is_idle : std_logic;
|
||||||
|
signal DAT_I_r : unsigned(data_width-1 downto 0);
|
||||||
|
signal SEL_I_r : unsigned(byte_sel_width-1 downto 0);
|
||||||
|
signal WE_I_r : std_logic;
|
||||||
|
signal ADDR_I_r : unsigned(addr_width-1 downto 0);
|
||||||
|
signal page_mode_en_r : std_logic;
|
||||||
|
signal do_page_read : std_logic;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
begin
|
||||||
|
|
||||||
|
ASSERT to_cycles(async_timespec.T_pulse_rd, f_sysclk) > 0 report "Read pulse length must be greater than zero!" severity failure;
|
||||||
|
ASSERT to_cycles(async_timespec.T_pulse_wr, f_sysclk) > 0 report "Write pulse length must be greater than zero!" severity failure;
|
||||||
|
ASSERT (not async_timespec.can_page_rd OR (to_cycles(async_timespec.T_pulse_page_rd, f_sysclk) > 1)) report "Read page pulse length must be greater than one!" severity failure;
|
||||||
|
|
||||||
|
SRDY_O <= CYC_I and rdyo;
|
||||||
|
en <= CYC_I and STB_I;
|
||||||
|
|
||||||
|
do_page_read <= '1' when (async_timespec.can_page_rd and (WE_I = '0') and (WE_I_r = '0') and (ADDR_I(addr_width-1 downto async_timespec.nbits_page_rd) = ADDR_I_r(addr_width-1 downto async_timespec.nbits_page_rd))) else '0';
|
||||||
|
|
||||||
|
proc_cycle_counter:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if cc_rst = '1' then
|
||||||
|
cycle_cnt <= cycle_reload;
|
||||||
|
elsif cycle_cnt /= 0 then
|
||||||
|
cycle_cnt <= cycle_cnt - 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
proc_state_next:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' then
|
||||||
|
s <= start;
|
||||||
|
else
|
||||||
|
s <= sn;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_state:
|
||||||
|
process(s, cycle_cnt, en, WE_I, WE_I_r, do_page_read)
|
||||||
|
begin
|
||||||
|
|
||||||
|
cycle_reload <= to_cycles(async_timespec.T_pulse_rst, f_sysclk);
|
||||||
|
cc_rst <= '0';
|
||||||
|
as.rst <= '0';
|
||||||
|
as.cs <= '0';
|
||||||
|
as.wr <= '0';
|
||||||
|
as.rd <= '0';
|
||||||
|
as.drive_d <= '0';
|
||||||
|
ack <= '0';
|
||||||
|
rdy <= '0';
|
||||||
|
is_idle <= '0';
|
||||||
|
|
||||||
|
sn <= s;
|
||||||
|
case s is
|
||||||
|
|
||||||
|
when start =>
|
||||||
|
cc_rst <= '1';
|
||||||
|
sn <= reset;
|
||||||
|
when reset =>
|
||||||
|
as.rst <= '1';
|
||||||
|
if cycle_cnt = 0 then
|
||||||
|
sn <= idle;
|
||||||
|
end if;
|
||||||
|
when idle =>
|
||||||
|
rdy <= '1';
|
||||||
|
is_idle <= '1';
|
||||||
|
if en = '1' then
|
||||||
|
as.cs <= '1';
|
||||||
|
cc_rst <= '1';
|
||||||
|
if to_cycles(async_timespec.T_leadin, f_sysclk) = 0 then
|
||||||
|
sn <= pulse;
|
||||||
|
if WE_I = '1' then
|
||||||
|
cycle_reload <= 0;
|
||||||
|
sn <= leadin; -- always lead-in for writes
|
||||||
|
else
|
||||||
|
cycle_reload <= to_cycles(async_timespec.T_pulse_rd, f_sysclk) - 1;
|
||||||
|
as.rd <= '1';
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
cycle_reload <= to_cycles(async_timespec.T_leadin, f_sysclk) - 1;
|
||||||
|
sn <= leadin;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when leadin =>
|
||||||
|
as.cs <= '1';
|
||||||
|
as.rd <= not WE_I_r;
|
||||||
|
as.drive_d <= WE_I_r;
|
||||||
|
as.wr <= WE_I_r;
|
||||||
|
if cycle_cnt = 0 then
|
||||||
|
cc_rst <= '1';
|
||||||
|
sn <= pulse;
|
||||||
|
if WE_I_r = '1' then
|
||||||
|
cycle_reload <= to_cycles(async_timespec.T_pulse_wr, f_sysclk) - 1;
|
||||||
|
else
|
||||||
|
cycle_reload <= to_cycles(async_timespec.T_pulse_rd, f_sysclk) - 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when pulse =>
|
||||||
|
as.cs <= '1';
|
||||||
|
as.rd <= not WE_I_r;
|
||||||
|
as.drive_d <= WE_I_r;
|
||||||
|
as.wr <= WE_I_r;
|
||||||
|
if cycle_cnt = 0 then
|
||||||
|
as.wr <= '0';
|
||||||
|
cc_rst <= '1';
|
||||||
|
ack <= not WE_I_r;
|
||||||
|
rdy <= do_page_read;
|
||||||
|
if en = '1' and do_page_read = '1' then
|
||||||
|
cycle_reload <= to_cycles(async_timespec.T_pulse_page_rd, f_sysclk) - 1;
|
||||||
|
sn <= pulse;
|
||||||
|
elsif to_cycles(async_timespec.T_leadout, f_sysclk) = 0 then
|
||||||
|
if to_cycles(async_timespec.T_release, f_sysclk) = 0 then
|
||||||
|
sn <= idle;
|
||||||
|
else
|
||||||
|
cycle_reload <= to_cycles(async_timespec.T_release, f_sysclk) - 1;
|
||||||
|
sn <= release;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
cycle_reload <= to_cycles(async_timespec.T_leadout, f_sysclk) - 1;
|
||||||
|
sn <= leadout;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when leadout =>
|
||||||
|
as.cs <= '1';
|
||||||
|
as.drive_d <= WE_I_r;
|
||||||
|
if cycle_cnt = 0 then
|
||||||
|
cc_rst <= '1';
|
||||||
|
if to_cycles(async_timespec.T_release, f_sysclk) = 0 then
|
||||||
|
sn <= idle;
|
||||||
|
else
|
||||||
|
cycle_reload <= to_cycles(async_timespec.T_release, f_sysclk) - 1;
|
||||||
|
sn <= release;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when release =>
|
||||||
|
if cycle_cnt = 0 then
|
||||||
|
sn <= idle;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
sn <= idle;
|
||||||
|
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
output_ctrl:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
async_cs <= (not async_timespec.pol_cs) xor as.cs;
|
||||||
|
async_wr <= (not async_timespec.pol_we) xor as.wr;
|
||||||
|
async_rd <= (not async_timespec.pol_oe) xor as.rd;
|
||||||
|
async_rst <= (not async_timespec.pol_rst) xor as.rst;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
din_register:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if as.rd = '1' then
|
||||||
|
DAT_O(data_width-1 downto 0) <= async_d;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
output_addr:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' then
|
||||||
|
async_a <= (others => '0');
|
||||||
|
SEL_I_r <= (others => '0');
|
||||||
|
elsif en = '1' and rdy = '1' then
|
||||||
|
async_a <= ADDR_I(addr_width-1 downto 0);
|
||||||
|
async_be <= (byte_sel_width-1 downto 0 => not async_timespec.pol_be) xor ((byte_sel_width-1 downto 0 => as.cs) and SEL_I(byte_sel_width-1 downto 0));
|
||||||
|
SEL_I_r <= SEL_I(byte_sel_width-1 downto 0);
|
||||||
|
if is_idle = '1' then
|
||||||
|
ADDR_I_r <= ADDR_I(addr_width-1 downto 0);
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
data_register:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
page_mode_en_r <= page_mode_en;
|
||||||
|
if en = '1' and rdy = '1' then
|
||||||
|
DAT_I_r <= DAT_I(data_width-1 downto 0);
|
||||||
|
WE_I_r <= WE_I;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
output_SRDY:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' then
|
||||||
|
rdyo <= '1';
|
||||||
|
elsif en = '1' then
|
||||||
|
rdyo <= rdy and not rdyo;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
output_ACK:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' then
|
||||||
|
ACK_O <= '0';
|
||||||
|
else
|
||||||
|
ACK_O <= ack;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
output_data:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
async_d <= (others => 'Z');
|
||||||
|
if as.drive_d = '1' then
|
||||||
|
async_d <= DAT_I_r;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: MIPS System controller
|
||||||
|
-- This file:
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2008 J. Ahrensfeld
|
||||||
|
--
|
||||||
|
-- This program is free software: you can redistribute it and/or modify
|
||||||
|
-- it under the terms of the GNU General Public License as published by
|
||||||
|
-- the Free Software Foundation, either version 3 of the License, or
|
||||||
|
-- (at your option) any later version.
|
||||||
|
--
|
||||||
|
-- This program is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
-- GNU General Public License for more details.
|
||||||
|
--
|
||||||
|
-- You should have received a copy of the GNU General Public License
|
||||||
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
--
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
USE IEEE.MATH_REAL.ALL;
|
||||||
|
|
||||||
|
package async_types is
|
||||||
|
|
||||||
|
type async_timespec_t is record
|
||||||
|
T_leadin : real;
|
||||||
|
T_pulse_rd : real;
|
||||||
|
T_pulse_wr : real;
|
||||||
|
T_leadout : real;
|
||||||
|
T_release : real;
|
||||||
|
T_pulse_rst : real;
|
||||||
|
T_pulse_page_rd : real;
|
||||||
|
can_page_rd : boolean;
|
||||||
|
nbits_page_rd : natural;
|
||||||
|
pol_cs : std_logic;
|
||||||
|
pol_oe : std_logic;
|
||||||
|
pol_we : std_logic;
|
||||||
|
pol_be : std_logic;
|
||||||
|
pol_rst : std_logic;
|
||||||
|
end record;
|
||||||
|
|
||||||
|
function to_cycles(T_ns : real; f_Mhz : real) return natural;
|
||||||
|
|
||||||
|
end async_types;
|
||||||
|
|
||||||
|
package body async_types is
|
||||||
|
|
||||||
|
function to_cycles(T_ns : real; f_Mhz : real) return natural is
|
||||||
|
begin
|
||||||
|
|
||||||
|
return natural(ceil(1.0E-3*T_ns*f_Mhz));
|
||||||
|
|
||||||
|
end to_cycles;
|
||||||
|
end async_types;
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||||
|
-- This file: Dual-ported register file with asynchrous read
|
||||||
|
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
|
||||||
|
-- This library is free software; you can redistribute it and/or
|
||||||
|
-- modify it under the terms of the GNU Lesser General Public
|
||||||
|
-- License as published by the Free Software Foundation; either
|
||||||
|
-- version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
-- This library is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
-- Lesser General Public License for more details.
|
||||||
|
|
||||||
|
-- You should have received a copy of the GNU Lesser General Public
|
||||||
|
-- License along with this library; if not, write to the Free Software
|
||||||
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
-- $Header: /tmp/cvsroot/VHDL/lib/misc/dpram_1w1r.vhd,v 1.1 2008-08-23 08:20:29 Jens Exp $
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
LIBRARY IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
entity dpram_1w1r is
|
||||||
|
Generic (
|
||||||
|
addr_width : integer := 3;
|
||||||
|
data_width : integer := 8
|
||||||
|
);
|
||||||
|
Port (
|
||||||
|
clka : in STD_LOGIC;
|
||||||
|
clkb : in STD_LOGIC;
|
||||||
|
en_a : in STD_LOGIC;
|
||||||
|
en_b : in STD_LOGIC;
|
||||||
|
we_a : in STD_LOGIC;
|
||||||
|
addr_a : in unsigned (addr_width-1 downto 0);
|
||||||
|
addr_b : in unsigned (addr_width-1 downto 0);
|
||||||
|
din_a : in unsigned (data_width-1 downto 0);
|
||||||
|
dout_b : out unsigned (data_width-1 downto 0)
|
||||||
|
);
|
||||||
|
end dpram_1w1r;
|
||||||
|
|
||||||
|
architecture Behavioral of dpram_1w1r is
|
||||||
|
|
||||||
|
constant depth : integer := 2**addr_width;
|
||||||
|
type RAMtype is array (0 to depth-1) of unsigned (data_width-1 downto 0);
|
||||||
|
signal RAM : RAMtype;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
process (clka)
|
||||||
|
begin
|
||||||
|
if clka'event and clka = '1' then
|
||||||
|
if en_a = '1' then
|
||||||
|
if we_a = '1' then
|
||||||
|
RAM(to_integer(addr_a)) <= din_a;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
process (clkb)
|
||||||
|
begin
|
||||||
|
if clkb'event and clkb = '1' then
|
||||||
|
if en_b = '1' then
|
||||||
|
dout_b <= RAM(to_integer(addr_b));
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
|
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
-------------------------------------------------------------------------
|
||||||
|
-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
|
||||||
|
-- This file: Dual-ported register file with asynchrous read
|
||||||
|
|
||||||
|
-- Copyright (C) 2007 J. Ahrensfeld
|
||||||
|
|
||||||
|
-- This library is free software; you can redistribute it and/or
|
||||||
|
-- modify it under the terms of the GNU Lesser General Public
|
||||||
|
-- License as published by the Free Software Foundation; either
|
||||||
|
-- version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
-- This library is distributed in the hope that it will be useful,
|
||||||
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
-- Lesser General Public License for more details.
|
||||||
|
|
||||||
|
-- You should have received a copy of the GNU Lesser General Public
|
||||||
|
-- License along with this library; if not, write to the Free Software
|
||||||
|
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
-- For questions and ideas, please contact the author at jens@jayfield.org
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
-- $Header: /tmp/cvsroot/VHDL/lib/misc/dpram_2w2r.vhd,v 1.2 2009-01-14 20:26:29 Jens Exp $
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.numeric_std.ALL;
|
||||||
|
|
||||||
|
entity dpram_2w2r is
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
addr_width : integer := 3;
|
||||||
|
data_width : integer := 8
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
clk_a : in STD_LOGIC;
|
||||||
|
clk_b : in STD_LOGIC;
|
||||||
|
en_a : in STD_LOGIC;
|
||||||
|
en_b : in STD_LOGIC;
|
||||||
|
we_a : in STD_LOGIC;
|
||||||
|
we_b : in STD_LOGIC;
|
||||||
|
addr_a : in unsigned (addr_width-1 downto 0);
|
||||||
|
addr_b : in unsigned (addr_width-1 downto 0);
|
||||||
|
din_a : in unsigned (data_width-1 downto 0);
|
||||||
|
din_b : in unsigned (data_width-1 downto 0);
|
||||||
|
dout_a : out unsigned (data_width-1 downto 0);
|
||||||
|
dout_b : out unsigned (data_width-1 downto 0)
|
||||||
|
);
|
||||||
|
end dpram_2w2r;
|
||||||
|
|
||||||
|
architecture Behavioral of dpram_2w2r is
|
||||||
|
|
||||||
|
constant depth : integer := 2**addr_width;
|
||||||
|
type RAMtype is array (0 to depth-1) of unsigned (data_width-1 downto 0);
|
||||||
|
shared variable RAM : RAMtype;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
process (clk_a)
|
||||||
|
begin
|
||||||
|
if clk_a'event and clk_a = '1' then
|
||||||
|
if en_a = '1' then
|
||||||
|
if we_a = '1' then
|
||||||
|
RAM(to_integer(addr_a)) := din_a;
|
||||||
|
end if;
|
||||||
|
dout_a <= RAM(to_integer(addr_a));
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
process (clk_b)
|
||||||
|
begin
|
||||||
|
if clk_b'event and clk_b = '1' then
|
||||||
|
if en_b = '1' then
|
||||||
|
if we_b = '1' then
|
||||||
|
RAM(to_integer(addr_b)) := din_b;
|
||||||
|
end if;
|
||||||
|
dout_b <= RAM(to_integer(addr_b));
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
|
|
||||||
@@ -0,0 +1,309 @@
|
|||||||
|
LIBRARY IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
ENTITY gpio_wb IS
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
f_sysclk : real := 100.0
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
CLK_I : in STD_LOGIC;
|
||||||
|
RST_I : in STD_LOGIC;
|
||||||
|
CYC_I : in STD_LOGIC;
|
||||||
|
STB_I : in STD_LOGIC;
|
||||||
|
SEL_I : in unsigned(3 downto 0);
|
||||||
|
WE_I : in STD_LOGIC;
|
||||||
|
ACK_O : out STD_LOGIC;
|
||||||
|
SRDY_O : out STD_LOGIC;
|
||||||
|
MRDY_I : in STD_LOGIC;
|
||||||
|
ADDR_I : in unsigned(31 downto 0);
|
||||||
|
DAT_I : in unsigned(31 downto 0);
|
||||||
|
DAT_O : out unsigned(31 downto 0);
|
||||||
|
INT_TIM_O : out STD_LOGIC;
|
||||||
|
|
||||||
|
sys_gpi_0 : in unsigned(31 downto 0);
|
||||||
|
sys_gpo_0 : out unsigned(31 downto 0)
|
||||||
|
|
||||||
|
);
|
||||||
|
END gpio_wb;
|
||||||
|
|
||||||
|
ARCHITECTURE behavior OF gpio_wb IS
|
||||||
|
|
||||||
|
constant num_timers : natural := 2;
|
||||||
|
constant ncycles_usec : natural := natural(f_sysclk);
|
||||||
|
|
||||||
|
signal gpio_0_dout_reg : unsigned(31 downto 0);
|
||||||
|
signal gpio_0_dir_reg : unsigned(31 downto 0);
|
||||||
|
signal gpio_0_din_reg : unsigned(31 downto 0);
|
||||||
|
|
||||||
|
-- Signals to form an timer generating an interrupt every microsecond
|
||||||
|
subtype tick_usec_t is natural range 0 to ncycles_usec-1;
|
||||||
|
signal tick_usec : tick_usec_t := 0;
|
||||||
|
signal cnt_usec : unsigned(31 downto 0);
|
||||||
|
signal cnt_sec : unsigned(31 downto 0);
|
||||||
|
signal cnt_usec_preset : unsigned(31 downto 0);
|
||||||
|
signal cnt_sec_preset : unsigned(31 downto 0);
|
||||||
|
signal cnt_usec_en : std_logic;
|
||||||
|
signal cnt_usec_we : std_logic;
|
||||||
|
signal cnt_sec_en : std_logic;
|
||||||
|
signal cnt_sec_we : std_logic;
|
||||||
|
|
||||||
|
type timer_array_t is array (0 to num_timers-1) of unsigned(31 downto 0);
|
||||||
|
signal timer_cnt : timer_array_t;
|
||||||
|
signal timer_cmp : timer_array_t;
|
||||||
|
signal timer_en : unsigned(0 to num_timers-1);
|
||||||
|
signal timer_inten : unsigned(0 to num_timers-1);
|
||||||
|
signal timer_irq : unsigned(0 to num_timers-1);
|
||||||
|
signal timer_ovl : unsigned(0 to num_timers-1);
|
||||||
|
signal timer_irq_ack : unsigned(0 to num_timers-1);
|
||||||
|
signal timer_cnt_we : unsigned(0 to num_timers-1);
|
||||||
|
signal timer_cmp_we : unsigned(0 to num_timers-1);
|
||||||
|
|
||||||
|
signal reg_data_wr : unsigned(31 downto 0);
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
SRDY_O <= CYC_I;
|
||||||
|
|
||||||
|
tim_irq:
|
||||||
|
process(timer_irq)
|
||||||
|
variable irq : std_logic;
|
||||||
|
begin
|
||||||
|
irq := '0';
|
||||||
|
for i in 0 to num_timers-1 loop
|
||||||
|
irq := irq or timer_irq(i);
|
||||||
|
end loop;
|
||||||
|
INT_TIM_O <= irq;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
gpio_0_out:
|
||||||
|
process(gpio_0_dir_reg, gpio_0_dout_reg)
|
||||||
|
begin
|
||||||
|
for i in 0 to 31 loop
|
||||||
|
sys_gpo_0(i) <= 'Z';
|
||||||
|
if gpio_0_dir_reg(i) = '1' then
|
||||||
|
sys_gpo_0(i) <= gpio_0_dout_reg(i);
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
gpio_0_in:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
for i in 0 to 31 loop
|
||||||
|
if gpio_0_dir_reg(i) = '1' then
|
||||||
|
gpio_0_din_reg(i) <= gpio_0_dout_reg(i);
|
||||||
|
else
|
||||||
|
gpio_0_din_reg(i) <= sys_gpi_0(i);
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
registers_write:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
cnt_usec_we <= '0';
|
||||||
|
cnt_sec_we <= '0';
|
||||||
|
timer_cnt_we <= (others => '0');
|
||||||
|
timer_cmp_we <= (others => '0');
|
||||||
|
timer_irq_ack <= (others => '0');
|
||||||
|
if RST_I = '1' then
|
||||||
|
gpio_0_dout_reg <= (others => '0');
|
||||||
|
gpio_0_dir_reg <= (others => '0');
|
||||||
|
timer_en <= (others => '0');
|
||||||
|
timer_inten <= (others => '0');
|
||||||
|
elsif (STB_I and CYC_I and WE_I) = '1' then
|
||||||
|
reg_data_wr <= DAT_I;
|
||||||
|
case ADDR_I(6 downto 2) is
|
||||||
|
|
||||||
|
when "00000" =>
|
||||||
|
gpio_0_dout_reg <= DAT_I;
|
||||||
|
|
||||||
|
when "00001" =>
|
||||||
|
gpio_0_dir_reg <= DAT_I;
|
||||||
|
|
||||||
|
when "00010" =>
|
||||||
|
cnt_usec_we <= '1';
|
||||||
|
|
||||||
|
when "00011" =>
|
||||||
|
cnt_sec_we <= '1';
|
||||||
|
|
||||||
|
when "00110" => -- timer control
|
||||||
|
for i in 0 to num_timers-1 loop
|
||||||
|
timer_en(i) <= DAT_I(2*i+0);
|
||||||
|
timer_inten(i) <= DAT_I(2*i+1);
|
||||||
|
end loop;
|
||||||
|
when "00111" => -- timer status
|
||||||
|
for i in 0 to num_timers-1 loop
|
||||||
|
timer_irq_ack(i) <= DAT_I(2*i); -- IRQ acknowledge
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
when "01000" => -- timer count 0
|
||||||
|
timer_cnt_we(0) <= '1';
|
||||||
|
|
||||||
|
when "01001" => -- timer count 1
|
||||||
|
timer_cnt_we(1) <= '1';
|
||||||
|
|
||||||
|
when "01100" => -- timer compare 0
|
||||||
|
timer_cmp_we(0) <= '1';
|
||||||
|
|
||||||
|
when "01101" => -- timer compare 1
|
||||||
|
timer_cmp_we(1) <= '1';
|
||||||
|
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
registers_read:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
ACK_O <= '0';
|
||||||
|
if (STB_I and CYC_I) = '1' then
|
||||||
|
ACK_O <= not WE_I;
|
||||||
|
DAT_O <= (others => '0');
|
||||||
|
case ADDR_I(6 downto 2) is
|
||||||
|
|
||||||
|
when "00000" =>
|
||||||
|
DAT_O <= gpio_0_din_reg;
|
||||||
|
|
||||||
|
when "00001" =>
|
||||||
|
DAT_O <= gpio_0_dir_reg;
|
||||||
|
|
||||||
|
when "00010" =>
|
||||||
|
DAT_O <= cnt_usec;
|
||||||
|
|
||||||
|
when "00011" =>
|
||||||
|
DAT_O <= cnt_sec;
|
||||||
|
|
||||||
|
when "00110" => -- timer control
|
||||||
|
for i in 0 to num_timers-1 loop
|
||||||
|
DAT_O(2*i+0) <= timer_en(i);
|
||||||
|
DAT_O(2*i+1) <= timer_inten(i);
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
when "00111" => -- timer status
|
||||||
|
for i in 0 to num_timers-1 loop
|
||||||
|
DAT_O(2*i+0) <= timer_irq(i);
|
||||||
|
DAT_O(2*i+1) <= timer_ovl(i);
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
when "01000" => -- timer count 0
|
||||||
|
DAT_O <= timer_cnt(0);
|
||||||
|
|
||||||
|
when "01001" => -- timer count 1
|
||||||
|
DAT_O <= timer_cnt(1);
|
||||||
|
|
||||||
|
when "01100" => -- timer compare 0
|
||||||
|
DAT_O <= timer_cmp(0);
|
||||||
|
|
||||||
|
when "01101" => -- timer compare 1
|
||||||
|
DAT_O <= timer_cmp(1);
|
||||||
|
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
cnt_usec_tick:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
cnt_usec_en <= '0';
|
||||||
|
if tick_usec >= tick_usec_t'high then
|
||||||
|
tick_usec <= 0;
|
||||||
|
cnt_usec_en <= '1';
|
||||||
|
else
|
||||||
|
tick_usec <= tick_usec + 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- H/W Clock
|
||||||
|
cnt_usec_clock:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
cnt_sec_en <= '0';
|
||||||
|
if cnt_usec_we = '1' then
|
||||||
|
cnt_usec <= reg_data_wr;
|
||||||
|
elsif cnt_usec_en = '1' then
|
||||||
|
if to_01(cnt_usec) >= to_unsigned(1E6 - 1, 32) then
|
||||||
|
cnt_usec <= (others => '0');
|
||||||
|
cnt_sec_en <= '1';
|
||||||
|
else
|
||||||
|
cnt_usec <= cnt_usec + 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
cnt_sec_clock:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if cnt_sec_we = '1' then
|
||||||
|
cnt_sec <= reg_data_wr;
|
||||||
|
elsif cnt_sec_en = '1' then
|
||||||
|
cnt_sec <= cnt_sec + 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Interrupt timer
|
||||||
|
proc_int_timer:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
for i in 0 to num_timers-1 loop
|
||||||
|
if RST_I = '1' then
|
||||||
|
timer_ovl(i) <= '0';
|
||||||
|
timer_irq(i) <= '0';
|
||||||
|
elsif timer_irq_ack(i) = '1' then
|
||||||
|
timer_ovl(i) <= '0';
|
||||||
|
timer_irq(i) <= '0';
|
||||||
|
elsif timer_cnt_we(i) = '1' then
|
||||||
|
timer_cnt(i) <= reg_data_wr;
|
||||||
|
elsif timer_en(i) = '1' then
|
||||||
|
if to_01(timer_cnt(i)) >= timer_cmp(i) then
|
||||||
|
timer_cnt(i) <= (others => '0');
|
||||||
|
if timer_inten(i) = '1' then
|
||||||
|
if timer_irq(i) = '1' then
|
||||||
|
timer_ovl(i) <= '1';
|
||||||
|
end if;
|
||||||
|
timer_irq(i) <= '1';
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
timer_cnt(i) <= timer_cnt(i) + 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_int_timer_reload:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
for i in 0 to num_timers-1 loop
|
||||||
|
if timer_cmp_we(i) = '1' then
|
||||||
|
timer_cmp(i) <= reg_data_wr;
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
end behavior;
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
LIBRARY IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
ENTITY rom_wb IS
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
CLK_I : in STD_LOGIC;
|
||||||
|
RST_I : in STD_LOGIC;
|
||||||
|
CYC_I : in STD_LOGIC;
|
||||||
|
STB_I : in STD_LOGIC;
|
||||||
|
ACK_O : out STD_LOGIC;
|
||||||
|
MRDY_I : in STD_LOGIC;
|
||||||
|
SRDY_O : out STD_LOGIC;
|
||||||
|
ADDR_I : in unsigned(31 downto 0);
|
||||||
|
DAT_O : out unsigned(31 downto 0)
|
||||||
|
);
|
||||||
|
END rom_wb;
|
||||||
|
|
||||||
|
ARCHITECTURE behavior OF rom_wb IS
|
||||||
|
|
||||||
|
COMPONENT rom
|
||||||
|
PORT
|
||||||
|
(
|
||||||
|
clk : in STD_LOGIC;
|
||||||
|
ce : in STD_LOGIC;
|
||||||
|
addr : in unsigned(31 downto 0);
|
||||||
|
dout : out unsigned(31 downto 0)
|
||||||
|
);
|
||||||
|
END COMPONENT;
|
||||||
|
|
||||||
|
signal data_en : std_logic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
data_en <= CYC_I and STB_I and MRDY_I;
|
||||||
|
SRDY_O <= CYC_I;
|
||||||
|
|
||||||
|
data_valid_register:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' then
|
||||||
|
ACK_O <= '0';
|
||||||
|
else
|
||||||
|
ACK_O <= data_en; -- and not WE_I;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
inst_rom : rom
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
clk => CLK_I,
|
||||||
|
ce => data_en,
|
||||||
|
addr => ADDR_I,
|
||||||
|
dout => DAT_O
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
end behavior;
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
-- 'Bucket Brigade' FIFO
|
||||||
|
-- 16 deep
|
||||||
|
-- 8-bit data
|
||||||
|
--
|
||||||
|
-- Version : 1.10
|
||||||
|
-- Version Date : 3rd December 2003
|
||||||
|
-- Reason : '--translate' directives changed to '--synthesis translate' directives
|
||||||
|
--
|
||||||
|
-- Version : 1.00
|
||||||
|
-- Version Date : 14th October 2002
|
||||||
|
--
|
||||||
|
-- Start of design entry : 14th October 2002
|
||||||
|
--
|
||||||
|
-- Ken Chapman
|
||||||
|
-- Xilinx Ltd
|
||||||
|
-- Benchmark House
|
||||||
|
-- 203 Brooklands Road
|
||||||
|
-- Weybridge
|
||||||
|
-- Surrey KT13 ORH
|
||||||
|
-- United Kingdom
|
||||||
|
--
|
||||||
|
-- chapman@xilinx.com
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- NOTICE:
|
||||||
|
--
|
||||||
|
-- Copyright Xilinx, Inc. 2002. This code may be contain portions patented by other
|
||||||
|
-- third parties. By providing this core as one possible implementation of a standard,
|
||||||
|
-- Xilinx is making no representation that the provided implementation of this standard
|
||||||
|
-- is free from any claims of infringement by any third party. Xilinx expressly
|
||||||
|
-- disclaims any warranty with respect to the adequacy of the implementation, including
|
||||||
|
-- but not limited to any warranty or representation that the implementation is free
|
||||||
|
-- from claims of any third party. Futhermore, Xilinx is providing this core as a
|
||||||
|
-- courtesy to you and suggests that you contact all third parties to obtain the
|
||||||
|
-- necessary rights to use this implementation.
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Library declarations
|
||||||
|
--
|
||||||
|
-- The Unisim Library is used to define Xilinx primitives. It is also used during
|
||||||
|
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
|
||||||
|
--
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||||
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||||
|
library unisim;
|
||||||
|
use unisim.vcomponents.all;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Main Entity for BBFIFO_16x8
|
||||||
|
--
|
||||||
|
entity bbfifo_16x8 is
|
||||||
|
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||||
|
data_out : out std_logic_vector(7 downto 0);
|
||||||
|
reset : in std_logic;
|
||||||
|
write : in std_logic;
|
||||||
|
read : in std_logic;
|
||||||
|
full : out std_logic;
|
||||||
|
half_full : out std_logic;
|
||||||
|
data_present : out std_logic;
|
||||||
|
clk : in std_logic);
|
||||||
|
end bbfifo_16x8;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Start of Main Architecture for BBFIFO_16x8
|
||||||
|
--
|
||||||
|
architecture low_level_definition of bbfifo_16x8 is
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Signals used in BBFIFO_16x8
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
signal pointer : std_logic_vector(3 downto 0);
|
||||||
|
signal next_count : std_logic_vector(3 downto 0);
|
||||||
|
signal half_count : std_logic_vector(3 downto 0);
|
||||||
|
signal count_carry : std_logic_vector(2 downto 0);
|
||||||
|
|
||||||
|
signal pointer_zero : std_logic;
|
||||||
|
signal pointer_full : std_logic;
|
||||||
|
signal decode_data_present : std_logic;
|
||||||
|
signal data_present_int : std_logic;
|
||||||
|
signal valid_write : std_logic;
|
||||||
|
--
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Attributes to define LUT contents during implementation
|
||||||
|
-- The information is repeated in the generic map for functional simulation--
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
attribute INIT : string;
|
||||||
|
attribute INIT of zero_lut : label is "0001";
|
||||||
|
attribute INIT of full_lut : label is "8000";
|
||||||
|
attribute INIT of dp_lut : label is "BFA0";
|
||||||
|
attribute INIT of valid_lut : label is "C4";
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Start of BBFIFO_16x8 circuit description
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
-- SRL16E data storage
|
||||||
|
|
||||||
|
data_width_loop: for i in 0 to 7 generate
|
||||||
|
--
|
||||||
|
attribute INIT : string;
|
||||||
|
attribute INIT of data_srl : label is "0000";
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
data_srl: SRL16E
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0000")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( D => data_in(i),
|
||||||
|
CE => valid_write,
|
||||||
|
CLK => clk,
|
||||||
|
A0 => pointer(0),
|
||||||
|
A1 => pointer(1),
|
||||||
|
A2 => pointer(2),
|
||||||
|
A3 => pointer(3),
|
||||||
|
Q => data_out(i) );
|
||||||
|
|
||||||
|
end generate data_width_loop;
|
||||||
|
|
||||||
|
-- 4-bit counter to act as data pointer
|
||||||
|
-- Counter is clock enabled by 'data_present'
|
||||||
|
-- Counter will be reset when 'reset' is active
|
||||||
|
-- Counter will increment when 'valid_write' is active
|
||||||
|
|
||||||
|
count_width_loop: for i in 0 to 3 generate
|
||||||
|
--
|
||||||
|
attribute INIT : string;
|
||||||
|
attribute INIT of count_lut : label is "6606";
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
register_bit: FDRE
|
||||||
|
port map ( D => next_count(i),
|
||||||
|
Q => pointer(i),
|
||||||
|
CE => data_present_int,
|
||||||
|
R => reset,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
count_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"6606")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => pointer(i),
|
||||||
|
I1 => read,
|
||||||
|
I2 => pointer_zero,
|
||||||
|
I3 => write,
|
||||||
|
O => half_count(i));
|
||||||
|
|
||||||
|
lsb_count: if i=0 generate
|
||||||
|
begin
|
||||||
|
|
||||||
|
count_muxcy: MUXCY
|
||||||
|
port map( DI => pointer(i),
|
||||||
|
CI => valid_write,
|
||||||
|
S => half_count(i),
|
||||||
|
O => count_carry(i));
|
||||||
|
|
||||||
|
count_xor: XORCY
|
||||||
|
port map( LI => half_count(i),
|
||||||
|
CI => valid_write,
|
||||||
|
O => next_count(i));
|
||||||
|
|
||||||
|
end generate lsb_count;
|
||||||
|
|
||||||
|
mid_count: if i>0 and i<3 generate
|
||||||
|
begin
|
||||||
|
|
||||||
|
count_muxcy: MUXCY
|
||||||
|
port map( DI => pointer(i),
|
||||||
|
CI => count_carry(i-1),
|
||||||
|
S => half_count(i),
|
||||||
|
O => count_carry(i));
|
||||||
|
|
||||||
|
count_xor: XORCY
|
||||||
|
port map( LI => half_count(i),
|
||||||
|
CI => count_carry(i-1),
|
||||||
|
O => next_count(i));
|
||||||
|
|
||||||
|
end generate mid_count;
|
||||||
|
|
||||||
|
upper_count: if i=3 generate
|
||||||
|
begin
|
||||||
|
|
||||||
|
count_xor: XORCY
|
||||||
|
port map( LI => half_count(i),
|
||||||
|
CI => count_carry(i-1),
|
||||||
|
O => next_count(i));
|
||||||
|
|
||||||
|
end generate upper_count;
|
||||||
|
|
||||||
|
end generate count_width_loop;
|
||||||
|
|
||||||
|
|
||||||
|
-- Detect when pointer is zero and maximum
|
||||||
|
|
||||||
|
zero_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0001")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => pointer(0),
|
||||||
|
I1 => pointer(1),
|
||||||
|
I2 => pointer(2),
|
||||||
|
I3 => pointer(3),
|
||||||
|
O => pointer_zero );
|
||||||
|
|
||||||
|
|
||||||
|
full_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"8000")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => pointer(0),
|
||||||
|
I1 => pointer(1),
|
||||||
|
I2 => pointer(2),
|
||||||
|
I3 => pointer(3),
|
||||||
|
O => pointer_full );
|
||||||
|
|
||||||
|
|
||||||
|
-- Data Present status
|
||||||
|
|
||||||
|
dp_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"BFA0")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => write,
|
||||||
|
I1 => read,
|
||||||
|
I2 => pointer_zero,
|
||||||
|
I3 => data_present_int,
|
||||||
|
O => decode_data_present );
|
||||||
|
|
||||||
|
dp_flop: FDR
|
||||||
|
port map ( D => decode_data_present,
|
||||||
|
Q => data_present_int,
|
||||||
|
R => reset,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
-- Valid write signal
|
||||||
|
|
||||||
|
valid_lut: LUT3
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"C4")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => pointer_full,
|
||||||
|
I1 => write,
|
||||||
|
I2 => read,
|
||||||
|
O => valid_write );
|
||||||
|
|
||||||
|
|
||||||
|
-- assign internal signals to outputs
|
||||||
|
|
||||||
|
full <= pointer_full;
|
||||||
|
half_full <= pointer(3);
|
||||||
|
data_present <= data_present_int;
|
||||||
|
|
||||||
|
end low_level_definition;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- END OF FILE BBFIFO_16x8.VHD
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,352 @@
|
|||||||
|
-- Constant (K) Compact UART Receiver
|
||||||
|
--
|
||||||
|
-- Version : 1.10
|
||||||
|
-- Version Date : 3rd December 2003
|
||||||
|
-- Reason : '--translate' directives changed to '--synthesis translate' directives
|
||||||
|
--
|
||||||
|
-- Version : 1.00
|
||||||
|
-- Version Date : 16th October 2002
|
||||||
|
--
|
||||||
|
-- Start of design entry : 16th October 2002
|
||||||
|
--
|
||||||
|
-- Ken Chapman
|
||||||
|
-- Xilinx Ltd
|
||||||
|
-- Benchmark House
|
||||||
|
-- 203 Brooklands Road
|
||||||
|
-- Weybridge
|
||||||
|
-- Surrey KT13 ORH
|
||||||
|
-- United Kingdom
|
||||||
|
--
|
||||||
|
-- chapman@xilinx.com
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- NOTICE:
|
||||||
|
--
|
||||||
|
-- Copyright Xilinx, Inc. 2002. This code may be contain portions patented by other
|
||||||
|
-- third parties. By providing this core as one possible implementation of a standard,
|
||||||
|
-- Xilinx is making no representation that the provided implementation of this standard
|
||||||
|
-- is free from any claims of infringement by any third party. Xilinx expressly
|
||||||
|
-- disclaims any warranty with respect to the adequacy of the implementation, including
|
||||||
|
-- but not limited to any warranty or representation that the implementation is free
|
||||||
|
-- from claims of any third party. Futhermore, Xilinx is providing this core as a
|
||||||
|
-- courtesy to you and suggests that you contact all third parties to obtain the
|
||||||
|
-- necessary rights to use this implementation.
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Library declarations
|
||||||
|
--
|
||||||
|
-- The Unisim Library is used to define Xilinx primitives. It is also used during
|
||||||
|
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
|
||||||
|
--
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||||
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||||
|
library unisim;
|
||||||
|
use unisim.vcomponents.all;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Main Entity for KCUART_RX
|
||||||
|
--
|
||||||
|
entity kcuart_rx is
|
||||||
|
Port ( serial_in : in std_logic;
|
||||||
|
data_out : out std_logic_vector(7 downto 0);
|
||||||
|
data_strobe : out std_logic;
|
||||||
|
en_16_x_baud : in std_logic;
|
||||||
|
clk : in std_logic);
|
||||||
|
end kcuart_rx;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Start of Main Architecture for KCUART_RX
|
||||||
|
--
|
||||||
|
architecture low_level_definition of kcuart_rx is
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Signals used in KCUART_RX
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
signal sync_serial : std_logic;
|
||||||
|
signal stop_bit : std_logic;
|
||||||
|
signal data_int : std_logic_vector(7 downto 0);
|
||||||
|
signal data_delay : std_logic_vector(7 downto 0);
|
||||||
|
signal start_delay : std_logic;
|
||||||
|
signal start_bit : std_logic;
|
||||||
|
signal edge_delay : std_logic;
|
||||||
|
signal start_edge : std_logic;
|
||||||
|
signal decode_valid_char : std_logic;
|
||||||
|
signal valid_char : std_logic;
|
||||||
|
signal decode_purge : std_logic;
|
||||||
|
signal purge : std_logic;
|
||||||
|
signal valid_srl_delay : std_logic_vector(8 downto 0);
|
||||||
|
signal valid_reg_delay : std_logic_vector(8 downto 0);
|
||||||
|
signal decode_data_strobe : std_logic;
|
||||||
|
--
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Attributes to define LUT contents during implementation
|
||||||
|
-- The information is repeated in the generic map for functional simulation--
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
attribute INIT : string;
|
||||||
|
attribute INIT of start_srl : label is "0000";
|
||||||
|
attribute INIT of edge_srl : label is "0000";
|
||||||
|
attribute INIT of valid_lut : label is "0040";
|
||||||
|
attribute INIT of purge_lut : label is "54";
|
||||||
|
attribute INIT of strobe_lut : label is "8";
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Start of KCUART_RX circuit description
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
-- Synchronise input serial data to system clock
|
||||||
|
|
||||||
|
sync_reg: FD
|
||||||
|
port map ( D => serial_in,
|
||||||
|
Q => sync_serial,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
stop_reg: FD
|
||||||
|
port map ( D => sync_serial,
|
||||||
|
Q => stop_bit,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
|
||||||
|
-- Data delays to capture data at 16 time baud rate
|
||||||
|
-- Each SRL16E is followed by a flip-flop for best timing
|
||||||
|
|
||||||
|
data_loop: for i in 0 to 7 generate
|
||||||
|
begin
|
||||||
|
|
||||||
|
lsbs: if i<7 generate
|
||||||
|
--
|
||||||
|
attribute INIT : string;
|
||||||
|
attribute INIT of delay15_srl : label is "0000";
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
delay15_srl: SRL16E
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0000")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( D => data_int(i+1),
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
CLK => clk,
|
||||||
|
A0 => '0',
|
||||||
|
A1 => '1',
|
||||||
|
A2 => '1',
|
||||||
|
A3 => '1',
|
||||||
|
Q => data_delay(i) );
|
||||||
|
|
||||||
|
end generate lsbs;
|
||||||
|
|
||||||
|
msb: if i=7 generate
|
||||||
|
--
|
||||||
|
attribute INIT : string;
|
||||||
|
attribute INIT of delay15_srl : label is "0000";
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
delay15_srl: SRL16E
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0000")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( D => stop_bit,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
CLK => clk,
|
||||||
|
A0 => '0',
|
||||||
|
A1 => '1',
|
||||||
|
A2 => '1',
|
||||||
|
A3 => '1',
|
||||||
|
Q => data_delay(i) );
|
||||||
|
|
||||||
|
end generate msb;
|
||||||
|
|
||||||
|
data_reg: FDE
|
||||||
|
port map ( D => data_delay(i),
|
||||||
|
Q => data_int(i),
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
end generate data_loop;
|
||||||
|
|
||||||
|
-- Assign internal signals to outputs
|
||||||
|
|
||||||
|
data_out <= data_int;
|
||||||
|
|
||||||
|
-- Data delays to capture start bit at 16 time baud rate
|
||||||
|
|
||||||
|
start_srl: SRL16E
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0000")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( D => data_int(0),
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
CLK => clk,
|
||||||
|
A0 => '0',
|
||||||
|
A1 => '1',
|
||||||
|
A2 => '1',
|
||||||
|
A3 => '1',
|
||||||
|
Q => start_delay );
|
||||||
|
|
||||||
|
start_reg: FDE
|
||||||
|
port map ( D => start_delay,
|
||||||
|
Q => start_bit,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
|
||||||
|
-- Data delays to capture start bit leading edge at 16 time baud rate
|
||||||
|
-- Delay ensures data is captured at mid-bit position
|
||||||
|
|
||||||
|
edge_srl: SRL16E
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0000")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( D => start_bit,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
CLK => clk,
|
||||||
|
A0 => '1',
|
||||||
|
A1 => '0',
|
||||||
|
A2 => '1',
|
||||||
|
A3 => '0',
|
||||||
|
Q => edge_delay );
|
||||||
|
|
||||||
|
edge_reg: FDE
|
||||||
|
port map ( D => edge_delay,
|
||||||
|
Q => start_edge,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
-- Detect a valid character
|
||||||
|
|
||||||
|
valid_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0040")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => purge,
|
||||||
|
I1 => stop_bit,
|
||||||
|
I2 => start_edge,
|
||||||
|
I3 => edge_delay,
|
||||||
|
O => decode_valid_char );
|
||||||
|
|
||||||
|
valid_reg: FDE
|
||||||
|
port map ( D => decode_valid_char,
|
||||||
|
Q => valid_char,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
-- Purge of data status
|
||||||
|
|
||||||
|
purge_lut: LUT3
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"54")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => valid_reg_delay(8),
|
||||||
|
I1 => valid_char,
|
||||||
|
I2 => purge,
|
||||||
|
O => decode_purge );
|
||||||
|
|
||||||
|
purge_reg: FDE
|
||||||
|
port map ( D => decode_purge,
|
||||||
|
Q => purge,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
-- Delay of valid_char pulse of length equivalent to the time taken
|
||||||
|
-- to purge data shift register of all data which has been used.
|
||||||
|
-- Requires 9x16 + 8 delays which is achieved by packing of SRL16E with
|
||||||
|
-- up to 16 delays and utilising the dedicated flip flop in each stage.
|
||||||
|
|
||||||
|
valid_loop: for i in 0 to 8 generate
|
||||||
|
begin
|
||||||
|
|
||||||
|
lsb: if i=0 generate
|
||||||
|
--
|
||||||
|
attribute INIT : string;
|
||||||
|
attribute INIT of delay15_srl : label is "0000";
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
delay15_srl: SRL16E
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0000")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( D => valid_char,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
CLK => clk,
|
||||||
|
A0 => '0',
|
||||||
|
A1 => '1',
|
||||||
|
A2 => '1',
|
||||||
|
A3 => '1',
|
||||||
|
Q => valid_srl_delay(i) );
|
||||||
|
|
||||||
|
end generate lsb;
|
||||||
|
|
||||||
|
msbs: if i>0 generate
|
||||||
|
--
|
||||||
|
attribute INIT : string;
|
||||||
|
attribute INIT of delay16_srl : label is "0000";
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
delay16_srl: SRL16E
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0000")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( D => valid_reg_delay(i-1),
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
CLK => clk,
|
||||||
|
A0 => '1',
|
||||||
|
A1 => '1',
|
||||||
|
A2 => '1',
|
||||||
|
A3 => '1',
|
||||||
|
Q => valid_srl_delay(i) );
|
||||||
|
|
||||||
|
end generate msbs;
|
||||||
|
|
||||||
|
data_reg: FDE
|
||||||
|
port map ( D => valid_srl_delay(i),
|
||||||
|
Q => valid_reg_delay(i),
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
end generate valid_loop;
|
||||||
|
|
||||||
|
-- Form data strobe
|
||||||
|
|
||||||
|
strobe_lut: LUT2
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"8")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => valid_char,
|
||||||
|
I1 => en_16_x_baud,
|
||||||
|
O => decode_data_strobe );
|
||||||
|
|
||||||
|
strobe_reg: FD
|
||||||
|
port map ( D => decode_data_strobe,
|
||||||
|
Q => data_strobe,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
end low_level_definition;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- END OF FILE KCUART_RX.VHD
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,394 @@
|
|||||||
|
-- Constant (K) Compact UART Transmitter
|
||||||
|
--
|
||||||
|
-- Version : 1.10
|
||||||
|
-- Version Date : 3rd December 2003
|
||||||
|
-- Reason : '--translate' directives changed to '--synthesis translate' directives
|
||||||
|
--
|
||||||
|
-- Version : 1.00
|
||||||
|
-- Version Date : 14th October 2002
|
||||||
|
--
|
||||||
|
-- Start of design entry : 2nd October 2002
|
||||||
|
--
|
||||||
|
-- Ken Chapman
|
||||||
|
-- Xilinx Ltd
|
||||||
|
-- Benchmark House
|
||||||
|
-- 203 Brooklands Road
|
||||||
|
-- Weybridge
|
||||||
|
-- Surrey KT13 ORH
|
||||||
|
-- United Kingdom
|
||||||
|
--
|
||||||
|
-- chapman@xilinx.com
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- NOTICE:
|
||||||
|
--
|
||||||
|
-- Copyright Xilinx, Inc. 2002. This code may be contain portions patented by other
|
||||||
|
-- third parties. By providing this core as one possible implementation of a standard,
|
||||||
|
-- Xilinx is making no representation that the provided implementation of this standard
|
||||||
|
-- is free from any claims of infringement by any third party. Xilinx expressly
|
||||||
|
-- disclaims any warranty with respect to the adequacy of the implementation, including
|
||||||
|
-- but not limited to any warranty or representation that the implementation is free
|
||||||
|
-- from claims of any third party. Futhermore, Xilinx is providing this core as a
|
||||||
|
-- courtesy to you and suggests that you contact all third parties to obtain the
|
||||||
|
-- necessary rights to use this implementation.
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Library declarations
|
||||||
|
--
|
||||||
|
-- The Unisim Library is used to define Xilinx primitives. It is also used during
|
||||||
|
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
|
||||||
|
--
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||||
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||||
|
library unisim;
|
||||||
|
use unisim.vcomponents.all;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Main Entity for KCUART_TX
|
||||||
|
--
|
||||||
|
entity kcuart_tx is
|
||||||
|
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||||
|
send_character : in std_logic;
|
||||||
|
en_16_x_baud : in std_logic;
|
||||||
|
serial_out : out std_logic;
|
||||||
|
Tx_complete : out std_logic;
|
||||||
|
clk : in std_logic);
|
||||||
|
end kcuart_tx;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Start of Main Architecture for KCUART_TX
|
||||||
|
--
|
||||||
|
architecture low_level_definition of kcuart_tx is
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Signals used in KCUART_TX
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
signal data_01 : std_logic;
|
||||||
|
signal data_23 : std_logic;
|
||||||
|
signal data_45 : std_logic;
|
||||||
|
signal data_67 : std_logic;
|
||||||
|
signal data_0123 : std_logic;
|
||||||
|
signal data_4567 : std_logic;
|
||||||
|
signal data_01234567 : std_logic;
|
||||||
|
signal bit_select : std_logic_vector(2 downto 0);
|
||||||
|
signal next_count : std_logic_vector(2 downto 0);
|
||||||
|
signal mask_count : std_logic_vector(2 downto 0);
|
||||||
|
signal mask_count_carry : std_logic_vector(2 downto 0);
|
||||||
|
signal count_carry : std_logic_vector(2 downto 0);
|
||||||
|
signal ready_to_start : std_logic;
|
||||||
|
signal decode_Tx_start : std_logic;
|
||||||
|
signal Tx_start : std_logic;
|
||||||
|
signal decode_Tx_run : std_logic;
|
||||||
|
signal Tx_run : std_logic;
|
||||||
|
signal decode_hot_state : std_logic;
|
||||||
|
signal hot_state : std_logic;
|
||||||
|
signal hot_delay : std_logic;
|
||||||
|
signal Tx_bit : std_logic;
|
||||||
|
signal decode_Tx_stop : std_logic;
|
||||||
|
signal Tx_stop : std_logic;
|
||||||
|
signal decode_Tx_complete : std_logic;
|
||||||
|
--
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Attributes to define LUT contents during implementation
|
||||||
|
-- The information is repeated in the generic map for functional simulation--
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
attribute INIT : string;
|
||||||
|
attribute INIT of mux1_lut : label is "E4FF";
|
||||||
|
attribute INIT of mux2_lut : label is "E4FF";
|
||||||
|
attribute INIT of mux3_lut : label is "E4FF";
|
||||||
|
attribute INIT of mux4_lut : label is "E4FF";
|
||||||
|
attribute INIT of ready_lut : label is "10";
|
||||||
|
attribute INIT of start_lut : label is "0190";
|
||||||
|
attribute INIT of run_lut : label is "1540";
|
||||||
|
attribute INIT of hot_state_lut : label is "94";
|
||||||
|
attribute INIT of delay14_srl : label is "0000";
|
||||||
|
attribute INIT of stop_lut : label is "0180";
|
||||||
|
attribute INIT of complete_lut : label is "8";
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Start of KCUART_TX circuit description
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
-- 8 to 1 multiplexer to convert parallel data to serial
|
||||||
|
|
||||||
|
mux1_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"E4FF")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => bit_select(0),
|
||||||
|
I1 => data_in(0),
|
||||||
|
I2 => data_in(1),
|
||||||
|
I3 => Tx_run,
|
||||||
|
O => data_01 );
|
||||||
|
|
||||||
|
mux2_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"E4FF")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => bit_select(0),
|
||||||
|
I1 => data_in(2),
|
||||||
|
I2 => data_in(3),
|
||||||
|
I3 => Tx_run,
|
||||||
|
O => data_23 );
|
||||||
|
|
||||||
|
mux3_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"E4FF")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => bit_select(0),
|
||||||
|
I1 => data_in(4),
|
||||||
|
I2 => data_in(5),
|
||||||
|
I3 => Tx_run,
|
||||||
|
O => data_45 );
|
||||||
|
|
||||||
|
mux4_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"E4FF")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => bit_select(0),
|
||||||
|
I1 => data_in(6),
|
||||||
|
I2 => data_in(7),
|
||||||
|
I3 => Tx_run,
|
||||||
|
O => data_67 );
|
||||||
|
|
||||||
|
mux5_muxf5: MUXF5
|
||||||
|
port map( I1 => data_23,
|
||||||
|
I0 => data_01,
|
||||||
|
S => bit_select(1),
|
||||||
|
O => data_0123 );
|
||||||
|
|
||||||
|
mux6_muxf5: MUXF5
|
||||||
|
port map( I1 => data_67,
|
||||||
|
I0 => data_45,
|
||||||
|
S => bit_select(1),
|
||||||
|
O => data_4567 );
|
||||||
|
|
||||||
|
mux7_muxf6: MUXF6
|
||||||
|
port map( I1 => data_4567,
|
||||||
|
I0 => data_0123,
|
||||||
|
S => bit_select(2),
|
||||||
|
O => data_01234567 );
|
||||||
|
|
||||||
|
-- Register serial output and force start and stop bits
|
||||||
|
|
||||||
|
pipeline_serial: FDRS
|
||||||
|
port map ( D => data_01234567,
|
||||||
|
Q => serial_out,
|
||||||
|
R => Tx_start,
|
||||||
|
S => Tx_stop,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
-- 3-bit counter
|
||||||
|
-- Counter is clock enabled by en_16_x_baud
|
||||||
|
-- Counter will be reset when 'Tx_start' is active
|
||||||
|
-- Counter will increment when Tx_bit is active
|
||||||
|
-- Tx_run must be active to count
|
||||||
|
-- count_carry(2) indicates when terminal count (7) is reached and Tx_bit=1 (ie overflow)
|
||||||
|
|
||||||
|
count_width_loop: for i in 0 to 2 generate
|
||||||
|
--
|
||||||
|
attribute INIT : string;
|
||||||
|
attribute INIT of count_lut : label is "8";
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
register_bit: FDRE
|
||||||
|
port map ( D => next_count(i),
|
||||||
|
Q => bit_select(i),
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
R => Tx_start,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
count_lut: LUT2
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"8")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => bit_select(i),
|
||||||
|
I1 => Tx_run,
|
||||||
|
O => mask_count(i));
|
||||||
|
|
||||||
|
mask_and: MULT_AND
|
||||||
|
port map( I0 => bit_select(i),
|
||||||
|
I1 => Tx_run,
|
||||||
|
LO => mask_count_carry(i));
|
||||||
|
|
||||||
|
lsb_count: if i=0 generate
|
||||||
|
begin
|
||||||
|
|
||||||
|
count_muxcy: MUXCY
|
||||||
|
port map( DI => mask_count_carry(i),
|
||||||
|
CI => Tx_bit,
|
||||||
|
S => mask_count(i),
|
||||||
|
O => count_carry(i));
|
||||||
|
|
||||||
|
count_xor: XORCY
|
||||||
|
port map( LI => mask_count(i),
|
||||||
|
CI => Tx_bit,
|
||||||
|
O => next_count(i));
|
||||||
|
|
||||||
|
end generate lsb_count;
|
||||||
|
|
||||||
|
upper_count: if i>0 generate
|
||||||
|
begin
|
||||||
|
|
||||||
|
count_muxcy: MUXCY
|
||||||
|
port map( DI => mask_count_carry(i),
|
||||||
|
CI => count_carry(i-1),
|
||||||
|
S => mask_count(i),
|
||||||
|
O => count_carry(i));
|
||||||
|
|
||||||
|
count_xor: XORCY
|
||||||
|
port map( LI => mask_count(i),
|
||||||
|
CI => count_carry(i-1),
|
||||||
|
O => next_count(i));
|
||||||
|
|
||||||
|
end generate upper_count;
|
||||||
|
|
||||||
|
end generate count_width_loop;
|
||||||
|
|
||||||
|
-- Ready to start decode
|
||||||
|
|
||||||
|
ready_lut: LUT3
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"10")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => Tx_run,
|
||||||
|
I1 => Tx_start,
|
||||||
|
I2 => send_character,
|
||||||
|
O => ready_to_start );
|
||||||
|
|
||||||
|
-- Start bit enable
|
||||||
|
|
||||||
|
start_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0190")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => Tx_bit,
|
||||||
|
I1 => Tx_stop,
|
||||||
|
I2 => ready_to_start,
|
||||||
|
I3 => Tx_start,
|
||||||
|
O => decode_Tx_start );
|
||||||
|
|
||||||
|
Tx_start_reg: FDE
|
||||||
|
port map ( D => decode_Tx_start,
|
||||||
|
Q => Tx_start,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
|
||||||
|
-- Run bit enable
|
||||||
|
|
||||||
|
run_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"1540")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => count_carry(2),
|
||||||
|
I1 => Tx_bit,
|
||||||
|
I2 => Tx_start,
|
||||||
|
I3 => Tx_run,
|
||||||
|
O => decode_Tx_run );
|
||||||
|
|
||||||
|
Tx_run_reg: FDE
|
||||||
|
port map ( D => decode_Tx_run,
|
||||||
|
Q => Tx_run,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
-- Bit rate enable
|
||||||
|
|
||||||
|
hot_state_lut: LUT3
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"94")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => Tx_stop,
|
||||||
|
I1 => ready_to_start,
|
||||||
|
I2 => Tx_bit,
|
||||||
|
O => decode_hot_state );
|
||||||
|
|
||||||
|
hot_state_reg: FDE
|
||||||
|
port map ( D => decode_hot_state,
|
||||||
|
Q => hot_state,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
delay14_srl: SRL16E
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0000")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( D => hot_state,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
CLK => clk,
|
||||||
|
A0 => '1',
|
||||||
|
A1 => '0',
|
||||||
|
A2 => '1',
|
||||||
|
A3 => '1',
|
||||||
|
Q => hot_delay );
|
||||||
|
|
||||||
|
Tx_bit_reg: FDE
|
||||||
|
port map ( D => hot_delay,
|
||||||
|
Q => Tx_bit,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
-- Stop bit enable
|
||||||
|
|
||||||
|
stop_lut: LUT4
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"0180")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => Tx_bit,
|
||||||
|
I1 => Tx_run,
|
||||||
|
I2 => count_carry(2),
|
||||||
|
I3 => Tx_stop,
|
||||||
|
O => decode_Tx_stop );
|
||||||
|
|
||||||
|
Tx_stop_reg: FDE
|
||||||
|
port map ( D => decode_Tx_stop,
|
||||||
|
Q => Tx_stop,
|
||||||
|
CE => en_16_x_baud,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
-- Tx_complete strobe
|
||||||
|
|
||||||
|
complete_lut: LUT2
|
||||||
|
--synthesis translate_off
|
||||||
|
generic map (INIT => X"8")
|
||||||
|
--synthesis translate_on
|
||||||
|
port map( I0 => count_carry(2),
|
||||||
|
I1 => en_16_x_baud,
|
||||||
|
O => decode_Tx_complete );
|
||||||
|
|
||||||
|
Tx_complete_reg: FD
|
||||||
|
port map ( D => decode_Tx_complete,
|
||||||
|
Q => Tx_complete,
|
||||||
|
C => clk);
|
||||||
|
|
||||||
|
|
||||||
|
end low_level_definition;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- END OF FILE KCUART_TX.VHD
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
-- UART Receiver with integral 16 byte FIFO buffer
|
||||||
|
--
|
||||||
|
-- 8 bit, no parity, 1 stop bit
|
||||||
|
--
|
||||||
|
-- Version : 1.00
|
||||||
|
-- Version Date : 16th October 2002
|
||||||
|
--
|
||||||
|
-- Start of design entry : 16th October 2002
|
||||||
|
--
|
||||||
|
-- Ken Chapman
|
||||||
|
-- Xilinx Ltd
|
||||||
|
-- Benchmark House
|
||||||
|
-- 203 Brooklands Road
|
||||||
|
-- Weybridge
|
||||||
|
-- Surrey KT13 ORH
|
||||||
|
-- United Kingdom
|
||||||
|
--
|
||||||
|
-- chapman@xilinx.com
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- NOTICE:
|
||||||
|
--
|
||||||
|
-- Copyright Xilinx, Inc. 2002. This code may be contain portions patented by other
|
||||||
|
-- third parties. By providing this core as one possible implementation of a standard,
|
||||||
|
-- Xilinx is making no representation that the provided implementation of this standard
|
||||||
|
-- is free from any claims of infringement by any third party. Xilinx expressly
|
||||||
|
-- disclaims any warranty with respect to the adequacy of the implementation, including
|
||||||
|
-- but not limited to any warranty or representation that the implementation is free
|
||||||
|
-- from claims of any third party. Futhermore, Xilinx is providing this core as a
|
||||||
|
-- courtesy to you and suggests that you contact all third parties to obtain the
|
||||||
|
-- necessary rights to use this implementation.
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Library declarations
|
||||||
|
--
|
||||||
|
-- The Unisim Library is used to define Xilinx primitives. It is also used during
|
||||||
|
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
|
||||||
|
--
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||||
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||||
|
library unisim;
|
||||||
|
use unisim.vcomponents.all;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Main Entity for UART_RX
|
||||||
|
--
|
||||||
|
entity uart_rx is
|
||||||
|
Port ( serial_in : in std_logic;
|
||||||
|
data_out : out std_logic_vector(7 downto 0);
|
||||||
|
read_buffer : in std_logic;
|
||||||
|
reset_buffer : in std_logic;
|
||||||
|
en_16_x_baud : in std_logic;
|
||||||
|
buffer_data_present : out std_logic;
|
||||||
|
buffer_full : out std_logic;
|
||||||
|
buffer_half_full : out std_logic;
|
||||||
|
clk : in std_logic);
|
||||||
|
end uart_rx;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Start of Main Architecture for UART_RX
|
||||||
|
--
|
||||||
|
architecture macro_level_definition of uart_rx is
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Components used in UART_RX and defined in subsequent entities.
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Constant (K) Compact UART Receiver
|
||||||
|
--
|
||||||
|
component kcuart_rx
|
||||||
|
Port ( serial_in : in std_logic;
|
||||||
|
data_out : out std_logic_vector(7 downto 0);
|
||||||
|
data_strobe : out std_logic;
|
||||||
|
en_16_x_baud : in std_logic;
|
||||||
|
clk : in std_logic);
|
||||||
|
end component;
|
||||||
|
--
|
||||||
|
-- 'Bucket Brigade' FIFO
|
||||||
|
--
|
||||||
|
component bbfifo_16x8
|
||||||
|
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||||
|
data_out : out std_logic_vector(7 downto 0);
|
||||||
|
reset : in std_logic;
|
||||||
|
write : in std_logic;
|
||||||
|
read : in std_logic;
|
||||||
|
full : out std_logic;
|
||||||
|
half_full : out std_logic;
|
||||||
|
data_present : out std_logic;
|
||||||
|
clk : in std_logic);
|
||||||
|
end component;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Signals used in UART_RX
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
signal uart_data_out : std_logic_vector(7 downto 0);
|
||||||
|
signal fifo_write : std_logic;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Start of UART_RX circuit description
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
-- 8 to 1 multiplexer to convert parallel data to serial
|
||||||
|
|
||||||
|
kcuart: kcuart_rx
|
||||||
|
port map ( serial_in => serial_in,
|
||||||
|
data_out => uart_data_out,
|
||||||
|
data_strobe => fifo_write,
|
||||||
|
en_16_x_baud => en_16_x_baud,
|
||||||
|
clk => clk );
|
||||||
|
|
||||||
|
|
||||||
|
buf: bbfifo_16x8
|
||||||
|
port map ( data_in => uart_data_out,
|
||||||
|
data_out => data_out,
|
||||||
|
reset => reset_buffer,
|
||||||
|
write => fifo_write,
|
||||||
|
read => read_buffer,
|
||||||
|
full => buffer_full,
|
||||||
|
half_full => buffer_half_full,
|
||||||
|
data_present => buffer_data_present,
|
||||||
|
clk => clk);
|
||||||
|
|
||||||
|
end macro_level_definition;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- END OF FILE UART_RX.VHD
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
-- UART Transmitter with integral 16 byte FIFO buffer
|
||||||
|
--
|
||||||
|
-- 8 bit, no parity, 1 stop bit
|
||||||
|
--
|
||||||
|
-- Version : 1.00
|
||||||
|
-- Version Date : 14th October 2002
|
||||||
|
--
|
||||||
|
-- Start of design entry : 14th October 2002
|
||||||
|
--
|
||||||
|
-- Ken Chapman
|
||||||
|
-- Xilinx Ltd
|
||||||
|
-- Benchmark House
|
||||||
|
-- 203 Brooklands Road
|
||||||
|
-- Weybridge
|
||||||
|
-- Surrey KT13 ORH
|
||||||
|
-- United Kingdom
|
||||||
|
--
|
||||||
|
-- chapman@xilinx.com
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- NOTICE:
|
||||||
|
--
|
||||||
|
-- Copyright Xilinx, Inc. 2002. This code may be contain portions patented by other
|
||||||
|
-- third parties. By providing this core as one possible implementation of a standard,
|
||||||
|
-- Xilinx is making no representation that the provided implementation of this standard
|
||||||
|
-- is free from any claims of infringement by any third party. Xilinx expressly
|
||||||
|
-- disclaims any warranty with respect to the adequacy of the implementation, including
|
||||||
|
-- but not limited to any warranty or representation that the implementation is free
|
||||||
|
-- from claims of any third party. Futhermore, Xilinx is providing this core as a
|
||||||
|
-- courtesy to you and suggests that you contact all third parties to obtain the
|
||||||
|
-- necessary rights to use this implementation.
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Library declarations
|
||||||
|
--
|
||||||
|
-- The Unisim Library is used to define Xilinx primitives. It is also used during
|
||||||
|
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
|
||||||
|
--
|
||||||
|
library IEEE;
|
||||||
|
use IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||||
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||||
|
library unisim;
|
||||||
|
use unisim.vcomponents.all;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Main Entity for UART_TX
|
||||||
|
--
|
||||||
|
entity uart_tx is
|
||||||
|
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||||
|
write_buffer : in std_logic;
|
||||||
|
reset_buffer : in std_logic;
|
||||||
|
en_16_x_baud : in std_logic;
|
||||||
|
serial_out : out std_logic;
|
||||||
|
buffer_full : out std_logic;
|
||||||
|
buffer_half_full : out std_logic;
|
||||||
|
tx_complete : out std_logic;
|
||||||
|
tx_empty : out std_logic;
|
||||||
|
clk : in std_logic);
|
||||||
|
end uart_tx;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Start of Main Architecture for UART_TX
|
||||||
|
--
|
||||||
|
architecture macro_level_definition of uart_tx is
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Components used in UART_TX and defined in subsequent entities.
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Constant (K) Compact UART Transmitter
|
||||||
|
--
|
||||||
|
component kcuart_tx
|
||||||
|
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||||
|
send_character : in std_logic;
|
||||||
|
en_16_x_baud : in std_logic;
|
||||||
|
serial_out : out std_logic;
|
||||||
|
Tx_complete : out std_logic;
|
||||||
|
clk : in std_logic);
|
||||||
|
end component;
|
||||||
|
--
|
||||||
|
-- 'Bucket Brigade' FIFO
|
||||||
|
--
|
||||||
|
component bbfifo_16x8
|
||||||
|
Port ( data_in : in std_logic_vector(7 downto 0);
|
||||||
|
data_out : out std_logic_vector(7 downto 0);
|
||||||
|
reset : in std_logic;
|
||||||
|
write : in std_logic;
|
||||||
|
read : in std_logic;
|
||||||
|
full : out std_logic;
|
||||||
|
half_full : out std_logic;
|
||||||
|
data_present : out std_logic;
|
||||||
|
clk : in std_logic);
|
||||||
|
end component;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Signals used in UART_TX
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
signal fifo_data_out : std_logic_vector(7 downto 0);
|
||||||
|
signal fifo_data_present : std_logic;
|
||||||
|
signal fifo_read : std_logic;
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Start of UART_TX circuit description
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
begin
|
||||||
|
|
||||||
|
tx_complete <= fifo_read;
|
||||||
|
tx_empty <= not fifo_data_present;
|
||||||
|
|
||||||
|
-- 8 to 1 multiplexer to convert parallel data to serial
|
||||||
|
|
||||||
|
kcuart: kcuart_tx
|
||||||
|
port map ( data_in => fifo_data_out,
|
||||||
|
send_character => fifo_data_present,
|
||||||
|
en_16_x_baud => en_16_x_baud,
|
||||||
|
serial_out => serial_out,
|
||||||
|
Tx_complete => fifo_read,
|
||||||
|
clk => clk);
|
||||||
|
|
||||||
|
|
||||||
|
buf: bbfifo_16x8
|
||||||
|
port map ( data_in => data_in,
|
||||||
|
data_out => fifo_data_out,
|
||||||
|
reset => reset_buffer,
|
||||||
|
write => write_buffer,
|
||||||
|
read => fifo_read,
|
||||||
|
full => buffer_full,
|
||||||
|
half_full => buffer_half_full,
|
||||||
|
data_present => fifo_data_present,
|
||||||
|
clk => clk);
|
||||||
|
|
||||||
|
end macro_level_definition;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- END OF FILE UART_TX.VHD
|
||||||
|
--
|
||||||
|
------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
LIBRARY IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
use std.textio.all; -- Imports the standard textio package.
|
||||||
|
|
||||||
|
ENTITY uart_wb IS
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
simulate_tx : boolean := false
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
CLK_I : in STD_LOGIC;
|
||||||
|
RST_I : in STD_LOGIC;
|
||||||
|
INT_O : out STD_LOGIC;
|
||||||
|
CYC_I : in STD_LOGIC;
|
||||||
|
STB_I : in STD_LOGIC;
|
||||||
|
SEL_I : in unsigned(3 downto 0);
|
||||||
|
WE_I : in STD_LOGIC;
|
||||||
|
ACK_O : out STD_LOGIC;
|
||||||
|
SRDY_O : out STD_LOGIC;
|
||||||
|
MRDY_I : in STD_LOGIC;
|
||||||
|
ADDR_I : in unsigned(31 downto 0);
|
||||||
|
DAT_I : in unsigned(31 downto 0);
|
||||||
|
DAT_O : out unsigned(31 downto 0);
|
||||||
|
ser_rx : in std_logic;
|
||||||
|
ser_tx : out std_logic
|
||||||
|
);
|
||||||
|
END uart_wb;
|
||||||
|
|
||||||
|
ARCHITECTURE behavior OF uart_wb IS
|
||||||
|
|
||||||
|
COMPONENT uart_tx
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
data_in : in std_logic_vector(7 downto 0);
|
||||||
|
write_buffer : in std_logic;
|
||||||
|
reset_buffer : in std_logic;
|
||||||
|
en_16_x_baud : in std_logic;
|
||||||
|
serial_out : out std_logic;
|
||||||
|
buffer_full : out std_logic;
|
||||||
|
buffer_half_full : out std_logic;
|
||||||
|
tx_complete : out std_logic;
|
||||||
|
tx_empty : out std_logic;
|
||||||
|
clk : in std_logic
|
||||||
|
);
|
||||||
|
END COMPONENT;
|
||||||
|
|
||||||
|
COMPONENT uart_rx
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
serial_in : in std_logic;
|
||||||
|
data_out : out std_logic_vector(7 downto 0);
|
||||||
|
read_buffer : in std_logic;
|
||||||
|
reset_buffer : in std_logic;
|
||||||
|
en_16_x_baud : in std_logic;
|
||||||
|
buffer_data_present : out std_logic;
|
||||||
|
buffer_full : out std_logic;
|
||||||
|
buffer_half_full : out std_logic;
|
||||||
|
clk : in std_logic
|
||||||
|
);
|
||||||
|
END COMPONENT;
|
||||||
|
|
||||||
|
-- Signals for UART connections
|
||||||
|
signal baud_count : unsigned(15 downto 0);
|
||||||
|
signal en_16_x_baud : std_logic;
|
||||||
|
signal reg_we_uart_tx : std_logic;
|
||||||
|
signal tx_full : std_logic;
|
||||||
|
signal tx_half_full : std_logic;
|
||||||
|
signal reg_re_uart_rx : std_logic;
|
||||||
|
signal reg_uart_tx : unsigned(7 downto 0);
|
||||||
|
signal reg_uart_rx : std_logic_vector(7 downto 0);
|
||||||
|
signal rx_data_present : std_logic;
|
||||||
|
signal rx_full : std_logic;
|
||||||
|
signal rx_half_full : std_logic;
|
||||||
|
signal uart_status_port : unsigned(15 downto 0);
|
||||||
|
signal reg_uart_baud : unsigned(15 downto 0);
|
||||||
|
signal rx_int_en : std_logic;
|
||||||
|
signal tx_int_en : std_logic;
|
||||||
|
signal irq_rx : std_logic;
|
||||||
|
signal irq_tx : std_logic;
|
||||||
|
signal tx_complete : std_logic;
|
||||||
|
signal tx_empty : std_logic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
SRDY_O <= CYC_I;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
registers_write:
|
||||||
|
process(CLK_I)
|
||||||
|
file output: text open write_mode is "STD_OUTPUT";
|
||||||
|
variable L : line;
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
reg_we_uart_tx <= '0';
|
||||||
|
if RST_I = '1' then
|
||||||
|
reg_uart_baud <= to_unsigned(53, 16);
|
||||||
|
rx_int_en <= '0';
|
||||||
|
tx_int_en <= '0';
|
||||||
|
elsif (STB_I and CYC_I and WE_I) = '1' then
|
||||||
|
case ADDR_I(5 downto 2) is
|
||||||
|
|
||||||
|
when "0000" =>
|
||||||
|
if simulate_tx then
|
||||||
|
if DAT_I(7 downto 0) /= X"0D" then
|
||||||
|
write(L, character'val(to_integer(DAT_I(7 downto 0))));
|
||||||
|
end if;
|
||||||
|
if DAT_I(7 downto 0) = X"0A" then
|
||||||
|
writeline(output, L);
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
reg_we_uart_tx <= '1';
|
||||||
|
reg_uart_tx <= DAT_I(7 downto 0);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
when "0001" =>
|
||||||
|
rx_int_en <= DAT_I(6);
|
||||||
|
tx_int_en <= DAT_I(5);
|
||||||
|
|
||||||
|
when "0010" =>
|
||||||
|
reg_uart_baud <= DAT_I(15 downto 0);
|
||||||
|
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
registers_read:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
reg_re_uart_rx <= '0';
|
||||||
|
ACK_O <= '0';
|
||||||
|
if (STB_I and CYC_I) = '1' then
|
||||||
|
ACK_O <= not WE_I;
|
||||||
|
DAT_O <= (others => '0');
|
||||||
|
case ADDR_I(5 downto 2) is
|
||||||
|
|
||||||
|
when "0000" =>
|
||||||
|
reg_re_uart_rx <= not WE_I;
|
||||||
|
DAT_O(7 downto 0) <= unsigned(reg_uart_rx);
|
||||||
|
|
||||||
|
when "0001" =>
|
||||||
|
DAT_O(15 downto 0) <= uart_status_port;
|
||||||
|
|
||||||
|
when "0010" =>
|
||||||
|
DAT_O(15 downto 0) <= reg_uart_baud;
|
||||||
|
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
baud_timer:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
if RST_I = '1' then
|
||||||
|
baud_count <= (others => '0');
|
||||||
|
elsif baud_count = reg_uart_baud then
|
||||||
|
baud_count <= (others => '0');
|
||||||
|
en_16_x_baud <= '1';
|
||||||
|
else
|
||||||
|
baud_count <= baud_count + 1;
|
||||||
|
en_16_x_baud <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
irq_register:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
irq_tx <= tx_empty and tx_int_en;
|
||||||
|
irq_rx <= rx_data_present and rx_int_en;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
inst_uart_tx: uart_tx
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
data_in => std_logic_vector(reg_uart_tx),
|
||||||
|
write_buffer => reg_we_uart_tx,
|
||||||
|
reset_buffer => RST_I,
|
||||||
|
en_16_x_baud => en_16_x_baud,
|
||||||
|
serial_out => ser_tx,
|
||||||
|
buffer_full => tx_full,
|
||||||
|
buffer_half_full => tx_half_full,
|
||||||
|
tx_complete => tx_complete,
|
||||||
|
tx_empty => tx_empty,
|
||||||
|
clk => CLK_I
|
||||||
|
);
|
||||||
|
|
||||||
|
inst_uart_rx: uart_rx
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
serial_in => ser_rx,
|
||||||
|
data_out => reg_uart_rx,
|
||||||
|
read_buffer => reg_re_uart_rx,
|
||||||
|
reset_buffer => RST_I,
|
||||||
|
en_16_x_baud => en_16_x_baud,
|
||||||
|
buffer_data_present => rx_data_present,
|
||||||
|
buffer_full => rx_full,
|
||||||
|
buffer_half_full => rx_half_full,
|
||||||
|
clk => CLK_I
|
||||||
|
);
|
||||||
|
|
||||||
|
uart_status_port <= "000000" & irq_rx & irq_tx & '0' & rx_int_en & tx_int_en & rx_data_present & rx_full & rx_half_full & tx_full & tx_half_full;
|
||||||
|
INT_O <= irq_rx or irq_tx;
|
||||||
|
|
||||||
|
end behavior;
|
||||||
Reference in New Issue
Block a user