From d39aad126e4cbc5204458d393f4a6cc3221ec33d Mon Sep 17 00:00:00 2001 From: Gehstock Date: Fri, 21 Sep 2018 22:22:18 +0200 Subject: [PATCH] Add SG1000(Not Working) --- Sega - SG1000/Snapshot/sg1000_mist.rbf | Bin 0 -> 718569 bytes Sega - SG1000/clean.bat | 38 + Sega - SG1000/rtl/dpram.vhd | 130 ++ Sega - SG1000/rtl/psg/psg.vhd | 134 ++ Sega - SG1000/rtl/psg/psg_noise.vhd | 56 + Sega - SG1000/rtl/psg/psg_tone.vhd | 34 + Sega - SG1000/rtl/sg1000_top.sv | 116 ++ Sega - SG1000/rtl/spram.vhd | 90 + Sega - SG1000/rtl/sprom.vhd | 82 + Sega - SG1000/rtl/t80/T80.vhd | 1073 ++++++++++ Sega - SG1000/rtl/t80/T80_ALU.vhd | 351 ++++ Sega - SG1000/rtl/t80/T80_MCode.vhd | 1938 ++++++++++++++++++ Sega - SG1000/rtl/t80/T80_Pack.vhd | 208 ++ Sega - SG1000/rtl/t80/T80_Reg.vhd | 105 + Sega - SG1000/rtl/t80/T80a.vhd | 253 +++ Sega - SG1000/rtl/t80/T80se.vhd | 184 ++ Sega - SG1000/rtl/vdp/vdp.vhd | 296 +++ Sega - SG1000/rtl/vdp/vdp_background.vhd | 136 ++ Sega - SG1000/rtl/vdp/vdp_cram.vhd | 44 + Sega - SG1000/rtl/vdp/vdp_main.vhd | 135 ++ Sega - SG1000/rtl/vdp/vdp_sprite_shifter.vhd | 48 + Sega - SG1000/rtl/vdp/vdp_sprites.vhd | 188 ++ Sega - SG1000/rtl/vdp/vdp_vram.vhd | 44 + Sega - SG1000/rtl/vdp/vram.hex | 98 + Sega - SG1000/sg1000.qpf | 30 + Sega - SG1000/sg1000.qsf | 76 + Sega - SG1000/sgcpu.png | Bin 0 -> 8216 bytes Sega - SG1000/sgio.png | Bin 0 -> 3214 bytes Sega - SG1000/sgjoy.png | Bin 0 -> 3835 bytes Sega - SG1000/sgpsg.png | Bin 0 -> 2201 bytes Sega - SG1000/sgvdp.png | Bin 0 -> 8252 bytes 31 files changed, 5887 insertions(+) create mode 100644 Sega - SG1000/Snapshot/sg1000_mist.rbf create mode 100644 Sega - SG1000/clean.bat create mode 100644 Sega - SG1000/rtl/dpram.vhd create mode 100644 Sega - SG1000/rtl/psg/psg.vhd create mode 100644 Sega - SG1000/rtl/psg/psg_noise.vhd create mode 100644 Sega - SG1000/rtl/psg/psg_tone.vhd create mode 100644 Sega - SG1000/rtl/sg1000_top.sv create mode 100644 Sega - SG1000/rtl/spram.vhd create mode 100644 Sega - SG1000/rtl/sprom.vhd create mode 100644 Sega - SG1000/rtl/t80/T80.vhd create mode 100644 Sega - SG1000/rtl/t80/T80_ALU.vhd create mode 100644 Sega - SG1000/rtl/t80/T80_MCode.vhd create mode 100644 Sega - SG1000/rtl/t80/T80_Pack.vhd create mode 100644 Sega - SG1000/rtl/t80/T80_Reg.vhd create mode 100644 Sega - SG1000/rtl/t80/T80a.vhd create mode 100644 Sega - SG1000/rtl/t80/T80se.vhd create mode 100644 Sega - SG1000/rtl/vdp/vdp.vhd create mode 100644 Sega - SG1000/rtl/vdp/vdp_background.vhd create mode 100644 Sega - SG1000/rtl/vdp/vdp_cram.vhd create mode 100644 Sega - SG1000/rtl/vdp/vdp_main.vhd create mode 100644 Sega - SG1000/rtl/vdp/vdp_sprite_shifter.vhd create mode 100644 Sega - SG1000/rtl/vdp/vdp_sprites.vhd create mode 100644 Sega - SG1000/rtl/vdp/vdp_vram.vhd create mode 100644 Sega - SG1000/rtl/vdp/vram.hex create mode 100644 Sega - SG1000/sg1000.qpf create mode 100644 Sega - SG1000/sg1000.qsf create mode 100644 Sega - SG1000/sgcpu.png create mode 100644 Sega - SG1000/sgio.png create mode 100644 Sega - SG1000/sgjoy.png create mode 100644 Sega - SG1000/sgpsg.png create mode 100644 Sega - SG1000/sgvdp.png diff --git a/Sega - SG1000/Snapshot/sg1000_mist.rbf b/Sega - SG1000/Snapshot/sg1000_mist.rbf new file mode 100644 index 0000000000000000000000000000000000000000..d9efdb9e354b7a59dd3580f0bcf1e5abcd36fa25 GIT binary patch literal 718569 zcmeFa3%G4rRUWwZ=1|#Hxx%hX(K!^*%(_iECan}W7wH*<};Hz6pe0`tT zC~6F79$P(C5GawfXncSotwtrSBu3Q4_((%g@!1-UhS;rQheQLSL6B$v|3Ai;(BYutP09Pc^izvfzd?X~CG=l$>BO<(j5(VxEiPu~6RcmMI9zw^EC{PTCd z>s{}C=lkCG{&&6SJ@0()d(gb^UGIC>yFTHMb|<>wtsQ6$s(bPiT^a&=PIYwXE~jU{ z1*q=pG5UOr#Te2(puYhMJ^LqvsOuB;HPv?JA+4NZTpOirX^Zj5*L9q8iaKJvdaU5X z7CrSbe$>MJHAN-Vk+18Zj`7SFdX^J>-Pd&v`7qZu;<(#vp^v%5Ie1)5*k1sO9Cgn; zq#--?^d0Is=Q@V?&^N{lzLu#QqVQo)+T{~i5BX4c2zncceAGn#N>Uu>7=z=ILT0a% zz#Fq3-^N-E&&X#eSsOa`H8wnEjN^Ja0!59K7o<7tC7OaDE^c;^eaiI@;$`3fvj}&!8 zPc!q!d^rx~K1E#-M>~BZC+B<-#5%&K?x`oykHq!y383&{tuf}jqNs~_k!YeH$NFi| z*MeRFdNJr{LB9c_o@24^6ZLNbu_wj&?C%97r>G@*s>%No5HY(0#M&6c`GlS}%5QWc z9~8Qw{;55BDJU?n`>2Q5lW3!k^%GMm(XbB69J}s6&51e^?R7o9GM>5*s>dh)L!jG1 z9JjWyW)k%z<|oEnBP1Rp${h3GfY?*+Q`AE{iF2##Vom2k96S1^TPeK2cxOCxgBW#Cmw#xgKMTq5d&WVdEVB7tntTqUmKI${d5&w&=;%^ghsA zK(v!M{xd6jJm^A2tg#X=yax2WppO7i|Ir}I#DhdU*#88G$B($M=XpXsabeGT=^I2m zcpkDI64zdJ>drY9<>*<*{h;vq3=r2r)c2F1{}04Da?I#?>}sOECL6u9F;6W*Z&*Xn z4?2ZRD2Z?ASqJ67J^Fe~^3)Tnpi+TxJnlm^gzoD>95d?RabwP?gFWTrD8`SzK3B-c zc-#6IFYK(oj|Xd@F6g+LXz$nYC{UaW>>mP(G1+sCkwW*Spjd;{bKOz?BM|$yg4q8@ z5PQB4W=}im^`JiiF(2LqzlXXn2YoImdal_Rk3DOyYkWS4V}}oIl!JKPk828bTo;sC z2Yc4^&q2Iq(w9BYGtRB1kL*#uj_(BV{EOQ7dKBkjzh@2K;6$FpxrdH5{68S({6G-# zAUz%Q2q%_P^HCmaAhC|yK&;P!u(NjNqK-Bm8;)AnP}jxdLVKU0 z4qjhL@qUHJJ+7bZd9CAX;0J+j0`Xcxnb+oLfc_g0UvGGg{Ynte%fAO=4WClc{|chW z>nv?iSJXj#$;bJ^wGrnp>tJ2HABy|rxIg+F5bvLV1VkIJd6fSHi2Zv(e*k(rh&`|S zq`-sqvL234Vm{Up=VSDtV=bgOCu+QS|H0$(9UvYX%Iqos4yf+q7}B2<>&mJqEng>j zF7WuXmZ*a|%EXIAK8W%Gh{u%o>YoJq0TAssgSd8iI&nQxein%LJUo}!KNiG#=*QZ) z=15T$&r6QaW5k|%_BlIbM1Y(cpi|_t65Km#sfgN!pam|rb z44Nl^cz$whQq;lsxs>CY!DCd{K|RNhI(XfB5r}Jo`Zt3pzX8Oa81P!gdg#mZme;bN zZv+vGxK^+}@~nXr_h~$DOk=ta0P*;+j=EM_3l<60*rR-S;?=7PLtDtzT zXCL<|tcC06M?wD>6j*RA@m%2R2iF;oInPgyALj`BK5^}G?a+_JJggz;RUnQRL_C6L z&*S#Nps0&IWxhuvah~j74&qwl`N=-sb4E|Unx5pudPux~<~1aU$A}d2!$FS&nf4Kn z;PL!y5OpLTbIKf__tDXR7Kn0?p-@^Iy|f&MV+QW*qXza|Kcvuc8ovgT5)JF1%-7Vq z|CJu`n#UT0cwH}5tX5ombq&0pl0ru;dHpo)Y(_kolWU%O_LTd?x@wB?qvtuxb2BK$ z>-XOd`aDpr=a{4+9rZCT`IAtcZ{jBeCIlt~#v;J$AFr!p{d<1vp1ecMk1RXCa6_TT zlRIKYnpRzxM!Lc+zebD?p{LdV%8x!-)P{F~VZ(G|Dc$ohy)4sOPS0}o*U&7J;-EWsa0;dLD|ewY1#|}QtwJoaIS907?$ukrG-~6ra(Jip=oK=h-*C7 zgCgO_Xl-|S$whQ~cH3u~ul|l=xJ=ILwYU zR}dnEEIv75N%w{E=e z_?k-`@iM1;+{rg=UtMCc+rx&(8S;O`pABgr1l^T*={VhKeE6lMyUZmuFlY~|;e)*z z2)r!S@GwIuzx}TaX(!z#0>{1YvxxD?Z;o)IXukKAH_A+|^gOtxdRGVxxvA;baaz}@ z<43~Csf=E+MH$?3RJQQ8e)Q?`gx_leud;OFsihqSUJ6h<()CQQe#6iL8Zm*>T2#Gy zHbortL~YcxqHuaNdQCm+HK#Y|gOllM9kK`h{ev^VD>&+L&{g(|J+`37{pztU*SJG} zwtcz&5T!qr4d1>)CI9J*DxqOhBVB?p`U=p?9T%jYdPqFUO#9_1w)(JaD1WVc`~O@^ zXNf-v%EaX*ufHbIIq5X6!X%#eo~?tVt(I|y{&F7|Rc;4H_@4;Sp?Xem_I>pKIijHJ z)8#}k9zVs;{w(^ek9R!V9<#3dy`Q^rA=t90wy2N8;m!ZYaUM6c{RF5z_XBQdBu;U1 zJHxFYoQi(-HE+G~)woHOe(#p;Ln%-^i02iA{5DWU*;%)N-pm zmq)?#RW#^#EO`*-AYLp0;oNbxG%nCbsd`u4Xmp4YBV%(&kVSL`PYE>ht??AOx+@En@9-hoNuM+!9FDd->%Eg?c-#w4;I_a8v^V@gly&kM(?qjMg-ocHD z>be^Nss2n)hCn}hoBW~=-mt_akA`xOAh-EST{OB;2%*s}I+a?!P~Vu_%<@$7 zHg|p3CEg7t5dJ0h4zF9~je}IoBzn&Cl8@S3@vXVbZvLdZQ^KNEZ}Q(p2TC!{8% z#v(A*Z(36mQezPq>t}0f-MaV0)_6vw-u)+b1vS4jIzhC39X#%zHns_>298=dz%J|Q z?M#ix0FN_q*8P_cYb|UW_GhD#!k9$Tsa>)P77LabxdZjD>Th`^UcON{?`(z?z73WW)w3JhmsQFZ^~9h=5UGlanOZe|FTA>D-35Gq5uQ$Z@9 z%Nil?_Zu4TTGOpZ7xbFV-|rh8d$t@;Wlfz4$W8;P`s7;!wd?8hW4+_(37;~~Z}PG= zwVr@D7J(nW`B<09K?t12b?R(DIUzOnI8R7TNR35ctRL6ZdaU!A_M4s#k3Ia;ni`AL zw5G-)rPsdoSnsp!_we5L6ur22?#lLwGGm3>*Kvk&fC$};Uy$`=m3Tbq{;tNn_5c|G@p!NGR&tu8|>I z-L8k74FC7nZ!Lc^GzeV!nrhOV0bxRF>_MK8nvfccz*xU&O-)FRMPRJow5Cpm)OxJ@ zS@oMfaX7(|pU%FqU``~em-;uK20YX5#cfCY?Z48u1ZI8x*_G`#J)i%F(-)tPTLaVIaTtZu z^ekZ%Oy)Gbn;8q%gw$mqRey{=efMGpa@xI^p&)b2?#0HJTl5M|Ybs;GHMQ)%_DR!U zj!wX2*Y3q{`o0X>#Oy@ihIs9(uNOOKdpX8C7KmP72al*$mov*th_yF+IdImkzds8N zvu>mZUszq`5_&*k^jAN+E@52@Lwp)iUMsrcJ&>n$YJTspUn}#x*6SF)qOY&@vLA%{ ze(*;hgh8*%A&1x0_Nk-+Q(XPl1GZ~Qby)>|?^CX+xm?4=oODfH!&AA!rJWS1G*pkD ze(NFIHKe<|`rh=|YiKIhbSbu`E)VT%dV;4`-1OaxW1&3hb!u$h8_#b-YV0wckeZMh zi@;dFX-!Q?jYVLr-@uw$kBvQBe!sXm-3h5pOrQ}`4K|H17;`q2zw?}S-g@fnkDjOR zUaYa1zI(AoV;9dWdhg@D^)COjYx~?+a_;N13&6OU;|bjK-HYR(>bimZsj;DF%x^+! z>;WG@s{VL-+G&=7oOUl}D99W&QX@=AHE?W4YW7thJ?&l`_uY%r?!{(JZ5L+W{13Mq zCrgchUi*4)XKMSz8v?WLSKhLL#dxQ1*DNgP**VHMNbq%IEO{CV>;QUUnr0MJ%i>0lp8+$d3 z#bSrw^ohd`aQddxyiWCV-&pd5)Y#)WAvGa27J;#TTvO|@&S%+g`kuVeM}JyVBcYns z)JULw2glmny&D~SmKc?Kib>ppz_g|YfEip=AHN>(yj)c~Qt$cmu(0%QHAH8mkM7J;#T)0*0bRR7)UH~&oQIqhC-@hH-?d$C}# zo14zQZTK8__HBzh<9fh$)AU_IBNxGR_KgH;`j*PEKn)=^?Oq&2Z`!@sz;ev)#m0B~ z%h5eJLgbp7b}!Cf|GJa_$#J_E1GTB&g}`)|unV2qHX&7`v7MiF&*(i%*zSAQEz_DB zy8P z5B_wWnvfccz*xU&O-)FRMPRHS*VKBf^I7(rz9(<=(Vy1TNT{YYH4>=yyB9|Xok7Q0 z_pleX)1G!Ows;h2+Pzq?*v(CMp1biWRzqrC6caau!1OF(2$e0m>FnDA%!YbGY6Frj ziUFji-HU@*O}iHxSdQ7fxNe-M?_O--aA|h<)6?$7aep~_`tHTS6||`w@ho9)GwMug zzUezK?e&?Q`iUmJ`7Gf?;b+Qu;C|{P^FKqU=9~ZGNq{-azL&YC&Jc7HQezMHgw%x8 zSOmuUO>1gGYAga{{iZcFAvG3(QGWQuVfwy=QAojQI{PN1#v(A*Z(36mQezPq>o={b zkx0$HdHSxPkx)%*Y9vt8ni>hzbU!r~sLk(7n07C2!*1HWxDA=Ue!8Of5!ohBNNq!= z(NE738aQ?f)0*0iPq9u&6)bjh14vD~7Y8Amb}u%t9J70|@twYVu?L5Xv#`OE|Mo96Rx8O&tr7J4{GTNR35ctlzYzCZxt9 zFxGEcQxj5S5g6+?t*HsAu?URyo7U7Qq^3_CM!{rG)0!F!)`ZlA)K~<@`b}$ULTW4m zBmJhQ!y|#3cAAX_YFbmHp_;DfK+2q+1CSPt2iOG6`GzwNaa^|883DB;tihVk>`QV4L-+9{*J^3 z7b3N8G^dmI#>?{AZ^rJ$y@x&N?v(cT_ikdpP=9#1SRCDd@$M!1`=0;IdzVY}_g!Fr z3;)hC`zNV?;KhtuE|1jj?;qW7S=e8%SuU<@M(jBw^hduveNA5P(!E7|?5nmICUp-1 zz4onp%1InR;NiCqC@0kb0@I!604Rg138_I?29y(01E375CZq;o8Bk704S+JJnvfcV zWk5M0H2}(>YC>udmI392)Bq@hDnn{LXq%KZ0@EiBH5$A4>FnEuPHmfzs?pfRPe|=T zr?yQ<)oASEC!}_vQ`;t_YBYB76H>d-scl4RT`MMj3j+FVW`b%9Icu7Ros7 zUJQ&HT&CTN0gL+fyB9Z*nszT{w00mh?Oq(*k2&pL%!}vb%<1o5oRuQxg}wf{&;DS{ zVSWA2kj z6Tk0y>!xnf3?VR`eM6`W=_aIxP#Mx0QtKhpq-zkEK5=N^*da`3-wtpZ(}Yw5#|~ja zY6m!tX+o-jV~0Sb);sKzDG)gQr^Au?M(d|FHTH;3YicY~x}vYgdY@&#Y4_rM6~|v6 zAm>k!^-+8NynWeCyB7neNteLZb+>|ocdt|@G0Ey{oJr=()JOU&b~e(+vEwU zZOHWXLMp!&$~x^{43HXJrrnDHi~4*wC20exY4>7AYdcc2?>LygdvV~~B&XerdGVZ> znZ5B@CyqIz0ebCQpV7&mVA`|pVJ|#^`u(0%QHAH8mkM7J;#T)0&!)8jHYKziCZPNR35ctlzYzCZxt9FxGEcQxj5S5g6;Y zv8JZaMFYC#)4p!`w7(sOso#yj#+usgeuk|RQezMPgw%x8SOmuUO>1gGYAga{{iZc_ zg^_CS%0>;AL&#)dMCeI;N2I${mw)y_ml}ELaR${8U|T>jbr_?+^a3s^@{2B9QrM*g zl^HIurixVM8dUlU%(l!_fmeaO^PyK^kZnWwoMY}4b6MI?NS76UX~F#&_vD_qV~p{hTauh0!K1!$OO6LYeS)$dgzBFD zysJJa0BJD^Df+6SP_bWxP}#2{`vuy8y}oKAYPM*6*4rjuJXjgMkj_|Lsc<7^#9XxRKmpfJK^>qwVrc*@UQW`dK2Z@<w{ifP+wD5xE*&BZS9;)c@vpJV*l%uaY5XTsLI8nzjGO zpSniA*QEeaxFH~RTZbY}M>jiouttvhj~%}_6fT0VX8-t4y!vYjGv=i2CpgGt{Tf!; zz}l0CEzchmbmg1b&%Nc!4^oZbb5cb=8_Yfy|s}Xvg zue!=-Un$2YouMn1o!m+NcP2ZD@q@1Jvjp8csXkv*xbSH15GxEqiay^*RX!(~Q`6@W|?VX0@3Wrmf(U*J}(p`bPb~EIq zR&(S~^A(!1hI(^sipg_?mRU-aWkDjRUY1a+&siWjD1 zAQU09r;Zf8NmsG`k$=5ou)Q6&OEdXA)v+;o)Dr@@DncO^=QYUEXrj0si3j~7Zm9pp z-+^{d|Ax#%x)Ecz%OKKwCEmCq=LI8`>nn3rO=trP-CTy!{Ti_rDxPfoRO$OHTz=*I zpd?b`iHR?f6pDs@{D_sobWAO=r-RZoXoJnZZlYYM&Qd${^^KgvrFDt?i+?1WYUU)! zl?i%=_EJ@km|Yts1j$($O!PTS1L#$7z*JP`R?o+H^Qiqopo<5HZ8GJ3~0jRKsE#bt{GG zIIY{&)qKRWAI?#Gn9CNwE$R~gnSZnJ$8yJJJ1)bP1Y6XWZKshgl|#kW>f_34-p&s> zGw;hD)w7(&GU}!5i+MhoX{O6Lh9!EW7-rktm5&=XHEqO(G#mi!!L#Xm6jvt4>59Uo zT5>`5GM2@S%4>uKmxcENdZJ|+RBjGX4uS=sEs^3D_@uFW;xlsSUf>gbwwyNOg_L?Y zK&|xpY}`iJC}l87&#O*dnW&C%=R-8FMtaXjK{*7?kggi#64@Br3(JKLRMsCMLW&-m z$XApVx6@ep4Q469&b{sD>yTm4T8}FtmAabrThyA`Hd~XR2qWEx-Kc%h-6a_~uB0oo znl#L29n@6XidDcs<1X2AlNkugs_dOL4Kr+(_T%{3jOYpi6hp9&JM8?t$&1T1W~Pej z>3U-2$N_eWt#O;w%OST{yrTceA8LShm2guHR@YE4Am0YG};YO8QA=t&$PQKfAFF^ z1um&8w5E9E?C9Y>Dr${Bin7u}%ic7>K(c6=!XABOsiIuf_XwH2h5%!?cV$4+!*KIQ zejdCG76Mc-GM$fcYF)0StJ{Mfpzo%#^^RQ+Rc|3tlNBUs*8S#R zm+_ohoPv5#<4uvRo(3fuI<> z={M5I`VBho)-6;UuBWJo0~c$`QwM@$M^f={wmzh>(XC&J4lW-7jzHzC>puDMiV{+> zkfLw%otmU_aGA2Q{CX8N+9<75jhv^DnVkWiC!Bj}LyR7&Dz=Pj;miL3&DFh5HFL{L zERc%=t>!$({uIm*(GE9fT07Rf^7a&-y=V&;Ww1B5fB&cCH%`7QxvW%9UQ>P?D_ON! z&1l`*`#_FGgQ{~jvYNrHKF9Ft1y`P#wPCYZGynC+AuSrH{2oDGm+nUAqK!&&OUaRp#e@vGCjD~Ab zvf0ml&$N5-B)b>)%K4U0yy^&@8jGW&1H@j8^<+aPtN-nwL%P=Eq*66LL#y$XDa?^} z_VVFR+rxg9`@s+DuW}9BhWnJ8v7FXeQ)MktxH5#}rnTW$a}HvM&JUoE+CQ99_m6pw zjT|0aI;Lq8%O(}G4cJO>pPO}$e^u56LeXc#X)#_Ms+{+$?8_Q5D>JjT68ESb#cwE( zA#~AiP1+jn;(|Zf{;4*>E@|Lo+9(f-A)RR}ORU49%B!rXhKi}J!J`j$C}dFgbpKAX z1nZg}Yy8dyD6Q49F~w$^WV~ukz0?a|xa#_Wnu>m<3ZsQytjRFR(Y)ENpqQ!cRx=v$ z-k7x7d*Lg@;8%HYd$>2hhth1Bc%!lCUP__6utIlqYj=RIo3Dn1%?9Sia zeK&2LWjX3Tfx>Kg!LqzW<6T&xLzcvYi7foAKh2*?&klmJ93@JNWkM}S^Ti4RYC(6= zYI(?(TB3vhYc5274wwt5L5X^{F_AoUVJ{!puKed}Jr zBo;TV*4^H$JD3CfEy&V6bdOoO zD9ar)huH>l0C%9U(!J4TJ`w>%<^unWOrU22q#usOt#S-Nb<41+0zLa&xN zV`#HN%p3nvE02?gbB&AL^cu_t<;L=9LIkG*LyPkr`9Ao^ejV;*GXh}t$?HZ@yk@r<`_HH|ZzV5}Vp znPq#XutdKj5lusGL%L(q^vv(q6@A^)4vKNkR7Q>876GYM^xVT3?{7n{+`#%ZUdHf1 zZ*nMdNTVo1aM9D>_*#>*>|$nJck9>hayZU5I3ksU2Gh$FcJ#qkW7VqQ`+ac_OVN;P zwXM{8j+CDLts@<`x{WR(J7&gn_T{ZZ6$3-`Q^gLfQdld8%-6b-^BC@}!&mfUqGZ0L z@pdNO$auV>%?JNF#Chv#LmM?t`nt!C^HT|V$TDi-JkP+@tg`goYq{{?C`b|7P=w5+ zHNPp+gVgids*_=R^I89HyKTTSH0q`s(W0k&*FoUJBDKk`-OQvUtyN)>dN5)@8OJaB z0hi-c|ME}lNy~A5R$n{KT4(X0ffQGb9doL@2ZrBm9SG>Fwj|i1?nn3K*>k_RuR1;X z5^EY!05g{#aQ6S0NJfyv!_>r=)P@h+tc~o*!f?IP0 z^Dr;7Mx+F0^ndPQPM(c6lEp-Xd78x?M|88lg0pWVZH$LF*58gPFV}{}`l@b@7{-`~ z$9OTch9*2irX~KlyS!=7KF)<-^ct476O%Rzug8St4L22|xR6^RYojc$E{j`aE9E#Z z&t45;>7)>g27__H(x=g2E8WZ4JEmlAEagX{^wD9N|f^s<>TBz?gL3>#>V1IRF! z!kegYkE}Vp86rCRaO(}0v$RaRsJbuzxYm5-q#jZ}P@Y6@VAI=5qbZ_YpON!;$DNKP zk*&<4f=SlOr8pnU{op^Q%lcTq%XhH3M)i3{UUtF6N3uEj+RE0l5}P?g@I1Tf9O1Gp z9P8_A?$~DB(Dw%NN%Y;aS7yRPidgu05e%luv3(|xE33mivR{o@D62l$sObd#WB>M8 z=RC(ex6srXiY~b5%?rU+Z3PuAS?_MvVczmaj7LSV>$96P?$%RV5NtU*+)vOy8T+Tk zkq?*Wl&gNh=zLXpaCluNc|9k~Qr4Ddv0NDm%a*^L1|n;zhMKQDf}MZUY}TBt zmK+u{az&HnEBMV4jmGX^+_ypMMBiEJcQDFRXTe68RTpp?4-#@zFvar8ivs_%+jM#HV=#TJsvDP(o zTlhFg-uG8PsN3jXP;0z&327tqF-b z8$a1%2}&Aps0{z`K#V*ibR(DVF6hf25$y5`xz|TfPwnEv{>HF=NSjAIu`vR6Wsq&a z!Bt_2K2r93*?TdSkI-my>;@>ue(o=4b{Es;9`bBG8Yv4p<|b9FXOlj=Y9T-)|H1m>uzAXT{9?)+>1bynhf-pi3qm&oW9Li11pd@Y|1;i~xU znLKJR(U)P1h8%t@g{cKa!9z+-+I@Xg%}$|P=2-z%u~Ed+?+NY-_Nx8(LYHas+Hr?f{{7Z3R_=Cn46?bq(-=6)qhA zhTnX8T69c#CmyEB=h4!Y23q&>4^gW@^20=V_@r@@nvZbhdp!Fgr}Q_rz1-sl+;nR+ zjj%OW_9{z?syO}u-9S9tsu#s@$bq34>>u@*LG^|bW8?y9?8_Sg+Z9coVYlp(8S|r9 zslZCgs>}?hE!qGl`eND2J?8IjHCJS1+n|oqg!rde$o}R%m2oYF%&m z%2crps5!zMVs_}8i0lUS7DI6v;_mp#A?t{3WMEDhqbyXDH>L#ad8B%snilaG()g<7Q#*^m7aOAEBm9;r;ChD4o; zSo#;GWplN1%+=dkKkFX%{Zi*?$?7ipxK#~(7PqX>&e51Nb`09S!yYEIGJzI2ddsp% z2G!!0d*Co%!5}(ftH$KIEm^R8agmTJ|AqVEEM9k=! z@^MFI`Sgc{-*LUowDO89I#MA7j_8XDK{{C&Ebl7IF>GXMk}-)Z8vP(r8o(_URW>{9 z9y~8Px&6{5{%$*hz1pZbkJ=PpwC0zmmwJ$g+=Rgp2D zPoe1bJ^x&uGa*OcMn`ZD5jaJ7#8tgs|CpyeZ6XNswzRgUic{ejT&UH5)jNu1G^gsS z#Szsu31YIY44)iU6!Pe~H>u)8hti@VwuhTTg_l092E52w8gZ>sJeM^v*2V2xh)gv{aF$#Ret|$hAOJEv9CxEG7aW zeG}&rKotkBL`jApLMSndM?vc5D>Q|g`<3#+7#)89&1kAfNVz)j6;d2^zJksPqVl4* zcxxkBKTEML=Bvn|zNs#z>K;)nS0HLZ63^qm5aKfK#&>4P06(SCPt@XD^m2DuVBya{*9_sk;Y|#+k6G@LTz>9vf!}IS4dI3nWY?^qKCTZp`LYz z0YBa6D>Q|+*E0KJJV&2)FK+C|yto?Ny;vZUvyL4b6@*K~5+4A_|6rNB z=VD?{xieY4N)#8tJ5ueK+N^uYAMG%ozA4H@=3^?ZJj)px1=Yry4|`n1Y3tif?rTfr zHtsFoW|k34YDe-NrZO;J>8|ISZ;m7xSii_isU6QHMilZJsZq7C-ijv%`KBri>bNMTrS&T!awZTQj zH2jW0fdhW-NI^fRK)aCgw_)%*$A|sY8)??SXz4)BHH57>%kPf85NH|7J4vO`odLPU zGS*a>e6)Rs66yp$5c9X6{<*RT-}3L;L4-9X%J3c$1x;9$?!`SWN2f+w^s1JjU>vwG zSvb^GgrD_t&VCGUNhZXhue@x6($c+}E1eQ`M(%=9&gFq&!C^>rh*~VS4**NPG`MQf z{nrnrKWPh6rml@Rw=CR~Sa{Xu(QSCMAj39)IP5T0iF<6Rq7JY5IsgTruv{CT%h#l^ z5?eTP!n>!7wfit{hoy?GSj{oyTt+@cn}iwe`pj!Qh6MjCs&{2~&%CIbH?u=&s@lx# ziVb}m98<$}>SJ5WR>`JW0=GJv0Vj0^h8hoS=WA8k3T?cHlUok7WHLsBzA3boo0mXK z#fD?mC-Hp<-}D!t-d!cFJr8AJgV#8Ac+oeHCjDFWU$ zd>y26cv8dK;vIFw>J2&Kl8xsrtzl^lwQ$etDXnXj^DRI1J73Z1Fc*wKN8Y7jd#R*jnZ;0XZ1tO8r08^rvB0*Dm z1m-ZM@N5FA5fJ@NUgI_wK~UpR^G&Kv!EPk+J0D7(XV5qXMA0`!2_>#@Q7w9B&1ORO zOWAB`%X!$pNAO`0u#FZkf8sV%ttUJMqNua-U~zCzho<;eJ`I~^BWCm6jXTSleVYsr ztdQykAw2ElEUqzXn7vrKWV)g`D9h9`CLhQrYTd`Y8d^=v)$T;)=6tD%9~&wA+-8>B zusHN?k3GD(R`d$jE*eU=*oa|(7jEyM$JBJo&9eimfGs+kjRsYmPt+As)p}$}3@3pJ zN>F87piddX@QB_*DUrj^ovW@}gWXCQ3V77~)_?(n&k7dK8{~T^tY*|+0Fb%Yz$yn% zv%%wXhYOxt;hPx0TpTKmS{oG}K*~=+I`M}TcqQ>E>uEDWf=3;MFwpN2nxVB-d|96X zI0&P@TrRxn3v#qfh*op43Dv4vV`rJ7mC4ij!tp499~RSjj!?3XA3ER?1h%l=tE({;Zgv@ZFmDsyWN5E^y7K7)H4ISkzD2{FFgFWFL16! z?W!CC6ud_T!`j(chuwza<*(B)R*-O^lU61C@eIM1SL*O-m1W>(?g-^`C_ajUc6kUc zm0PLbx6Z0z~4hgM~6M!bin+P*}*ayG!HnPx5d~ z4i4wU^PYq4C+KmWE%|ZlUG#uLf2IjNR8WXiFS*6}C!;+Q>o)REzMf)TMZch4M-hI@ zrFpSu2J|=SZA{nQG=~IiaIKa%mP>32K!1x?9eNH{WV@(i*D92#Peqj|n?R9^-NvSz z4y?9xU|FzIv_FvFoI*To_hLG<-3jQmohre??C9-NdX0?6KC+*6|2xXTyrqV#u(t+( zjtPJNsl#X7fC4Vv{K(j+V>YZX;Ct-b)5Vp!3~L=a>8YNH9Nt zYj!b>jtbfZx4Z(BPC})t~mL0dLbFoF&d3!qX?oVrGtbXr`BO2QbdThbO^9T zT9OIp7-E5oynrigKxzOei+cP^tsia!BE!fo@yu7eRWc9+K2la|YK}DpgRcTPa;7#l zt{GuutAbuwQy>F*VQUJ`aF3(H-iFp(p*Jrg$WZygfghBk?G6u#H|CyXr3yqFMoZWi zE8oMUlH5vn>Nn|Q-$mVe)6i&QF*QmPFfOea-<@u|jjM-rlhnK**-X4j*|0CpE>O1% zFTlh#MN;g-)|AbGmu_0Lrfe3DKeZq@I3px+>5+KoXP++<#h72g0=8s2>nIkhS?;4YkbQKA-$hO)HbK*4~qmSd3EdzIx(q6@EIa>eKt z0%d}4tTkD2>jX8j0QMTG6!~ejxROPMN&gY=MVGTnRR_+LJwr8L(Zj37JpzQ{?VkhE z0|Y&x(lzEGR-=#r2=f)}Tte*Pd-D8(ZnZ=~d_R{-wU|tN=POkLh2UW=#&Kw!bMe_)4&ih65P^AVVq?-F!thyDKj>qEPSYqhr1^;eWW# z4JiqdS5ya5w^$aOgmSQRGIIHh>2I}|f$e;SrVz4lwU97@h&Ox8h*!S~Z+gvFbjj|$ z8JXVNkHY7D>y6dGXwsgqsXZ6xD`UL%yl&l+1>@9sL!7S=pAVc?CKdSE=;G+pyUqf~ z`3j9k!Od#%B%yYo11Sd7NI{&h(8SnzeNzXDY~*L3|5tGgrterLpUd+Dt z-HSDRgm5eQ<+{Czii762pB@Y?ms?zA!zrKMp@@EXOtOf82dyZPfuncSSs0kv8$OxxDN|gLPC4y^o9^3x0OPM!LxwL`E?TwX*4$Y+7m@p>l)Q~AeDF6HgMRqRm=^2nc))YM=Iggh|L}0uKhTKa8v4B&! zO|MGBsTG1`|6_qP=6pr-fW+5X_wX>Ya0*pqYDM!Y?c2Y$@XnQB>>tx?1C?-v(wx}# z@qi4d&>9FO8+=P5a&+KN;{w?z&n^_v*X|`DbKAQ`-HTU-%>j@>Ns>|m$G91RtTh%x zu}}J0bl>$gl$@9zFJIhXH$-~InvYMwwOHy|r-y(i$E!j>NZI(ZZ_m%!GN0ulvP2l7 z%&aw1S5)&A_#QxO@d(a)e@6qC%7+puszDETi;!+cVx+-eG zbt}P|fGnqEUUqdm;P43(=NKf<0@uga-)Tm3hDwg5QE0>$b)RcIP&Vw1%2$kZjRAfp zyGNTi=GZ`#@7(8#$%)-Br?vO_xfVPz z36pejXKs%@wWy?L6G7;M4JPF1eN^wLEf#Pwr0I*P4XdQ=B8EVO(Uz0|=*>C1xT_s& z39or|gg3QlS(*jG9$#v81v>xsQdg8*nX{m5&rEjE0lK+};CS|l=4{?Yech_Lbk}H7P<6Z`UBER(if%!Rm4z5lhQs!V`U1WvS1~ zeDUaw9m8UTh}F2%<0oq~(~HkyB;w11zI`JUOq9Y+j4pmO=eq_B9WKxR-|#sUup)U1 zc7jz(O|q&ryxho+);hpu0ySn4Wf73zgUK?J$XsbGQVKR=>M|G;JK$Ji z0akP_;4+=Oya4c(7)3{Q<{#QBBUv~VKXKt$)E**5Xrnhh;>hP=9O%q z2!WJh1Ui{ez4d|a3*Kol+`pnYyuRr^8V{E&KUPRNta7f#m5izuc}tm$_9BV69$-UxnS10QcM=n`m#cQK9j=SLbY2#ZoTDyDi{_@|-ntF+3 zXR8m3hwCS=A(f5d?V=TGU>z)7o!1i6AUUZINtu_<(3|YW+=Vv0FdbVk@+c=BE5(lr zwwwn!N5i;dqicjjDGx^mn%TF$h3Yl0DI8zpP-D~dt2-5DTKH|oXgHf zs)IOsnAtaF$re_RpeU8;>v(!#ePosIp7N^zCmDej3wQb+;B!BtcqgtR!sj50(xIT~ z(fUVDa%u=zaW~2H1s565DNmMg zSBKqqmSed*;1q}!{E>p6mvSPMxN~nGpUG$>+-X6NZ#jA2k8$k1?lwGT>Xt9zo5sBd z^jJZ~;Ti=C9-<(O&&igH+w2=2nG_zph9M45msr6bs^#{#z>OZ97E1ux4B3NNzjh@u zy{R-q+7Kd)+>0LOMLnW{o!gNTIAJ2nias$C0=yD;D0(jJWzKxv=PqbTdnl^dV9%#bFcG!6e`f?4Dpy><>FI(kN`7N%q^gWlVs6_9r?9@;Zd zZir%Yfl4bMh90{ePzyirgWIj?iQk2as6kz~p-j>_e7`k!am^NY?k#WK zKctTPb?yNM=ec80@=G|-y4tjHYLnzWd&;Cta-6e9TuHF5VM^57)AD?ttWU5PcN^xofMB|<7@2tS@sgc57aYgZ2i z^~}H}Xmj1$G7}mf&ki=KJMsFp~A9I2JBwPxrcPfSqPpFtIsqeQLh53}b7GF~=MoS!@)IidqaWm1UB`b0s)RX0vGUs>yViaw3SMBW0hu-LwiW`M3sxX6 zca{d17NuiA%n3cKrb@5YI5hEEAS*A$NH>Bx@{7${H^boqaE%l0d@$`KrtSNgwC{nT;WD zq#&@QpF2e3a|B`}81f`BN1GA7&UNz@2Mf|1b8wjiqp?=B#5Ag9$$|5gGK5^uG17-E zuI!YFcThpfG`J@d6LIy$8!t1mal-N4i>|;1@Kp>cNO;r=SvFht-Q)4i66?rsKK5ah z@m8JY3?%k$T9q^y!KyPW#635vw*z5iv~%p{D|fWcvV^K%i|e7Tvp_pvp)ulE%o1b9 z&$#Wr$m=*AY(%u zDuN9;T)UyRqz6xq~5PPGRbu9igsz9VaiVQj<+Zh8N~46~-_6;7T=z1PY>SQg{$(1wQ&Cp~7O& zz0}&wngLcuo~qOfJyanG((7`76s;2%o;k#JAWP{*vW$3aC)F?_Uaf`JtzpeI)pzj$ zs1LRTN|RdI977pBe3BCML%QxCd_^_cGHW?%8dehCw(+s1PAnfW3esAEtzd>Hg1GnE z!|~)JQIJ)|)n7)yj38Tfx+qPecTq}W=`ofm`mI|v#Z(!|OHQfD34f?rROFQxy#4Mm zi-**K;J5f4en%{Vbd8}Be7Qn#V$Ijf(Zgt;;AGMYYk|l%L#v457@QMirtewzd^HBRqpC`x$l~Wm>->u=h6q>F+s80hLv4CGsA0iE9(i-vxTE zDNE0D$Unl84iESMQ`j&X&Qx8~w5X`ZPYGr@#MT2iB(H?%rLhv|!!lAtg2|L~xvwJ? z&jjF?+&AfC1?0-IGoDs{YFJZJ0m-7lAIg~zNtf@wPdst5>yo`_p+u%udaluUfI+;J z%*TPZi%P>rn;`8?pd$06$V9z#RG_KE`fUAps7C5#ODw_p=pZwl`@q8~L7R$52Ye+0 zjENt`1ewP{F6n@|4tU69iBX|sJd97llg~_Lv6EvcNHIu2a#il#7@hi(L?I_=B6|)= z4c9YEM8o>5M)xjJIUEeNhkZpI>FL?gw@FFm>OE-e1oSBm%~W9)YgfUNr#|PDiZCJv zPChu%&mzbageiCqxToMP0VUQ(C;O4GwUKWcG*fFyEMa*0*jz-70rnI&gm&vP{?lJW zMWNaa+EQ@1;L1f-6YV)uzYZG(kh`!mws#;(3L6T3Wc-2yE>omHUxKo=W_a07wE}!U zME1(b?RHe7lx(N<75KD03=pBhe_f0{7E0QA_FP%18VHq|nD%_NzYRqMSfuaO!zG=IJ0gPc}0e zsGNWD63jAKlbthD8Hd;*Ki$XEkQjj`CO{ebI)(wGrQJ6H(H2de?TxK~(eAEy_ho=V0i&#_k3TiEcN{G zuGKE*49b9cW^}|g(g@=cT!vRxc!i^l(zdA;B}E3rwdQ=y^Nj3T553Eg84}wV%I1kAXOrkLO&L5)`E5KkkT%TodPxUcd1&Z`&V`4*Tg0PC6D!WNBqD zPATD<^#1@HUp-MNy1Tl=1KEKd=8XRb-OZnC->RfLBhC=sz<>`dvE2-NKY1oC@Ew#$ zfqO1INx(KV_O|8)6Q1!gOv?#RTW-_iJ^}|Vu?0%vlskg~|C(052OM~ktr{eTR9-&H+!hBUJ4?XHP&+O~jHO42Q`^@UoC#+aO((z53P zvff%$Ya|9$N=nI;?5WYVlcdLF2v5oOSiq_cAa&0V@$>FQ%feloqI3ub{}r8(MW6V? zsvu@H#y)jRcljvx4UV()L)edQR~{JR7Ew?2_Lnmt%Wo>g2Q9ck*gwC*=`~+rc?!aH z2U0^u1tU>75z57SMrf~-x|Knfa3YVoaZd&n!Daab(S*sezN9Bj1&F_g&S)rP9lYsF+4 zdnykh*u@A;;_TRKHGttkM;77fR_%ClFCxW3EGl}Ohni~w!RRxhWG8OY=?n1?Q?=uO z5;`d8t^H~eKbeOkuF4rHB4Pv;Pfn~U%vP6dtSMo^bRt!cB*M`JH(_YYiKAtwAupIB z>3u*~~YSfZ5%9s9R6S1R-oC)@v1^Yb@ zSb0i6j_2q>xo*vwbB6^93llHXYgHDQwbVU99;^KoI+tGFXGCZ{)b2P&w_y}$o*`+*3 z4+kzJn{fh%>k}0*iqFzsn<6?PfG&ZPBR~}}3NOwNqhQ6tTS+0|e>tNMABnm8aDLkO zm7B`FhvLplIjxzm*vGlII1*C6Czc<^yOnDE#zS6%v%I2p{N^kAWje|n8L!24_24s` zad^*HSl~(k8Wxb0#k%EuA)mf;UugV~pld@>`smn70M{=aZ zS9nvNuh2N5S}g3P%)Ao%FVs7LmOy@B$S9{-DSXnWaTKKY-*wdbuzb`SW7Pe4?#H>Dw@pr>Okl zWU;B_VAP?l!(>Sg7^s1%Aeq1g%9{k)rB9YG>3V)ZRnlVO>smKUKm0>ffq30=csPG& zVNhbU=#7=TH?FaY;Sh|Q?dB~4B7CoW84yf4gp7pb0XaDop{xAi<*`XeGbA7dlMzxV zOI4U>bq%m`g#wT;SwPa5XuAb~0)6u%(8N1rFm)I#UOoP9jPd7eO=U0Ot2csJQ;x0P zqr#gmx>4hcpx=@}C6IiAd8S#WgHs*?viMqIJ_%hf)SX~Sv?A0xaG3$`l78(t>obG# zG9OIpKApb_$>DsW88oO^Ax#{fs{@CD?~rqOrq`KCZ;+Ds(TYsWU}({wf)e7TL-7F7 zhE94gpyOXP(lX=7JgV#p!Ftnyah#Vr(OuX^K(Vq7+ zRAgGqN#$AnY`Koun+A+hO9~*NJj4%0`wkB<@hx69rk0gmq5Pbrb0$=id1Ih4kMK)9 z2Sv~*gPg%pIADXH19U!baOOt_1a%oOMlciFr2lZ3$yJ^o@ZxMHv&LLvF&Hp_N%!#h zwnS~T$f9!-#u=1yrV^<%~0(CNz zc^pu{a!`(>K>pT0e0WNs!w*|7Ge$5mWoziA;i=(kRZR&(VgnC$2|e5|zJMww!z@%) zGzy1~wSdm?eMx|VZ(iWoEJJgTyD<3T!w8SWXB>=CG};vR@=)Oh^H4E z4>%Cm#71{y910a-tVchatjJ&Rh?MM1A=u2U)@7YPa>_PZG^lGRV}xwy*p-y^{Ua&^ ze0P!ZcrtYK#;h$Or8N}1aYS2&q!qe`U`}>(iJlOq1KLwGVkl@{-}KkWigy$wJ5Lu? zfLkW^^^dJ=Ix3OEwCe1znKw)kV~OadlhFLprpy_`NtQ*`w|YG`W-O|H2FiktV<$F7 zDkWE&q;#tZk)1`kpX_Wt>PzImwaM_YD$gqC=H#voIl|m>W{u2-&Uz`O$?KUV@CgEO zB2`(ELNr7@j@+W**|R}*y{gncn2t`8J`%D&s61OXv4Y3rlhJke5|tdggHUDMax;SU zt8k>_SblY)$tg(})3ecIs`S>M@vDxlY_K893)$`q=h@VPL~Lo*>AA4TKBo?U$eUAtvYKC0cc zKqU`|~1)^NNYs ztT2x(s%p*0GRhDm9{4C)l;o=y2{)yZiARkqGipt85!m7?Q+7JAg{vy$&-;f&Wn>9F zDa#{#=~+=0EYRA$FQ_~=*<5>O+$Ur&!Y;&zW=z)M#H6)c`rVgb8WBeUcK5azx0p_? zQoxw6*`7ryf{$P(+t6hrnQCAk8X+Q&V>g)MN1o=6kwU$_>u?J@0ONO;%EBuZ7;b^l zohf)f-r~3#%)?Uzu3l+~31*BJLqnp5GH*?Tr)q;z)?lod8d&Q2(+~%Mtt_tO=AtS7 zX3MQHFu&>_X;Q2m)iGsE13bl|AWscW?`)$^#CnbVdhb$FFDo0%Xf~`ZOPAOm+Lci* z7R0GJr+8ck#XSmt}>2)QClIkGlvz#B!v(M@; zvsh=HF#^wL!aI4KRr)e7qROZ!4=i2nGMB)CI5`7fPiRb;q()d38E)obmTaz={I;b` zNLHJ)N9Ru3B+=R!6B5I6;+##I1>Rm&rViJ@gEzu`Z;fVv3U-#!W?URCm%O~e&SG=& z%L>&=;FhQ=YjyDGD4*IaWnHm6^7QEH)?p`Uy+M~Y(6M}_<#ofznUqIZA95Y6anl(q z8zNTCZRHs*wg=gI!t)e(om)PJD{2o<81UOB0ERo%_!|++JDDQE7vr5v_>%vGRe#tW z0K0SC70A0Up15`u+`n^)BZXKLgP#OXa=g`Ge@+J#XN|oq*y2TS!W58IX9{#$d?wwDZiewGCUJe6vsBRqXSdCfXI(|y6%UbN2K(`Qd>QB4xqv8c*IDU zI^XrN)9V;MYQ|i7%Lxzv{y^O(0Tdwom_+Y8l^t6NaiVe0BSr(th{vAMb9klX2i5zq za-SeyIG2b5vWbHxaPYBt96*7>^-Mq`(t{t0+r!nwab!m#;6e9fKR6CV;s82&!4I9? zLmfzln3AdCm-y5HN$5+SS?C9)Qoib8sPd(IYbf-WLRkmCCyA2d1&wgiu0?=~BOy7y zdl6qxg>{kmHF+2!?dyxXFfO-nU{e^XzmwT?R1bVh&gjOcnJ|qRk?`-*AS6qG4O%`#U~yB zuC>QVuhqc>nKW1C#GG_$n+57brAgK%pK@MPC`pwYQZR>u_p~yNde$NlO8igho9~CX zcSI#m03+{XsTq!(llH*)c$gB1YmI&>;W~v25H|nY9N`7;*vlGo@TKZ&%IC_Ow5F0@ zsDPYgjZim09O5B{CNv3%*{n1hWPwPBpd`s!VL*dr77mqnqRC?EuO&+rh)HHCJ&X5K zwuZc=6d3XP#G`HbaXNvJ9-&ym*5ej}X8<+C>oDOZlt^n-tQE|L#4qsx5Wa@6wzP(9 z-6J}21q&ynVK&>nhL<4Z!O3?Qb1=%XAX@n&o^xZAlyoIg(a=Gd;f_*p<6;VB31{@2 zUm@EO+jXzURfabJB2E_MI6)FpT2ed`_C6)@ARYcw-z!Qu$6$vv6GqJiSO8xlqPPSE zu>uj#24vZcXM3Q*02E#iOzTHQQG|}#3X&L>TAGZc#Z}MJv2Nn3qechePlkGSRTjP; znEbd;>KJiAUI%62;@W&uu`3p)3<)k36r zorZ zQ2E?AQ|w+$p+>)V)02yYQ67K}d&6OS@-lLZ#Z4>wkk791-4Wuji0t%?4+cGvX8}@+uErZR&5;G9>d>qyWU`vw zn)2ANV~)v!G_(22oh;PmNL9*iW=VK6V;rNAe4)oBEZqDB3?dUr4JLtS6F2I9$x2Kj5|hXxoqF;?$(V$i#D<*1 zxo!^3sW9%PabdG)zT9H}^Y=V6yvO!|))xQr@o(cW7=>a-QJ&sb@3EP-COF>k>mLH2 zHT?$X0(~yiuTQ+H*;PiDIy_?GO2SKkC4jp}p!z#;z_mzl|4M^jTDARyWAZYTs7KQy zgl0k}{I|48JWW0fk37vFwuy{UYNQSeLsk|72Uso2c!*G>P_HRgH0z%6tq|=!#<5UY z=3EpI0iiU(&0asX9qR!~fU}ymyFfE-EC6XIVP^(<2 zQl#e0V|c>PW*|a5Ea{9?qAHKrPipohXtI45%E*pzK4P#Nh!~9loNWq42E(${34xX# z;bA4=6wLt%uP900d;&N`oL)n%oHFq4)RZ*vS}82PtLrAmCLKo-h+ zGIcPXWlF>&%sP#x&P9v_I?>UKa&KX-bU}k0n2v2S);l!+E^3njxtW1Lc9MG+JUjLm>FdJKH@#FK)^VZ<~;<36ud|(#5nTb%H zw&ke~lhJBK1~-z7uz)+M#}0U}Qs(kXPGeqExms#5S6w>^3Cdw%Vyx%onjch%VB_!m zi$7F*pp{5ANoEpe(7i98NIvrQ(no_>UWEBg5?a5QB0r6BHN1oidVXDmNG4;|a^1Me zyd%Qhi3@)~*^PqhoWbjB(u8T^9M$Crj)5OrCHgGG9psiI&h9Z3yeSM(wT9=2rJ zaEECXVh{{zw}0%D3Y3@5kyn2Wlzq}k0i{o}nUVX#WL6sc4kmlF1@v7!P3eG?3NlSj zPcagqk2L7HXp(sowM|Mwzq}uUlMXMIzx$W4#BgttdMZdsW5V;xf6)|Z{fcU`Rc&Vt zEO9KdbIrs|RGEi}FO#IZ)x~FFz2{*$mnABzF3DnTcIq(%EDEqb&M+(w4tc-;T`wuQ zYX(_Bm@>H)Zd5=FQssZL3Nf&gTYV))EoBT|k0@2gKPT8=@|9=95*2S6vLT8$GA3B%kpDhiOLJGz~40Rk@$?$my^V&5ckIjbyS+GDIH>H9tzl2$Ci*6%gR9#o) z5E|yIdCOl^$raJ1>X{Iam5-B#oAQdBVd^s0r$QyjdAACg_OFtzFSj+H(%{cix-}1ny#eP zwS10+OnzV;m`YY5!jD_@VHXpwGY-jH}LXTaLIrae;m9?FtT=~;L_P(5Fv z5hbSIl0^==7D%}kQ=VVRBbsBfypn#oLfw>kZsncLQnE~Y^A#$*h{lL{k0QAqpNz<| z?B=T~i{YKK=(Z=a=2^ zj#})(m2Z|39yq^m|FY1|N&K2mPv~ad9kauvFs7cb<`-9;(;kk&I@T1N z;g0{BHg33ZB)u4Z1;-sTtxVG}%afZd4}^p)N@RJeTHtU8vQ)@4web8qs%!Bq9Rk`~ zkmU}~Qq3rN0dF3K;69LUHlkr6#V5U(Nua_aV?mXwNT>gKB=f$L>S zW@N|R3oZihJ4zNR=PNXY>MUhOiR@Fq1#Wq*DnyIkgJ-iUGxA=%xatZWt?j(wZDjK< zT92#BjB^${MpYL29Ifm6axL=h)nYU5Wzk(NPCm<$R9?;kiP$%_1a9>7T4+}-IZJ}3 z&eHwq4@iS16C*Hn5V*V?Ofz3m9|P~LDFoRBLSmLoJF|2zkZ&^YxHF*?&n3*#&61cH zXTFjcO}^MsVd#aattEw8{e0Dk2Db;qNb-2=yBbG_DC;&uh!|gVo6)m>%iz>%6bSRd z@rJ3NA)g|3NE@Fmp2a$^#Ja&OIqrCdSyFMU*q1$=>fW?jL8;M=rU+ zWWvdR+0u=hK9wPfKR{c?@^NtCF-q!+U1At37kJ=Is{C4?%G21~R(}88Uy{}}@vt*r zMT@5+z{Mb7%%WBwAJho({Dy4*D;)W?yDHZfTUEIwO-z#T6GWLmqNqi4PDSZYHDylr z=GcuTSLN zdwg^RiN7MN2Npawv*jIKx|R1@x(B$hddMoWAj462|7!l)qxr=Z;;uv%T!zNgGT&88 zljY`mMqPJdHD9IqGgm@WS^mc##$`VB43G>x#elNO}K%fetNX3E#q5%S_1{C=lZ6!#+sQCGOe`Cx!*WUY_H)%^W zVUBaw9Ao_ckMI1AG3T0V?6uxuISY8P$?A6BNr2R|`oM3cCbmA5`T z?PU`J`JK^ClK-F!?MQ9SfE}qFsjUcXmD_V_M`|kqTjlng+L79dz*f0Er*@>aBCu6% z`$tq5$D+jDA1YAXU;<@TJ~k=lyDR=GW=cBHlaBCu6%`$tq5$D+jDA1YAXU; z<@TJ~k=lyDR=GW=cBHlaBCu6%`$tq5$D+jDA1YAXU;<@TJ~k=lyDR=GW=cBHl< zuvKo)sU4}U2yB(xb81IwD*{{P_MF<0+KRwdxjma zBCu6%`$tq5$D+jDA1YAXU;<@TJ~k=lyDR=GW=cBHlaBCu6%`$tq5$D+jDA1 zYAXU;<@TJ~k=lyDR=GW=cBHlaBCu6%`$tq5$D+jDA1YAXU;<@TJ~k=lyDR=GW= zcBHlaBCu6%`$tq5$D+jDA1YAXU;<@TJ~k=lyDR=GW=cBHlT2@e zUS5U3_2j?*><>)AX-Dc+I8DK6N9xu1ESx>37A#)h+L3xaJ_~n8YQf_5tsSY?swcD#S5nw0#Q*EGuVGz3L#AZ=b}OVxNNvltdNx(0{d789(M;cpg7NFa zA%X{3Dhv&q)sb?2Xz8D(s>6!7+#{N;oWf{WoUUiNh7OW5+ZKe*uYpEB<_;Bv_D`kL zkevTRr(93p_D@->Q9*PJ99|zsMha5=JCvcdxY~f5t!iZ<$0%vx3an;R3KR4}+-HY2 zYg7#@?Wz18i}W-bqiKq*N+%pj07fe-vq%9|LBr#J@Dt@K5dgQ|HKJ2>T9M*HAkCpK z`!TcJXp{%}4Dm{c)hP1j}ERFgCMEAg=1*GWsh6eS~Fa7->VW>U-V6 zd}swuOmJB1470E$uUT{-DYL?V{|#`T-muDwm22%a4cM8U@McM^FviL%8{qVWWW2h* zLg(u6bh^3$Ipi@^txRC`V$TLe)hufUui1tRC%f!b)Ro zEl2C6pk8OqwSs?fe4`CcK9VOgL<`Kzu(VNjw0LHxcd+Q{5@`czHy`*#i`?FN9Rh!k z`_Vo34@!uffL_RzSC-fDUa9o`#P~k?{<|NjI5d+Hd#H}d$24&Yc%6FI1BUEuvsbu1 zN!u%!_fCgv4w+2|c%gVQ?y0nkv8zh=8%^-vl~X(89`0&-O7|-6n(QlrSWW|yDJPH2 zu13Y{*sajXtb*#)=@D8nfetN;@!++Zcr}PR9>ZH7uC>np>G(arfFq;qV@pN+7Urq< zLOq7VSh0K5CFCHyS6!n)Uxdmx(pLu-GY#e#GTl+fe%u5?S~|G$yfj|Z_0!cYr38vA zNR@KZVy%2YZ^dhM3aXPe&Nye@5cAv_PU{@&hTTZEnLK^zZ3%eP&Tv;D)R=3Cu*t9R z>x##^%RdW58?5LgkllGCL9w_|m2uTLc1zr_Yk;w*#zE`GAQr3a9ZM`n4<}xYm9~$h z&6jP*7W;#x87=WTskJI(WFc5I&@$k~Z{eb-m}Hfjb+JN97xqv5yR?>hA9p=6DzXTaf(a{Gr}we2fGF*_ zo<5rn$LZ?i`7^{=aa5I466nOtJGK*6Qs4Nla=t5628`Bl!~ozw%^5U!2Xxgq*vQbh zqqBW1v~N65AHrOMIFh0?P;1jI(xe=BMoqw=4fryh4y6P-F z*&de)dVT4NM3+iiEzvRyqcJpFJbQf3OQfo_YclIpZInXKdOoZcE3>av8-4H#|9bl2 zpC6*Wq$JcKmcDsnRIoZmjwNyCI0koLGe*V|R2DiZmTb2WMxeM!a~O1r^g>>mF!!t_ zswmlN!L4i#lTnXY>z1sNQ|S-6X0{a~&{5$3;6>0R`--1e%?AS=gtD8=j)jDKZl)~w z+|JT?^&617;~Wpt65k+0MIW|v(IZrbg?w&L^}o0Lt9y4HuN6n z?-BoflFRGHu`%>r!MLi>Z8|skn{r8hK#J*5XtT0c=_`YLN%32pwgO3(ymurOO$+CDO;*#M^A5z571IrVKXuzCdY-28TSM`?ZsbKuH2t(UZFdxG<-Wj% zCD*AMH5b2rwJ!A%;Mm6)ZjV^k!+q6t`jXvqw6lfYIFJ*Kc3mMP4jU4A4LowAAfGb4 z+ivNvDN@n99dZ~XhG8cbmre-}FRk_dsQ&U#9xdzcCDr=Suk1)eM72a-BK+ZZDRZUreL%&6E7~!qwvFz{!ExtLF$OxrJw4mMJEos~5Q&n>3 zQWnbJ@VdI@cF{6O=lcKo6=OIf9;nO0D{;IW`COKET1mGiAc?sZ8$zryQ}rm3K2%@k zKc$B5gn7JNIe$*@OtrEWQSSGwTMUPy{ z-~6rf2)cZt8M@0Ab*AXQBdsW}T2&%op0q?ZBCHt~W-C`|*Vt~;9*58{ja&*fL+Oii zkutR0S57AaF@PfqD6whk*d~ zdO8ls8Dbnuu{R6ZsQb%xR0^Aq2GH!BJQR?ohIBP)<~0Jnr5|rFuMYHvko2V}UV%O> z^Tjf-6!?dXbzbRQ$Yskx^H`SSd^OSZHpgUJM^)NrOw(UZiZ1hQnRwC1b?WM%20XT( zEXH&q3_bX|J+-eSb=`_xsd-BuN)5yYGE|2KI4K$Q>?;EF5SdFZjw~^etk{-wrj()R z*MacjLRbS&0H@e7_SWA$_tRaOk1GF>_ju-(tKXmak0n-F*6l&5!6d3I6BVDXYdEWU z2PNEAH}GWvN?UBv>ITkeU7{>{922%P&?>c(K%k$dUd?1U>oVwFOdDzT{vz6z=8#!a zkXPc_M>FcO$|=a4BT*r&Mg>ey{4|rZbY)5^wnT42s1>dg{G)bo?yr1cXmBHfUF; zr;R~y?R(;9QMYi6;R>8E@*ywr&H`|~jdcM6Gl-GnkZ9`sp>m_*;X{XKJX!IX)Dxcq zUV#Kp)K%j_bYp(zOlKiFJmnNlN8mVdzrg)wFug|Md1V7!}(8!szKAkx4x2oMd zA@fdHMcZ2XEm}Hk?UWeWbIityu?#C*7*4pp)yU2DldD^_jR7k+*YxrIEbkZ^PQaxd z)h3p9gHx?v`?RQ?PDnM!c_ehSP_No?G&ovGZFPh|p<#8=e$MZt${SdMEX3#%B?jLh zy6J5I#}AqQ{yVD6yI=|bQ#M}u@JMqv87o1B-6#yzK}>HUaCn=?Mpw5Wa(L%U7|i7z z7X|9m=~HTdI=~>UypygqVwtQB?nJpTh_|nwUo(Yy+xY%3LF$9=0nK!KdulHn<4aG# z^%Hc+bhVEn!s8W?;vL4}@cenj;uN&pymN=Z<$LM0slBAvKCO5t9^Al?&Z+&iHyDTE zVCkuIgW?$Nr=k`*0hg+96_c){uuqVT%_!?}A7ezCaG7ASr3;}t9G=vtULb|mNgE9; ze6Weq37^9%2f^i(MvU{bQA;9*|V$Z zI?K9<7)JDsb^8)KIrR_X&a<9WW1v5>Cg@Bv5i_^aEj;N5t3G=D(q}2ve+}(P)*_HX z?F7RyBE{+tPEGtZ0b!0u{4gB4@(jHZ99VFqm{Sb{MvE00BWr2aa0z91%p;SER$lSdn*ZK}HV>u`;*dtt?9o>=`L2B|ec;v8BDZkfBQ}iaDhfTJa9D+)$}} zb1*?qEh&ZVn;WE5O2n*UGzmcp+~dG0RE#C3#yF9JKcq{9exv0w)&5Kxg+w(+v~foq z_N_cGRpv&z*RF0jsIj!%LTEoDqaKAZ#Vr{wfbISFp z&fCaPW@CrO*`YNiDf!MU#K7V7Jhz#g6aYunlZvfzmY`f48>J9Uvph)rDZi3KqPABh zz}O_%ezM8@oFJ)(euG~2oV)^+!AAaBkaJ|tm$}3$V%jm%;MDyC-@-4zDO^payH@Szh*4J}F3$lFwbo~3nqI?(A4d&8`C z3`EAx=*3%Krx=_0%{HR0_vBff#aeMmkvyi(O717uhkllZQG&yJtNCZ9%BM(8Bb}m6 zznS}~t9~`=;f!b%yQnw0#2M=4UB)z^d#T761UKt_G^tp%dUv{dW91ly%R3H~&VP~4 zg9BWX%hKYc#}W#@F7IsB*<`FQ?G2|_e&|L?PEFiZ7)(vG#R|r+r^~zUq#=G?R%lh} z7**$&eG&B;#q6ZyaCMO}X3Rt}UEV3IIBe`1PsK!|o)aJYyVtUUI=4+&;St;{`oX(K zXYRh3ErfQq3Yr{)4c=LTk>a{AU4Bd(-3mw{CK+5$yh*cx%iNVQ(~a^VgIIE5Z4Qiq zT)yX}h|=g!)61%CQhJJ2=RHj@n3M`Cik-5Yfl%MP3yy|idFf$99{}lgb%7nd;GNU4 zvQmgbC@Y#$zJTgR9PDuB7zsXBozidK)!9@F`eLO)sdGOt$Vv_vFt7sNBbMZp)GF6l zX*6XES;QnzEAzThL?#$CN>%?&NJ_x>-x?xP<$P=D>e`3r%b`fERE{k}i) z9j#e^LF!L_qgsc<%hWeFFTbv=SPv^t-(6ezk@v0K9uALLxh0mhm5SvTtNne5Wy^>@ zdRHT|c0|-a;Y&pd%zUNT;3S1uO|Ncw2O5?3#zkYI zXS*R~6f|Ovw$8b4&?T0d82}Bs0+})ulkfkJkbFp!FKUmTKZ^}HJ2a%3=W{EMT!FX8TJtRG#ywcAD$wvtPdcXC|84W+? z2$BDJ(gM-Fgx<}Ji?KNcn-$9QZbI;=<8X_J4;b0*aSQ+Un)UA%F;5&%k)kq3(2_J9 zeQV~;go%M})npzu6)cU{t&Q6BL)VkiRrFWwJ9PVM zjld|dF~fs9a4Hb`4DtrN>|lvD|5fAhy7uf44BG~ zuxJ{L;-FUptaDkhvtTM5> zWTbO{pvh#M`b{>J^3&>8C><>D-^I6X$C~0*$iNCb$k1%k(emCU%H=Jea=@0JNVhn6g3Qt8;rFrEHxCgjF(#?&VX-6!?E^8WYF1npL6)HSd0!nx@s z{Q2&Qw`QRm(W!}6LTV6c6KhJ1*6PAPY_6-vIL^!UUsj21b2MePM#it2)1xfF87WNldhOnxn7`NqSHch7r(Ue)aBZEPY5S+9a6BbVHpx3oTG7z=%_*9eyB?m_4`2;29}< zE%A08tJ!R5!&*ja5E7`Z#Gl&cZKuep0_#L;?l(HVDCSm`)XgA%$gk-nDh;mU$T~Df z#X7{4%Hm$*F6p5bIoB#8>V}pe=3rLWPF+=LR9-ljn2SDZRreLgEap8H&R5Gc8nU@o zIO?48tk+9)Ln!qz$Fh?s9Z=&HO&fpsTR5DTh|dVYBjg@R3Cb(iXNs+heJJc&-9kE3 zo>ic}28*!PLEzAvQ=F*gy}$x{9Kaq$E=5AK;ax}}Sl9IWd$_Pnhcu{FIMJQ^(&qB( zpU=%SR>9F+daE#o!otMGs?+)7-eH)b&gE*T4>4=+TWevgUU=PQFiU$JLJ1BlY4Yhh z5Abdsd5KWh)K*T?VlrDjyly=#eZ^WBrS+%3LduJUJh!ki21$daC8m2@17=Ql-;>Bk zILFA|KL}l$c#qr04b&a%pAMNjuv1I%m1eq2n^UGuxF=>mKtufICd1P46Do4=# zzs%Sob?d%$JFZtLAws8$ldAv44klW>nF~2X<6<*}`?$E0>0vHhRvQ*i5{9ETb8VPM z-Z!AealB?Da(?`G!gwSL9YvKT=s~frQAf(Z$tpl)6m(Q|V=AdiXV7Uqg2i$&V2(@q z6;_SzF>i%45_(X)r-%$%ao@=0+x|uxk(Auq4O>mQKs?y1x>ftUk|xF1H2u~en92iI z=4oNOXoBH7=($L{>XAo%UUp$sEc2ilP;V#D-bT7l+97BT#8eE`JA)Qeb+A2@g|&-i z6y6jqMX4sC#0`0rHU^!6m_u+OuFD*zbYG*iKh^z*po8+7BZs*cvFZ)#QkOMOYRa(a zDUU`rLU(3gVdnuXGZFzciNBUqJB=5`AvKMS0LHr#Gs~06e;-QZ$pLkVv9zPn3JsbO zL=waNhpY!1P2+aPOY*uvzn;Fqzwhg14xfIUK`5s~;uUqdEG-`lSVU@mTDM@k+pj9eAhX=p4H~ublol*pTWRTp4G|p6RD)J!ZVbXwpRq9fRo}Bb z@;@J3T%nke_t9ryh|RN9!&lK8%GRUJ`HG?gS<&aqrP`ch*_B%em8VfL$&X6SMcGwx z^o^HNb)hWZ(t1H7N-fnref>2Bm8w^|9L^-$bn!cWm2!r+LL`(`$S%&cR@Dk3YZyum zldA&z#41kCxa67}s8)k9OVG%EmcG8nD--!SsE`n6fd+GssXo* z#D1NbUDNaebpjVE%~fIG*re|ZsOm8+ zjXr+AwISl1RzFonEKh*_%i9mk!}J9q8wj58JU}bF8aJi>E0e5n*H=Eg zz}D4GJMsptWu_V)ymyA~mZ~aU4=dNl1)oRVu7i*3b|KZOzFGlYz0PZae3KYS> zk1(~uhJxHr@z?2yfYdecfNs0uqi>&E8F`_SzUVOa5-lY3=BAYx=N^&mkd3{Y`tiVL zJ3QeKL^qH%H<87ro2Phs&(OI?bveJ~+%;l467Y$58ldPK5?FF_pqOD81)nD7yykbu zc4hfO?OXpeki4W#wQS^YGGWhXmzvPl{p?;;P@ME%>lJwdv9TwhOS9cjE6r^u%}?rF zQ06*YFZ>*=TVYoNk8Wz;A)i%Y1>>jZY+BLE&GD@_Fr#+1GqRachPxNZWOg&Ujm~+yR`G?fuaAC5&jlCyq2|L}q z|BgYvbH|QN_8}e)-z-#EagP|WSU)fU*qf$%Un2#wqv$z2f6_utRMGJ;_vDOElP!zCOJb_LPDoz z`5Z`5nB<=aTesUU^BIxFMcmNr2YQu9d436NDNG3$ZuMVo&AcP_IJ^YI|p zvg)K6q-MKg_SJmhrXpL+M5N{o(ULP*!BOh$H>6`fDSCU0bdWlnZk|Dwu3P^U!7fus z$4aecA6CgoS3l|Qc8@*fnWbo}!i(D7(2P8#R)EOLwTzl(D>=LZRD4IG4(WfzyC@7u z>Qun3MkR^DC9vv4sE^(`y-$-YE3X47tU#@-pk_sBCydQ;)EFwRzLyU95sZG3r7NyR zWG+=+*P1D=oE8=OnkioZIBBd;6nc6ot?bm-3Jj3xaHgvma^qGIfmNx1pZ};OHq7cZ z#i(>J`qoP?tv+HdMzxA&niA`bMCFuSV{=eR6$sb{psZ8QM)~=31jQ`FM1TrKAC`-^ z0>2Ovn>o~=YR^ys%Uitd20@!;UD zt}fOVYfs*AfYFz>#{x6PB8k^xh2hOsv^rhhaj0Vd>v{DhgVq44`2FMebl%X)1vee` z#_q*J42WKaT+^fHU~?QQnThCRYw<;Y+$kMjmv>W@X61ghH0<1q<&XL)Rz)|S0t6!k zv3|jcz`MYiGM9I0RInhWe@a#7W1OwPUyzFU<$J?r>aT~`W@S!bn-0%=Om!u1;V)Ji z8dqy8NWYw#4G73Jmh0zvL`^FDV)2BvG zl@$6j0@y8L9WU=v=L{t}yLEY|4sWbWif|~qh zf$Gv%mv_oV+{uR(hHeZDj+t(w52RHr+$KQu+^0w-r`~Jn<&fQr>%P?9zxZoE4f}r| zcQ3MQ(LIpoyB9zB9+$249!M^N?q2j_=pM-1_V^yiE&C3?;3K|IdEHLREml5yS5~b1 z?!|B9T)YsvQ9K!@IO@_3xdhFH_ArnjrFC9qnhBcWGCFfv_ zcp&?(eNJ&bT|lRSxbN4wAVTLw6EnO_=vu0}H?$*OBZ!2Q#w+H>NQ)%7(`~H^uK(Z< zSoLX^{-E`dkM7@}dUi55zW08X@R!yrtrdK)WKYwJHSZgI>e4Bkt)*bb)5d|*$QWE8 zIENgQ0n~}5bExr6aK=EaPmYDzAa9je-`u43|}Fyz=q&ATUVg!t=YC`Xw3 zDQER|3-XX{=p9R9nqG))l~xg?bC`bMH+HgVV5sK>=j73dk~1ts{WT1xpGb<~&`ap4 zr&^$N$xgmQX2i< z1PHOHp*DG)Q51(LK~9y{JM!B?FL6Z>NEwE7AT1x4osR{}AjK&@^>7TU=b$!PC)++N zc$-HcqrLc9#fQ;zlfWycoPLG_VR>^_+B!u&hkh^LqR-*z zUu?S_Qv(t?{XI6Hs1g=ofSoM*RQw0*T0W&3c726{@diX2kxIi&o0^PS+J+Ow5corx z?hno^Q-(PrANIvLI*>z%9N%K#O@(b__1XB(N<}ad^B6EWMRpl1&#G^grH!QD+(1QX zt>#fW{iK!!%>5I5Kl;25)il5a-grX}XgOWUCWt(p>q}WJ2^e$~H7UKPHb@GOi+yHQ zndfSrr7E%Y_>@G|!CA#jn)=OH5+JHNurv?crq3k|4ve*bAAu@I1RI_kZSVjdV`^ol zm2xIk-Y+9`LgyIq{Ee2EimQ_s0u94=b+h7cM*r*4O1BP1!B7*7%@Obn&@5YjYB+Zd ztIBA3DX&u2vVh{6lTr>K`@f<|P_TMW#i&IqnLRim_s*CGbO#$n^XWFh$3IQReoVU# zw@Ng@I&n;!>m{RYwC$(hs9OKr*W2gWSje*@@*&@>X+25?Z-2%x;c`d~Bgu!ay!}Fa zJb|%UX;J1{nWR(w>Xw-?6V5oZ;6=Q2`3j_^SK>#|NWX}!?4JRoV7*GEjMfqfovIHuCV%Zja~zN&;-avn+YL77u!#Z3rZQ!hhyh@6Kzs7qb^wbrRK zJ;Q5y$jq-{ajZ6rt^4AHQ>#uZ8E=T!r?sdT({KD4)jC6|+;|)gg@SpMsZ>#LEC(af zh%Q0XVwLD-bEUnuT+1)jj@D3zH9h&L1964a8EiR-s4|Cy5b!azU37&>+4s_L% zI+laP+i8gSKfAsSwg@ z#Tbi;?)*0wG!U`09Ors;JGH8{{RaXIh+__~bj#(bD0WmYbH%D-Gbv0fuahAKva9LK z|2*>f#J$I`4kcrUznqA4I<`HovL+*~CEC))Ug%w5n78ijq0xH3FN5i++Q}NI(x`m( zqD(!G=!7yDucvtkJw+6mPZW5L*jkUWotchwkMA%34tuXDJQxpmEaM~Y(eJ9 zk4{6bA*}xyxW(oWo4)#!H0K~^a!8WPTc5(cJ9?!y;_pNc`(f+9n~BMuhMt>x zLR-{XzZ*6VpS)K*xsi)t4I!BZBJRV)wd*Ldm zOm3#K81k1=gOw;NXfi@`#5S8$YKExUqcn$b3<&c?t{93Np?)aK8FOzIc&+&O%3o#C zgMvf}Rjyz&uB?vXlvY3aR;849ucyDu-mlBc8a)Pk!4sa`9|$EUbpci?Km9^VYGZ-I80KJTPcT_A=Y{oTdyR34O7GeqlB!JfHls*}6-F zQ>yO%I*sb;SkV-vJDsIU3F`2D`20U!k`O|(?&AJDmj9TqhbQcJgA6WDc(m(VQZ|Y} z;A(_5%{Jy0---C-B$+D-WTxpe{%)*^CilwEneRt-(7B<>$y{%s*q{R)!fk(Ei7_Mb zDI`r730hJd%$0(Wt6dU)6~hVMQ@*j#?{oCd*md(@Kksh9u0cf4+GpLgh>kzFl%@gp z#=Q&T%=Zs7O17HvK-!#R_$RlKT}_|;?cPo0!F84%LNY1_#+N7gM8Ib+4BI`K(4mk} zdVz!X5~P5{IMLSy9qH;@JyhWNrYT7T_~(@1R4{7y?Eco)KnlZQs$ zgSbPIz#BvL!2+4_t-lu5oB8T*wsFN+#pT8(KUMNwiyv0k#*)-UC(Gg(&xCiZ%@b}V ztG-I)&xx$N)r!)sS?AjlsZkTC&}nd@Kv9#(WouJ*FETp%WkqSXhd|;Bh(6FVbo#ZC zj}*xFd+EjVYi;0>r_c95vfGVEOhCvMnG>4$`!qW&pXh~elVr~+135C@s~^)o_h$zw;<&k)k-{wq@MhNVu;ZDbrXymU ze#TBQ9pDG4)=VLSGB%>84`KwD{b^mgA)P&}p0NHQ{m3alw9j{F7VfntuOmgYSfwx& zW~M_YJ8laZx(N+L%lpK)>JbyZpkqy_jlI5A$>ph#sy&b3Y%J^tJ-JViklT~&-8-3~ zj0Bg=tyBBm-@x$SEW77OF=mm$MfO%w(}L9ZP0@3Zq?Fk7?@*&=_KO%}L!349xm@Kk z#Kv{u`u5iIQgp}8Sd9lQF>q|ppKE)`sho${Asf(E>f&NzjLz{>3ldP>S*99 zOb?1#Q-z#@;b@31NVUQBqfm3|SUQfSbTalvFe2sN)-(F#8z9s&iq??=Z*?Iz5n)7n zxs@hTl~ZoiceF)yj9Ce2aG3)+lwp}Ok?Kx8DL~!1)x;OEj&l#jc?UCHiwW{5>7Ho@g5x6 zkTn?!f|XIFtsY*HyTxjJ^jV{*^u}2pCqV6K`kh}!eZ59%9t#spmNG*xR*;I3-}P6f>BSrk zTrPq+=1|e)wkrM0JE|ZOH`>(@6?It|7rO)}gObcFx2j*>AwK)OE~ExRMISwJwn!E4 zL8p6p$DxW+HOBN?#ZnLmLRqQQN-Plz_42OB%tnE$SjuX>!M6=k7t>dMIZ^+8+`Y&$ z`Th3|j@$x$KYS157AqgUW6rV%(mJ~rKhnPTr;t+}H>*)913dFr{AcN*%8aVI@~X~t zBp}~*-DXYSob_eDS2Xh8E_BFxkxelJZqpdGZ+$5oQrqUc)9qo+(#$dvq2<4nF>fk~ zx|odSp{S!`U69HR33C1B5Oc{|Yj{=~NiP2zKaSR_1ff;```paMVxyJM==@@%p>wfz z-lg{$9hF8`EJ**mZ(_#32-fetf)M;R$pc3AJ*!waYq_@iSWieKD2Jhd3V*uX3X8f!G_*o zk8S6TJ7wua!F_T`Iwl2qEJb*ps<^v>epuRhLFDrxng*Hl@k16yaDX zVrmXh4h-LtKs(vBc-C%x)}nJeacG}ag&-_%Bjcn2ds@@a%xT>T0t$)g3Mxkfm?GVKtWA~{fNn7jhKu4Lta zk+-R5n9Vb1pNlx$;?o`2Eg?opUH|bWYuuB3D$;ZAI%MJ@r@xURXic^}0E^ibd*v#N_z!a+D zJMFZ}6>YnRQ+y}Sb8n0(1)SnE74bzWHIMCL=}+JN&k{v=InTp;Mld><>mwRwG%&aQ z#!@@wK?W9Euu6vriitpE;Ee(Rbqbc#5=@+Z-Qs+Ehng08KTFCLPgu23Hd;-F7NfNo z82a#4Qdr4|L8}!u3b;Zr8BZJ^3w%nb^UmuW?*GNWDCqi{TZ?*Gc%>nK1XIde`Szi=PwimpHmc5Lb+Eqc?(LijJ2^xsm?`w8X zH-AtZk?U}y#F;r1!>{iqZ;@ywkw zaWck!O0-&O`IG!>kQxn*ln%h?q7sBxe|P|^$F&HhH4Isgc9}bqZ!@!k>Q-8>XXX2m zl-uNy*0DJ*jfbRn&mXv)hN8(tV`FczL*({_1xcxGNpqi|FPchoEBG2eg_#5M;?bGKq#06vm(st3;i}0 z)v0o3J|qn`4$WTfSuVc)x7((i1sl&rPv-SzRcq!MqdM&&4UI>YhEG*$B%wSiyI5U8 z0Wnv32St%HxJ^Qpo;9&O*y9P=z+w*Y>|CQC1rNXB=dzYF^)4rGlGicTis!&o!aLTLvqwf4m!T!HD}K6mDa1lz--tn5SoU<8hi;UGfMgxt6mYc;o8ySnp}Kj#3SaYpJCI(Yuz+xMn)XV*Yw@b#yWLb z?;kasGOW)1t`T}?Qq5vEYF>}=4py&EMr@m)$)HC2xhpyM-_EJ)b_2O&+tr60ox?^9 zVMgWC>gJQ&cdr_6fzfayVC2(A(qFf3>{%pI{$I1bj~Dk-4FlfFvbT#E9fz-5{;7G( zs^Of#d(0(>26idfRWb|)hf&xMMISv+Fr!1HzB@gj(YV~~n;o{``;`;FYY$7e;jVhnZFK|!Og zlL|pMre`dLd_x|0A-Led#?{d@bLS!fCPsIRUY!J%e}43Bpm{a}+8XzB1FGrpF2`^G zd@3rl+YyX>uCeNe^X>P3fB@dPeBUKIK4L>@boo@CUyeqK-HRcyd-0COJ0CBp z!{OKJ;RUHm&DZgqsM(9bX3F$y82sq$=>oB`BKPL~U(7jn$6!f+6KT}gG3Z8xMZ51_ zY!d+p_p!Y}@YzYpHl72&Km9RwKz;B%1{JMO>GNCI4HVz?OSi=IJbUe?{K_xT9G~}{ zlnumg@%hdj@P6JW0^IGX#fq_j4ASl`^4rCl(4E@b-$Vr5N?kGuh<+|~;M*;#{pvkd zGe+f&I&$FDloqK)D@d74v(zbDIS>{p_vWF_nDbqL)-gg#HOA&lGg+E@SxM&XUQBW@ zw#3GmGFb*velw%lP`@)e@sLj|Vh>V`--vl`M}*y4e4iR@kOFs;tkF@B6Bzyp}QDUw{E?$S57PR z9dDvB*6CLzqTD8UXET?=$!?J0SUGk^kF;YFp+brk-!%b}Q8kJkl&w&>0a_5e!6BF3_1qwk$84gM5_U|aZIyNBSI<0E`|w>8#?0Tgwz-v&+;1F6tmfqG1G z7dhIdVx1CmNp`Lekh|RUL-~eg=N>CMjr(Pd&^ca1(lyq0>jZ*HU&5Jo5G*0qukP(6 zf%U0A=CYPR!Az>=aS*ejvolkQIgmOn@r@`>dyQU2pd2YP=oK9#6@p3Xz5=6z)yOO> zhWpZ|isPNIfyzJaq8Q%jrVxbN)D8!29o9fe>cU99Anv96M*Xp_- z6Lu}U|Bio${Jx}>Y|A_-%*}Sgxq9=iYB-j%TgmDeJ2`con35|i)#iA4$Dw1w1o>p| z6-FJYj@XC=>Qx~%oLpVrMK3-PdufA_715nJOJBU{$5^*ga&s&da<@`QA<=Wkd;4kn zg@2X9byjq{me8x&ks8rWmv=?)0llnVKeB?X$|F_=_wvrxfTZIs$F8U-usZ&Axl_k9>!h!sWNHKYC|> zwR`dI17FyGJ+mj;3Vm?wSu5x%gFEW8^m9gg=hqhiYQ#JnW3B00MBpiJO>N%S_8PVH z0nVotgGwhA}OoX7)KfkUHQET2fcc6k@ z!~1$929rLGmRR|KbG}5*p;kkThx-H4Rbt{W{Z}6tgpwg!hGVoic^Ba?v=YxWPgBd| zKB0qFe?duv{nu8y^HdrdFPjkOoH}BOK9P||;UJN9$s^D6a$_HTsreh0`+-HzQO+P> zBgH3`t9^!f6FIc;+TYfcVwCS$__ALz?39l)7mm%LSdWr6lruZS;}9w?i_4fK(aK^I z(fL3lDPi0#z87EWcEdUgW9=3BP7Qc;#%_kG<&UvzIw+M=`|fDQQY&JPdXX4LZ83~4 zh~p6IiIewrU$xS(dHpF5QK~R|u#4C_TB)($5uSPVwVR!_=)R^k%O+pCAjB+6bX!Od zqJdhc?HGOztEO?ymTfihpD9iC>g5;#ZO|yPos|FLm-PlAcw*~26$>dji2FmR>jD~! zt8;?`sO-_kBL7q3bV;c&wick$3An)I}7 z$zDY0#Q7^C7;Ng1y+83sq~igbXO@cbh^aZ$&LgL0(roRq#v|s3*fNebNJKLf`Z=^~ zN(}NW*@yigiiHrX&a1i;Xk=tavx%N;>7R4D$lafy@nQ_Q6Tdf=L5=&A=sO&U=c9TA z_xsKsh@4wc9J35{ZCj<4Vw)ja5$`)%`iszMA@*Df&%C=~|CgkI6hnD`hyZW)Ayn1lNNOP_3kT)xirbq*@LZEr@&^6FvisNOeXa zuMTGxe*6C(Dnn`MZ)lx)FtR1ON3}D24$BgRn8X>ExzQl{hw?KQU)=TAGowIJqLnUO z(MK#*x7Eq0j}USL`Dj!t(V0K2&AIlE|2BD&$E##VFA5x3@K!fbxi1K-q{s0d>2cU* zEQZ!xpL6UrUmO~y7Hgr>O`YR>gQQT&uJ|Pf=h4zuQ8y&U>ogkHQ~StYv+8A~Qpia! zB4M9#?{&lLQ4VXLxyI-UoQ_OGZ%}QI(rHa3IHc%tl+_!owpdVtZZEd5Gt3Y2tLltO z9bZ58_i=b->EOKD@(R6sV68Zhng0yz`zp=b^}G$MSOO8vwh~;!7V=D(8zGm@96)u$ z;qYqa@BaluhPop%8(Fc=n@A`$UNT>y)FtKnZ!P(l#w*SVqK)w85m!If)(2$PrDej- zZq{7e>ptDtcuSnK8myGR@pYqhR(pR|qfhMg?%nUrcKh(pv`424mDBDzPfk{V)RPof zc=Dzc2iN)tKr1rcAvK(6x7!XWZ4QIhN^nK#_7-Vd%Yf)K{`16{R!Z~ui9a8kb>}L9 za^KSMSzM22W*2f=i!`nKg5GR*0lW+h?pd&F48u~ZZ0fe|n`G5eaCPy^LvqE&pO4eD z+ZL1bQkut8njYHRy5DHif0-SzxB@GVFFH)+JDJs|&3N7x6MkA$B4yDwMdCaVXmdMU zh0L8B{w>$halarm>r-UZR&n@@;-|ib|g{@4MsVX#XyyIT7(!n6#qsSP(kEF{Ea@wchWDt{u-SCWD%K)JJ}17AtOj@U98tsvPQWFy-g;pATGRAWYdIL)vDs}D`PS7xo!%fT4sVlh?gDCucRt3@F5i=T%NI?)Q2JYH zZ=PE9U4YCxfI7jdoNDbtg$s7lOzyjxF7K$Zg0?&S45NJ-pYfezx1k7DI4{ z$uD&`?SfQ<*+6xw#G&m4)2sR0TPEsty*;nW#j&P$Je(LF8a|cJFHm6=l z%=AOMQ}f-8bP{Lyg;X^c3+asq6DF@l9 zkK`1Nht{etZ%a#-WJSsM@iAGb3HBwr(3fIF$<0EZkfmt<5QFTk@N*p5|N0 z;d)A8FJyeFSK1-d41IK_zvAqx(!uC<1~j7{z?E#R8MFs7)*|EC?)K6j?N!Zaot5PW zEP~OfOAe&Sy~JMJ#md-|*Ry4bg?Z&!EGzL%FJFR5j+HIIpj8>L9ueHjyUM68`7#Reiul>N z{~!IM+A~UNM&leQNSAjUmQr>{|ACe6{hpQj?!}=*{TZxu$&pjT=+)&N9DH_yR%TrJ z`fa*%nIVJn5UE*=hE|qxHlkntt8wu12YtauTtu(l{HZ^g$#4A;H`(*8i9fl%sqh!S z=W_bBU;9Dp^>046`psu=alWs=)@%&_f3fn>yNcy!Qukku{)69|Q(m6x)T zqjIK~w^~ZjE$b_Bl;NbbRYe=Lcv3iOj3 zB`tSIEbT!lR!imG1XG`JorFj8tB zhfhPA3@E8-w&}-y*)+ZA8u~iW>z7C5i!n@$8ak45S(9gCOr43r@*)-Km9`qIZnIyd zjfOhaAta-!V$07V<|r4WplY)z(N@;yP}7)uh|NYuE420D=lvrhWvuA=BohDKv;;+4 zF?9amL+cmitv;?)xJpq+ui4O4H*A+u>rmZ+hO@A%b+S^b$Fvfyb?FKQ|J!UibHa_B z+CO(EsbrxyM{BnNZ8iGdD>>zzj_@pP`g1>gh?m|Ht^7Hg*Uk|+o6+Yg_~-d;c9rR@ z7b2>0qO1J!beK+rL%f0p~!v z8d!c0dU!>I!pbfI1*L1ykywfOcjfhUj#1ILCE06q1m`s=26h#Kjz9} zi3Pwp6lksJ>j+RN&uc}+7NNq5^Y#@h8Rz(_TZUhMJQII#WgHkTHdf=8xV}}Qi-A^T zkCq-0ZiXip&t)9(Fj%=X*Wyx-e9J~1)hWSlY_)f%&4O9Vl3A5zD^LI8e-f#Vy{2Zr zE2)__O!gDjyYmFMpF6@ZFu=L!fk~N@d~qUqcI4!-Hwd%aoP&`c1MR>(MAu4#HmmDy z>FDy*Jg!SAwKZw96VvqG&#AF#$XQedJ+7Aap>kF$(_=D2OL3`{g&dnzJ6zK?H~QY} z_rDr}Y^OM_mTn25vRW^WXf>%R!(lpE?_G!=Es|RzJX2a*JJ&oHyY?GmrZ4(QSb34S z3@szkCTnkvI!Z(H+#V92p(vjZf7f!X|E|TaC_uO{Ny&89L8LvdOc+VOx^5HId=MrV)GH|D}a1Na@y-%xu$-~kMlR2y*8oTjh-hfwFTkww!pHl$`4_Huo!%C7v)I zImG@WbVypPMYQ$%f`@V+|Bh93J?vE^D%|VF#>mcl1`(adE-MC0-{Zj4c2SWir`@$m zlv`dym?kz$r7JaP_sdxCHT2MAC@map(3k_TnX+7N&SQ~ja{a+iMvQ}LPjqJ(^vE8X z9ZFkjhde*6wZkjxx9uvl*!WX-uANG_u2Eb`4ZH$rUEFF6XH5$`r|P)OPgI9&_zw=q zirtyeINuUG<7Dj|Kt6`-rh{Y!TlxPh&%nsWUwO$o1JHAY*>%Yma zAd8(UXED+l{cdB3r4CIns@xMvmqTjIkTY4Y5%yi4qZvaufa z(6-jrcn!LDU2SyE16v*kpV50~&=wpsf{QP@jWtF)vdKQ(WhAzT`fv@QGHJ=D2O_iV z8mkaXbU}C}IhyrWavTShNJd;@S?xA+$N4UprJs1UCh$CSCuC`>GK{TA(QPZjXnyXW zou(J88u{Y^c1ifRzW(FgGULIL=O&GzQMED%2$b(GYV467P2{+a@MD_SJX(83zW6H# z{Q5BR&uBekzH#eG%e9!_oNiB_@vFs89n%%xns|$bNye59ew(E!#ne=m8$sq`b7nDb z92wuo_*`#CnUtU?`v?nR^r+#T)KH*=eCLz#ITr64FlEe{j);t*+@SQra)3AYsS)ah3 zFrp9BZV0jO5Rd-jW(B1B(Zb9WuChMg!;%=+(GmcEWfBHU+~q?%IF&B z9d$orqHk@i{z`f8n?=OpCv`MpB_ATVxv*Oq+N4pmt^Gu$Y6k)tGg9*W=I!>kzR*BD zc{lED^5SHHbaQi|UHAGS4-oI%!FcE694LqBlZNq9j(yHiukEFo!*t;Hr(?w*H;3`Q zk751tE-u(H<1a@~FN8T;E&cXHc4qMV)1+!+JEN(1Iz4X}#_;yd$rJ&&_wfym?ejk2 zE;xqTzS;U)c-sqNXf;AW`}y;}x9I3;!r1e-V&wp2k$UHj`h)N3+`iu?>GwbaJbiRC zg4*-d+TY|?=?Dg-#x5|7@n57o(&0?VEhOp~hKH;CpS#E{-*p+P&IAZ644S&jR_b9b zC$g*(EPgUZkaBDwMP%ay*I)lw-h1keZ$&m2r}SXf>lr z9iOOKRDymE?_3T-~nYsTV8ERKP(BF)HCgH$*ssAEruoQg)f1}bo$o<9#A zeWjeLT6L0&T-gUHIpKGI9hZOkSEBvWDER@>o<#$p?mg85qySdG9eA5nN@?_{Yu_Pt z%|0kNTNM>5ranUY^<9_Z15$8{(x#`W_AG#e%Bdo&p<|TW9vCe*?4_iXxw1ZMnZrmikRT;gN>c^@ANIFL z>^KQBHDW~UUFb*oDwlV?QPs<(SIFD%XSAYC?+Pn&0u=S-ozX~1Sy`bUZw*v)2I`AS zO0HX}4j)s$S1oO03@gOY$5vK4pLL=;bHpnvB6WG^xCdfd(T+hZ)&kV@YuphVLAab% zIypa~UI(cjy}Zji4!t06bfdeH3aJ`7siBYl7-MHomv^I; z`sJ!OXB99C*A`p#IQmc;=@Ys53(ZN zE49>|wXktHtSA(*9?Q9v^e%qpkDsPb{R8>ki@%6`UG2v_9_hdD3%vxY zH?-J0Qxb%=Sce1|CY>&Vd{=QRONS-qiicEF+${uJLnL58d{Byp1~JA&$s^~PKT$_Q z$6BF8s`~cqwrP4%bej5{2Ru!m{1phyrEQAL`SdW`$KYFL2r*zJI|1~XQisR@+2r(XBmZXG{TsqY|PkG~CYc}G)rJ1+6Sm$5Y zI%z?Pst&*T=T;Na7!z!ST^6FlGgAYqpdx(l5VwgSGIG<4n{qY6nq4Ck&hn1tk}YIi zuN&a|J586Iq@z!C^B7I@6y8s#O4elapxqRwg9FZ-!;6k;;cF#!F}|KxmN498To!Dcy=QFJ)Pj*{0A0bz zRMb5r2>c9J>q5>#WP9MLM6039|Huw5XeOfTFa13qaXW0ljcn$NN z*bQ5yc`8g-uB$2YfBsQ}JmTougZvPSS-{xPs+D??KX2v2*-0QXFIkY{ake%;4N;iy zV##2RxM)bWenz@9+0|?|OzI1c9mL8J7EK0M4hfnrKRi1g>Hpfm?tmIk(7VS`#B zGmf(y@){lDTF{84E)+DHy}6qCMP1~hSISKo-Mx7Ds)ktN4X1+ZiQGFYJxvzX79}I9 z=K9%Dr&Kk-Qn8=bvY}zmLNGuo830Qf1$He(N1J*1laL8Ve%Wm{y~Bu18NMwyxkk!v z{m{;Xmr7}E!EV)*70t3a{ri82es9ZKHSMOj41R_(&=_LpeR_j1k8`#e>w`V?pDs^X z2B~Tz$^H`co1GC`nHZ~8qz8)=n)y5T!+qpHbgjs=)>#1Y=l?AZu~24aPyNKMjAxLm zeyI`QXF_s@A<8ks;cDa#0hm>d*N|L$skaCQS$^aVxgPt8y797j!Ck8_qH&CbwJ!}0 zT2V9-N+(y9vm#uC=8C&T%qR!=}vwx=3$J}DBI@J!rgSVDlDzx4%6j$T;($5MzV|#$moM2t% zRh99r%l-bEXFF>*b;&JR-ejJa9`|V(Ox|Lh3z1Pyf%TZtbCmN%?Ua5CDBb2_Lqc0z zEPUW}Z{1vpN&&+t2tIR)dolse zYK-Qovd-$IuJp3u&a4*BDH7{2N*(ffDaE4E9^Fy*H%am@zAcXA-UJ{R)-Y6@#$ND>L-!Sf{K(%L%0}JW6WlF>`wp7lRntmLrk&#v08& z&OQtTMtr5i@c{u+W8DA8H%-&0xYOaSMBWL-C5L$TovYaR1R{5IQ1hm|%qpAZAe-lA zR}OrJieI9vdr$ABm?B)yF#=p}MDlwS@xZ}PkdNJ)v=1LXgq*+qe4K8dG&ZRF0k@wD z=<7&*bkALLwR*ytuT{{yO$OqOxn>iGA4X$%Y9wl;-hz z{s;g#gaQ*So?{fDJi(Ha299W*3MY@Aj*e8DZhpvrPAD&PV|#N`?@Mxr!e`BSmPI}K z*rNzmFE-%kXHP@yhb$&t%3lT*Db%dB#^{7&P?N(%C6nlt_k^WQIeGep?L)lhWR^prQUPP)Hv2dZ4Q|#w@j%Ti+ zr~g)h)QVYi(cb-w;9q+HCN}Q|2p>%$cKw!T=Yj)a(7(K!*u8ic;Ap*MGH~EAufP4d zDnNpAB_n!o@vFYmgpK><8BxqDx8{Y|d!{7~mYEP(74Dt=2 zarfdC-;;;*`@e)=(RBAB2;R2#_4sSw()b1PC;Zm)_&wy~seYlAN&3tke%D8LFHRSx zPNQ7E?~eNOJ^>99-@OP#`4#Ix)e&WS3Dv2+kI#^`r}VQNZBd*T+U-dsz$ws2kq`aK z-C#?pPU*@gcgk)_FM_nRT2=~~ImA!eR2 zT{37>!a@*ZK2kpM^a;`&#=EpLX`Wi0(2v zyFQFXp6m-fYN30Wiwn!#NuzdQEw<*Cvl8Fu@|mX<6?Ry7DU7v(WJhe_SkC7VDiIMX zq+I-xQ_Uv{WJQuee2flj$)zk)Snmi>S59#rbejF0X%s>ZJ*6*G?T`6wx*08(-|^fY ziFjAC&%z~2@vBl8!f#Qc&a<23M-eI8Tq~nr$8dX8vt(c8M*m*cL|a~b*mKNQ66a!8*eRsEVN#wX zapVo0Gk5=A_TB~Pwk^BsT4(3$!|ucB%kJv|zQhCBX|C1{1UX=n>If9OZ#SkB8tKp_ z@(^iT0t9)LMImT_llXO~NnK*lbb=a$fKXytK%o{7gFy)jRsazwgd(T~B`B$q6qQ0y z3xB`=7;~+)&*S#$JV33r&iU4ybIdXR<1xpa>#^szzeI>gVX@abx?HDb6{b{ts7N_m zU_qQfq4P<6f}8(FYWNiS^JtA68=m{6$D;fKcEt9vC=8({-SBAO4Ca&|80C1g>ZrIE zVSvKdE4!ss^@F;~Dc4re@XmFrP;~ulE7sB)v0!C~oWuS)xVCg;D`LjPs8sK>>(uNM zT!UwnN~B-ep#1YcMB0lEXYq7z8nF)d;j-p*cNZ!8$Qi;BU#!H(@YApiiZL*u^R0VUHU+Zl*Xsjd|D@(gG*`@O|T*^#(ZjbEd z^VeEpkH>d2Qoc>#H!IJGow1jEqbl3HfUSGT;qU&j_U2_MpSEd#)Dcit zIjal$xoml&*v-3PDnHZ`L+BPj|42--8S7!G{|d2IjSE`HQa}Uf?bBZ}QVIiMK6b@s z4j;>A=dMDMN0YJ3ZRT$=V}MvB^CocM6-iHfQbwUtw`b3#3q`5SQeBzba8kF4+le*x zGfi)&aLsF=zrI^=k`kj-6v=ihi`Btx5nq>QT<$GYSk9px-}&JF~ zTjjta;a&@d*1kvL_eS%PR5eIib3WGt2?h6*0gPBl78p=Z!g>~DX^%n>&^0z~B@ z-wp@olW?03w~j0{Hd(DSv;?uLVIrYVmD53rN-?-JSeJeJRRDoKv?h`?a#5?~sMtif zlR5RWrK^V2>BK@N#XK$roD@oH7WW^4cK1$s;=xtK{8he;rNq40x;c_pyt{_X9eDD3wZGM1Oon1w$`R?clzE;G&;H177-F3SP%2jf7pD4L zk2c}V=%&j%j8p>HISzquJ_!o!#Wx*)^aWs#!QWoBWc7J&df2Ap>W+h+`Q9|_BV&e( z{TrKEEXp&m=6QlhoZ#g^q_0nH#>$#e9c4RG4h-ToNX0cXKsF>^!iU)TTJ*`>Jb&g- z89|7&-%sN|%Jna{&iquux2WoS#DybWiEA@abj{gXE``0R)GN44dkBQhenvycaI9CU z=t}NR*9M9Rq)g;q>`;5}$fn^QS#dW#%)8&+r3@oo#A4 z-i=04r^jN{QmdZpb9%2>SSd@v7@T5R)G)S-pK2P6E2TpTvL!Adwe-|HrplULp{m)( z9QxefSn8WuYa&?fmFImWYCi9`K<(Rki4}?5heaw#(0k3HwzjBYir9@R=DGU<{v{|1 z&W97B)WeW_s$3E2cctqg@(v>!s$Bt?A*ie`2Qy=sZE;)hGuPbIXKO}flws$@vR|SK zij*HnM#-L_M{2zor7OK_BjtbYc$Tj1Zx1*N9#%VBu8ZkW9UdC zfu5)$zYwvSkahS9WneAVt!gWq5nfu0&|*{=)L|z-^?$Z{7NPeUAt*6(&9Y=AopywS z>(&v97!0-VXgzoA$KG>86fTI5)>4caJMi!3u6l^WTm zTmcUy)wf)P<-wU z2l{=%$IBo0DN4WLiP-BlOm*$cl&8*vCj=G)Jm_a-5j_lM3eRa(yQ%dIz+-3Ud&U9_ zV>7ha59T9xVK$^FY~Q0RRzT$~8|U)Mk9}LID9U)Q(gwBn$eW3W!Kb(X#b0_g_2j`x zOgZ`+79JI#dUB`BjW=iqRkv%LITIyv4cq9Xhlul*#z9S1Yhg8kj**5EDlj=mQ`KVc zLQhjJ-=4tck3q`6Y7#*}p}18}JnUhTS9Ks2>|UgDoNZw%o@?+`$1$ z@=I2walu(h*?Svj(K0x{EhulqPzW{|2{gODU?zBl>(tg{`YwUq!D^MbJeDHoE zbhwb|Mr!(mgZ`9=J+5JEE(XzFEv!;oPJEkW;U5nlz!p(#pHAOsd6!*Tw551HX7}PW zeaD}t5$#fem7AgHP)e-5s}@;)de;hBD!%;Xvobadtp}an;$n8l?UdlZ))-%<8%6Sb z465Bl9KOb7$Rh?-j@`Qt9}io!hK-ZW-eu`9wPM4fu52o8OQfp5Eua3>k4>P!RXUOH zz~vSo%oT%5biEu_Hd1^Zd&Efe#JQqA+d|;Wy58Z3x`8@ku@2RsnJONRx&xt$H6Ybd z+0Y%BCZ`q_lgoBVIVwhg&Tyr0M_=GamE=pBDkyOirhTUUF?^u2>IB!cn`6_(hx@GP|v@tBaM z5(@<(aP(PCZV`Z7anoh55$Q-7;L(zvfE##@gqL>-fA7mHlYmnyDmd|fe7P=-#;Zxn zH*waikA&lQwKg#J+P-*V4Xz%cjtqed=p3mzJ7V3CUgB6Y-*sv6T`k7K94Lv0?79}< zQLnUo?`AxrH#WtV*)}YQZBS!Op^S*dYOqMD1na-}&th7i0^6bMT(xH=Tj?B%mJ+K+ z!NKKL!J;o`hqHWXYwRlPM)u71r|XJa-dcaMHb=D9Z1NplB*8qdN;g>ry>^l#98Kcp znAfRN!YGcT3D5Aed02+emdG;*r{JV7&ljjj5ZW?cg;Pg{;*Lh=*2pnqBag~F zCG+n2S)dMA@8Qxs@=Zah8t1XL7U6S$0A=~e0G7|a*;?NcsamIiPoxrXy3qENqP`v8 z@YZ@+H$b*xP8ji#mhB9~;ZnBR=FrFLOeJg)rdgiaee6AuWh0csMRs~Lns{4yk1jEv zqv~m`=!}ZJ9PWW6QaK!}pdb<{Vume4v!^=T0 ztRBPSuFR|sqz{*>=G>Xtu*2lIFx`9lb8z})yBGP((eL$FgFg0EAN`0=FQ0n%;%jI3 z`n~VHweRqKFgRq-Z>-evp;n5q)EQZ!w+z*-&C#`XF`yg^#z(LaSG|VZVC6k z?caML{Tbq02H+W9nx8TT&x?GwDW|93ZPAwqzQp>+e;EE!#`=;ihlC~XSZZN+@bfaU zwjL1!+_uE7~z=9>fNisi5HBEr2Kxsar)S0TvH>y~v|Dhcms zS6Lmr2;w3X+!{k*^FAf;a%zHiyFhqQV4XWNtVcVxoM|eN+i-dPb~tE~A}Bjm{k%8* zrvElAPqh-0z@0%|C}kB)EVLGsD&wwp()2!x5SJd#Iy1Pbs83TnMo=mo@`SNYw&r$= zQIyf$L7}*FFGt;Y+8B=Jd8T`1Sy#txmC;Q{V^<@*XJu6CEktYiFY68=WT$vH`CaNn zJI*TsgK_ZabAseDkU+}7kGFh`ULFCJs1SE&zdMsr3;=pC0%E&Bq97;Qb&S!oRa>qQ zmAw(5W*RPcn)a3ph2V#4<91gNe)22pqi&nwH1F)YQm^RrEx!fwbWkC&({Y$)wyHq2 zFXU{2#lY9gPzTXBeljL5$s7PpsKW{@X>c0Bt1-+zionNmk~ z#L?-WJnQhpMqg-}A7b~Y2g%e=G6KK_sQMI(ZPCCf z`$ZGWri>1id6*qFt%Wg8-05M{BWgZW8e*ExHsa;#&B(nTpn@-^rUIm74zG#4>aniN2qb4I+N#S3~7BOtuU>=`>TyomYbFohhzLv_I z(K@YBHl`Ljgyc7~QiZvuxm8iE8k>mFWp>toL4s@We%Kd+l zw6%1K%sI!iCSQTj^awX)`5n?iq%-{$;K4qq3!fpCvE4Ud{21wIsgTdTbY=`^JegK| zK@$#WwIUHk4g-^ljSAS{_-59rwm%%Rdr7K}ezB;?7=<{)(TYq7N**{M%v{Q*k<%RX z6-RZeDU(xy9EF~0sc3reW_$xSccfD5meoaXkv&dz{zx}gkLfv^{;b0%Yqdglti`3pyQTfNbb0r>$ zWCWIfRPnLe5%0(p_N-wbOK6U+W!+j!Hfyg<)w00^^N4g7#M~s(^ie|GYh{?6m~ic$ z?*fq?aY_u*_&cw9m+&;mSv?DgtZ2YqotGs9T~|j;DheW_H8OLwVW4*yIm#=bS}9hf z*@gwS1+QXWL({2wl?!s0M2%nSrxyG%7{^T zdG2Es*O^w8C{_W@)Q9nZ>pxZ2g{3w*SLXn`>Dl-# ziiQoL*cd-u9fLB4CR3#r;RQsivS<%9!<5-saPytYGuF{tw|zoY4HB|H|8wPBDQLmq zhx|-mDMnK1*@~937_>yp;nU>x_w^b4O&ag^ILXxWWrdoL^WqK8Gfz zku`QErZO{8iRkb8<JwEi{F3;wmAjRCNN;!^9}^Or z12$K^0;(t%uieek!C#aSe#TZ)?)~N;T9Z{2452~$h*2tO9?FdO*D7@)3l3Ejvn_E`MyrXNob29*oi>|-E89dZKqQWoR zBJFdruM4ySKLW=-!c1D1TedTBhMXQ?u>0O``p!(ezDQ7^jhvIQ3jD%skUe$^RagFsiR5uqT4CiD3j+%T-AP@&~AG z;#$96NBjQReAHw68ZUR19 zA~oIJe}GNkX-Y~>=q+T`CLQcAx@EnM_Cd=SVh?ue;<9_uFMpCtq2gY(MH6g(7w%iE z#3aMov>UQ@c1!ddfRxaGEzds#Y+9u*rw$b18ltz$0O)Cmt z`ZjyS*LhCg@GW%SzmFi}jQRv5d&S&$_!?QqU$VqZ=!Xx|f4FG8p?Xu>o)Y#-0_Ge< zwr13BBG5Xp?_dw)>E7*=_%a+bd z%kB2n4-n{Au|?F=(10NU1BJ^jCy3F0_Ki=+p1$_MW2?U#VKQRHU-t2p$iW zsR%&8r9z1`UlR(Lo*H*E(%$~2MdV1!Y5Laph?B^;!2pgzu^b^RIbE{m5w^(dO~s;m z=3aA6^%x+HQx^qYd=M+nbR5SHKj`IROB)mAmV7nNGnKyPuh7U%Ki2d>DD5CtS)eYNO1Uzr zY*5FZ(|Z0PT(O0@n|JB9^~nW2vvm1JShH>Vnm0Ke?%%hbT&Ri)INC~_#8q&YkQJ`$=itPfnFW2R3cWnTb)_|nva02B85=& zGG3)WKvGAu=F!|-v~|tm+1@KkVlgwD?-41=knAxYO6ep%-bTgyk-^ns{h#5i)DRC| z+JgIwWLzsA*<*S9pOw!f82z(mAKY9=%%qL=`>o z6J&7X@^}#r+cCQrhuOG(xJ29>a&z~av9WTB=~=18{D|>UQ`f$G{E^Ruj3#7JhD+35 z;A4!TYuQZ)B$3jl039c; zyZ$)HO-7;A%JH*4Z{M#{cYbR zJWURGsi@W1`H7%;p?tl6ail_k%<^G}14-;zEOW=f0;~)m^1;tu4tV6GE=^!Y&!#*L zX}5<>58i=rD_z>TL5ieEbX6vJW*y8cU#{?RI~R*wRkQ_@cs1ru7d%okKkm`+8^i?i z-3-?tGpatPKhyB?<3E9Y*7N`I^q7TBV}9(Pq@$1oF~9xm>1AfRK-Ix=A5JTCs%tM@ z!$%>r2pe@p_%AFX`PY0DHf?pUJfT%7W*zmSB3$X}8sC3fpZTgS<5iAfJCgY+6U z^4~Fq++$Y?2uEYq!(&tf5W5>IK0o}QN}#PSA!o z1ItyJnr6Oobzn%}k&T{d^ zRv5C}rU?wlef#5obJ{K$IjD6u6hQSvvboIIT4{YsA>Z@b!hkxj%n}|CB21dpQXpm^ zYW2?>6FG2CDBNAtTk?NPAH@Ygq6t-N}UJBv7@pnEEJb|4&BDLT9yR5gC3@9Lcn}!NNZRnbxHzt~^MMGpdXP^jXsM6X)3}~=oot3vYrMc1 z5ieR4J;ITLzU=qa(%|*OolhMwoMwGy89)57CM*C^t5oS#j!$wlgboeodM8x93e1Zk zJN5b z+jIQncEuY9j2H`7ON3q#lyzZi5ev;Zn-SGrXEm4&6$A>7dD!G^9d#8H24aa$$NSk4 z8yUa{m9|+GeWE!>sv8cqJ##d{Rn+k|znZTQ8#k~T&~3)*3aW06yjVuO*b(La6H*QPh3){IHH%Xa>ZTUmJ} ztvxk16>|Bml?k#|Zc~YsJ(8B=1>qllhDrTVS?1&%+CUs7Y_WBnltWF)rnRbSX!+5} zErV}Y%GxJMwVUbP{JojswgJfTOgWmdq0A_s+jG)yW@&_h6OIfg9Px~DFehzW02&z) za424VC}KY}eQ%+NXMu0Q(NS|;NSDb0)fW^}x8<2&HOp;_UlCs74B5s^pn@@Q|F~hC zFQ`Tx&O#pWv{!whj&)*|YV5u`4g{h4z``Dh=> zYn)jNvYUlGhZpKd&t}kd*0~lMSd?n=nqyf3n6C}$%*F27z#-gO=BvDhO|e8VSHQ8J z&r->xvQFB!@ORs<@!R52+d!dT?6HV4)nQ(KFZv@~YjFU`2V$fX{&* ziUy=go}=ZG-V?SA5o%qb)tvbp>uDdTY8jF(W( z6-C%9Aox|Cp|4geIA)$Q%{K@|i)b4nX>|-EG_C7`=AJ@{D$R>fTTx;G+JM=39PoiayOo%TU~2eWOyAB6ZDKG6?E~%k085 zX9I&CW5Z#$l{6Hu+PHp((kH~DPS(ZCmY*#l3=5W$gSAYJX}vTxpVqCflpUs(Nr7o@ z;Ra-t_x|WdW0?;#eOy^kisMmIq1yA(y}bV!(kYh+q7S^GvzP|Pl_I)$5_p!hLM^Ek z!77SgNG~>%1=XVRzjl+ADKy)raKNr+f5u@QmgchZ+6N#-8~dy|;E<_`y8l5_EtyQg zS|L%I=SBb!f(AX0$2_a5I#2K@;mMja&kT6PoJl0=Y1{Y2KItRwypfCWgQ2)(t`n7W z;B%wIUP%9BEdO|s0m-)r$kc77t0EdWFgE3hov8j!zKf0TJ^2%g_yjkmH{k9j#1{Y!;j&6Y;5RqjTM8%7)4oGN0qX)h0@v?bY8(v8 z8gVS=YpBwogKZ_+3vq-1^YS)Ql$fBafuk^ffI~NChVAxW^jiRKZXRS`Lc&2`$&626 z$(VS&l=6*ll=8Q0;U_P$*N^YtGdt8^To*1tMagFXl=O>AgrY2wYLr5cN(~=Ua<8Of zlV~#vYU|TqKCg23E8ac3dy!XMS2~AoOEwGT`C?UK5cGWi)H|pD==&R}8$Lwt9c#Ln z;mq#EeBWW2b3D8ss}7gJ_ojEecT9<^y?(sp$%U#=P|jbDKD%S^J?g>u&-x(RLBTeL z`Shlhy9CgTbSDmk3Y>u{snhfh{!;YxPIgizj>iY@Cn-V6)+Rm(HQ-ONCEvYBj%4>@ zzNt$%#)uDl*dz4z+P(N5ak1@H&3N@g*qrt^igE`%ZC<^YYDne9)$|R1{}hpON$=fU zNcE8#K4;)$(ASC-t&9LqWBD>o_ix3h@wQ1Xi9~%!lnZ-Bs*?!Yf?ie_sn)JrMyjl6 zTe@wkIu+@~q}Wos?6MV4-yfUb$tjB>m*Lt{SxqI8vR^LIsAy|xEt}-`7~ebiCf}wj zfU_@J3`OjVyw(&0rLRIg99PD>M#3+XuwAg=&N&4)Rs^6Tr7RPq(51&$sUAUP-dM-V zc}Z6%Qi(G*($qKN8e>F*yL@Nz8NabplW#x`iVh~HT#zGOk*OFct&?D6F3lyR*g}ux z=fCE;kLVtaQ5vyyxKMW`eVtQ}@)uc0qzs@(qRlvBLn2eJ5w)i<91p>;mb228Q~ei= z`}^A>3tMNV@klP=&79xFU?c-eyO^N$>c)CSn@Dj$op&lpb2e5^jIsxNOcsseh(q`I z6zl&;#NBBYdQu=&PMLLh8-9i)dIsh15>(oFaB4w5KDqXf4f9FxN zu{KnsYJ~y2J4y;ZZRrd}bz)|m%@$BA-b}m7v5GhBwIYn1Y8~U{Z)`vh(oqLUY;B{= zwdzgzi}_{=l=YrGdmQa5M)2A<*NAi{D826C!f>j3aYx$+d33g~1CsuVuZSGj5-Dp) z%N=@)YqMknojIMED@QTVO~rXs)+F(ub=t!xI-998=DEodt&grCD_X^8^jQ}FFZ*M$ zfwqY)9qy^PbMRm z`I7-KBGsW##h|??7sgKV+~L8Afv!_^q%0dk7<7FyRDH=)X?6Ab^<}>j_C&e^MCcom zqW1bZ%V{v4hYMvLqTGo)j*2|(_IU-v?yi|{M(J@63PSz63^hs}i!uq_u{rzI2pDsg zcH1($d=jhfAxpee2j$i7Q=rPYrRJp8ifwt*>U$oKsLMr;^~Z z-5f3yWvr#R99ZGe3r}wq1YUZy7^$Iz@^GP}mUgWWrMXF-Yg-~tKL@rvF^-@@Efigf zmgBIcc!#oHG04D`EuajppkTvH(3a&Wa>j1D_g%b4|9{Eu#Sg!?b_~9c(tU@v{maqs zd*L@Ye)41Q`Ur95?@udreDJ=M{{87|6x%OHdD(uJF~P{Hj8 zS1dciBkDG}_~yCPQ;qLDDCWu{VU_mC6B-%YX0TB6I7VI#s$vCJT-2$g&dEC^(b6sm zrmqV(xt*nQ)sz0dW2ky7opV-C+MAT!j)!5oclwN$Sr_Ng2+wGIAC{}vV=vS4tlux= zyP{X1uSlP&aW01EJ^v}So{rrc1IHyRD~SWiPuH{dYcu^?k!-PDtFZ%-#jfrJiYRwk z%x06kW%eb82Ww@jW9<~RIvC0lEgNhkFT!~5q_K$jgGIcRQUPtA zWumaIIo@p7K83ul5k-4BdG+yu*sBh8fb)Jz6l7w<+oyl~9kDICtm(V&$zn8WxD$bw z0(wM-Hx<7aUH&L}n46Rq|JOx7IjSrPLd zFJxWdKf&S5k(5Y{IA%2yn=vD$w!S6hSMmIKjv#1crLC@EY1?} ztt!1{RSZ+t{DH_Ue^n_5wAcuuwFqmTF}!7Y_3+M8#x?V(XG}8jW`=R=rfeLuGTeA# zBS&V`XpA!aU|aI1Y6rPXspr(s$A9w+iWozD{fZIJPA!eKcE_1vY8w-aOBRYkvtx3G zz}d{<7{RrEb)QlXsH!Mi&ar~VzLahb8#Ve4k_a7e9h4Xb;)U^|HAg#LG=4@cYU4>QTG7TeAZH9nB2wyM)+Wi@y zg5b>mK*x|ub@&iYD2h#Yh2e)vrUQbn=W5bQV1#~d6?_|ICqvDih_@j!mEP&YA8Y<9 zT!ZMNv($yUs@hrVx@TAy%cK<{FdfvYhrjwE#E?O%btZy?PAIyXj2(@ZsFAQSs~<@f zj?Tszqs8VzsabLknF^z{G+%o?O@HK{QvNjY3z03GA{UIAWS6;69JvZQh}BHlJz~ur zMI%9;3stcV@#vqyG^T?jTaIuRdtnXe>K^PXKs)-bDm-WJP@pU<{>ovxr1wvZFSPUM zqf$Bk>pnS1&Xl2ZrmZV$BcTsHqg=DvEqjSjiHUGF^N?9j-e=_JDL8o3PeL#4)Hqez z*`K*~?ZjX@N4|Jh0fQ=kfhvCH$0I1`juP#gU-v6Qy+)TahX4gzP)#nFnKW05zK9NX zELj;>>@U_R^~F5{>#ci>YeqR&`yBtzbMOb2-z@wV$F-_o`&(D6i_0%EcQu;j&NUJu zGa*1T+8|Tr9%Qu9EYGT0wyX$+(aUmr%L>mcwyXNc3vUQ!8`N`7t4S6x)OlrkNUPJV z<@^13sPhWAaLf#yQ|Mf24RX9*BvKnGvYqwTY`796GKU2KCb} zzvnP7uZ3HiMSr2B);c|s_ch$O9Ji0Jj&8{n!e)Sv9A!_bH=eT`o-PK&?0yhPSxBH2({%Sd$8BO?+Kno z`P?PH-wFlmK^eB3W612$=S-iQDcFQhVauFT=V|(1K2vK4EL9+8SepE~SkCitxXe{6 z^W+P4pb)ZalvAw_v*_V6SFOAlrC45I%TRN;6ieIt5|nT+D5q&{%Xyj(muY>x1O=8K z^UF95-4R*eTHFS9={{V-GEM_lLwYwuca2Y~t2vBopub=U6@AUWkR`Z6|GH)1wd!JLY4+r>vc;k)B zV%&81b!+68p^%sZWy(<~GtOOI7uwjDqTId&r7&3t%9e`CKsl#(<%IoC7}MZc@fFKb z4a&=)T47#Fyo@JM*PZ7DepS1A`jmbZniXSJ&lG>i**6E_Irj&FvZ^^Rwv2v37MSKO z;_Cb?cQ4otx1g5DHTQT@ABHrnOHc{c`FyGrn8B`4dJ~MYp`T}zu2ezTx~Gbq{|dXT zKj-k#_ujMbaJiZ8Uk>lTIlOV1nE52co!ektcyzd&43+6kg^IGn3S-0l9r6FIP|6owghfAsJ^UFP2Cd3)uPRy1%A1>7X z$RFo)xZFE@gyN0&Q=O)p>F|Cs=k86?%BZjxjI`y}8D~ieDsMl%hw8oQ?4G83?|j!U zr;2E!d}~ndro*=)@#ZxO5t>o>Gs)Xfuw$UGqYPWNqP**kzqZ)&9Lmb0^Svj-mNS*< zT_2g^(PUf-`2yErsb83&&)(C9n+jDA< z)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z? zYLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n z+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!( zY~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&& z)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;= zkJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErs zb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W z<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>` z2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA< z)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z? zYLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n z+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!( zY~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&& z)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;= zkJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErs zb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W z<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>` z2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA< z)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z? zYLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n z+jDA<)Yb@W<=b;=kJQ!(Y~|Z?YLC>`2yErsb83&&)(C9n+jDA<)Yb@W<=b;=kJQ!( zY~|Z?YLC>`2yErsb83&&)(C9n+jHvEjMQoHA4g@HLd)qmN#>{i(*rptxl3dqEL>}( z>b>R+O_U)z3pC-Xc$R5t7r+d2E|@14Gt-&cc{+7_CPSM}{Nxyw(U!QXf5zua7>BN0 zy8}Voxg)*NxTq`XVQR^9uF5cXpcJ#z2uNO#=34o*Aj};@yoI0_(CJu|^I(`OSMJg% zsJXk^5>F#8b05Uzc;8o1KgFxtVGdgRXo~HkY0qG5+w7t<{Y_eUig(Bs>X2XSD2`P> zglG6FCM`tqTz7Y!E$JNnuU8u~{};0Lv!`c{bExN{c9F)neS6X3srHtFp{6@uQpoSm zIF46h6|XDOV0>}8s9*X&4e=J52hjG)I+4!OI9Hj**3~duZoLq4Wy$E@ zAT?N1z5rs?zv}&zz$@NDP@=}`xvmklm8wrs{ZqeEG^U?3@OEMbGM7Z>UzFtZVvw43 z7@-Ko=~$Af2Bi_A;l&v9w52=Qposs3Dj*u=@LProUI09R84`GOdUBl3@0p&6a-N=? zfjzT!pA#z18$))U{`_B)c|SgN1U{|%shbz#onJ^T;)^BHR|)VIvfry+Z(+zrJ)i%1 zFy2h3n>lrD=D?LlR%o7XXi(C2jvlEVQ%SBfXPGNX`IE^~Xtzk!98TMr-3RkEb!Y9U z)Z_|8xQ-|lz!TK!wuQ`%GjlrKs-L4lpd6=1=dg0kSK=%~cyfMH)u5dx<|Li)zg|26 z1@ojo9FIVPYnooCy#3?WI2I>qlvP~{*GD4P4r|@u0ugdsgw$&V7EsMHCUx8%ofmCJX%U3~9?<{lKVe0S z9$4WZUp&kii$pN>$7P?Mu0oJz^@t)TKQ~4-QVTOn*`v@3!H(lo&m3V*=0;Y+>FBC> zlN6PueR}9(=_H6w!W2=b!BGy^OX?8YO_fDqRt~6WLEITvi?b6p)A8J4>Xq2(UNRQ& z|DRgHaR?k0l#neQFMGO?1vVDRk_j+G!W790+4P8>&OZ@!h6K6cM-*qP|KNBU2;3{E zoZGxxSM7%c!ZsZVPPcCb=N~R>%ZUp2a+O#kQic|>KqfBKKhO4K1rjQPMo+D=+<5^Q zB^7fBwJZ@Z*?-2DO$Thb$%v5&Amub2orBAf48g-k{OCBnQFlW-)n-)&??NToQ4Nhr zSv@)!2F|faGDb4KnjmzXKmaEkuV_$L6h9KtF-CnweLBHalb$Z!D-`iXQ=2v9xyBGp zp^Q$OlH&eG(B-WspGeQN6J_zYEh5ItY|}DWmDN5K3L_h2$UG-PL8xS zS>x+y=xT@^=`=egn6}t4Kd(b_NNeO{ciC>p3Z$%FGzGIyYpsGSYYd7TjGpo%&lP*( zNv71!9f|+y3#Wtj%>&wWG$aNJT^*`0-a?Idqj0z=FA-9_-3Y;!EH!JW(Do3dkEYNn zVulEy(Mo;>AoEN38Wv19O=iL1DOK4|M;RABsCFr7!pbzep=O$a3Vrk=ah(3cci9{V zkR?9|tt4{ln|ob}Jj#fwbB5~ND+8)c%Qdo&l4{u%pJS{C&m3XERHtl4@sv*it9 zX>?XSZkvv|TWY`o1fw8nHc&V^$C?{k;7WgHYsi1yYu{n!D2!oQ$jFQtSiP$9XB^fm zg2}Z(mZ@%~2PO86#?W*4*hpzc*eh~?b0A5q%T^mC^rUp2x z*}rmurS!DtUMf7gS&ijvZ@StBi&Ev8pT2kwwLMFM+Q_k=`n=p>Kt@uTU{glE2WDi_ z+}ZuLh(#)5B|9{$0Se7w<3JyFRPR-U)+(xApwsjde*AjwVZrq=FriW%14K*tc~Uyb znzL>;^4WdsX$8&H)>j+rq3NbokehY|BT7;t3o{F=%gd=2)DN7G-o(@CW}uNYUFt+Wy|Fv zA*Bx7ult4q&8q*|)@Q3;aJMNU;PaX!)XK!Gx_zdFnS8S>2$Bb%qP1AE{*JT|YXO^8 zH6a2%O34!PV?!fs7@2wfl2FGyo|Om-T6IUuxFzkG*OHIsTU80O&h8y;A4Ixd={DvT zr4N#GFZyeSL}kaAWenk>6mZ*8A#Pn=aCh?se_%R11@xdy#JV5~TH&xWuu)6-&@3qH zS`UvDN7lVqLV3zlZJG~n@{}#N*pVCq?0w+P!`zuC@zuh^D7Td?Q`Sj1CkpQ$Vw8^r zPCp;p706|R$|JnXlN)udJTa>bi=}+Le}Y5RAkcN2Hxzo~dy2?#vV=L2iWKHPDnpQ@ z!!iHNe}i@Eeqs`nknuk!k^Qf6rQWXkiT&k+!O=OQ{xG_3^7dR~PI=d742dL>vc!wP z*AVEWhFJo!BGG;?j3P2JX>A zO*@_*-FSJQZXYWJ;UNU2%a*q&RmxRBVb=877KEoS{tKu$+_#I)a_wQBdXCfErq^z! zd&k#Nul@%gq&!@X$7;W+bx#>J%n=@=EGN>|kti-E(A#cayE(m+7tt~Ec=#Y8JzUTw z>ggMe?j0zxfIQJBQA`_9>_&H^9G^t@Y5J_#@}c8xwLjs^e9FzyW1T#m9tGw0_93=` z!lF?&-8;UfN7@3{>D3Ql)2kQK)Be-fnZ|c40=G^E`d#;?+arTd`Sbr*PB-i6M~aTP zX*5T*8IU9!F^JC?kRy|r8qBcYo^H*8IhBl$R@7{>BN4Jd0xx>QT+CMzI1w_wi9`m1(CFF8{MM(_v2G!z ziudvMQRdLU`XAGGzwl}RmvO{6t;3x3XJle+MGQd?e9SmD_bpb2ZmJt0Q>}c7(GDjE z>r<>9Y4iAT7L$o&NPlKeMS#2by7Iyb!y~LhLsMO^``kMr=lfRpg`#u zDOD+#h=G#)K)S}2N^l-Oij!@|mv$Lv>%!{lT_m0$COyom_JD%Y6@-nEQ3lH<>jWi?sg>WvrQu)-?TQbvzR zjM+It#bqYlm2pHM!wQ$PPcu7G13lf40~W)Cu2s{B*pE;~%O1fq+*Dj?hB1^lZ=^^T z8RMfF%6zFd^U6vrFj6rAZg09~&54vsaHtrlrCsY37x%n9{EGL%ax)#c^W>0!9K)u? zv^h30e=y@xssVR}u1dy@)v?)Tw2m8E;LC&v$GEvDABPQtYhJls1M#`r<&xu(^`BJe z*(MjVwUSdw<_T(sa@DE)cIa~uf5r#cwl*tmf(#1g#pXwUE4)Ukq~=(sdC#l+=-~Ct z#d;Ht(^FdmzR2p*NC((cbb~U}={{WS^T4>%bZ4zEfmS*4;aw_e!UwFjjYXGDTxg6Fsi3f;7|{!VI7o8>J@F*jLoYSbPD>lg~c+;nanBc4b8n@{%7dAdF6dybUw3G+<)JD z&u4DDD4#q*`^VpS@9EvgGbB;Aobem zbVvCbD0d&HeC?QWMgi?(U-eO?LHXeW<#o|Myr6(4iniQ+{KK&Yv@a6n>$K$xWwAw+ z*_JQSCQvBL7Cq9Y7uxd4Ym{NjPrDS#Py0}zym2}I{hvin5y%QNmC6JweN3Gkj^==nCEtH2E*knhwC4&^OQC=%A zL-N$TC?BiWt`$vE|19W}CcwyLZt^;nUYC3NzxrQeS57KN=Ypq79bF{JTNH-_CbD2_& zuk54{ny}lsdev*I!jwv^4P53aG)Ext=inMYg2v7N&&`v}80u0DBZQ2>OnKbe%VBr)`2SDMJ*alHFXt@GpSeR#K zOVBk#wZ?^EifTn;N={8Ikf?@|2tl%12NBT#qQpEkJWUtUdiH~y+)iAMJ0Rz2`nWPdnXcj}PxAx~nLsDg%Qk7IboN%Fvq!I>Y4P@4FfGVT(fcp9YB^rwHk z>r_GooYOliB&=m^ViZBF<5AIeR^8;iKHrkhEUq;j>jjZO+_l|gZ6acbCLzS}hb|*) z@GSMo$3;t;OrFX!k(H?MxEae`go?6WB-EgRfvv73e9nTTUh*8^n#mocO-@HYMxg^5 z7Z3>KhOx=VDCq3`01D9vC3K4R>f70%otm5AQFkne6(sj&2B#JWwP~5m*8Ge^jBrY* z4hj7}Q&KI}Zdb@lO^il_7cm(h>N3XlJVZ%JG9< zzG8SPQasA(@;ZcZs_tr4GAC*TG_ZCLd_m%tMD5{dd(j0~KffVcYV8cK2o8S!<8Kc7 z>;$3?@`^~97!i|f^lN0GWlTzI;UZo4$x$Ad`SeZybvAI!rk9H7vpSyQ7P9H0bc~a) z9SjE@k}8h~tn(;_rq^4cKH@p!s9q&nztf5XSIUBr+t$2nseaG#rJJzzr{n2pYUHX8 z8m-KWx?XT+r6Z%aBW+W~{4n8Ghsr+o@nPoLqZL!SYg|GFU&CfKA;#?bsBVr-C!l&= z20Mtg^2C@~Nygap&(X-XDqPQ%l@rdI@U&c1^eI4#9L;l+mZB8Q!e;1bm}}K23V}RM zU;4@TVYOygS?ASfga_xaUb{M&`r=Pu;7U)HS*Wt6xBW!Un90Krr}ZK`K-JcsbjqU*-r_vUsGoDrF*?9;B{ie#CE3tYCAF9Ikm)i(u7Te`8ge z%*Mu-5^cf2j9e<(z$}w;ZavBM;dt9u+;Nw*Deau|sJGHv`7_K}ln1`AT-5cw-0C!; zP(v?^UI%E71=rzkzOH08eD-?^e?0qDi*sz9O)Tru%xTu>eTk-&YePe=$YWevf@?iB zvuP~ch9I4@)~X0*P;{U{qHwlXKH`kiHh89!o%vl4HIbjN`=jt%Jas%Z^@u2Ys zfBj&XGieaG-A}cyys(%5(9{-Vo!GS$mksIg>N)G`YQ#Z|x!XNNJWc z^ub#Fy_7G$fiU}72`X5<_|%X(N_b{$YTXNF;x4Qsi^CH;==;L&N7G-!s@wG0oCX@j zNRQFh>RL{vc#~O27L+h&+$7Rf=Jf|Bo#YzVs0xRDv9$vmLY~e<@&HPrKM|AWp?uvb zz%hoec!~jPnbhf1D1pa*?Em`HDQ#! zn5WnEqt@f+f3xia&wjJIF;ixtSt61%UreWOlvJZU32n4g)5lmldyNvK#QKeig8c9C zE)|MbZP8F|WvezWlcs`uqC%bZ&b`A7%DHo<88X(Pid`$9bG{%H<2%3b{Z`B&r{6Fj z)jqAE2Tp!>jDFCbvABjhqF8|JTD+rED;qrZ=r%@EBNQJ|?W7ZHWwrV`a@T=qVv3xq zyG5Z$T>sEN{27Qc%&T!J9`@hd{_eb2v&{<5-Gx_70iY~%ut|Bl=ldoG&^KS~mCH~( zV#Vh1n45GSdNGF0Q0gO4Y@mBgBKr@idRNRxxJt4Q%s68j??Ywv{j4vC9l-J&s<^y)aQ_Gv7$-xUTcCFDwvriMgr+D~?=SuIX zKzfAd5#tjuMcpT%HGZ_H`|tRR-vy5EJ(W>w{L5X z<8UqS>SDj3AGcM+*>Q-rL`Hk;Rk5opzAHz!x9xh3iE$;*i}<2BCR{51rVqaO#LIoU zBxkvC@jt^tlTX%+Oi&z2+B9>>q$wT-z})eE-@TAX-LTUVBV>1fA8-HTeI<}w)1$9@ zgU*}#51zu-_p2`~z0vM%RMk%&#EjnShw6%KHW*-0qv#d-{G9J)rDHs!^rw;wil1J+ zm2^;J%Z$P`u-*j*1^@7~P-3Ic$S=1=ZT049d_sErnQ*^z`V;Ta(AvQPW}^PkRL9kO z4`0h?+zAOEK7No;9WHD`p*)>F;RL&rlh@}|(M~Gea)3uWdn;+bEhxv=-Fd?{lLr^L zUj2~f*v{_7rwI7EnEy;(%cJ`ag95h++$c|K|ITe}dG$l=eJNWQi0SF+^!Sg$`!-%ukeE)w=}oir4wO8znCVWT)9D8$6@TL=bn%8Qv6Ui- z=9OElOz5?|BM2i^jbr@A{saRp19Q`wyOb!g4lPCw=CoU?(i$!!MZZ2G#flgH-q9D| zg5s3th&14lVt-G?*(y|@~vN^LCc8rt~#*NbAWPNls0{51^tg2-NDr*xNd~x() zO6DW&%SKVy9uX8kEL~~^bCYmTDxQ@WppN}Jm66(@mh3-_bnVWK{h%Dj?os=|z!7tY z11bE^GG@d|x1%4v-o4d>G(FDM_{aYHirsNXMdZccXdhFX+sPp#SmrG`6&l*)9aWQ0QWcj8^S{rAH$;GYTUV1@rj!=H4{@RQ7qIZS0>)mpLP>_K2@lT36$1sYYW_ zYMspoe z!$xJSAxKt0QMxxTX2dhrKB#BbVM>z95rGe-p=*?p$$FB2R$KD)^X@cK^8+|NkTT~C=+%bg9x+;J zW6R+(adg0@=_!p@93w)1>qhRQQ`<}IfhN6T_q^2&1cc#Dbwiiej1|JI&~*wg$QCY7VI0j z|K#uCbj)uUQHeYQn35v6(Cau(_b=4SW!H$O()*@lq-0+PjD#p~jU9sl)u=)#{djvP z8*!$PzshHuxQ>sa<)AoRQtMNpi0;u(F=J6IvZJC$Phf}=35QF?37STfEhCq*(hh(B zgFgVrP45_d`R>J!KDT?3Ty@9bYrT8%yxw>CzW2W6j=_&z?-(5W4&ANz7W)pr{w2E? z|GZMGJ&<4WmMCKn}0eH%GSGxjLGUB>kc9T#>&otFysxrR2()w_^OB_I)=L{pKHv(x?1$PI`0V9SrlC z@#Lr6tKCU@4RHEAFJa6e7QpE4tfl;FOJ3lB955} zLv9GFaV|9vvj+q`g+N1GbVJd{xW({tYW+#N?R=;0o9UZa(Q`!7TJ9CfxzS-C>lDQD zIdt!G%!OI4RK1wL)@W=}Y_l}Z0D73CW**)po{(~tv@af`%zlz;m?B^N@-&3XCNngG zF(x*qDFSnWGl$v=Izm0BBH;x}3_rDSR&GIz0F#8?pZ(QzB?P=j=QoYg>gzk*`S!fh zWTg6zYmpF`1CA&eUV$ulS##s3uE_>D?J7WshCy@6LMrZMODin8UkO_;WF2dVHz3if zxHM0Q1TNNFwKa^O8f!R(+sVkGQ#E64)scQ>&-_r5WW2pTz48&79th??;UqlRldwTD z4e%}U;S+>|4+(RxC}L7tB`FDX$ODtk8f{tQQ1?XCA&tGUdqInMmJ+&) z95FI1Z}Tgo(o^qe+Y45S@RbdP>>K>pV^7vS2ahP&7W*`P*&nvcCh2ta#P8ac+E-zD zkaCcN4%?Se>q5%^#;B+KKN?HF~B`{EAR^ zs|G3AXh(<2`N9EqWL)a0rWq!BF-q4tl{*k%$UFX89t99D9|QQw!5M3`mdBdY&42Pg zr=KWrXAcV*baV5d)~fiyE6#4AUt9k_c{UzxKQJ+Ah-r-}{$ zQZ?f(CL>mUR!Z+2l6OG!Lw>-RSQV9#Z|He*Z5+?X);AxHlsQS0?@w# z6J@A7{+bU=(^LK-2F@W~PZ8}{?No^;oys$Sz2Kj;px&|xEfEOKIASdGJ9~RBQ{_P*90m`m`A7V0CbaC zlIG3t`mK8Ul#>o~q|mq+kPsJcb?5WuFdcHClv=wmtk{ZNf;1@C11nDs49K?yAy98< z621Pgpq8ArA+`%{J4(79oIx0UwZ3($I`O)UC;)G&o|S^XV}o6@UKKz--kYX>_lv2Q z{K%rdI2pW5#E#*RpH(2$(G@S%0Wtd{vZL;>lzPr%gokO0<4D#DBUFqU2nR8*_jN7< ztvio`k@Cb*KBiY;uULHr3|1l6B{BI~{H3SGy$egV5;z>5AX8w+cepF45{1&Kl`D){-mIoeLNVl={=jRKTH=zHgP|+J0x_nDs0%Z~ zgpw>PlrHPGDe(wqKl2*&!Kvf!f=bdA-blX$2D}cCoi0$VH*uIzMLte{lW*#Z1G7%pfMyAYCjd}zZ~6l^zS2`2EjOB!!!IS;5&}{N zRJ)UI$-NQ@%aCs2!YkoIhGE!UHCovs)M1;6*A-GMVr##w*L%8{Kk_Fgw946=dOk7^ z=4<#Z3p1D8#J@WzegfZReK_b(#II?QE@XVdat4)*wa zvyzc<;eaD+JXONz12UE{t>oqK$=5j|Bll?WF;Cd}O?bJ$#tgI}1QYiWfEY^jlBrxb zX&WYY1%ME2cTz(1bo2Iq>^tb?HGug*a9DS~k{Z5}H4nHm2aM+|{vCV<7u@>I@fEl= zG9prPr(w8#9}x*cVGV!|R9(sPl#>qZ;Tcx*eB0<#yq~MMuMt;SUwTGa_}dYbM$5Ya zqW~A#U@VQZD2W7xJnrE1ewN_SMOz@ic9p+l)*kL?B~-fL?U-#-f=wv3`)+!Bec$2hy-FWG zfRmsQA;;_+t=y49yse6?$w8p}jx&9PiQ{;B+s%18-8;UArs$vbeyFcra535Wrn`ae z7_?gQ!Htt_Tvpr-F}9Dl?*N6h`3Wti*zvPINXOyAt1b5>Oy3w3b}zE?4;$QZk&=X_ z_apy1P=`t)rePw4D@iVHmC~k_wsT6o&NYupC8lBZ_M0n{HP*G4V{Z`x5o3bc&x^!b z7#w_7&8U$KJa?cexDK~gHHU-SK8B2wa!Q+n?>Ris>m@ag!9p)mM6+<} zOl<5mjuLQMRQKl9&e+0q?{H;N%{~_V)>@;$ZYx~_M%&08GBpu|CY=mTFRf@B-%`mY zdcJ${D}JdFxnB{%<@o$cmTZ-4`1c};g$Lj;lYFA9=~!k;u@{Wm6tt_Fv7N3 z5W3kwrFWRQ6enUv17G|dQhJ-0M#nd@v?{mEj;vF18iCb~X0ZM0U=Qi$lyPSEaaA)y zl~d+%88>EM?bXI!1Ilefp?=1HCz7*IU2*;RkjOec z3;5PErcz|Q!U+e`W^Pc_rycdSgWbFFwZAoyyPJR}QVf5!44^W2OD0+|xr!3%*!NfA z#{ZhaR1zrz(%i|V@>ynedsI0xqhPpj=Dy-@@O#L_DLEy3A`&MfWu%-(n3Y)=J0V&U zD7gu5s508Dcv@S0NUP!unynF0oIowvP#;ay8bUwgSZrDMlPzh7x|~ce;#CBMdyN4Q zE$miL2fkM3h0mO7fZ9K6V-;^2tbajmzRIb;{IAQX#|~<8&7L$o}Dz?B|$MJAcS|j86 zU6UaYG0q%*vXycLA6uGCakzM$9o9`j8QkM?Q{3P0pG;Zi)$HSI^BfVRZw~hkM#@mx zo(>m^1Gnz>AC8IC!}&FF;*EXj_2~hom>lcMcuzJXs697y|rnQ-M?7&+o|L6Gsl@c0i&yy-YVzm~Pdqd3NV#Ls@}(#rX8+*} zzBTddzxa#%?!`}jRqZ?c{LUiXd>ZtBPvns14=0zo8F&z8mVDNyeH622$zt&Sl- z%D3YEzVGX)_kFME1sZ5+E#RFCD^XsWGfjyMYXi3fq51mASV_&zNv~v#PBGFa z20vq^NKY=l2sE*_{P{XWF;=1eeP#z)*bsvwFh3j?zJBs8QEsaccV%&n;%$?6OnDiX zbjiDwprjYj{@hMY))hDyP$M99I<+f4nH7IJtv=>Wjc5-|JHZ)%Nt-8RsIh1(3md7ixRSDW&c zKgh{A_0>6+wz(9jsk;ifhT>4;SFEsU@+HX<#hPr|=cq+2klJg79}|y4@0=3CGrBb! zeRo;2jUv*KaL$krt^~;*Wy1h>l7SKpJbdWC5FFf=0$%tu5k%O{Qy#%q6ble)5xCRA zyO!MQhjlvr?tg?zfOzyvv~1vzW2b;Le8y#mD~-&;ZfOQTa$C^P83k2qb_#6K3oVr` zGQ~gaQ_@2}d)UI@TilAo&_KHmyN06pN$|Q2kM{Uu#rNqvdblpNp^l^Vm{Tk?mlrd3 z$26rK*Dw4Z;Wit zna%kq4%S*7pw_p6`U(b8rUN)w+3U)@cRQ|=kG%2L1{^|(ZrQ3@X9F+I)hmbE^NfA# zCmY4tE)&PRT7XLw`IEKki7vDFJAW80j!Yfo`MB6#Qb-*SeLZD@LCLPpWQ4l0C?TN7 zGI(epsDy@oDtWN9(@P%yKuj%oPE790V^DG^S6-E81dXUhXH`r}2{eaPhelhPHAtcC>l1c+gl51?uTZ z1CtkUCP_gQg%|>asKu*-3UUdTp_OJBaS}j+sYn!g3y4};k^-d+QX~leF+_`01Pp2! z6)mtT!I1d*eAin0_dEAKJ?RM~mfHJy&TsF%-q+e|@88SW_jf`Vya$b(qI2NaF`U)S z+G`XcZ%D|THGp*JqByWcs4;a)PeZfhCPsTc#0&L(L%Fg(vEM=EesS{!ivc844vu#jiMEhkQMECM6Y7) zSe9x>(Qk_oA+3h#HyjG2P&H}w0c3^@Fl1OKp>3ljE^v(i&Y-%z3?Kt2?K? z^fMvh{|P^B(D!QW*68|HZ^M;p`pJ1}iRzFBc>V`i6xeGbg->u1*q~Qyoi5$-nP_x; zYC#CR4s&fZK~o%gVOBKqDi(hmC4r9^NIwfZq-QCGt#3Z@j3IjPB%Z#Zdhty3aH zkS`zr7KvnmI}P|m)J}WwyMw4+^${>B%Gy;tb<8*{A#j-E2#>{qt1aAyR9=MjI^F(Z zh+y(Dw!$ug90)&czdB8UFiBPp#eE3P7AFMZDMZ>~P=dnvqyqom|3b{Ihbn59FWUN; zo|YG|YdWK#Ypx}1#Ybr+2T)v1GeZh0rNCJ-8Ui^I`jV%(YbtH{YMD=?14tx|xKOxY zmGWlwMG8i*a-6Xv%OWCF#w4-BMx$7)NsLE_>%Zz=ms~6f&$##gX_r;u+WuJ(|e|D^J?W5a&oew zW`r7tPTv@>xada8$L(@uSEG}V%=z0^fu9S%4D#_q3cQ9TB&MA?RKd|yF`2WlOr zt=(ZNlZcP~nl5R>P;)g_pi37wF?owucq2z@|4+13mz?PwFVefyd_y_VP2Q5bTQ2s>Y^T6S|5l#5cm@98LT}j*$7P8r141BquyU)XmDsf^ zwZ~A#(xTOnD%)x2Voh&s#&(FU?`gm2I!_Ey^Xl$qP(uefY2^Mp3$_(#l-b)9e!bM2B&G59nADfRy) z9t&ZgceR|~Ja6G8_T{hJlk;^BfXrK6uEz7Tx_qn0@*jgW!guwSOZj2G+R~?PzxUG% zz4hkVcRXsd;*(+IolxJXWXn*JV_~X&*k`P2_`C!5Azo~%M6G=eJQL1%=?-#y5}5aI zhThR(b`zUV@%Q`gvJ)1sqJf$x3-NOLZ&D{DK1)fdr|df^Z^E^-fbVA}-pNGD#lFMX zaJlcWq|2q0eXR+5DfYAPkea-?N3Ch>3n?j68xP^z9>~NvQXU!zXsFjONAuWBsYt6y>8>|s@~{2H=*Z(Kjy8?d zr#N7dp1z6;A$}rN?a+sjc!!GF(%b>}Nh+Iu!ZLKq=R`+PEo>RnXMU|Yy?(!-ZKZKF zNR?eG)`B&cBq*Pdo^&8UiJYmaudqQVN;X$Mb+QH&RmC|gfN;kbE~J*UvIU;(di%&5 zk&+W%*-Af4dUgS+hoZuLR9`vvarYvdysGy9a{>qDwxC|*)s1V zWOrRrqnk$U_KFYqm`EiHz$!)QDZJKKe70yxhp*}euP&CqL~btQYXddlM8+L{3Ssq3 zMjD|A^|yj4Kg_r3Uf(8C5hL(ZT&Ftnu_BnZW~`FXf_6v9QL9+kf*T*wFYAoAREc`Q z?P8d4$1~Z%FRlmbZ$4ANwR5)gwdPar*8xxqJR%}}-h5hl%{gr%g?Yw68xfL)C=n9M zyBF2vs8zwCSU5Qa{?Xy^bN|=)TDyNkh)wJ~Q?))=YL8kvk&uI?1q4;0%BSkU1yu+q zQ)e$;rJxy`adsJT9A7GJ6(LyjtIe^&2<4=yD;X6UMx2GmQzz_`CD+*>4Sl%Tt38=) zjC>sK1r9lsbt*HzY^cZ}G~!IEi0#;sd-VUp|18W_M%xa;dMjCafyg<5>tP<`h%YJa z3&;*!tqHP6i`K-BVJmC0jw^9SmSl*|g3ToYSivhY@uX5T~#;*3O?LfhxQ5*J8iOEnqy%)VBKoJe%F zjFqKF`9(ig^<+&>fz7Nl8>I5f^`e#wmt35a6j|kT5-&-TURhR7)hICS5@$Fu0fh>a zDfzwPoOMdkGiqaDyCSc4*Q3*~;FnZfQUWOy+Di|Z>@@2>a<0z6C`EXd_q^i|G35H6u!t(?8y(>Wrc- zxMZLXkLYPUA7mz#YU&`zRp2Q|EX&nxK=DQDv+Zz3ue*T4p3_5*b9oO#X0*fsl zsq56o!e7u1=)Xq749po}HAb?K2>ElC6cH zq;T&N_DTzw@k}WleWb)ArG@U$QsPKyE#+Vz{WNx(xqI^4J z{OZqcDYbjiU$I`c?4-mG9xKb!eN(u2-Oq9z@m zDM1nt{B`Yj{+kc@|DOOn)5=fAkkcna`~#wW$FF7T-@=+xeJ{>TTb`DX4?ea4$H7a# zv~$Y!3{SLaTX*8RPTU%rnENE-RH{7c z#&_53vm2{MQRSH8Q>f#)9ojY86|^$75JtM5G1@O1rPszPbYyeQA#XhEbm8KWwzL?= zg(rzsmyM-m1`3-o3a3mAE>S~n&bX| zbhtab4{^uCDN;UQUSP}311axzw<@;07AdFa&RSiM^R8aKxxGG|PIz?9SDAP3)uWrw z@I|KDa=Y{BQp&Og(+^i4#1>c%M-NKj0n1-JMDDHedGQ4xv~Es^!&lyuyCN0qF6Dm6 zNGZ1?MdZ(Cr5vx2^3i*dO1z&bU{XB#OO$njTEAP`R+U9TY!|?9N#|N zi@@J}oe|%|=w!X7%9l}|tXTaBYF1xygJ*n5Bf0rh!(kO~hFNMM&M}Lx%X8Rk{~#1u znVZ}%S723$XQW!A?P-FrI<2szE3D0il7+Yx1Ev(?5(=QD=KC%Q>Jz3gAS3qKNhyss zOU%vTd-L~w+!2Ra<;}jH`Nnh2;=iksmPtbw`{eLb1-C6FqMo|s6hBmp5(;H`9=l(F zcv`3A;ZmUsP)3(ahMLF*kwcyAim;e+gt}--6Wvj1-4dxF;%LCqI-cYX+OI)y`p^C{ z0QE4qB;uK8R$`zRTySRJ68DmLmNT?qy;PBUlOp3=jN+%+z(Is85V>fLNSQkK81{rp zN@H&c$aGXR50B<!!U664bHLIRyPpZ2e(>me#@W+Bad=88sV!-ponf-E`VAqIwSAY*|>X@ywnX=zZ% z@^z;jh|Nra{fW_?lU({lEDw;ITZQ~>ke1+I+^AjUBA`(S$oieUv`f5k_c1i;ynLcO zNg{+q7^3>D4J9pUV#RY-nY3EQ=PUlBVu~^)w&$ph>%aqrho}uqIzDAzI=o|-I!&^M z_Sn8y;$G}u@m~DllV=HuEFn!p6|*Zx0?l*?ZpqrxMWGVLT8&PzL5B-F*SsfU0uzpgSG5 zjlO+sxPoi#Zi=2waUxkA!qMM#I7$M?L2f!$3oFQuBG97$^mi_l4Vax{T~wXU2&9e@ z1q8+eHS4rNrC$5&idKaa=b|ei%SnI(AH`KyieYX9)hI^Cif8D;+~HY)F9{gCye){V ztu3dw&J9fz6UkEC^eecV9_+9G;*!8u&rMvjO=tpIc?BgriBi*}Ct|@@@PtFAM!x`v znB=i!ekx6BrbtEUD(y8s1Y;@k-teLP;*XRd|y&iKH6PpXy5F zEu_FI-8%k={C(eT-muj<5#CC>)>FhLMv>HX4BcM+YFF?!e~Gz9ZrT&{WsdM2Ze_uE ziCm&GA&I{U<=`unTf}xA>hp|cfjzE>HK>fM$hRrk*A~JMbAA5uFO?cQqdUh7qs0bQ zc)J2d*VH8d8bjF`U9=$&0%Xs^k+s(3S^Gf5{bdjGw`UU(1t9FT;Bg#b>aKtn-cFWg ztYwIMToAa-i}B;ZatUq)BnpM(Isw3UxPt@TgIJ7X5ojs;vsFTy7~W2&*a);e#f>al zJE7Zo#T`u%VX}l#DIw*cbE7N`GSt-r7$2*x)J59`&=6%?f$}b?^oYihQ#$*{@n7CvUxZ*_P$edsSnK5Dd$2fAb@ylsqrFYtAs2$*o7K zEL7=ph)vYV0@o33@H2OG(IA5PWV-|O>n%FDlEJjOsmsbR(&)$|zNP zLCWxtbI*5+&@LF+b`E4i&{7LooL_~hW&!1y56xXjP?xp0ouKNm^ufBzP7qnfBf1vq zzEM>ajx_H?jrL8F%D!jEXZZHfNsjA3TvAqf|sB@aJyh?wyxIu7!Uz{pvjAi^It?Nu3SvlgCB+= z{pg;Xmg1fc-n&q@{;)H*b6e~PG9usN{jfyDEGT=aMMlqM!Ro1hSVLrR&rC$S0$y< zZ#@`pc2+}M-#_q_1qE2de^M*Eu9E~vP1+z2Lonz1+Fzy2Uf7(W+Odi2%*zJ?$9iJAU|3XROaj*5cZkZnOM5!9lW_`7Ges%ee#^UaXo z4zV=iHM=jc4nE_6-#mHaKp)9G;Yfy~-MuD?HFo}ek+NeA;U&bOCk%we#L@#sPDwIl z2rxja@H^*yo+ap8M$D%~FJjS)d3K`-eV4^Bcp9uD7T5KkkEMiWZAYcgp0s|$e)m_> zz02m7C-uHVcBj-n6E&t%216!F}jNB(uHWLM;S&S<(i8xrMy)D*sBn0Xl>uC2=le0F1+LLGPXQmplLWcJ1+I3vsjxz; zAxA7-`wU!iX)-fA#6uTbA}vzPJT=IzE|bVQLgS(Rga@izVS!^cpx2v&)}B1%lr0=1 zEpabf)$P~vM5@n>-~LmD)eG|Km)zMJR)Q13b{y?^6sw(XMsCKlcMzhs;@elAol`Ce zI!CG*8FDB3@U|k{k%AyTn*|i&*1J;OIjL?~`Cm~sFv1mEBT}LASQN$)YIK%1YFe|q z4tU}l96=oqcw=To&R}(6W75$_BZtG6{%k$G&7M5>@&hu$Ruz|ybF2tFd=O|BWH;;q zr?Ov>idgzW(@rCEmR5L*p}c9M%2(GZW#LOptHn}r#U#H{IRO*FSV?c?)aGK5gDV=l zy-uyj1Q~o;JCVwAA~HEe@UzSMi|UccA08@!oo{g zQj5VCtQy~H05a>q0oGUDi0>Rd^#MpW^e%eQCAf6Dk)gP>5$T;%oh6xzYHkziJu&p% z$OA0-JT?I}$;?=_Mz`94dw{-2zGvTiety7WcGrwW)5F*t{WjMo&)T5K-gd~cRin7p z2)VJUG8004l-CuT1_2VoFvmKeE_eB>1Z$U;E<~i_Cs%oq_(c9hs$48t@YVW6U7n*^ zaYm#{kta|Bq>8>JCVWLc>&3VHec>gicn;8O$j-_&%AtzaHR^h0(TQ%6W6m1?@AELfBw6Me(}a*p)B0~9(?B%5|3AB;Vbg5)9F-FvDRt4G+ioGxzZ@G zO0QnyK-X-+s9QD988k9L_g`Wp@j{)qg0^?D;OZPpdh`x=P$6iPj~s!W&E;@k^^CWV z&r(>BeRF(+nuscee&Rd+eCAh3C5BHer(6^^jNRKeC(SCo{)Lx>^#z(fUQ4(lX;0Qr zXIxav*F{n-OsdwK(UF?l|(R^B@-ef4{nb>Rs4 z@s1{`6uF${gYYD0gPRU(mAJEcq`-B3bp|+6*`Z9&Po5Ist#Ow%0pIP9c5m_dy+#fJ~S|JD85U9(pkDc|~W zcUSY<^dCRHTvA@9zWc~$!|i)nk^1uP?XLX`_q^S8Y_Z;K$-83T2zR8!qev-RYOi)n znH}F>^;Pfv5~Y0Wy*JIi|AXbx7f@>pyR84+&n2f4V3)4U^9mubN+m~!@Y`Q&lAS6A zpWYs5dlN+`IouRhSXe;PlCGbvqE++(H>(w&kvg?(Ltbrf_5toT-b}y znqr0~18UER#P@(`>yPrd{6t_KmBW8YLt#v5_=C#O6Q(0;fmrEM-EgLLeSqKo&EdcP zOGJq#((Auf_%$;;vL|Ljk{6*7T*Z+hEBGg`XOh&BLRU1FkOGFn@r-lf0Z{+x$?Gsc zRpS_(Kb>VEF~%AwY33OpCKa?UJ;Q2_CF*&>DO?CGXOiPPLD1l}$NmEnZgVxMYQhhReX*RD6Rg&pu zJ8x?U5nzb;pDSV=l?T@PPwiOep`B!yj(HlIa_kpnD}Yi*v5R8BiJTn^a+>I5w{MeZ z|CAqLzi`Lv*U^;}RjI-=bJBSUOY^HoWU@2J=lPc0B!!}fTE588HuUBqvMx)J>71!2 z!l1DUP*rGh@@4{4n=4oq8Pt+_a6GdT+U6J7SpQ?9X!JXfe)NZj8bnqtk(x72^|Yzs zV)ceER}|pKE-O^jotO+g9iIG_?{hWxm#*;P=J^+L?(#bkO>rM$ZcY_v0%HgNK`93y zQt8AV8n^ff(8nRUjbmbmAvuo~Q0t`+UJy|8Sy6<<^8>su*iH03stK=Iy-(njqK#yh z*^=8FW0Er`XEI~NvXVq+4U8)}+KTf!*azO>l*vt(X%cTX67 z3di8+D1m@87vlsSIosJbBSOMqD_1i%BpfwbH{&ACB82$WL(P&JhU2&Wnc$nIf(vDZ zWxPXQt=u&DAMkzG#Sm^&Wl3axk-Wl4>q(tCC;Db-mC#ip1IW0#=iG4TTB|flYpyVN zE`04ysga1{#R0P%RF9>n#U!4yi8-D-gbJGAN+ig8vXvB$6@D83-8TwTptXKk_pt=+ zx@l%kNMu~IMY~PCEqWzY2)39>SOvo+zfgmq`vw+4iDC8?gIA(0rd85oF0H`j_3u*1 z2+28OW>Va?KO+O0N6S+>6j3$VWLL>j^t;#S ztZW!O60)4zU$D|s(nf_ETx82maXx_69@~~`^m308NkW${3W-|oV0b<9%6VbAD9wnD zoGfK}(j>ba4ejCjY1MNK*Khh-ySK$9gpUT4DLW7Iy}7gwpi4&8G{z*(7cy!=RNhiH8 zxyBk;PTa{9Cr7D%_+PQHF_&@eqzi>a-n3bYj4*8SyETv&#Mo{mVV#5Dl}pqbBAsr6 z4LcWqa+&6^hJEpfwT|~jI#N-?w?Gs!{Nh!vLx!lSY43F zghB>&T4>fu!p_oXr%7`DQA;?6&92nLQ5hO>eJGraDVh629SErWci{^*P%@LT01?_^ zr)k3#fI76b7;O4!Rs0k(>9*8WfWe$Zdxe(jQ~x;C3?&igIyad#&SZ^OH`)*}^R&!x z-Pxj1X8G0HR>XV5?vo9*sMUd_$mk^i7A_-$kSLIPYU6K@r}Ptr>d4-zYk)g-$}MOT zow*hakK~}GC=H>F@U*n75FxL_X4*%1^XZhPcg>+$s=$@+<`Rfl*CtjsN#^1TPf6%C z2r8%hc$5f^VmJMCuB%^CQ^LmT#k9{&$cfjtO^;xAuoqdq(j>}(PvH^m(w8ba( z^nta>C-%CY;j1u|gK)IHOZPt4@23OOG;e;AQ(PTD4Zly$ut%N5i(gzv5Q}1N)G^ej z1l-Xv7Ph>*&$?9Ct%e=p(C1>~eaF*NE)SqR9Zpa991mai$B@e^o=apDsQ(SuVSj1M z8gT%9zJZNI+6@|5ldR8^XYf#0df+EsLKV++0RUdaJ^bXKLB(lDz_+<-pHV@IaquY$ zJV0x)Q$J&n8%AkRmC@#olJSgOA4PgLH`i_$9r!&f)zeucm3UTAl;Bu<^Pqd%5rq!D z=CDsJ5j)+SPN6tHedXrnmGAuXsJXj-9SLj4V1L`li}%ot4Q^GU_PogV<3z%ZCu{fO zY~dh!W?iIc&%Ixjmn$AUsCD0MZZILeX4*5QwC`I~&Mi{%?!`RzBxD3i8&HH| zTzQgTxaSL!r%p&Lc;PkRFMLo#)cQ4~rMA4-ze&%V8v#6FIV)QX1yX!REHA5I_hO_T z-}3?BNJ*+8g&tDa5q5+QAO;Yq>`;1o`m=usUGpW1ltjvbQf}2m4%>+wxa1bTX}^S4 zSQR{0+BK;uHRY62yX!IyAYeZy(j}`Tl2YlsA~w=8;ejEoltd(&z&b{W9m$1Wj45tS zQ74f~diavcn0RE-2wXf&jx7y6v^E=3hhJMm>>zq&9xbHSlXpvX_=evWorlA%J*_i7 zMv88HYPoddTkJJr?(&Md{z9uq|zJ6OP);7ms_c8grSm(~Np9ZL7wzGv3-0pyTm#p1>$~%Suu%V4_9Xx1eJPEpNe2n zN6>+l>T|x8Rt*5Ry*3gt8np*cX^fMR(Yn-qdtAB8JSp?*t*#m0i1C2-%Aw>G03awa zaC)Uhsv(k43^w+4CsJzICMAZhG>Y7Pf2*WlNwAR7yvza%$y*XE>AS zBux&Ha`hjmE7mgu#LZ4;*K_uWomMs=|LPp;Dgh3M+XICYa@kYdGwz}^R!{03ngyYM zb?zn=Bl)^LEwES5=dis10x7OH*V!LfeUFdN)ehtFaFP4Av_xe^D9P;*JC*uq>UWYBX}e08Q?wjA&1F}N8nWJ$Ct{XPb}wefU`xS@weOI(yT1Gh-Vxhxcm3GCeTUi-Df4#M2ex=0vfebi z-Vr-*n*CC_;QPPV-=@aVJvjwa6T%HkU?~{qv?v7fYJ8W)Xb8Rm5XOaJc@Viq~pa^77I5JPTQP7W)^S6ammRg z88TJjhf4sSDk;~jsnt#Zdc15P$MZZ0EF>t&wg_$*6eEKopncxw@%`+|e)RdextcAo zRknGt<&E@-G=lTy6%Ld~hj%=+cHv~Fr^>t3uQZoDK=_T!w!Z!#0ZW*RiI9HL@p7R= zXdQhiDA)%$2hl*O60st$^BnSn>neggq>)Hv9BY0{DIzL-lt>{i{6{tV`l>YWl96Ud zEs(+qVIVg`9zaCrK*|S>-~8(&ZTXC)zSi?jJ*ss_<*nNXZ1EA8vPvwih)|3HK}rO9 zlTp891u1ZcJ#%K6`b^CB=&irr))!KTwE=suRs!Rr) z1i)-Y+av?m;?SpP`_7YhD$?>!(&>c26YZ071s;FVFR-#?%&CRzr_Wh+j=l#fa%R#* z?OK!roN3z+dug{<^daWzK(UyNoQy)A5I0XfNiJn2nWIj_O9?&gq^BS?1|?=u#Z3DS zTn(NPvN#`1fiT-gXatlGB_@;@?K9zOOG124H;1456QK0Ro!mi%P+d;sv6GC6KCJ># za#Od8nr(KXC{L~1YJ$?KIkZYpkkO~)aTKi#g@G@NttqTOtVNpT|NJzVTnbQz`IegH zsCY}Ls5S->2<<~t2L*jruw-gIxy=K_%8HoN9=UWw`&2Qn-29lIrj%$cxh5p>_c^yI z>_W7-@trSAtO%|cIZaPU4RJx<$b=sI-7T3_RkEx0nU+Q2_TP{=Y$j?DV7^({T zne4a*R+ooohpAtxHMX_G^g*CEgKpev9^)6NieMDX;_s3pN|d$6~06%fbJ| zG4S1?`KU5DV32Mwb~M$iD-^*yL+SJljSPwFZ~l9E^5AKYS$`qLFC5MH#93*<#xxKF zW1}YV$4MVdX02`WC5nWetnka4P?mrtrhLo7qRHDZV2J=QE-{)~C8VMN2uqp-*>cla4d;{bgr>f(F2PYBZ-~DyU5R{-IO@Z@w+Z(c1)4AEQ7PAgkq*l8`5cx zf{be^fV!2^f|QO!a5((aUm#y|c1#?K5x;Q-QYe5mJ4(``HhU`BJRd28$G#(}=9=eu zAskejc67ix;6i0;mXWgVjFLV)bA7)05dz9uib>3Xl7l5MvO$)yMO_ADx|DSIy;#sv z`F|gKU2fPhuUyK?8!7fHmC7S4ge|oVuJJAyM{_%+>KK%%JroH~con8Me!yDow1N$3 zz*-0i!Bsw;nkfa5uS<`1%pVwaC;nhdOJb)DA=nJ3dvX%;|7Dk}tSz6;vxJn&ZtQ5z zn1DUdm%XXW$(4jkV@kE_RNc}Oir-C9RsMmJno<=W{mSq;5~GC#z>=t zZZMsHo0#w-yZz7V*8}SiF}Tn!@=$rGsNS=wWdQA*2qoRg`j(@&b8Z>Z61AoMWJ0sF z`CA0z6mlz(o15zR+y9+()M2zI;@wIYnSM<k@E98bVlzsMD=CrWP?&goB^OVp7^O9!+);?u*S0c5OUwgg4a@Pttz`gU%>4YY%f=3^-$p8)Y zKmzLcPOhMs4tiO%9mPB_!x*c*If0cjLHIUQd-Y2b^e=bxUCb0RvwjvX8?a+Q!3%u7I*89jlg9z^F(9`CP- zWS+zrHx_nW!I~GHsaON2Bf{&35b6*nG2qn_;?1Kkz7f1RzQh>#z09u|C5Fd8_ruX}mlx-=^(K~br%6o|vNBWW47%$N zJfp==u45oVdUHyo(0^;Y7cs1*)aEQ4!7m(Mw)m~t(#^NM;#YsO@j}W&TZ+qXJnnJF za%^ai)y;_Fk>B?@Qhwhj*Xif5AHDX!xgkmrdtP3Oz{4YUFS6I~RP4vA*T7z#5rkmh zRLBV2C1uQ76u7`3C8vr$8Pm%vet2slYMF>PFSvX0>df?vb01SUQrKHWg9(v209)=? z+<(KZBva>IJYC}rj<2|f0x9n~Q(v9kbz=X{b>S{fVq=CDaT+L=++iAE>63Ti%+0%R z-UnPupZfq7V~ddjfB>XGpB+lC$jHO=S{`l=AN7|GANxzuWNLzk3yBzXva60_jn&k= zQBZ3effx0Ms9+F+lv*ZaDk_8kP41MIPQi*4{EA;iYEy~@hZgZf8T_+@Qp?cI?}=jr zgre;)eow1dl1+J-*eMz=FEBHfz%5{l4NIK&-BW9J_C3V|Z)Z9J-|$b7Q=b+Nc1Om{ zXqVBYRjbG6P=TmO)>7F&^{jaY7O^EnT3h&(Q72yuPig~)y7qfweYDiWKJ!~n-shRr zC#QPU@DXW{CPKs_a9N2Ih?273$%mA-VWuoD!@w9PCT40bb{vmL>BS!|2lK>-a&lbs zPoD8&wctk@19@g%zL`s;nESgxERu&}K#(t$x za^lz`1r{IyNKW}|F%eOO`8@m7SfVSZDpJbPrivKnn+$$y0zQ$7A=|}OhM=&TqN`L- z6?SruTt??-@fX`P!dm%&b;*L7MP`NijclY~Wm&iMW~A`3r7%)R%gje-_ zzIs*Gvtv;4@s#6{KQ6b*a2pvdl$JOrhtfA2oHuT>3p;0*c#=a6onkZyZkOuByF6M5 z#8~2=bgnbzlz`KLS7-(E=(jlgYMsh=5nyW!h>X@@MOjH~$C<=raykB}sm&u-?X`K; z#7LJ2N_?lDNO^OrbrZ>A;|eE{jl$&6M2cZm49Wt@q?W%TwNonDT8ZRHcr=1W;u-(L zi&;`osIe@w=LG)x`cz+%g8JTHM*nftyAFoBX4&MF*{e0>$q#MGt5t&{+XG;H67$(4zvXWMWug%ynJlxZ*}}+o&E5 zudu5`yt64yrn~{NoQRvi)9DxfR%kwrKe1JAR?`w`L@?q}y?fC}d4jn*Lx}v=@H(9_ zvt6xxlqxU_E zgI;`(hg-ygcJb9ZDv$eo00FpmXp;FTXBB&VmX42nM>Fb1jK;8=Vd z-PuQ!!)1MlkE|FpSKMdQ0@T_DH6C%{J&DP%Dn;Xie{#SU9WsYbt?L!8(Vd0g^j8jt z+voYpL3oAQ2-#PuBT#Bg&cow#5X!~8@=-EM%uSuHCzhtl8yqplKBf0Sx)fLUuIlR6 zdAoHIq81J_qxKYTZHutS=QLs~0Hw?+u@@pwMv>}hNsO>asmN*Z^%YX|tV(&5dmyFB zb~>qz@>AJ6yxYC_d9S*!G4Eb{N+dq~{=79Y`wofB+A;V|@Vk34b>6-Ba^80cckdY7 zy*2THl&^a4m&olN$VlmZhhO+1`*$C)-t9YFzi|Kl&+!e8W6M|l#+Gu=me0n9d$!<_ zyBK{Br&zb=eMOi%~hhA;Gh-}G3 z_ish?RRoJFz@2FjIX(q*c>as?I}X~ZbYyB52Mb4xt8Z)I(Tqfn zkVv0GCh9zoWIaO$UhLS{FGyUp!(&)_tsUc(Aew_U+Qw+$v3Hn#U=eIRU|*NR#=$VQ z1ZWsHE^Y(@%b;O?2ohGpoFa!&^wOVVb;BcvQ=WDPcH($__|;$Jk#j(eyrf}3Z*hj( zgNZ>&B+;KUi2$xistSWN2~~-q2ZMHY_{qSW^(xkR!~zOdt*^w2WMYYgB)NT0Ly3`8 zUNp$hCsH-kPpRY)EKe|!1DhX2A{kU3%7izD zDv?!PWK_dH5^v4ThwA1miX4%!S&{c#DuoicX68Te4!fGyzn)oER5S`xPDzH$G-T#cYeP&GR|nR;f8?)CjH4NQT`VggqP)V3*xxoDw8nO zX@|4(PckW}J8p9dDPtoV!>i7c!sLO&FW4n1C$Ord;9FGD=ekU}UX+9GZ;}m+P9}$x z16__prN{x5u%2VBr6S5ajlweM_{Z3j$2ya@;l{$8Vj@Q^S_PQO8{T{;pstuYwd)7} zDFm<@((tK3W<;_vA%^Q+oh9Uu5I=cfmz$&t61V7ZZ}S`9aS{9RIa;(S6j2lM|1&wgeP@efZ8hrFVfdZuO|r z)m`OL(G(tFIUzE*iBxy0+F^U-B_D>OQM3@pcre)2`m0g!ij<^$=1z!a*dUpeN{}>O zJh=9Re$+rGJ4Hw)QhO&1l)5-0fR$fh6`MbW?~vuWDi%qZi&m7%32Ne}YzwGq7N9S> z?8sQ%p(g;5g@6=TZSjGkVS0&OUZjL3Vuq|BTHUwI4Uo9VM@n1^sKs;;TFtnCjhTaG zSEOZ>GRIKEf34f3nsU1H^S*YSZk!Re`hSPN|gu? zV-aUoi7nv(M_Y(Ev@9xCkD?qZNQb(lU3BHm9BSOEG|qp0gVoc}$)m;SiR*-BH$Ckk zK$)i2<1g>Kk+~%q^UI#7jy^3;FNi)|%+n%k+1-(D7z5g)Jws0+d`s7AY@lMRtGvWU z!F)Ii;!Uhss|-^{2_-N?7yQt9C#*@HP1T-5Eh4?=T9lB3jm$k$fdXl8T~dayhER>gUBaqcx5Fb+a<7ZF;w4c7tUQsG zf1dG0b+0+-Wq!HL%`M*I2b2?GUE^n)h~xO%KHd(Mzzg+J(XtzXedSgA7LsAwU`@2F zAE)a&EOZ>Ubck|dTmHoOHfz>0$VIAZQ}H>H9y@rHU9lVITtW2*qx>$=$SDwLN8 z_{zV(_4oAb8+?J4GqN|!q}h5y8O|M;CaA^^+-`wZ3sjjs;~zoy4xwlv<7BP_+K|BJ zw;tdfeGya7&s$urL%BhjuaCuG;0i};I}*Hy6D5zEKD zu&HzzK_f=6`s0V4+_%oCvn~f5L=A(FL8}xd1EaihW|2ENM~!tvHa6l0U%an>YI5qT z*t`nr>>|>wf(lyxLzCxlXyk0GH_YVgrZMq=j1 zmoiIa-NmY`o%3p)zsa1lkuQWK`f|8|LuvTub6)Hu_SOJciun(f+}W)NBKjb42Jsyf zIpzB%)tJ}QFG3vN^$q_x?^)prf#29x<;;@Us5|vlu=bl8%GW|Z zcw&n+8k#uRG}S<+?b#qe*y4jnzSmO<{%J)AK1OQdhEnr2JEWuAcM%-@TUvgs!muJKq4ceeHGMHS359G(Vgp}jvnj)89gM-J zeLe#3j1@63cb-u@R?mV@Fpz3_GpbJnXT^vVf~FKt&(W3bff(N3O!Rg^^H2P$_1OMM z$-YDTEhU>z#v`eQ`m&C;Pb}rp;q`BckL`3D(G#5=gM3qde5Ljw9Irkfs;hI-3iIAD zz3v#?>{4*1GQwD8E||5oFYb7FC+}WV3fm&!I$pg71yT^>Wy04u^mi^jURDB1R_E<{ z^nt{=Cr9=juAP*CuU>=j>YT^xxQH1@@p*(&_!a9Urjy5s$X+5s#&_^H@5*~1Z{DYs zbl-CZe|2Ufr+N=>xPt>*c()s#XiMrR{E{ag{Y(E4$uQTQP^ZX7$?iE=DpIwpNO+~e z>}Ywr$K6DIcv$UO7a-dViX4&J><~gV@A|*j5A(Xo>$Luc_-+2&-86G8Ob8ZRq5f z)&PH)Q}IP)b6wWutFvrRS2k6=Fk%&m)RBl+1R^bXEvKiJE)^jZG0RBBp&uN+FzXSUvcS?H>o%<7@xGwo67)MyaXkr?yqrm3K1{p3h!C zb%!aLB6E3WDwUKHue1?f(uBu$>*lI?QXEoczQ`6WS(<6$>zcbw>p4sEEa?;fL@GL1 z5tNm=3|4NW@`5ymPwF1G$~9z^rOZAWALp+@cn3$U7;R-P@|P>)by0M{SKNCoK~P0A z!WOo97}X_Zr>(s4SSP=+p=`F-#7mw&iH*+%?NeWPdnMYbz<&;qWK;b%Ksl2}EwKQ?PZYM(go|=$vWBGX=YJ0Ha>pMI+NPQod>0)ggucG(&v?6T1pYtPO}y%`WE*8zU;}=22D&*p)|ESRta|g}aL6Bogj2H)S7)mHhv;~C9Za64 zQwM68!AEPYtr&Q`#ujQaRW5#;`8BCS=Z&tm^g5n<6u7+;?ubQ}lSGfoG>%*kT%BVB zc;f3tq74oyNy@sPJ{736UeHVIEUTJjq{e7$e|$y)R+i%9UF7woo>XgWUH3u_ zO{9#`>n)Y-L`$i)coKG=m(*22)F9<4;-Xr>)fuO-X=e+O$-+R~o2;<8i%SG*59IP- zdE~H|&vyv!`vvQrlt(|~+dw^h_hRk!yL+>}es6up;Ah?21NrQCFP`4QyBF`&y8)%9JymR|Si zmygTSTBleMpv%LRVs5fJS-ZSMp6pP1_FxV2-Ciy>%6c*TZ`9_k4G_P%aY3)!9wZ|G z`(h1MZn^SDQ9QfR?mV?&oyxYmay!&zzDn$7Sr^o68f#c+b=hZJ6pckKD|=3}vG390 zcYKMqb#eXk-D9qS>Apvd>kgH)fCjT3CB zst}Fe{TsSnz(jm_qha6av|6A@#_1__u22>KcU0wVc`R1_=BmZ^ z5L{A)ccIb??eQDkz1Rg&m2!KT;L;t}>F=7ux=9FmIPOWgN1E=X&x^sv>PUFe38#nR z23H0((LLG+Ii;}Oim{PD2+vZKp#CS{HyYdjs1JJsB6S(Ha(%==y7zbOO9T(C)mQm^mJQLjr)=`3lbA3+o9Y4ETLU2Mnex``ycE;qVR;r`g@4bJ zv1$(oUg3XbFJPVd1VX;Y4IA|yEX!W-!(=Z;c#5sFWr=HHC1Y}GsD~xYdo?5N!WLw1 zIi-SdT(GsaEK)ne)$3=W(D*Y6RXY-P<|!cBI~F1l}s$gPhu5n)>b2u3VjWox|boqPM%i z1^)j*DIek&#NIA%B?1p}>a8&S|B~kINWIlze>+ltn~}O)pDz~Z2a@m6KEPi9_DlT* z;s?9)CeQlbg4*`)C-IibJm6Umd75`U-|0r^(=Nb@&kn}pE5SjnFR8j;Ty@+YS*fff z4dzn)JZ*!f$UukE-ax1wfO?7-;H9vp%R|O|*9qOu!3lbU)b-TZIM=^^bfGvHz`|767&J!|08?BErMn9JkgirfghX2 zi?O8^`Qh-L@1bQr`MI=iNbc7~wFKH-MkJ!5CK=j;mc70cS==Fw1P%|&60^Cs8M%a1 zBhFScG#lYwZY9+gnBel|-V!$>9RZ8-mwaR|#=Kbdj76`;V@%7Wv+t+d=CX@nJVX_nCLSjr5bG!pC`AWdj@ z1bRSZ-`2o=0WuqJlG_miH6s@C(k ziXbuN$cLo;MMjx@J~ zE>U69pLK={q>%9w+$vEyz3!wUr6NQe6S7uxFaVE--}90y6mk_^pHkwHi0K2(G95ee z%_qz?T8gYvOtxD!fTkI@I--pa<>Cr(k144kTHw`K$Wb;c%ZBJyf8Dv`^iQ!UK+-6T zmc|x$$p%zgG8ccaoDr)jSv)ze@!M!O69T);*In<@0rf9iY%cLj@{V_-yfk$Q2^bA7D2j56a^-3< z{CIX**CI9In-X-dJACmnzWI>F|C$78HU9iP1Q@YLt-8!mr8b;)j!<5%bdDB z9G;6_aTjD}u01H!W#W!l2&}y_f65U>)X02*?si&!j z)gFlTw2O`1h+ZwOqHu;I*N^NHZQ>pvh&x97LBP9-(%&UDEMrod$(iVZJMxxv$@iV^ zbu1Qg+owOo7e?Db%mr-mf^i3a>D_y#C|MYb=A^3j^t+aFD|*Z)xO)dt!$Zw9GhklG z*B?yuCRu2{`)@3Ps>Hf|&Ieb5R;G+xakL#Gal7!X5R|VGvLjdmilw_7{{sVBz*LKW z044h&*a<=@M2;5*f$97rTp=}V6ocC4D~NGtH>8oVOLk~W@y-2 zbxLAut4>HZ`J2u*LOh?{V%0)Jxv)FFg}4V>X2L|SPt0aSkN^8GhhZ$)D_M*RbP@&t z#SoXGW~u5DRRkWl`@{?GQD;5b(;}!QVC!5_^7aZx!2PjPi0r}RaukG}Svc?#*S#G@ z!@FXkss{{@eq9!|Te=gxd+zp)U(}8LYxN3q*|ijm&jv*UO5Sv0eBfay%At7l6AXW==i+ z!n^eNR_Zd8I)AUyQ3YO4vu6GjK1O(Uhm5-+;)=^tXvuic$ruEPangE; zS{$*ZLq6J&*%Bm zcKhH#F62Nm5ey<5+XWw|IJ;0kQdn_pEoV%x6M^d^*YIRrNE*pKjKT<-3O(u+gu_c^fRfyWw1@!Xj)xjL8f!{OG(ode_G!^+WcYmPI$ ze%tPNe8+W3sW*Zgu08yQG8`k9shlJVDC!&AX4Ul$7IhpHFtb@IgX_&coqjK5;=58sW@uF$He; zZw|ltXBw$1UlxQCXi`$g>|Ng`_>HP?mB`&jNcn7%D8-&a1s6>?IDNZGI@t=@xR3P};^w0svwr6RwD7irH=X7;6QDS6KyVKA=md^+8KqHsSv`Pl`P?ZnEHL5QI1y@h`W-kw2 z2&&cbZmx+ddO`C5c$TU5OYLS&z0#Rheyz@VQMM+r4ln;i0k>K|M%zf=0TzoUD;oBl zZB-9LQ8memRGBHw;7eHP)vJLQXZK1rfs4XI-D}38#+MDdNTpekA|UC_?5i$0g*>%Q zpqjh>auQs>@}{X=*Zdywxz93ip8O~^1L|me+L{U&<2a(1?=p4Z4XfJCK+CFu20jZv z_{infl2B;NxNFSf85S^Y1RFLiK(89WwB=YyIJ3 zt8)?GvVU=W_f2X02p(Qq%Yp01Z7C39)76M9nIcDD*?0$AKrqUL|y|7q2@#?jv)RtpKiuYE6XOQwvAsYE+>(luKv0OTaFkJIS z7L~?FLngX^l@4(Fhw(9L!538{kzQ2P8OQ1K?wWJNwUD;1PIk+dS^+e7q>L@{>eSWQ zs&$Vos|#+!#?$myevk62bHiP*N($HLz$o)2YA&lDeGgCaZmvJ_*{|leq#s*f{wm#z zPy3hPF5k%V3MY*9t8}0J>dU9gUxIrXDf3Hk+uLEj;!8Zu%)3mA!zhE%OC&oe7$-P|#J7!vw6DFKA*$=n|!lRP)0C0Q&fl$VW!W zQ_fzNq5`9?QS#O#9p!ODy+Sea0bJKF_6?-#-;i&y`fdi;@wQZz<`6|)=HDXONl&!skA~~2j$I^?YVG8laDK6B3*TMBCYf$fa1zIA8rk?xKgELuI zIxD3ZJ@6)=T4KD8D0BD^$3OZFBU8dikHNG?75$8>D`a!V>>L))&^OeWwdW%!n2wps zye(M9gj$NxO7pTb`z5e?nRqd+k}S}1JRRo-RLk)Q^NoJ|c6G(0BzS)b9! zSZK~~rrN^c#)OVG|6vVq$(`O@)D{}M#*l7Qcc>L#2;n@IoU&4|_1u%f8ag7ZJ47^^ zt}g6zG*NJM$Wh3GR%9I6S~{4nx2dBo00l(B&8vU1Aa!mWP$c z`6Q=6g;-D)sa9I&fw2HAvXqVwoGs9F^JR6`D^r5c-o_Xdhi(B5`OdN=-OqS*x1j_;3G{VsAqd7!EoOwyDq;Q=!4Bh55w^LS2!N_7*eg_%Dy<)(7b0G~_BTh&NQ^**qGK{ETId`4 zYKQCoVUKNAKqa^bVa^OA84-KMmlF4wZktgyCkdKCUqUgNLh$^TQ7qLhpfgFnU9*jV zrPi4cH@?5r`V~Ju>l6lfbFt!3;mFZLYq2Vfq`PtfY~qCmc^{+{V7>b7u`S6#>0lJ3 zXabA(d!A@&fYiJ5!ZKoDdcPA4*SeBes)wlo-Tkg_rBOjDhjtp%#2Y#I4C9)t9RSIi zYom$yHSoi_qYS}zP{3|}FF{g_!kv_2Bv~$|exRWuAWg0LH}#u}ZDi%zGWjyM6oF7u zUb0HNbPoUd&x!bnl^qbs?C}m3WfO|(?~Y^sGe&yP<*KFB9cMS60a`>m+~^ThGffKv z-CZHjpZS-$6L;gU;JQGM^cEMQ(z4SP6=lSBiTNx4?!)1Zq^fnJ`NOmgSIaO%W_Wi) zRwGby>u5}tUN7oOY)NIr#J8r3-RNr}qi-)$g^P#Lte%v7vMdjCOe|7#vmXf3Ts38= z%Fm(AM1>X~h*_WKTFq!fzSo|Izs#E+TE5J*91aJ@jG;x8 zC=XRdP*X|~x*3*<%B41`6lGc@b)L)*9wt$SIo2q0_TXn-$}62+yZB`>#VE_)FgNo8 zhz!8d$z9O#@IBvhxVk-DJyx(E7gFM$5AkR)vUo~Brygg9U1B~CQjKtOrJlQpVL;=F z+LW3-kU)}ATz#*+gEj(HtIZTS`CsD!1B$)M0~{MduVM-whRdH-^P8~xwRVHcZ?7L- zA{stOdXZmrQzlmwFCjzga33UJ>3MF$Q}Zr=$Vcr&Am0+Mm$V+@@B0tg=E=Y3uVMwN z6|7yEA;kksM63m^8K9BNQF1w?sJPOxArH_f6@#040t^;Ip*5CBGFlxU;nC5tC~Fey zvP{2}V*GH+=iZ1(D)1I?GRwE7^CzEf?(t>m1dT5_UnGD01-mCK@9@*~Pi2Jjdv%0` z12L06O)G>N;g`Huy7^n*hLXF-J{mb5@3fy9JKj<)6|tDneT!U6dbo|Z#hkH3$Yw(W zKCw-HiwG;5R$ht}enKo_^21mpMsZ7}ZnkW6J^iU`r`c}zVl2w;#hb(Xej&Cz_Qwtx z(>L6Ah|cU@JREz+;43BQ@Z9I4;OY#0zLvk!xI1O3p7HG+gYIrHZ5b>IyB7~H^Udw? z)Jxmd8R*q{w#3vg!AVysiY(+NpOw;!?D6=n=U?Uv5_VD|9`Mx}s;hI^!f)G|lGuXb zgbGw@HYFDI(LeEKQGUWs%Dt555OBESSLsYrrC`Gyfx33^`JM6vgI$c7g+J%J6#JO7 zpZlY6h5Jpy~*{BQW3Jzi&CqIu%!dr zT1nXg`OuYZy|1U!;pWBMjG!Q%WapQWnn$vFxYNz9AlH!mUX~H9-&!L>qk{lDxeuS= z9rBew9i2dc!-bedBx*v?C^PSerhMhNtcF|W^xHL&Ew$*1xC6DtqJ<0>Ru!Q}Qku)t zO{A6Xj0@PFHtY$jrC_%GhLwX*CSQJn6Ka0BXEHW>$1geb2AJ zipL+$WqOUH!!?nqx{_n%(5Rn!0$35rsS{M?rGYOm2X2PSxpJz-G=4>Dk|ty?4ndV)#NiCy8lH?uEVgIR}`deJAICD--H(y=L}hZkQg zI6t3h@!}+n*iK}MmnAwabE$0)f7{{(S0Xi+AGJ>XsZWzQzDP}jz>NH8p zNHI{+Q{3vP(zJrB87YHCM|_31LA~M+`{+u4221DnHYi)bNX^L(j!K6atrqDzWz&6~ z?NK=z`;k(6@>s@OMe`kQUb6KwKbJ$TQ>q)S*2{;2Pn?vy7e%|f<;2WgxKhRo_>?-( zn78#2vKQJ^TQyoPbE-|=#9Vj0I}&Buv44+matf|7qb#I{cITLI_NUh<*4ca9`>niH zi3cvb--N6yQ$^rfcCfWrs;e{5cntb*xXW=oY_h=6*I-j}zb6m$)j3j%{@7AFQZuV! zJ5nG=kfbGL@?`cvuJJEhpi7Bt4q0JX#X5fxRkjor=d{P?YI>#!LV7$^d3Cg-gSG;$N;a$mWbVgsRQ!sbf zO3I37*-{gVB#15C*ED-o{NQ1vaCMMIdGu5m{amv@KGWEy$zACCexaZ7>dmz8+zAYb@>-gLkrheliUvPe~ zd+}HP6NkfX0{Q>u1F2`R>gKA0sKcOkR12FM7r1vc3s;T*{ukc^{2+Jt4_7~FRd3?P zEU=gI-h}v)=#%LE>A%XH{mQHhcdmmzH>#SM%xveF6+G6kpMwWNnS;LGY zY--F; z5eutc_i42ZW7N17zNBSN2KWcrmjHd=67Ghf9rsQKX!R1U_?Zcm(b){v%Im{z!YD&x zUMfQ=zGj|dkzO5UFv}9n(xPQ7L>Z?LZ+vN$(@i=YbIU1XF}MGbP^-wW=&|kL9ZS29 zY2xgC-!J3f*)%eRKPZK~u)JvGm+gKjEgWrBXCt}Lv$%)K5wR@9#`v%`Ob;=Eya_ta z4+|rD*&oEJMJws}tA13&TJFTuJOX44wY#w1H&rt^70yU$8C3<6`Pu%4xg>0ayI5e% zu6MXq#i(qCbT<*x;zw8|u#4dXz3{z753Yz?>SEoX8}HUC>VNiQ8&?~=J@{xzdy4Wx zNOW%o6w&qV=Jn3|jjXwLxRNB`0$B3;IQ+B11^f*11}%(@8T(D3(njKC(^ZLoRmsrd z@~rq{{s#fO5)ovCSyM__!U66?rxSERFAP)Ej<#@@6zOdTs2jg!YDp>ZMR<0WK4_M? zJLL~37GOtYGv6H(mV9f!;xp8J2Kb})ZwuH4kKq6V*<1la$2qu_C~cC=xy`enLTM{2 zUGKrBe~C6}xG_V}JmC_y;G|CyY6v==D*TTQ$A95f zF>NATSyFfBrX?suJ6D2u_9)i5D^^IgMQ+EgR>~5;q3*SeQK*2gb}^TLjedisCD)8; z&5#IMDnaks)6AIAAy6Hwru(t|esplCywExxj*PL`{syCCe>l4)gu^ZxsL$B?30VOy zv?(vF9+FQqMnVw4S3!2hC|(V8nKb9mdsaS>GK`cnp*buJnY_MY4FEu4H)FpS% znD&msKFLigM$jfV;G*6G3oJPGrHf+5_8Dgh&7q+McLi!UWC= z7sk!y#Vg#4r|oq?LVObO=oj7DoHA=D$e7g{D~=*t8`XvI;vZ^yG`r^mN9^0-Hf6My zm^6l}>xCSase_2ufk6Ij(*4NZqj|sppwg#=m#Tu~Hu;tBIUH_v3uiLO83%~-Wo*s* zILrFObyRy@o|iHwVMn5_?(G2b8L>QBx%h@FRIrFbiNRp2f&d{jgt)>KSNH@`qNwkr zN`jz*LZ3#u>Of9k8wjs!KU>40!SFVw%?;f}m4gPR^^o_Z3(n>>= zFd00 z6*#vD@aq--BSSg)SL3+hR9rMhOs--89&if?xImKRk8U~9878A+fO5^wUzWO^=x}`L zXG48gqAULBtTFli>rymVNpF?wK3z$f?=24mpDRi6ygLUV2j!arPAZa! zeLJM@@%es(W4?ywKqz$TxibTCb;hU+@*9AZ0y5kYr8H=j!ovbueAUid6Fo>y|GBco zeLPaK2QpGrD|J}xV3bQud32opm?z0MDYgyN*Z5qW-HS;rucVxX?#MIE4oB80bx|VN z2EJP5vf4V65%eTaT>QV=yV6)$(z0BqbG)7b#LHFVB}Qp5!XyN|8rdXD&Ak&H_F)?l zB90OWgA;|g1VK!JhecUh4X9U~MQU=wpWdeosb^|w-kea;(To~T3O z)(Wq4K?^a$u&1cP-qu12%bq%q6*ATJ@@ad6q&+M3lW>v-D`%Eqq-Hr1Vy{ywGE}M> zHM+H0X%rSg1GsC=+C!eaH(H1(!8oaHk%AyFh$^#L7(d$PY%>WEnu`RJ3N%UxM1;^w z)Z2ARag(_OvM1ccqouRyx*krdGwGhrQd_uAL7vP@JvT*4I-ZW!Ob(F8M07ugZ5DA3 z{Vah36n+$F6SENyuTe(F8(~~7Mt1gPGAO+D#3tDZq=3bGOMA-oPsaUJW0iX@m=~lY z?>RykuO!qL^DEvicO{YGT#}ql;3`kS$3zY?Z!*|;c5ZH?c_q%lHXbFl^;|qc;sesJ zQ_@o~@t(r6P`MZQwUpEG#iW`{hyr#@6hQ_^StTAx%X zCl+6v&eW2DXh9tcXGM8jQ-dbLeyCe+ROkIqxijgkSkW-@(iekp1pW->kcnnr7H$G_OClUnKh6X>(=VU z>#@pg+QuND-?7~cm`dOF>Z$dX?=~9Nras})mI^n9{!hPPX+{kO6pw2Q{^@%pM1mB4 z^_EGY=>m{4zA2;E96}`53v)~$OGp^$<^eJ8lh#WO_Zp5?ZsP}sk!7=hXL3jZVj9KE~>G9h;xOh8_8pi;%hR0s=rB>gM^Xon(+_VxQVVvZU&>9Oi zp(L@7#sP#VLIUDuDkdUM+$CuSS&Ohx81$_)W~ylAY0{ClVd_AHkb;u6`i;DwYFxFi zl>K2Np1Hdw4Vh&h;1b>&z~03{RC=>ysx^}Am4qzWETT#R!&mqYYltYtuUG~P5>^=l z2^o}>cr*w@|L6p?)pw{4@K;{p1i`!CEbiSqySGXFkQY<4LKx0Ms)BM6m_ZV@HMQuv zrHNY)8T|-leg)}ti4IJVT#z_{KtdWXDC5?|w?|#Al$Hjgo*F%z`^AYU$(>rZ!D&r| zPS7)rR;YW<2QykyV1KYAj!ufXn~4(`jj@M;nqT}FcHE>`cT`c%1tTSLB`+X|ph2L@ zp`%A`PYJe8p{fS?jx^^zI?PP04!Bd5|AGbKgYKg< zq;B%^MKSAjg_z-VB#+-5ijE7j8`#w#4dZm|Yzbb?90_KeH)q2O;A505dBUceyoQ|N3%;sLVNjOjI^QU&=Ry_wFRY5 z!h>uBmFT4@5HS^Tf{b^@MrSP%paF?CSM)R^{Qdd&_cX)Q4`)(>i5bMf+9U{4R~Nd! z>AFnZ)W&cl;jWo}L;$f5-9TUyCucAc4B4Qz*DTk%JeULme@j2w+-wN>f|r!zYz%Bi ziRTUJptR}&p9ED|s&TqF`|N)|G~x>zH%nr5l4{5O7>`)HP;gN%O(s@UPId57t{s*Q z#ae^gq<#)Vo~IyOei#@*`p_Wb;J?)60Vr8<8w%vQ2nOfvkgCiT(WI4=MpDD~wR%ch zDV%>+I)lW}F=Q@NW8J6S+3g#nEJNipdeNv!PAh#+DPC{%R?D$VN7DYwJ2J+V*l_|k z$7k&a)fHGj#ltVv1sj9MuU70y(#{vw3}6w=Q9r7Jm)^r`+z_2JuD&4*Bl)id>Ig0( z+nJh!k@S=EqC=IOgVFl-dl4tyd^FaAQkrPOeY>b*pxh~NS!Ri}Alv71VKBrZ32zSc zhBSin{$@DDX2n23Yjj8OP?+7VR@KKJN;5%%yI=rRzaziIGeSeu*oZvMDv{+Y39H2hc5R~A{j7t^j)A%!snLYWOd5e82%XfFk>DrnMcTQ&jIcp_l;Wf;w2}kG3tdu>P$@30^BeyIZ`EXkd3sFAilMu_< z7H&KF=`GGK-gu(B00MhRu;8H)9&HC10`TbI#{wuJJZ=y0Be$$DR9j}$voX%N%`MGA zBl9IsfBB6TQa?Y~q>L>mS0|p8)XCY&*F;|LxfB8KHGncaZ17psLh`@$0W42{bRD3q zSLA!>3KMkH^OwsDmDW{2vjkN>2|Tnq$s z4a%S|-)@qYVBcURl;m=kvk!!h+w2r(UwB)JIE)pMYR3%We?`T1ZDTgH$PX4hPcbFUCcBGcRjW-cC030C`-|wOh_B zCguYag>wAVh>cauZT1!g4Z){`RUi5QQm~5jYy(o3RXCp<3#;8$s~XnP--}Vi6kng! zN3&UdD62vwDOu(GJJ=`598Pp9DUlHrr zDFQeI24!A7aFr-_ow800HX&-9FQtNAD(s+JVIUwIA%H zP%6(tjsR{wRC+_wQ;w8(1KdRfOT&g>(9cGR?^-iqT0;6cYvo!l9mOvvD&jb+qjrZ@ zi0hPgo7`^#A>)V@Yj7)0?@{tp+=A9s_3z)-GQ{(W#RE;K>kb1@)tOq5a!?M%&UXG5 zvdxMo3I?sb#0RdL)sY63MJbZ@=Ac7Y6rW6@pfa)d(+RC&-6QkqJp`hdP^@RQ;~_R# zF1$76rbs>Dedv$~1r*tX{mD_#-{l-%Rtc*()Vf)LM;ZwuQK<0vKSD5ND`_smDPPTM&r~XtTv$QxVI=Kuqeh^QNpEB zaF}N`r9Nr+`+~wKR?e>2!Z3<939NkeVwhBOQ7^;WFLqyh6TscS^QEi$zBzj1S1;OA z6EA&$>kV&~@4)W({^?g=y6VCOtOk8`_j4dWE8g+DurJoF)r+@&w*k1dL)v!zMZii7 zd#roJX}sq@G3DYpn@Km23Fph2a$5}5!|{w*zd-AxxF*SYj9f^X5F~yAo4HVd&8<6% z=n$#Tz`obVt}?D)RHNA8k7l*keZr_fA4$k;z{`)yJ-@Si2S4(+&ZMK5`IVarUY!Mr z0+r~b*KhKEy%cDp!O~QoYj97+LItJy3OoM<#lW|>)Ws)XDGp)Cj<^iHssQ?aHQ}TXENGgMY3e5zJ zYzNgt9_Vx!nDU(IvDl&`tcd*dYx)dUk@q8_ z(OhruD|AiaCS5wnUWRw_nrdw~20gQ!fHJ-uJw^`roI_A+HkGcO=KJtN6B?8 zA*IzYlPsw6t@!TR?cW@iu1XxcTsP#ATRL~~4@fo6?%J3(4QOG5ED)ore$UrOnQehl zs2fC}HE(Cz8tAEXgP}4X_RU<2JBD1a4V)LsQ_5%;wbRcv3Ztv#y*o1?SYrTt0awIs`{wUi_KgZfpVsArDC||we>M%8@b|9vr#i`p zw(*nOSq-u5Fxp4IheBc}0WMP%`HCX+p|k@T9;C!d7R`)gaE* zZXw0=R`l54g>i%5E#3fu6x%nVH0WXDkl3gLRbz_3g&7UEjR&v{iX zF7?6TQSyszH`O9sfDD+3PoyMwgVY9xb7WcPJ~7g8gU!4<$}yxY(8w-`5~6@J(PZR< zp9MC&x{E3e8SfE9HLGRtU3f(m!L~%X;OVo_S)IM~4OH~@=fHehYMdk2u+8c~k{GB_ z?#TUITlv_30?&1c_nk8L_VpCcA0p-FkuD*Q&0-bFuvcAhmgB4rUf_oC{_1-XaI04@ z7V8c#VIAhc>cx@YV%@QN@x^!B`nxIiLjPtB1cONRTMuY{9N!7K{C31im!EJ0JZ{0+ zS2ZV^NdEe#3RnR~zMt0k`%KK9x+6ZEQgw16(F#sfs00xOv zv22cydDF5UxxF<=7knYDyoquykG2{o6KThU0A0A4T?A~Yo_gG$hv1QDBH2L&1Uhsr z(Ne}O?=b?O!N=&6oR3kMQ*EbQpK!N*G+`E#>u-p~a~{>A3ym(>f_cvW*8+oQ^GkE-s&zOgO_z{G)TZE1fOSlK^eIc;JH%&A^_8MhkytpAX{Rdb(xMw zrkwG|K3qz6hF=|&P6&SXDM8!>YU>DqqPWTV+*(h0(GS{xxfqIoR335+<5PnwrNQ=UJxoJ;Y>=a&^2C<^FF$~bNs?xJH^{B z9JpR*04`DIOLkzb3(B?A3Mc@hVy|dWEdLZK+K3;u;-Y5#`yW2yd!GG~PgtYXO7%jr zt3Xg-n{dLbN>CMDYUS3g@wO+oL|Z4Yg=T=oa4ARYpO#hyZoQ!HTXn5V_;XgAEu?%f z9Y39()rciKjGMH2G08kg{=H^?&;Gadw+*g^Kf<4HTDa?tycy;1>~GRN-rPV3oBs zN7^+~w#ywUfsts(<#yadsPSmG@LgRv}T=T8W)xVwD7W@aiU>Qa&HO+ib(7 zJv9eRBz?!nfwCU->(!zXU&bd2ZuypVYtoMMv(xc&E(_ zyhjk#td_xd^0Mm8<%=R6mFD8l=k!W+)O}oOCW+7L?CeXU6u3N`&mG=!q@-l6(Xg>6 zapg$qA>G5>l*=KR)!0RT0I3h&3d^lW3Z~hW zq+7ju(Vx92WAC#UUu@4_ELJbR>Q(o+9=P7&L&X}%j@64#{fxtTI>&h8Evo;;e>Y&! z4Cr=Dl_NIqsP6v%&>`#+<=3(;*uN~E&WZ|uFolRn#nc+(?4wc;n1Km z;8b3xQUFHN6H;TLnvj~18jHYKyQ!yEL#i3;b_(sLyM(a^eLDLlq{bpJ*3Nn={LLtT zFWMiC@^NeY%ym{HsO&H%D+Yy=06QJ!8@EfL*fmZ}V*t{ zLTW4mW9_D%S_-M~>MmaC8_V$?K~%F^2HzbzA>)om`L1)Qa>r}TKG9qG*iT4h=f%KT zLZr5P^p5oqp|B4j*8i3Yf?pq5WF#YT1j(6OiDNsJ|T}d$w|8hsGj|?bxj>Y zGN2;UXlxslS!sXSS}Mu*wJ%JVHIvPn<6U079`L2LmeYNfm5`PET2nZ#VAuTI+9Ic? z9}t_ZEpYl@71tPa$xvT>DnFHJnkC&%q4~XDGktzF;;`d>{i--FQ1n%Z6gp^`JKEGv3JX)3#n%PCGNnL?92a5 zSOPYIpmeEi2e8QMP4A;c@vwDNxQ-ZEnw!Y*weJLaYWuKk_0)sn^U?i4HcpHk0}O%a z@Ep>0m~Wa0j~KedoSIOFyt83%Z;V~NcmVGZKuT;!Ik?hlpVc5_hjE+MK>jg5acGkB zFC$sY;*Cfx+Q!%{ig9`MH+_iEG|h2mvHeIr{>BxWXa!ie94TDiA94%JZdRy0x@u(0%Pr_o*ISJUR9lW#VE_ksG53eY!ggKO-PMJ zV65HLQxj5S5g2PX_0)vaSOog)a0``fuYOO)PE0^xLMlM96tP!br#%(kij%kU?ESp4 zs~0(?1lZ{)@!5+@L3|30r`Nu*2VIeB#+sj2J6zts_>t3E{IYdVXWv-FCZv`^D!jUj zSNfUXw0bcBIjzYHP>|?flUEU`_`hbvYw9TnFFn`x-f-pg?8R~49L;AhHjd#m_9L+O zd3myg7^G)izsIT7y!`i2dUI;aA1XY1+hwo%`0orEpJrVK6o4q-$vcTtu-VE3@W|`d zmi7S1sVdNcSX&0i7HE#hueg_oZzrDKPKZ@vGEZoauy9<(XJODDgSF4~sxK5XB{P&r zC93K|;a0M#Ep*Bj!qR7*{Q9T*o?l&OepPW99Qy>gvaW(J*tKRnI@l-I_LNGQvOsEd z8e3p^pP$)+BsU_(V|{9|qoOPlVhl)~J@-3%L73@_X)%&UNrd?V}_v%H329I%JQHN)-k&pnbDAc7WW9LmSe0rQi~%kW4k!o$y(g@CeGI^ zJ!z~tQj3EuW4k!o30mO2glGQfvh(HD=3E(TSX)|eHvfWmEt_9nea@A!hP9>jX7kG< zwb}I?Uv~0$UwCzwd0ICLarRjqX;5;b5F|SuWm>%$jx>pZV?V849EsGldU2_5j&3qo zM=;?f%`R!_l`U~E#U-DZZa%s9#Csk~l1&GN?-8NW67*RRQ~SJ_L)cTP%+0>3ht`^iL0zv-{x)C zx-Gi=lKrEn@JIPw>CppL^%`QVJ;WN2dfF#Ft9&`#LGc#2UyRX)7x?x#c=@3n1XVTn zIF)2oJ9{?y(jIv9Z~ABByx*WtbD%Sty8o}wKL25Pi1!oE>M;x!Q9mcyb#w+1fKSka zkRS}CTkXWsV@HBZ$H*K)mYFm#Px(wBOCsEfiz3Fk0RHUReW{<)sL=?DWvxtgHmRtz zG?R3gr_4Bdo*unqwsGEOmHMS=M)|=rL%_W#4YD>-8iAj~ioZwO%D|(e4LGJXkB--4 z_~~y%MLOlY>nsbVr83E=R0W?(uJws!qG^$JOVSoty7RVXu_P_E%Q{WdY~R*;3c#Wu zU4buy>?G3^-0pgx?kZDIyDd(cw0_}Vwkp=6wc${mWJ~citFB)67cHc^1bg!?smof| zrrI^_aZN`6NTpxLh3|gJ`1ZWxBm)QFIZu<1yp_TMaUsB-+d(bE;Lc3!_%&5^4b11^{tg00fxx$zZe4x-?qPDM4`vtZ zYCf;3^ZHihK{cCIdwY~5+umNn7+IKLzIiapPfdthf?%qIo)MT@Hr%^XU`~jeym407 zYBR7m6LV@BxemlA5KyA&3WodNY0-Qh&V07|n0(io9Vl8DDMKPQ=k^d`Hys7F(suB= z1ZuGQKBhL;AW^VH(3VpvaIjF(*;)e6TH$9<%u{LGgePBn%bciA1f8(brf<{CeQF?| zlrj&e4ZUmbhPPVP@#Ldm9-=hh>i%@^{RZgUTkM9mE|+u`U#m@w(h}rBmggd3b9Ih_ zC4#k_S^^JNSO4)or!zF8FjgC7DHV}2ibE|H`|wq&x>f|d0GnV@Sherp$C9p8BM9b! z>i5evF^W+wf!o*B=U(S@m?;WKjV~!;W)UK0Nt9ZZgoMIlyc(z1YPBq4MB2}vrQH;8_6fB-VJ^J>s e#<`k65UC!oy;2^dm?jD$C91l*?W+G "CLOCK1", + clock_enable_input_a => "BYPASS", + clock_enable_input_b => "BYPASS", + clock_enable_output_a => "BYPASS", + clock_enable_output_b => "BYPASS", + indata_reg_b => "CLOCK1", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + numwords_b => 2**widthad_a, + operation_mode => "BIDIR_DUAL_PORT", + outdata_aclr_a => "NONE", + outdata_aclr_b => "NONE", + outdata_reg_a => outdata_reg_a, + outdata_reg_b => outdata_reg_a, + power_up_uninitialized => "FALSE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + read_during_write_mode_port_b => "NEW_DATA_NO_NBE_READ", + widthad_a => widthad_a, + widthad_b => widthad_a, + width_a => width_a, + width_b => width_a, + width_byteena_a => 1, + width_byteena_b => 1, + wrcontrol_wraddress_reg_b => "CLOCK1" + ) + PORT MAP ( + wren_a => wren_a, + clock0 => clock_a, + wren_b => wren_b, + clock1 => clock_b, + address_a => address_a, + address_b => address_b, + data_a => data_a, + data_b => data_b, + q_a => sub_wire0, + q_b => sub_wire1 + ); + + + +END SYN; diff --git a/Sega - SG1000/rtl/psg/psg.vhd b/Sega - SG1000/rtl/psg/psg.vhd new file mode 100644 index 00000000..dd4bba90 --- /dev/null +++ b/Sega - SG1000/rtl/psg/psg.vhd @@ -0,0 +1,134 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity psg is + port (clk : in STD_LOGIC; + WR_n : in STD_LOGIC; + D_in : in STD_LOGIC_VECTOR (7 downto 0); + outputs: out STD_LOGIC_VECTOR (5 downto 0) + ); + +end psg; + +architecture rtl of psg is + + signal clk_divide : unsigned(5 downto 0) := "000000"; + signal clk32 : std_logic; + signal regn : std_logic_vector(2 downto 0); + signal tone0 : std_logic_vector(9 downto 0):="0000100000"; + signal tone1 : std_logic_vector(9 downto 0):="0000100000"; + signal tone2 : std_logic_vector(9 downto 0):="0000100000"; + signal ctrl3 : std_logic_vector(2 downto 0):="100"; + signal volume0 : std_logic_vector(3 downto 0):="1111"; + signal volume1 : std_logic_vector(3 downto 0):="1111"; + signal volume2 : std_logic_vector(3 downto 0):="1111"; + signal volume3 : std_logic_vector(3 downto 0):="1111"; + signal output0 : std_logic_vector(3 downto 0); + signal output1 : std_logic_vector(3 downto 0); + signal output2 : std_logic_vector(3 downto 0); + signal output3 : std_logic_vector(3 downto 0); + +-- signal outputs : std_logic_vector(5 downto 0); + + component psg_tone is + port (clk : in STD_LOGIC; + tone : in STD_LOGIC_VECTOR (9 downto 0); + volume: in STD_LOGIC_VECTOR (3 downto 0); + output: out STD_LOGIC_VECTOR (3 downto 0)); + end component; + + component psg_noise is + port (clk : in STD_LOGIC; + style : in STD_LOGIC_VECTOR (2 downto 0); + tone : in STD_LOGIC_VECTOR (9 downto 0); + volume: in STD_LOGIC_VECTOR (3 downto 0); + output: out STD_LOGIC_VECTOR (3 downto 0)); + end component; + + component dac is + port (clk : in STD_LOGIC; + input : in STD_LOGIC_VECTOR (5 downto 0); + output: out STD_LOGIC); + end component; +begin + + t0: psg_tone + port map ( + clk => clk32, + tone => tone0, + volume => volume0, + output => output0); + + t1: psg_tone + port map ( + clk => clk32, + tone => tone1, + volume => volume1, + output => output1); + + t2: psg_tone + port map ( + clk => clk32, + tone => tone2, + volume => volume2, + output => output2); + + t3: psg_noise + port map( + clk => clk32, + style => ctrl3, + tone => tone2, + volume => volume3, + output => output3); + + + process (clk) + begin + if rising_edge(clk) then + clk_divide <= clk_divide+1; + end if; + end process; + clk32 <= std_logic(clk_divide(5)); + + process (clk, WR_n) + begin + if rising_edge(clk) and WR_n='0' then + if D_in(7)='1' then + case D_in(6 downto 4) is + when "000" => tone0(3 downto 0) <= D_in(3 downto 0); + when "010" => tone1(3 downto 0) <= D_in(3 downto 0); + when "100" => tone2(3 downto 0) <= D_in(3 downto 0); + when "110" => ctrl3 <= D_in(2 downto 0); + when "001" => volume0 <= D_in(3 downto 0); + when "011" => volume1 <= D_in(3 downto 0); + when "101" => volume2 <= D_in(3 downto 0); + when "111" => volume3 <= D_in(3 downto 0); + when others => + end case; + regn <= D_in(6 downto 4); + else + case regn is + when "000" => tone0(9 downto 4) <= D_in(5 downto 0); + when "010" => tone1(9 downto 4) <= D_in(5 downto 0); + when "100" => tone2(9 downto 4) <= D_in(5 downto 0); + when "110" => + when "001" => volume0 <= D_in(3 downto 0); + when "011" => volume1 <= D_in(3 downto 0); + when "101" => volume2 <= D_in(3 downto 0); + when "111" => volume3 <= D_in(3 downto 0); + when others => + end case; + end if; + end if; + end process; + + outputs <= std_logic_vector( + unsigned("00"&output0) + + unsigned("00"&output1) + + unsigned("00"&output2) + + unsigned("00"&output3) + ); + +end rtl; + diff --git a/Sega - SG1000/rtl/psg/psg_noise.vhd b/Sega - SG1000/rtl/psg/psg_noise.vhd new file mode 100644 index 00000000..7dee6168 --- /dev/null +++ b/Sega - SG1000/rtl/psg/psg_noise.vhd @@ -0,0 +1,56 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity psg_noise is +port ( + clk : in STD_LOGIC; + style : in STD_LOGIC_VECTOR (2 downto 0); + tone : in STD_LOGIC_VECTOR (9 downto 0); + volume : in STD_LOGIC_VECTOR (3 downto 0); + output : out STD_LOGIC_VECTOR (3 downto 0)); +end psg_noise; + +architecture rtl of psg_noise is + + signal counter : unsigned(9 downto 0); + signal v : std_logic; + signal shift : std_logic_vector(15 downto 0) := "1000000000000000"; + +begin + + process (clk, tone) + begin + if rising_edge(clk) then + if counter="000000001" then + v <= not v; + case style(1 downto 0) is + when "00" => counter <= "0000010000"; + when "01" => counter <= "0000100000"; + when "10" => counter <= "0001000000"; + when "11" => counter <= unsigned(tone); + when others => + end case; + else + counter <= counter-1; + end if; + end if; + end process; + + process (v) + variable feedback: std_logic; + begin + if rising_edge(v) then + if (style(2)='1') then + feedback := shift(0) xor shift(3); + else + feedback := shift(0); + end if; + shift <= feedback & shift(15 downto 1); + end if; + end process; + + output <= (shift(0)&shift(0)&shift(0)&shift(0)) or volume; + +end rtl; + diff --git a/Sega - SG1000/rtl/psg/psg_tone.vhd b/Sega - SG1000/rtl/psg/psg_tone.vhd new file mode 100644 index 00000000..7ec6b552 --- /dev/null +++ b/Sega - SG1000/rtl/psg/psg_tone.vhd @@ -0,0 +1,34 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity psg_tone is + Port ( + clk : in STD_LOGIC; + tone : in STD_LOGIC_VECTOR (9 downto 0); + volume: in STD_LOGIC_VECTOR (3 downto 0); + output: out STD_LOGIC_VECTOR (3 downto 0)); +end psg_tone; + +architecture rtl of psg_tone is + + signal counter : unsigned(9 downto 0) := (0=>'1', others=>'0'); + signal v : std_logic := '0'; + +begin + + process (clk, tone) + begin + if rising_edge(clk) then + if counter="000000000" then + v <= not v; + counter <= unsigned(tone); + else + counter <= counter-1; + end if; + end if; + end process; + + output <= (v&v&v&v) or volume; +end rtl; + diff --git a/Sega - SG1000/rtl/sg1000_top.sv b/Sega - SG1000/rtl/sg1000_top.sv new file mode 100644 index 00000000..f15cb73e --- /dev/null +++ b/Sega - SG1000/rtl/sg1000_top.sv @@ -0,0 +1,116 @@ +module sg1000_top( +input RESET_n, +input sys_clk, +input clk_vdp, +input pause, +input [7:0] Cart_In, +output [7:0] Cart_Out, +output [14:0] Cart_Addr, +output x, +output y, +output vblank, +output hblank, +output [7:0] color, +input [7:0] Joy_A, +input [7:0] Joy_B +); + +wire WAIT_n, MREQ_n, M1_n, IORQ_n, RFSH_n, INT_n; +wire NMI_n = pause;//go to M1_n and generate CS_PSG_n +wire RD_n, WR_n; +wire [7:0]D_in, D_out, RAM_D_out; +wire [15:0]Addr; + +T80se #( + .Mode(0), + .T2Write(0), + .IOWait(1)) +CPU ( + .RESET_n(RESET_n), + .CLK_n(sys_clk), + .CLKEN(1'b1), + .WAIT_n(1'b1), + .INT_n(INT_n), + .NMI_n(NMI_n), + .BUSRQ_n(),//? + .M1_n(M1_n), + .MREQ_n(MREQ_n), + .IORQ_n(IORQ_n), + .RD_n(RD_n), + .WR_n(WR_n), + .RFSH_n(RFSH_n), + .HALT_n(WAIT_n), + .BUSAK_n(), + .A(Addr), + .DI(D_in), + .DO(D_out) + ); + +spram #( + .widthad_a(10), + .width_a(8)) +MRAM ( + .address(Addr[9:0]), + .clock(sys_clk), + .data(D_out), + .wren(WR_n), + .q(RAM_D_out) + ); + +assign Cart_Addr = Addr[14:0]; + +spram #( + .widthad_a(15), + .width_a(8)) +CART ( + .address(Cart_Addr), + .clock(sys_clk), + .data(Cart_In), + .wren(WR_n), + .q(Cart_Out) + ); + +wire [5:0]audio; + +psg PSG ( + .clk(sys_clk), + .WR_n(WR_n), + .D_in(D_out), + .outputs(audio) + ); + +wire [7:0]vdp_D_out; + + +vdp vdp ( + .cpu_clk(sys_clk), + .vdp_clk(clk_vdp), + .RD_n(VDP_RD_n), + .WR_n(VDP_WR_n), + .IRQ_n(IORQ_n), + .A(Addr[7:0]), + .D_in(D_out), + .D_out(vdp_D_out), + .x(x), + .y(y), + .vblank(vblank), + .hblank(hblank), + .color(color) + ); + + +wire CS_WRAM_n = (~MREQ_n & Addr[15:14] == "11") ? 1'b0 : 1'b1; +wire EXM1_n = (~MREQ_n & Addr[15:14] == "10") ? 1'b0 : 1'b1; +wire EXM2_n = (~MREQ_n | Addr[15]) ? 1'b0 : 1'b1; +wire CS_PSG_n = (~IORQ_n & Addr[7:6] == "01") ? 1'b0 : 1'b1; + +wire VDP_RD_n = (~IORQ_n & Addr[7:6] == "10") | RD_n ? 1'b0 : 1'b1; +wire VDP_WR_n = (~IORQ_n & Addr[7:6] == "10") | WR_n ? 1'b0 : 1'b1; +wire JOY_SEL_n = (~IORQ_n & Addr[7:6] == "11") | RD_n ? 1'b0 : 1'b1; +wire KB_SEL_n = (~IORQ_n & Addr[7:6] == "11") ? 1'b0 : 1'b1; + +assign D_in = ~CS_WRAM_n ? RAM_D_out : + ~VDP_RD_n ? vdp_D_out : + "00000000"; + +endmodule \ No newline at end of file diff --git a/Sega - SG1000/rtl/spram.vhd b/Sega - SG1000/rtl/spram.vhd new file mode 100644 index 00000000..d4e8dd90 --- /dev/null +++ b/Sega - SG1000/rtl/spram.vhd @@ -0,0 +1,90 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY spram IS + GENERIC + ( + init_file : string := ""; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED" + ); + PORT + ( + address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + clock : IN STD_LOGIC ; + data : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + wren : IN STD_LOGIC ; + q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END spram; + + +ARCHITECTURE SYN OF spram IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + clock_enable_input_a : STRING; + clock_enable_output_a : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_reg_a : STRING; + power_up_uninitialized : STRING; + read_during_write_mode_port_a : STRING; + widthad_a : NATURAL; + width_a : NATURAL; + width_byteena_a : NATURAL + ); + PORT ( + wren_a : IN STD_LOGIC ; + clock0 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + data_a : IN STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q <= sub_wire0(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + operation_mode => "SINGLE_PORT", + outdata_aclr_a => "NONE", + outdata_reg_a => outdata_reg_a, + power_up_uninitialized => "FALSE", + read_during_write_mode_port_a => "NEW_DATA_NO_NBE_READ", + widthad_a => widthad_a, + width_a => width_a, + width_byteena_a => 1 + ) + PORT MAP ( + wren_a => wren, + clock0 => clock, + address_a => address, + data_a => data, + q_a => sub_wire0 + ); + + + +END SYN; diff --git a/Sega - SG1000/rtl/sprom.vhd b/Sega - SG1000/rtl/sprom.vhd new file mode 100644 index 00000000..a81ac959 --- /dev/null +++ b/Sega - SG1000/rtl/sprom.vhd @@ -0,0 +1,82 @@ +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY sprom IS + GENERIC + ( + init_file : string := ""; + widthad_a : natural; + width_a : natural := 8; + outdata_reg_a : string := "UNREGISTERED" + ); + PORT + ( + address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + clock : IN STD_LOGIC ; + q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); +END sprom; + + +ARCHITECTURE SYN OF sprom IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + address_aclr_a : STRING; + clock_enable_input_a : STRING; + clock_enable_output_a : STRING; + init_file : STRING; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_reg_a : STRING; + widthad_a : NATURAL; + width_a : NATURAL; + width_byteena_a : NATURAL + ); + PORT ( + clock0 : IN STD_LOGIC ; + address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0); + q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q <= sub_wire0(width_a-1 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + address_aclr_a => "NONE", + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + init_file => init_file, + intended_device_family => "Cyclone III", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 2**widthad_a, + operation_mode => "ROM", + outdata_aclr_a => "NONE", + outdata_reg_a => outdata_reg_a, + widthad_a => widthad_a, + width_a => width_a, + width_byteena_a => 1 + ) + PORT MAP ( + clock0 => clock, + address_a => address, + q_a => sub_wire0 + ); + + + +END SYN; diff --git a/Sega - SG1000/rtl/t80/T80.vhd b/Sega - SG1000/rtl/t80/T80.vhd new file mode 100644 index 00000000..398fa0df --- /dev/null +++ b/Sega - SG1000/rtl/t80/T80.vhd @@ -0,0 +1,1073 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0247 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0210 : Fixed wait and halt +-- +-- 0211 : Fixed Refresh addition and IM 1 +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0232 : Removed refresh address output for Mode > 1 and added DJNZ M1_n fix by Mike Johnson +-- +-- 0235 : Added clock enable and IM 2 fix by Mike Johnson +-- +-- 0237 : Changed 8080 I/O address output, added IntE output +-- +-- 0238 : Fixed (IX/IY+d) timing and 16 bit ADC and SBC zero flag +-- +-- 0240 : Added interrupt ack fix by Mike Johnson, changed (IX/IY+d) timing and changed flags in GB mode +-- +-- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM +-- +-- 0247 : Fixed bus req/ack cycle +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80 is + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic + ); +end T80; + +architecture rtl of T80 is + + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; + + -- Registers + signal ACC, F : std_logic_vector(7 downto 0); + signal Ap, Fp : std_logic_vector(7 downto 0); + signal I : std_logic_vector(7 downto 0); + signal R : unsigned(7 downto 0); + signal SP, PC : unsigned(15 downto 0); + signal RegDIH : std_logic_vector(7 downto 0); + signal RegDIL : std_logic_vector(7 downto 0); + signal RegBusA : std_logic_vector(15 downto 0); + signal RegBusB : std_logic_vector(15 downto 0); + signal RegBusC : std_logic_vector(15 downto 0); + signal RegAddrA_r : std_logic_vector(2 downto 0); + signal RegAddrA : std_logic_vector(2 downto 0); + signal RegAddrB_r : std_logic_vector(2 downto 0); + signal RegAddrB : std_logic_vector(2 downto 0); + signal RegAddrC : std_logic_vector(2 downto 0); + signal RegWEH : std_logic; + signal RegWEL : std_logic; + signal Alternate : std_logic; + + -- Help Registers + signal TmpAddr : std_logic_vector(15 downto 0); -- Temporary address register + signal IR : std_logic_vector(7 downto 0); -- Instruction register + signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector + signal RegBusA_r : std_logic_vector(15 downto 0); + + signal ID16 : signed(15 downto 0); + signal Save_Mux : std_logic_vector(7 downto 0); + + signal TState : unsigned(2 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal IntE_FF1 : std_logic; + signal IntE_FF2 : std_logic; + signal Halt_FF : std_logic; + signal BusReq_s : std_logic; + signal BusAck : std_logic; + signal ClkEn : std_logic; + signal NMI_s : std_logic; + signal INT_s : std_logic; + signal IStatus : std_logic_vector(1 downto 0); + + signal DI_Reg : std_logic_vector(7 downto 0); + signal T_Res : std_logic; + signal XY_State : std_logic_vector(1 downto 0); + signal Pre_XY_F_M : std_logic_vector(2 downto 0); + signal NextIs_XY_Fetch : std_logic; + signal XY_Ind : std_logic; + signal No_BTR : std_logic; + signal BTR_r : std_logic; + signal Auto_Wait : std_logic; + signal Auto_Wait_t1 : std_logic; + signal Auto_Wait_t2 : std_logic; + signal IncDecZ : std_logic; + + -- ALU signals + signal BusB : std_logic_vector(7 downto 0); + signal BusA : std_logic_vector(7 downto 0); + signal ALU_Q : std_logic_vector(7 downto 0); + signal F_Out : std_logic_vector(7 downto 0); + + -- Registered micro code outputs + signal Read_To_Reg_r : std_logic_vector(4 downto 0); + signal Arith16_r : std_logic; + signal Z16_r : std_logic; + signal ALU_Op_r : std_logic_vector(3 downto 0); + signal Save_ALU_r : std_logic; + signal PreserveC_r : std_logic; + signal MCycles : std_logic_vector(2 downto 0); + + -- Micro code outputs + signal MCycles_d : std_logic_vector(2 downto 0); + signal TStates : std_logic_vector(2 downto 0); + signal IntCycle : std_logic; + signal NMICycle : std_logic; + signal Inc_PC : std_logic; + signal Inc_WZ : std_logic; + signal IncDec_16 : std_logic_vector(3 downto 0); + signal Prefix : std_logic_vector(1 downto 0); + signal Read_To_Acc : std_logic; + signal Read_To_Reg : std_logic; + signal Set_BusB_To : std_logic_vector(3 downto 0); + signal Set_BusA_To : std_logic_vector(3 downto 0); + signal ALU_Op : std_logic_vector(3 downto 0); + signal Save_ALU : std_logic; + signal PreserveC : std_logic; + signal Arith16 : std_logic; + signal Set_Addr_To : std_logic_vector(2 downto 0); + signal Jump : std_logic; + signal JumpE : std_logic; + signal JumpXY : std_logic; + signal Call : std_logic; + signal RstP : std_logic; + signal LDZ : std_logic; + signal LDW : std_logic; + signal LDSPHL : std_logic; + signal IORQ_i : std_logic; + signal Special_LD : std_logic_vector(2 downto 0); + signal ExchangeDH : std_logic; + signal ExchangeRp : std_logic; + signal ExchangeAF : std_logic; + signal ExchangeRS : std_logic; + signal I_DJNZ : std_logic; + signal I_CPL : std_logic; + signal I_CCF : std_logic; + signal I_SCF : std_logic; + signal I_RETN : std_logic; + signal I_BT : std_logic; + signal I_BC : std_logic; + signal I_BTR : std_logic; + signal I_RLD : std_logic; + signal I_RRD : std_logic; + signal I_INRC : std_logic; + signal SetDI : std_logic; + signal SetEI : std_logic; + signal IMode : std_logic_vector(1 downto 0); + signal Halt : std_logic; + +begin + + mcode : T80_MCode + generic map( + Mode => Mode, + Flag_C => Flag_C, + Flag_N => Flag_N, + Flag_P => Flag_P, + Flag_X => Flag_X, + Flag_H => Flag_H, + Flag_Y => Flag_Y, + Flag_Z => Flag_Z, + Flag_S => Flag_S) + port map( + IR => IR, + ISet => ISet, + MCycle => MCycle, + F => F, + NMICycle => NMICycle, + IntCycle => IntCycle, + MCycles => MCycles_d, + TStates => TStates, + Prefix => Prefix, + Inc_PC => Inc_PC, + Inc_WZ => Inc_WZ, + IncDec_16 => IncDec_16, + Read_To_Acc => Read_To_Acc, + Read_To_Reg => Read_To_Reg, + Set_BusB_To => Set_BusB_To, + Set_BusA_To => Set_BusA_To, + ALU_Op => ALU_Op, + Save_ALU => Save_ALU, + PreserveC => PreserveC, + Arith16 => Arith16, + Set_Addr_To => Set_Addr_To, + IORQ => IORQ_i, + Jump => Jump, + JumpE => JumpE, + JumpXY => JumpXY, + Call => Call, + RstP => RstP, + LDZ => LDZ, + LDW => LDW, + LDSPHL => LDSPHL, + Special_LD => Special_LD, + ExchangeDH => ExchangeDH, + ExchangeRp => ExchangeRp, + ExchangeAF => ExchangeAF, + ExchangeRS => ExchangeRS, + I_DJNZ => I_DJNZ, + I_CPL => I_CPL, + I_CCF => I_CCF, + I_SCF => I_SCF, + I_RETN => I_RETN, + I_BT => I_BT, + I_BC => I_BC, + I_BTR => I_BTR, + I_RLD => I_RLD, + I_RRD => I_RRD, + I_INRC => I_INRC, + SetDI => SetDI, + SetEI => SetEI, + IMode => IMode, + Halt => Halt, + NoRead => NoRead, + Write => Write); + + alu : T80_ALU + generic map( + Mode => Mode, + Flag_C => Flag_C, + Flag_N => Flag_N, + Flag_P => Flag_P, + Flag_X => Flag_X, + Flag_H => Flag_H, + Flag_Y => Flag_Y, + Flag_Z => Flag_Z, + Flag_S => Flag_S) + port map( + Arith16 => Arith16_r, + Z16 => Z16_r, + ALU_Op => ALU_Op_r, + IR => IR(5 downto 0), + ISet => ISet, + BusA => BusA, + BusB => BusB, + F_In => F, + Q => ALU_Q, + F_Out => F_Out); + + ClkEn <= CEN and not BusAck; + + T_Res <= '1' when TState = unsigned(TStates) else '0'; + + NextIs_XY_Fetch <= '1' when XY_State /= "00" and XY_Ind = '0' and + ((Set_Addr_To = aXY) or + (MCycle = "001" and IR = "11001011") or + (MCycle = "001" and IR = "00110110")) else '0'; + + Save_Mux <= BusB when ExchangeRp = '1' else + DI_Reg when Save_ALU_r = '0' else + ALU_Q; + + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + PC <= (others => '0'); -- Program Counter + A <= (others => '0'); + TmpAddr <= (others => '0'); + IR <= "00000000"; + ISet <= "00"; + XY_State <= "00"; + IStatus <= "00"; + MCycles <= "000"; + DO <= "00000000"; + + ACC <= (others => '1'); + F <= (others => '1'); + Ap <= (others => '1'); + Fp <= (others => '1'); + I <= (others => '0'); + R <= (others => '0'); + SP <= (others => '1'); + Alternate <= '0'; + + Read_To_Reg_r <= "00000"; + F <= (others => '1'); + Arith16_r <= '0'; + BTR_r <= '0'; + Z16_r <= '0'; + ALU_Op_r <= "0000"; + Save_ALU_r <= '0'; + PreserveC_r <= '0'; + XY_Ind <= '0'; + + elsif CLK_n'event and CLK_n = '1' then + + if ClkEn = '1' then + + ALU_Op_r <= "0000"; + Save_ALU_r <= '0'; + Read_To_Reg_r <= "00000"; + + MCycles <= MCycles_d; + + if IMode /= "11" then + IStatus <= IMode; + end if; + + Arith16_r <= Arith16; + PreserveC_r <= PreserveC; + if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then + Z16_r <= '1'; + else + Z16_r <= '0'; + end if; + + if MCycle = "001" and TState(2) = '0' then + -- MCycle = 1 and TState = 1, 2, or 3 + + if TState = 2 and Wait_n = '1' then + if Mode < 2 then + A(7 downto 0) <= std_logic_vector(R); + A(15 downto 8) <= I; + R(6 downto 0) <= R(6 downto 0) + 1; + end if; + + if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then + PC <= PC + 1; + end if; + + if IntCycle = '1' and IStatus = "01" then + IR <= "11111111"; + elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then + IR <= "00000000"; + else + IR <= DInst; + end if; + + ISet <= "00"; + if Prefix /= "00" then + if Prefix = "11" then + if IR(5) = '1' then + XY_State <= "10"; + else + XY_State <= "01"; + end if; + else + if Prefix = "10" then + XY_State <= "00"; + XY_Ind <= '0'; + end if; + ISet <= Prefix; + end if; + else + XY_State <= "00"; + XY_Ind <= '0'; + end if; + end if; + + else + -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3) + + if MCycle = "110" then + XY_Ind <= '1'; + if Prefix = "01" then + ISet <= "01"; + end if; + end if; + + if T_Res = '1' then + BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR; + if Jump = '1' then + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= TmpAddr(7 downto 0); + PC(15 downto 8) <= unsigned(DI_Reg); + PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); + elsif JumpXY = '1' then + A <= RegBusC; + PC <= unsigned(RegBusC); + elsif Call = '1' or RstP = '1' then + A <= TmpAddr; + PC <= unsigned(TmpAddr); + elsif MCycle = MCycles and NMICycle = '1' then + A <= "0000000001100110"; + PC <= "0000000001100110"; + elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then + A(15 downto 8) <= I; + A(7 downto 0) <= TmpAddr(7 downto 0); + PC(15 downto 8) <= unsigned(I); + PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); + else + case Set_Addr_To is + when aXY => + if XY_State = "00" then + A <= RegBusC; + else + if NextIs_XY_Fetch = '1' then + A <= std_logic_vector(PC); + else + A <= TmpAddr; + end if; + end if; + when aIOA => + if Mode = 3 then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + elsif Mode = 2 then + -- Duplicate I/O address on 8080 + A(15 downto 8) <= DI_Reg; + else + A(15 downto 8) <= ACC; + end if; + A(7 downto 0) <= DI_Reg; + when aSP => + A <= std_logic_vector(SP); + when aBC => + if Mode = 3 and IORQ_i = '1' then + -- Memory map I/O on GBZ80 + A(15 downto 8) <= (others => '1'); + A(7 downto 0) <= RegBusC(7 downto 0); + else + A <= RegBusC; + end if; + when aDE => + A <= RegBusC; + when aZI => + if Inc_WZ = '1' then + A <= std_logic_vector(unsigned(TmpAddr) + 1); + else + A(15 downto 8) <= DI_Reg; + A(7 downto 0) <= TmpAddr(7 downto 0); + end if; + when others => + A <= std_logic_vector(PC); + end case; + end if; + + Save_ALU_r <= Save_ALU; + ALU_Op_r <= ALU_Op; + + if I_CPL = '1' then + -- CPL + ACC <= not ACC; + F(Flag_Y) <= not ACC(5); + F(Flag_H) <= '1'; + F(Flag_X) <= not ACC(3); + F(Flag_N) <= '1'; + end if; + if I_CCF = '1' then + -- CCF + F(Flag_C) <= not F(Flag_C); + F(Flag_Y) <= ACC(5); + F(Flag_H) <= F(Flag_C); + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + if I_SCF = '1' then + -- SCF + F(Flag_C) <= '1'; + F(Flag_Y) <= ACC(5); + F(Flag_H) <= '0'; + F(Flag_X) <= ACC(3); + F(Flag_N) <= '0'; + end if; + end if; + + if TState = 2 and Wait_n = '1' then + if ISet = "01" and MCycle = "111" then + IR <= DInst; + end if; + if JumpE = '1' then + PC <= unsigned(signed(PC) + signed(DI_Reg)); + elsif Inc_PC = '1' then + PC <= PC + 1; + end if; + if BTR_r = '1' then + PC <= PC - 2; + end if; + if RstP = '1' then + TmpAddr <= (others =>'0'); + TmpAddr(5 downto 3) <= IR(5 downto 3); + end if; + end if; + if TState = 3 and MCycle = "110" then + TmpAddr <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); + end if; + + if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then + if IncDec_16(2 downto 0) = "111" then + if IncDec_16(3) = '1' then + SP <= SP - 1; + else + SP <= SP + 1; + end if; + end if; + end if; + + if LDSPHL = '1' then + SP <= unsigned(RegBusC); + end if; + if ExchangeAF = '1' then + Ap <= ACC; + ACC <= Ap; + Fp <= F; + F <= Fp; + end if; + if ExchangeRS = '1' then + Alternate <= not Alternate; + end if; + end if; + + if TState = 3 then + if LDZ = '1' then + TmpAddr(7 downto 0) <= DI_Reg; + end if; + if LDW = '1' then + TmpAddr(15 downto 8) <= DI_Reg; + end if; + + if Special_LD(2) = '1' then + case Special_LD(1 downto 0) is + when "00" => + ACC <= I; + F(Flag_P) <= IntE_FF2; + when "01" => + ACC <= std_logic_vector(R); + F(Flag_P) <= IntE_FF2; + when "10" => + I <= ACC; + when others => + R <= unsigned(ACC); + end case; + end if; + end if; + + if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then + if Mode = 3 then + F(6) <= F_Out(6); + F(5) <= F_Out(5); + F(7) <= F_Out(7); + if PreserveC_r = '0' then + F(4) <= F_Out(4); + end if; + else + F(7 downto 1) <= F_Out(7 downto 1); + if PreserveC_r = '0' then + F(Flag_C) <= F_Out(0); + end if; + end if; + end if; + if T_Res = '1' and I_INRC = '1' then + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + if DI_Reg(7 downto 0) = "00000000" then + F(Flag_Z) <= '1'; + else + F(Flag_Z) <= '0'; + end if; + F(Flag_S) <= DI_Reg(7); + F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor + DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7)); + end if; + + if TState = 1 and Auto_Wait_t1 = '0' then + DO <= BusB; + if I_RLD = '1' then + DO(3 downto 0) <= BusA(3 downto 0); + DO(7 downto 4) <= BusB(3 downto 0); + end if; + if I_RRD = '1' then + DO(3 downto 0) <= BusB(7 downto 4); + DO(7 downto 4) <= BusA(3 downto 0); + end if; + end if; + + if T_Res = '1' then + Read_To_Reg_r(3 downto 0) <= Set_BusA_To; + Read_To_Reg_r(4) <= Read_To_Reg; + if Read_To_Acc = '1' then + Read_To_Reg_r(3 downto 0) <= "0111"; + Read_To_Reg_r(4) <= '1'; + end if; + end if; + + if TState = 1 and I_BT = '1' then + F(Flag_X) <= ALU_Q(3); + F(Flag_Y) <= ALU_Q(1); + F(Flag_H) <= '0'; + F(Flag_N) <= '0'; + end if; + if I_BC = '1' or I_BT = '1' then + F(Flag_P) <= IncDecZ; + end if; + + if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10111" => + ACC <= Save_Mux; + when "10110" => + DO <= Save_Mux; + when "11000" => + SP(7 downto 0) <= unsigned(Save_Mux); + when "11001" => + SP(15 downto 8) <= unsigned(Save_Mux); + when "11011" => + F <= Save_Mux; + when others => + end case; + end if; + + end if; + + end if; + + end process; + +--------------------------------------------------------------------------- +-- +-- BC('), DE('), HL('), IX and IY +-- +--------------------------------------------------------------------------- + process (CLK_n) + begin + if CLK_n'event and CLK_n = '1' then + if ClkEn = '1' then + -- Bus A / Write + RegAddrA_r <= Alternate & Set_BusA_To(2 downto 1); + if XY_Ind = '0' and XY_State /= "00" and Set_BusA_To(2 downto 1) = "10" then + RegAddrA_r <= XY_State(1) & "11"; + end if; + + -- Bus B + RegAddrB_r <= Alternate & Set_BusB_To(2 downto 1); + if XY_Ind = '0' and XY_State /= "00" and Set_BusB_To(2 downto 1) = "10" then + RegAddrB_r <= XY_State(1) & "11"; + end if; + + -- Address from register + RegAddrC <= Alternate & Set_Addr_To(1 downto 0); + -- Jump (HL), LD SP,HL + if (JumpXY = '1' or LDSPHL = '1') then + RegAddrC <= Alternate & "10"; + end if; + if ((JumpXY = '1' or LDSPHL = '1') and XY_State /= "00") or (MCycle = "110") then + RegAddrC <= XY_State(1) & "11"; + end if; + + if I_DJNZ = '1' and Save_ALU_r = '1' and Mode < 2 then + IncDecZ <= F_Out(Flag_Z); + end if; + if (TState = 2 or (TState = 3 and MCycle = "001")) and IncDec_16(2 downto 0) = "100" then + if ID16 = 0 then + IncDecZ <= '0'; + else + IncDecZ <= '1'; + end if; + end if; + + RegBusA_r <= RegBusA; + end if; + end if; + end process; + + RegAddrA <= + -- 16 bit increment/decrement + Alternate & IncDec_16(1 downto 0) when (TState = 2 or + (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and XY_State = "00" else + XY_State(1) & "11" when (TState = 2 or + (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else + -- EX HL,DL + Alternate & "10" when ExchangeDH = '1' and TState = 3 else + Alternate & "01" when ExchangeDH = '1' and TState = 4 else + -- Bus A / Write + RegAddrA_r; + + RegAddrB <= + -- EX HL,DL + Alternate & "01" when ExchangeDH = '1' and TState = 3 else + -- Bus B + RegAddrB_r; + + ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else + signed(RegBusA) + 1; + + process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + begin + RegWEH <= '0'; + RegWEL <= '0'; + if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or + (Save_ALU_r = '1' and ALU_OP_r /= "0111") then + case Read_To_Reg_r is + when "10000" | "10001" | "10010" | "10011" | "10100" | "10101" => + RegWEH <= not Read_To_Reg_r(0); + RegWEL <= Read_To_Reg_r(0); + when others => + end case; + end if; + + if ExchangeDH = '1' and (TState = 3 or TState = 4) then + RegWEH <= '1'; + RegWEL <= '1'; + end if; + + if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then + case IncDec_16(1 downto 0) is + when "00" | "01" | "10" => + RegWEH <= '1'; + RegWEL <= '1'; + when others => + end case; + end if; + end process; + + process (Save_Mux, RegBusB, RegBusA_r, ID16, + ExchangeDH, IncDec_16, MCycle, TState, Wait_n) + begin + RegDIH <= Save_Mux; + RegDIL <= Save_Mux; + + if ExchangeDH = '1' and TState = 3 then + RegDIH <= RegBusB(15 downto 8); + RegDIL <= RegBusB(7 downto 0); + end if; + if ExchangeDH = '1' and TState = 4 then + RegDIH <= RegBusA_r(15 downto 8); + RegDIL <= RegBusA_r(7 downto 0); + end if; + + if IncDec_16(2) = '1' and ((TState = 2 and MCycle /= "001") or (TState = 3 and MCycle = "001")) then + RegDIH <= std_logic_vector(ID16(15 downto 8)); + RegDIL <= std_logic_vector(ID16(7 downto 0)); + end if; + end process; + + Regs : T80_Reg + port map( + Clk => CLK_n, + CEN => ClkEn, + WEH => RegWEH, + WEL => RegWEL, + AddrA => RegAddrA, + AddrB => RegAddrB, + AddrC => RegAddrC, + DIH => RegDIH, + DIL => RegDIL, + DOAH => RegBusA(15 downto 8), + DOAL => RegBusA(7 downto 0), + DOBH => RegBusB(15 downto 8), + DOBL => RegBusB(7 downto 0), + DOCH => RegBusC(15 downto 8), + DOCL => RegBusC(7 downto 0)); + +--------------------------------------------------------------------------- +-- +-- Buses +-- +--------------------------------------------------------------------------- + process (CLK_n) + begin + if CLK_n'event and CLK_n = '1' then + if ClkEn = '1' then + case Set_BusB_To is + when "0111" => + BusB <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusB_To(0) = '1' then + BusB <= RegBusB(7 downto 0); + else + BusB <= RegBusB(15 downto 8); + end if; + when "0110" => + BusB <= DI_Reg; + when "1000" => + BusB <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusB <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusB <= "00000001"; + when "1011" => + BusB <= F; + when "1100" => + BusB <= std_logic_vector(PC(7 downto 0)); + when "1101" => + BusB <= std_logic_vector(PC(15 downto 8)); + when "1110" => + BusB <= "00000000"; + when others => + BusB <= "--------"; + end case; + + case Set_BusA_To is + when "0111" => + BusA <= ACC; + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => + if Set_BusA_To(0) = '1' then + BusA <= RegBusA(7 downto 0); + else + BusA <= RegBusA(15 downto 8); + end if; + when "0110" => + BusA <= DI_Reg; + when "1000" => + BusA <= std_logic_vector(SP(7 downto 0)); + when "1001" => + BusA <= std_logic_vector(SP(15 downto 8)); + when "1010" => + BusA <= "00000000"; + when others => + BusB <= "--------"; + end case; + end if; + end if; + end process; + +--------------------------------------------------------------------------- +-- +-- Generate external control signals +-- +--------------------------------------------------------------------------- + process (RESET_n,CLK_n) + begin + if RESET_n = '0' then + RFSH_n <= '1'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then + RFSH_n <= '0'; + else + RFSH_n <= '1'; + end if; + end if; + end if; + end process; + + MC <= std_logic_vector(MCycle); + TS <= std_logic_vector(TState); + DI_Reg <= DI; + HALT_n <= not Halt_FF; + BUSAK_n <= not BusAck; + IntCycle_n <= not IntCycle; + IntE <= IntE_FF1; + IORQ <= IORQ_i; + Stop <= I_DJNZ; + +------------------------------------------------------------------------- +-- +-- Syncronise inputs +-- +------------------------------------------------------------------------- + process (RESET_n, CLK_n) + variable OldNMI_n : std_logic; + begin + if RESET_n = '0' then + BusReq_s <= '0'; + INT_s <= '0'; + NMI_s <= '0'; + OldNMI_n := '0'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + BusReq_s <= not BUSRQ_n; + INT_s <= not INT_n; + if NMICycle = '1' then + NMI_s <= '0'; + elsif NMI_n = '0' and OldNMI_n = '1' then + NMI_s <= '1'; + end if; + OldNMI_n := NMI_n; + end if; + end if; + end process; + +------------------------------------------------------------------------- +-- +-- Main state machine +-- +------------------------------------------------------------------------- + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + MCycle <= "001"; + TState <= "000"; + Pre_XY_F_M <= "000"; + Halt_FF <= '0'; + BusAck <= '0'; + NMICycle <= '0'; + IntCycle <= '0'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + No_BTR <= '0'; + Auto_Wait_t1 <= '0'; + Auto_Wait_t2 <= '0'; + M1_n <= '1'; + elsif CLK_n'event and CLK_n = '1' then + if CEN = '1' then + if T_Res = '1' then + Auto_Wait_t1 <= '0'; + else + Auto_Wait_t1 <= Auto_Wait or IORQ_i; + end if; + Auto_Wait_t2 <= Auto_Wait_t1; + No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or + (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or + (I_BTR and (not IR(4) or F(Flag_Z))); + if TState = 2 then + if SetEI = '1' then + IntE_FF1 <= '1'; + IntE_FF2 <= '1'; + end if; + if I_RETN = '1' then + IntE_FF1 <= IntE_FF2; + end if; + end if; + if TState = 3 then + if SetDI = '1' then + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + end if; + if IntCycle = '1' or NMICycle = '1' then + Halt_FF <= '0'; + end if; + if MCycle = "001" and TState = 2 and Wait_n = '1' then + M1_n <= '1'; + end if; + if BusReq_s = '1' and BusAck = '1' then + else + BusAck <= '0'; + if TState = 2 and Wait_n = '0' then + elsif T_Res = '1' then + if Halt = '1' then + Halt_FF <= '1'; + end if; + if BusReq_s = '1' then + BusAck <= '1'; + else + TState <= "001"; + if NextIs_XY_Fetch = '1' then + MCycle <= "110"; + Pre_XY_F_M <= MCycle; + if IR = "00110110" and Mode = 0 then + Pre_XY_F_M <= "010"; + end if; + elsif (MCycle = "111") or + (MCycle = "110" and Mode = 1 and ISet /= "01") then + MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1); + elsif (MCycle = MCycles) or + No_BTR = '1' or + (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then + M1_n <= '0'; + MCycle <= "001"; + IntCycle <= '0'; + NMICycle <= '0'; + if NMI_s = '1' and Prefix = "00" then + NMICycle <= '1'; + IntE_FF1 <= '0'; + elsif (IntE_FF1 = '1' and INT_s = '1') and Prefix = "00" and SetEI = '0' then + IntCycle <= '1'; + IntE_FF1 <= '0'; + IntE_FF2 <= '0'; + end if; + else + MCycle <= std_logic_vector(unsigned(MCycle) + 1); + end if; + end if; + else + if (Auto_Wait = '1' and Auto_Wait_t2 = '0') nor + (IOWait = 1 and IORQ_i = '1' and Auto_Wait_t1 = '0') then + TState <= TState + 1; + end if; + end if; + end if; + if TState = 0 then + M1_n <= '0'; + end if; + end if; + end if; + end process; + + process (IntCycle, NMICycle, MCycle) + begin + Auto_Wait <= '0'; + if IntCycle = '1' or NMICycle = '1' then + if MCycle = "001" then + Auto_Wait <= '1'; + end if; + end if; + end process; + +end; diff --git a/Sega - SG1000/rtl/t80/T80_ALU.vhd b/Sega - SG1000/rtl/t80/T80_ALU.vhd new file mode 100644 index 00000000..86fddce7 --- /dev/null +++ b/Sega - SG1000/rtl/t80/T80_ALU.vhd @@ -0,0 +1,351 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0247 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0238 : Fixed zero flag for 16 bit SBC and ADC +-- +-- 0240 : Added GB operations +-- +-- 0242 : Cleanup +-- +-- 0247 : Cleanup +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_ALU is + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + Arith16 : in std_logic; + Z16 : in std_logic; + ALU_Op : in std_logic_vector(3 downto 0); + IR : in std_logic_vector(5 downto 0); + ISet : in std_logic_vector(1 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + F_In : in std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0); + F_Out : out std_logic_vector(7 downto 0) + ); +end T80_ALU; + +architecture rtl of T80_ALU is + + procedure AddSub(A : std_logic_vector; + B : std_logic_vector; + Sub : std_logic; + Carry_In : std_logic; + signal Res : out std_logic_vector; + signal Carry : out std_logic) is + variable B_i : unsigned(A'length - 1 downto 0); + variable Res_i : unsigned(A'length + 1 downto 0); + begin + if Sub = '1' then + B_i := not unsigned(B); + else + B_i := unsigned(B); + end if; + Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1"); + Carry <= Res_i(A'length + 1); + Res <= std_logic_vector(Res_i(A'length downto 1)); + end; + + -- AddSub variables (temporary signals) + signal UseCarry : std_logic; + signal Carry7_v : std_logic; + signal Overflow_v : std_logic; + signal HalfCarry_v : std_logic; + signal Carry_v : std_logic; + signal Q_v : std_logic_vector(7 downto 0); + + signal BitMask : std_logic_vector(7 downto 0); + +begin + + with IR(5 downto 3) select BitMask <= "00000001" when "000", + "00000010" when "001", + "00000100" when "010", + "00001000" when "011", + "00010000" when "100", + "00100000" when "101", + "01000000" when "110", + "10000000" when others; + + UseCarry <= not ALU_Op(2) and ALU_Op(0); + AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v); + AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v); + AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v); + OverFlow_v <= Carry_v xor Carry7_v; + + process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16) + variable Q_t : std_logic_vector(7 downto 0); + variable DAA_Q : unsigned(8 downto 0); + begin + Q_t := "--------"; + F_Out <= F_In; + DAA_Q := "---------"; + case ALU_Op is + when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" => + F_Out(Flag_N) <= '0'; + F_Out(Flag_C) <= '0'; + case ALU_OP(2 downto 0) is + when "000" | "001" => -- ADD, ADC + Q_t := Q_v; + F_Out(Flag_C) <= Carry_v; + F_Out(Flag_H) <= HalfCarry_v; + F_Out(Flag_P) <= OverFlow_v; + when "010" | "011" | "111" => -- SUB, SBC, CP + Q_t := Q_v; + F_Out(Flag_N) <= '1'; + F_Out(Flag_C) <= not Carry_v; + F_Out(Flag_H) <= not HalfCarry_v; + F_Out(Flag_P) <= OverFlow_v; + when "100" => -- AND + Q_t(7 downto 0) := BusA and BusB; + F_Out(Flag_H) <= '1'; + when "101" => -- XOR + Q_t(7 downto 0) := BusA xor BusB; + F_Out(Flag_H) <= '0'; + when others => -- OR "110" + Q_t(7 downto 0) := BusA or BusB; + F_Out(Flag_H) <= '0'; + end case; + if ALU_Op(2 downto 0) = "111" then -- CP + F_Out(Flag_X) <= BusB(3); + F_Out(Flag_Y) <= BusB(5); + else + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + end if; + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + if Z16 = '1' then + F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC + end if; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= Q_t(7); + case ALU_Op(2 downto 0) is + when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP + when others => + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + end case; + if Arith16 = '1' then + F_Out(Flag_S) <= F_In(Flag_S); + F_Out(Flag_Z) <= F_In(Flag_Z); + F_Out(Flag_P) <= F_In(Flag_P); + end if; + when "1100" => + -- DAA + F_Out(Flag_H) <= F_In(Flag_H); + F_Out(Flag_C) <= F_In(Flag_C); + DAA_Q(7 downto 0) := unsigned(BusA); + DAA_Q(8) := '0'; + if F_In(Flag_N) = '0' then + -- After addition + -- Alow > 9 or H = 1 + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if (DAA_Q(3 downto 0) > 9) then + F_Out(Flag_H) <= '1'; + else + F_Out(Flag_H) <= '0'; + end if; + DAA_Q := DAA_Q + 6; + end if; + -- new Ahigh > 9 or C = 1 + if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q + 96; -- 0x60 + end if; + else + -- After subtraction + if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then + if DAA_Q(3 downto 0) > 5 then + F_Out(Flag_H) <= '0'; + end if; + DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6; + end if; + if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then + DAA_Q := DAA_Q - 352; -- 0x160 + end if; + end if; + F_Out(Flag_X) <= DAA_Q(3); + F_Out(Flag_Y) <= DAA_Q(5); + F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8); + Q_t := std_logic_vector(DAA_Q(7 downto 0)); + if DAA_Q(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= DAA_Q(7); + F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor + DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7)); + when "1101" | "1110" => + -- RLD, RRD + Q_t(7 downto 4) := BusA(7 downto 4); + if ALU_Op(0) = '1' then + Q_t(3 downto 0) := BusB(7 downto 4); + else + Q_t(3 downto 0) := BusB(3 downto 0); + end if; + F_Out(Flag_H) <= '0'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_S) <= Q_t(7); + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + when "1001" => + -- BIT + Q_t(7 downto 0) := BusB and BitMask; + F_Out(Flag_S) <= Q_t(7); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + F_Out(Flag_P) <= '1'; + else + F_Out(Flag_Z) <= '0'; + F_Out(Flag_P) <= '0'; + end if; + F_Out(Flag_H) <= '1'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= '0'; + F_Out(Flag_Y) <= '0'; + if IR(2 downto 0) /= "110" then + F_Out(Flag_X) <= BusB(3); + F_Out(Flag_Y) <= BusB(5); + end if; + when "1010" => + -- SET + Q_t(7 downto 0) := BusB or BitMask; + when "1011" => + -- RES + Q_t(7 downto 0) := BusB and not BitMask; + when "1000" => + -- ROT + case IR(5 downto 3) is + when "000" => -- RLC + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := BusA(7); + F_Out(Flag_C) <= BusA(7); + when "010" => -- RL + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := F_In(Flag_C); + F_Out(Flag_C) <= BusA(7); + when "001" => -- RRC + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := BusA(0); + F_Out(Flag_C) <= BusA(0); + when "011" => -- RR + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := F_In(Flag_C); + F_Out(Flag_C) <= BusA(0); + when "100" => -- SLA + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := '0'; + F_Out(Flag_C) <= BusA(7); + when "110" => -- SLL (Undocumented) / SWAP + if Mode = 3 then + Q_t(7 downto 4) := BusA(3 downto 0); + Q_t(3 downto 0) := BusA(7 downto 4); + F_Out(Flag_C) <= '0'; + else + Q_t(7 downto 1) := BusA(6 downto 0); + Q_t(0) := '1'; + F_Out(Flag_C) <= BusA(7); + end if; + when "101" => -- SRA + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := BusA(7); + F_Out(Flag_C) <= BusA(0); + when others => -- SRL + Q_t(6 downto 0) := BusA(7 downto 1); + Q_t(7) := '0'; + F_Out(Flag_C) <= BusA(0); + end case; + F_Out(Flag_H) <= '0'; + F_Out(Flag_N) <= '0'; + F_Out(Flag_X) <= Q_t(3); + F_Out(Flag_Y) <= Q_t(5); + F_Out(Flag_S) <= Q_t(7); + if Q_t(7 downto 0) = "00000000" then + F_Out(Flag_Z) <= '1'; + else + F_Out(Flag_Z) <= '0'; + end if; + F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor + Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7)); + if ISet = "00" then + F_Out(Flag_P) <= F_In(Flag_P); + F_Out(Flag_S) <= F_In(Flag_S); + F_Out(Flag_Z) <= F_In(Flag_Z); + end if; + when others => + null; + end case; + Q <= Q_t; + end process; + +end; diff --git a/Sega - SG1000/rtl/t80/T80_MCode.vhd b/Sega - SG1000/rtl/t80/T80_MCode.vhd new file mode 100644 index 00000000..7322994a --- /dev/null +++ b/Sega - SG1000/rtl/t80/T80_MCode.vhd @@ -0,0 +1,1938 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0242 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0211 : Fixed IM 1 +-- +-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test +-- +-- 0235 : Added IM 2 fix by Mike Johnson +-- +-- 0238 : Added NoRead signal +-- +-- 0238b: Fixed instruction timing for POP and DJNZ +-- +-- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes +-- +-- 0242 : Fixed I/O instruction timing, cleanup +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_MCode is + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + IR : in std_logic_vector(7 downto 0); + ISet : in std_logic_vector(1 downto 0); + MCycle : in std_logic_vector(2 downto 0); + F : in std_logic_vector(7 downto 0); + NMICycle : in std_logic; + IntCycle : in std_logic; + MCycles : out std_logic_vector(2 downto 0); + TStates : out std_logic_vector(2 downto 0); + Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD + Inc_PC : out std_logic; + Inc_WZ : out std_logic; + IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc + Read_To_Reg : out std_logic; + Read_To_Acc : out std_logic; + Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + ALU_Op : out std_logic_vector(3 downto 0); + -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None + Save_ALU : out std_logic; + PreserveC : out std_logic; + Arith16 : out std_logic; + Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI + IORQ : out std_logic; + Jump : out std_logic; + JumpE : out std_logic; + JumpXY : out std_logic; + Call : out std_logic; + RstP : out std_logic; + LDZ : out std_logic; + LDW : out std_logic; + LDSPHL : out std_logic; + Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None + ExchangeDH : out std_logic; + ExchangeRp : out std_logic; + ExchangeAF : out std_logic; + ExchangeRS : out std_logic; + I_DJNZ : out std_logic; + I_CPL : out std_logic; + I_CCF : out std_logic; + I_SCF : out std_logic; + I_RETN : out std_logic; + I_BT : out std_logic; + I_BC : out std_logic; + I_BTR : out std_logic; + I_RLD : out std_logic; + I_RRD : out std_logic; + I_INRC : out std_logic; + SetDI : out std_logic; + SetEI : out std_logic; + IMode : out std_logic_vector(1 downto 0); + Halt : out std_logic; + NoRead : out std_logic; + Write : out std_logic + ); +end T80_MCode; + +architecture rtl of T80_MCode is + + constant aNone : std_logic_vector(2 downto 0) := "111"; + constant aBC : std_logic_vector(2 downto 0) := "000"; + constant aDE : std_logic_vector(2 downto 0) := "001"; + constant aXY : std_logic_vector(2 downto 0) := "010"; + constant aIOA : std_logic_vector(2 downto 0) := "100"; + constant aSP : std_logic_vector(2 downto 0) := "101"; + constant aZI : std_logic_vector(2 downto 0) := "110"; +-- constant aNone : std_logic_vector(2 downto 0) := "000"; +-- constant aXY : std_logic_vector(2 downto 0) := "001"; +-- constant aIOA : std_logic_vector(2 downto 0) := "010"; +-- constant aSP : std_logic_vector(2 downto 0) := "011"; +-- constant aBC : std_logic_vector(2 downto 0) := "100"; +-- constant aDE : std_logic_vector(2 downto 0) := "101"; +-- constant aZI : std_logic_vector(2 downto 0) := "110"; + + function is_cc_true( + F : std_logic_vector(7 downto 0); + cc : bit_vector(2 downto 0) + ) return boolean is + begin + if Mode = 3 then + case cc is + when "000" => return F(7) = '0'; -- NZ + when "001" => return F(7) = '1'; -- Z + when "010" => return F(4) = '0'; -- NC + when "011" => return F(4) = '1'; -- C + when "100" => return false; + when "101" => return false; + when "110" => return false; + when "111" => return false; + end case; + else + case cc is + when "000" => return F(6) = '0'; -- NZ + when "001" => return F(6) = '1'; -- Z + when "010" => return F(0) = '0'; -- NC + when "011" => return F(0) = '1'; -- C + when "100" => return F(2) = '0'; -- PO + when "101" => return F(2) = '1'; -- PE + when "110" => return F(7) = '0'; -- P + when "111" => return F(7) = '1'; -- M + end case; + end if; + end; + +begin + + process (IR, ISet, MCycle, F, NMICycle, IntCycle) + variable DDD : std_logic_vector(2 downto 0); + variable SSS : std_logic_vector(2 downto 0); + variable DPair : std_logic_vector(1 downto 0); + variable IRB : bit_vector(7 downto 0); + begin + DDD := IR(5 downto 3); + SSS := IR(2 downto 0); + DPair := IR(5 downto 4); + IRB := to_bitvector(IR); + + MCycles <= "001"; + if MCycle = "001" then + TStates <= "100"; + else + TStates <= "011"; + end if; + Prefix <= "00"; + Inc_PC <= '0'; + Inc_WZ <= '0'; + IncDec_16 <= "0000"; + Read_To_Acc <= '0'; + Read_To_Reg <= '0'; + Set_BusB_To <= "0000"; + Set_BusA_To <= "0000"; + ALU_Op <= "0" & IR(5 downto 3); + Save_ALU <= '0'; + PreserveC <= '0'; + Arith16 <= '0'; + IORQ <= '0'; + Set_Addr_To <= aNone; + Jump <= '0'; + JumpE <= '0'; + JumpXY <= '0'; + Call <= '0'; + RstP <= '0'; + LDZ <= '0'; + LDW <= '0'; + LDSPHL <= '0'; + Special_LD <= "000"; + ExchangeDH <= '0'; + ExchangeRp <= '0'; + ExchangeAF <= '0'; + ExchangeRS <= '0'; + I_DJNZ <= '0'; + I_CPL <= '0'; + I_CCF <= '0'; + I_SCF <= '0'; + I_RETN <= '0'; + I_BT <= '0'; + I_BC <= '0'; + I_BTR <= '0'; + I_RLD <= '0'; + I_RRD <= '0'; + I_INRC <= '0'; + SetDI <= '0'; + SetEI <= '0'; + IMode <= "11"; + Halt <= '0'; + NoRead <= '0'; + Write <= '0'; + + case ISet is + when "00" => + +------------------------------------------------------------------------------ +-- +-- Unprefixed instructions +-- +------------------------------------------------------------------------------ + + case IRB is +-- 8 BIT LOAD GROUP + when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111" + |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111" + |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111" + |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111" + |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111" + |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111" + |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => + -- LD r,r' + Set_BusB_To(2 downto 0) <= SSS; + ExchangeRp <= '1'; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when "00000110"|"00001110"|"00010110"|"00011110"|"00100110"|"00101110"|"00111110" => + -- LD r,n + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when others => null; + end case; + when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01111110" => + -- LD r,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + when others => null; + end case; + when "01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" => + -- LD (HL),r + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00110110" => + -- LD (HL),n + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aXY; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + when 3 => + Write <= '1'; + when others => null; + end case; + when "00001010" => + -- LD A,(BC) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "00011010" => + -- LD A,(DE) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aDE; + when 2 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "00111010" => + if Mode = 3 then + -- LDD A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Acc <= '1'; + IncDec_16 <= "1110"; + when others => null; + end case; + else + -- LD A,(nn) + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + when 4 => + Read_To_Acc <= '1'; + when others => null; + end case; + end if; + when "00000010" => + -- LD (BC),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00010010" => + -- LD (DE),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aDE; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + when others => null; + end case; + when "00110010" => + if Mode = 3 then + -- LDD (HL),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IncDec_16 <= "1110"; + when others => null; + end case; + else + -- LD (nn),A + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + Set_BusB_To <= "0111"; + when 4 => + Write <= '1'; + when others => null; + end case; + end if; + +-- 16 BIT LOAD GROUP + when "00000001"|"00010001"|"00100001"|"00110001" => + -- LD dd,nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1000"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '1'; + end if; + when 3 => + Inc_PC <= '1'; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1001"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + when "00101010" => + if Mode = 3 then + -- LDI A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Acc <= '1'; + IncDec_16 <= "0110"; + when others => null; + end case; + else + -- LD HL,(nn) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Set_BusA_To(2 downto 0) <= "101"; -- L + Read_To_Reg <= '1'; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Set_BusA_To(2 downto 0) <= "100"; -- H + Read_To_Reg <= '1'; + when others => null; + end case; + end if; + when "00100010" => + if Mode = 3 then + -- LDI (HL),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IncDec_16 <= "0110"; + when others => null; + end case; + else + -- LD (nn),HL + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + Set_BusB_To <= "0101"; -- L + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + Set_BusB_To <= "0100"; -- H + when 5 => + Write <= '1'; + when others => null; + end case; + end if; + when "11111001" => + -- LD SP,HL + TStates <= "110"; + LDSPHL <= '1'; + when "11000101"|"11010101"|"11100101"|"11110101" => + -- PUSH qq + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "0111"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 2 => + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + if DPAIR = "11" then + Set_BusB_To <= "1011"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + Write <= '1'; + when 3 => + Write <= '1'; + when others => null; + end case; + when "11000001"|"11010001"|"11100001"|"11110001" => + -- POP qq + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "1011"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '1'; + end if; + when 3 => + IncDec_16 <= "0111"; + Read_To_Reg <= '1'; + if DPAIR = "11" then + Set_BusA_To(3 downto 0) <= "0111"; + else + Set_BusA_To(2 downto 1) <= DPAIR; + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + +-- EXCHANGE, BLOCK TRANSFER AND SEARCH GROUP + when "11101011" => + if Mode /= 3 then + -- EX DE,HL + ExchangeDH <= '1'; + end if; + when "00001000" => + if Mode = 3 then + -- LD (nn),SP + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + Set_BusB_To <= "1000"; + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + Set_BusB_To <= "1001"; + when 5 => + Write <= '1'; + when others => null; + end case; + elsif Mode < 2 then + -- EX AF,AF' + ExchangeAF <= '1'; + end if; + when "11011001" => + if Mode = 3 then + -- RETI + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + I_RETN <= '1'; + SetEI <= '1'; + when others => null; + end case; + elsif Mode < 2 then + -- EXX + ExchangeRS <= '1'; + end if; + when "11100011" => + if Mode /= 3 then + -- EX (SP),HL + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aSP; + when 2 => + Read_To_Reg <= '1'; + Set_BusA_To <= "0101"; + Set_BusB_To <= "0101"; + Set_Addr_To <= aSP; + when 3 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + TStates <= "100"; + Write <= '1'; + when 4 => + Read_To_Reg <= '1'; + Set_BusA_To <= "0100"; + Set_BusB_To <= "0100"; + Set_Addr_To <= aSP; + when 5 => + IncDec_16 <= "1111"; + TStates <= "101"; + Write <= '1'; + when others => null; + end case; + end if; + +-- 8 BIT ARITHMETIC AND LOGICAL GROUP + when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111" + |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111" + |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111" + |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111" + |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" => + -- ADD A,r + -- ADC A,r + -- SUB A,r + -- SBC A,r + -- AND A,r + -- OR A,r + -- XOR A,r + -- CP A,r + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" => + -- ADD A,(HL) + -- ADC A,(HL) + -- SUB A,(HL) + -- SBC A,(HL) + -- AND A,(HL) + -- OR A,(HL) + -- XOR A,(HL) + -- CP A,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + when others => null; + end case; + when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" => + -- ADD A,n + -- ADC A,n + -- SUB A,n + -- SBC A,n + -- AND A,n + -- OR A,n + -- XOR A,n + -- CP A,n + MCycles <= "010"; + if MCycle = "010" then + Inc_PC <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusA_To(2 downto 0) <= "111"; + end if; + when "00000100"|"00001100"|"00010100"|"00011100"|"00100100"|"00101100"|"00111100" => + -- INC r + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0000"; + when "00110100" => + -- INC (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + TStates <= "100"; + Set_Addr_To <= aXY; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0000"; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + when 3 => + Write <= '1'; + when others => null; + end case; + when "00000101"|"00001101"|"00010101"|"00011101"|"00100101"|"00101101"|"00111101" => + -- DEC r + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + ALU_Op <= "0010"; + when "00110101" => + -- DEC (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + when 2 => + TStates <= "100"; + Set_Addr_To <= aXY; + ALU_Op <= "0010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + PreserveC <= '1'; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= DDD; + when 3 => + Write <= '1'; + when others => null; + end case; + +-- GENERAL PURPOSE ARITHMETIC AND CPU CONTROL GROUPS + when "00100111" => + -- DAA + Set_BusA_To(2 downto 0) <= "111"; + Read_To_Reg <= '1'; + ALU_Op <= "1100"; + Save_ALU <= '1'; + when "00101111" => + -- CPL + I_CPL <= '1'; + when "00111111" => + -- CCF + I_CCF <= '1'; + when "00110111" => + -- SCF + I_SCF <= '1'; + when "00000000" => + if NMICycle = '1' then + -- NMI + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + TStates <= "100"; + Write <= '1'; + when others => null; + end case; + elsif IntCycle = '1' then + -- INT (IM 2) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 1 => + LDZ <= '1'; + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + TStates <= "100"; + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + TStates <= "100"; + Write <= '1'; + when 4 => + Inc_PC <= '1'; + LDZ <= '1'; + when 5 => + Jump <= '1'; + when others => null; + end case; + else + -- NOP + end if; + when "01110110" => + -- HALT + Halt <= '1'; + when "11110011" => + -- DI + SetDI <= '1'; + when "11111011" => + -- EI + SetEI <= '1'; + +-- 16 BIT ARITHMETIC GROUP + when "00001001"|"00011001"|"00101001"|"00111001" => + -- ADD HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + Arith16 <= '1'; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + Arith16 <= '1'; + when others => + end case; + when "00000011"|"00010011"|"00100011"|"00110011" => + -- INC ss + TStates <= "110"; + IncDec_16(3 downto 2) <= "01"; + IncDec_16(1 downto 0) <= DPair; + when "00001011"|"00011011"|"00101011"|"00111011" => + -- DEC ss + TStates <= "110"; + IncDec_16(3 downto 2) <= "11"; + IncDec_16(1 downto 0) <= DPair; + +-- ROTATE AND SHIFT GROUP + when "00000111" + -- RLCA + |"00010111" + -- RLA + |"00001111" + -- RRCA + |"00011111" => + -- RRA + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + +-- JUMP GROUP + when "11000011" => + -- JP nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + Jump <= '1'; + when others => null; + end case; + when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" => + if IR(5) = '1' and Mode = 3 then + case IRB(4 downto 3) is + when "00" => + -- LD ($FF00+C),A + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "0111"; + when 2 => + Write <= '1'; + IORQ <= '1'; + when others => + end case; + when "01" => + -- LD (nn),A + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + Set_BusB_To <= "0111"; + when 4 => + Write <= '1'; + when others => null; + end case; + when "10" => + -- LD A,($FF00+C) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + Read_To_Acc <= '1'; + IORQ <= '1'; + when others => + end case; + when "11" => + -- LD A,(nn) + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + when 4 => + Read_To_Acc <= '1'; + when others => null; + end case; + end case; + else + -- JP cc,nn + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Jump <= '1'; + end if; + when others => null; + end case; + end if; + when "00011000" => + if Mode /= 2 then + -- JR e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00111000" => + if Mode /= 2 then + -- JR C,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_C) = '0' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00110000" => + if Mode /= 2 then + -- JR NC,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_C) = '1' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00101000" => + if Mode /= 2 then + -- JR Z,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_Z) = '0' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "00100000" => + if Mode /= 2 then + -- JR NZ,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + if F(Flag_Z) = '1' then + MCycles <= "010"; + end if; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + when "11101001" => + -- JP (HL) + JumpXY <= '1'; + when "00010000" => + if Mode = 3 then + I_DJNZ <= '1'; + elsif Mode < 2 then + -- DJNZ,e + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + I_DJNZ <= '1'; + Set_BusB_To <= "1010"; + Set_BusA_To(2 downto 0) <= "000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + I_DJNZ <= '1'; + Inc_PC <= '1'; + when 3 => + NoRead <= '1'; + JumpE <= '1'; + TStates <= "101"; + when others => null; + end case; + end if; + +-- CALL AND RETURN GROUP + when "11001101" => + -- CALL nn + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + IncDec_16 <= "1111"; + Inc_PC <= '1'; + TStates <= "100"; + Set_Addr_To <= aSP; + LDW <= '1'; + Set_BusB_To <= "1101"; + when 4 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 5 => + Write <= '1'; + Call <= '1'; + when others => null; + end case; + when "11000100"|"11001100"|"11010100"|"11011100"|"11100100"|"11101100"|"11110100"|"11111100" => + if IR(5) = '0' or Mode /= 3 then + -- CALL cc,nn + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Inc_PC <= '1'; + LDW <= '1'; + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + IncDec_16 <= "1111"; + Set_Addr_TO <= aSP; + TStates <= "100"; + Set_BusB_To <= "1101"; + else + MCycles <= "011"; + end if; + when 4 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 5 => + Write <= '1'; + Call <= '1'; + when others => null; + end case; + end if; + when "11001001" => + -- RET + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + when "11000000"|"11001000"|"11010000"|"11011000"|"11100000"|"11101000"|"11110000"|"11111000" => + if IR(5) = '1' and Mode = 3 then + case IRB(4 downto 3) is + when "00" => + -- LD ($FF00+nn),A + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + Set_BusB_To <= "0111"; + when 3 => + Write <= '1'; + when others => null; + end case; + when "01" => + -- ADD SP,n + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + ALU_Op <= "0000"; + Inc_PC <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To <= "1000"; + Set_BusB_To <= "0110"; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To <= "1001"; + Set_BusB_To <= "1110"; -- Incorrect unsigned !!!!!!!!!!!!!!!!!!!!! + when others => + end case; + when "10" => + -- LD A,($FF00+nn) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + when 3 => + Read_To_Acc <= '1'; + when others => null; + end case; + when "11" => + -- LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!! + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Set_BusA_To(2 downto 0) <= "101"; -- L + Read_To_Reg <= '1'; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Set_BusA_To(2 downto 0) <= "100"; -- H + Read_To_Reg <= '1'; + when others => null; + end case; + end case; + else + -- RET cc + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + if is_cc_true(F, to_bitvector(IR(5 downto 3))) then + Set_Addr_TO <= aSP; + else + MCycles <= "001"; + end if; + TStates <= "101"; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + when others => null; + end case; + end if; + when "11000111"|"11001111"|"11010111"|"11011111"|"11100111"|"11101111"|"11110111"|"11111111" => + -- RST p + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1101"; + when 2 => + Write <= '1'; + IncDec_16 <= "1111"; + Set_Addr_To <= aSP; + Set_BusB_To <= "1100"; + when 3 => + Write <= '1'; + RstP <= '1'; + when others => null; + end case; + +-- INPUT AND OUTPUT GROUP + when "11011011" => + if Mode /= 3 then + -- IN A,(n) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + when 3 => + Read_To_Acc <= '1'; + IORQ <= '1'; + when others => null; + end case; + end if; + when "11010011" => + if Mode /= 3 then + -- OUT (n),A + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + Set_Addr_To <= aIOA; + Set_BusB_To <= "0111"; + when 3 => + Write <= '1'; + IORQ <= '1'; + when others => null; + end case; + end if; + +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- MULTIBYTE INSTRUCTIONS +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ + + when "11001011" => + if Mode /= 2 then + Prefix <= "01"; + end if; + + when "11101101" => + if Mode < 2 then + Prefix <= "10"; + end if; + + when "11011101"|"11111101" => + if Mode < 2 then + Prefix <= "11"; + end if; + + end case; + + when "01" => + +------------------------------------------------------------------------------ +-- +-- CB prefixed instructions +-- +------------------------------------------------------------------------------ + + Set_BusA_To(2 downto 0) <= IR(2 downto 0); + Set_BusB_To(2 downto 0) <= IR(2 downto 0); + + case IRB is + when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000111" + |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010111" + |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001111" + |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011111" + |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100111" + |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101111" + |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110111" + |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111111" => + -- RLC r + -- RL r + -- RRC r + -- RR r + -- SLA r + -- SRA r + -- SRL r + -- SLL r (Undocumented) / SWAP r + if MCycle = "001" then + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + when "00000110"|"00010110"|"00001110"|"00011110"|"00101110"|"00111110"|"00100110"|"00110110" => + -- RLC (HL) + -- RL (HL) + -- RRC (HL) + -- RR (HL) + -- SRA (HL) + -- SRL (HL) + -- SLA (HL) + -- SLL (HL) (Undocumented) / SWAP (HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => + end case; + when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111" + |"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111" + |"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111" + |"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111" + |"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111" + |"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111" + |"01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" + |"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" => + -- BIT b,r + if MCycle = "001" then + Set_BusB_To(2 downto 0) <= IR(2 downto 0); + ALU_Op <= "1001"; + end if; + when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01110110"|"01111110" => + -- BIT b,(HL) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1001"; + TStates <= "100"; + when others => + end case; + when "11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000111" + |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001111" + |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010111" + |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011111" + |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100111" + |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101111" + |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110111" + |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111111" => + -- SET b,r + if MCycle = "001" then + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" => + -- SET b,(HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1010"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => + end case; + when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111" + |"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111" + |"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111" + |"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111" + |"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" => + -- RES b,r + if MCycle = "001" then + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + end if; + when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" => + -- RES b,(HL) + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 | 7 => + Set_Addr_To <= aXY; + when 2 => + ALU_Op <= "1011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_Addr_To <= aXY; + TStates <= "100"; + when 3 => + Write <= '1'; + when others => + end case; + end case; + + when others => + +------------------------------------------------------------------------------ +-- +-- ED prefixed instructions +-- +------------------------------------------------------------------------------ + + case IRB is + when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000110"|"00000111" + |"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001110"|"00001111" + |"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010110"|"00010111" + |"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011110"|"00011111" + |"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100110"|"00100111" + |"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101110"|"00101111" + |"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110110"|"00110111" + |"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111110"|"00111111" + + + |"10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000110"|"10000111" + |"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001110"|"10001111" + |"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010110"|"10010111" + |"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011110"|"10011111" + | "10100100"|"10100101"|"10100110"|"10100111" + | "10101100"|"10101101"|"10101110"|"10101111" + | "10110100"|"10110101"|"10110110"|"10110111" + | "10111100"|"10111101"|"10111110"|"10111111" + |"11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000110"|"11000111" + |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111" + |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111" + |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111" + |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100110"|"11100111" + |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101110"|"11101111" + |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110110"|"11110111" + |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111110"|"11111111" => + null; -- NOP, undocumented + when "01111110"|"01111111" => + -- NOP, undocumented + null; +-- 8 BIT LOAD GROUP + when "01010111" => + -- LD A,I + Special_LD <= "100"; + TStates <= "101"; + when "01011111" => + -- LD A,R + Special_LD <= "101"; + TStates <= "101"; + when "01000111" => + -- LD I,A + Special_LD <= "110"; + TStates <= "101"; + when "01001111" => + -- LD R,A + Special_LD <= "111"; + TStates <= "101"; +-- 16 BIT LOAD GROUP + when "01001011"|"01011011"|"01101011"|"01111011" => + -- LD dd,(nn) + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + when 4 => + Read_To_Reg <= '1'; + if IR(5 downto 4) = "11" then + Set_BusA_To <= "1000"; + else + Set_BusA_To(2 downto 1) <= IR(5 downto 4); + Set_BusA_To(0) <= '1'; + end if; + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + when 5 => + Read_To_Reg <= '1'; + if IR(5 downto 4) = "11" then + Set_BusA_To <= "1001"; + else + Set_BusA_To(2 downto 1) <= IR(5 downto 4); + Set_BusA_To(0) <= '0'; + end if; + when others => null; + end case; + when "01000011"|"01010011"|"01100011"|"01110011" => + -- LD (nn),dd + MCycles <= "101"; + case to_integer(unsigned(MCycle)) is + when 2 => + Inc_PC <= '1'; + LDZ <= '1'; + when 3 => + Set_Addr_To <= aZI; + Inc_PC <= '1'; + LDW <= '1'; + if IR(5 downto 4) = "11" then + Set_BusB_To <= "1000"; + else + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + Set_BusB_To(3) <= '0'; + end if; + when 4 => + Inc_WZ <= '1'; + Set_Addr_To <= aZI; + Write <= '1'; + if IR(5 downto 4) = "11" then + Set_BusB_To <= "1001"; + else + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + when 5 => + Write <= '1'; + when others => null; + end case; + when "10100000" | "10101000" | "10110000" | "10111000" => + -- LDI, LDD, LDIR, LDDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + IncDec_16 <= "1100"; -- BC + when 2 => + Set_BusB_To <= "0110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "0000"; + Set_Addr_To <= aDE; + if IR(3) = '0' then + IncDec_16 <= "0110"; -- IX + else + IncDec_16 <= "1110"; + end if; + when 3 => + I_BT <= '1'; + TStates <= "101"; + Write <= '1'; + if IR(3) = '0' then + IncDec_16 <= "0101"; -- DE + else + IncDec_16 <= "1101"; + end if; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "10100001" | "10101001" | "10110001" | "10111001" => + -- CPI, CPD, CPIR, CPDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aXY; + IncDec_16 <= "1100"; -- BC + when 2 => + Set_BusB_To <= "0110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "0111"; + Save_ALU <= '1'; + PreserveC <= '1'; + if IR(3) = '0' then + IncDec_16 <= "0110"; + else + IncDec_16 <= "1110"; + end if; + when 3 => + NoRead <= '1'; + I_BC <= '1'; + TStates <= "101"; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "01000100"|"01001100"|"01010100"|"01011100"|"01100100"|"01101100"|"01110100"|"01111100" => + -- NEG + Alu_OP <= "0010"; + Set_BusB_To <= "0111"; + Set_BusA_To <= "1010"; + Read_To_Acc <= '1'; + Save_ALU <= '1'; + when "01000110"|"01001110"|"01100110"|"01101110" => + -- IM 0 + IMode <= "00"; + when "01010110"|"01110110" => + -- IM 1 + IMode <= "01"; + when "01011110"|"01110111" => + -- IM 2 + IMode <= "10"; +-- 16 bit arithmetic + when "01001010"|"01011010"|"01101010"|"01111010" => + -- ADC HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0001"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + when 3 => + NoRead <= '1'; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0001"; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '0'; + when others => + Set_BusB_To <= "1001"; + end case; + when others => + end case; + when "01000010"|"01010010"|"01100010"|"01110010" => + -- SBC HL,ss + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + ALU_Op <= "0011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "101"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + Set_BusB_To(0) <= '1'; + when others => + Set_BusB_To <= "1000"; + end case; + TStates <= "100"; + when 3 => + NoRead <= '1'; + ALU_Op <= "0011"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + Set_BusA_To(2 downto 0) <= "100"; + case to_integer(unsigned(IR(5 downto 4))) is + when 0|1|2 => + Set_BusB_To(2 downto 1) <= IR(5 downto 4); + when others => + Set_BusB_To <= "1001"; + end case; + when others => + end case; + when "01101111" => + -- RLD + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + NoRead <= '1'; + Set_Addr_To <= aXY; + when 3 => + Read_To_Reg <= '1'; + Set_BusB_To(2 downto 0) <= "110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1101"; + TStates <= "100"; + Set_Addr_To <= aXY; + Save_ALU <= '1'; + when 4 => + I_RLD <= '1'; + Write <= '1'; + when others => + end case; + when "01100111" => + -- RRD + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 2 => + Set_Addr_To <= aXY; + when 3 => + Read_To_Reg <= '1'; + Set_BusB_To(2 downto 0) <= "110"; + Set_BusA_To(2 downto 0) <= "111"; + ALU_Op <= "1110"; + TStates <= "100"; + Set_Addr_To <= aXY; + Save_ALU <= '1'; + when 4 => + I_RRD <= '1'; + Write <= '1'; + when others => + end case; + when "01000101"|"01001101"|"01010101"|"01011101"|"01100101"|"01101101"|"01110101"|"01111101" => + -- RETI, RETN + MCycles <= "011"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_TO <= aSP; + when 2 => + IncDec_16 <= "0111"; + Set_Addr_To <= aSP; + LDZ <= '1'; + when 3 => + Jump <= '1'; + IncDec_16 <= "0111"; + I_RETN <= '1'; + when others => null; + end case; + when "01000000"|"01001000"|"01010000"|"01011000"|"01100000"|"01101000"|"01110000"|"01111000" => + -- IN r,(C) + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + when 2 => + IORQ <= '1'; + if IR(5 downto 3) /= "110" then + Read_To_Reg <= '1'; + Set_BusA_To(2 downto 0) <= IR(5 downto 3); + end if; + I_INRC <= '1'; + when others => + end case; + when "01000001"|"01001001"|"01010001"|"01011001"|"01100001"|"01101001"|"01110001"|"01111001" => + -- OUT (C),r + -- OUT (C),0 + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To(2 downto 0) <= IR(5 downto 3); + if IR(5 downto 3) = "110" then + Set_BusB_To(3) <= '1'; + end if; + when 2 => + Write <= '1'; + IORQ <= '1'; + when others => + end case; + when "10100010" | "10101010" | "10110010" | "10111010" => + -- INI, IND, INIR, INDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + Set_Addr_To <= aBC; + Set_BusB_To <= "1010"; + Set_BusA_To <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + IORQ <= '1'; + Set_BusB_To <= "0110"; + Set_Addr_To <= aXY; + when 3 => + if IR(3) = '0' then + --IncDec_16 <= "0010"; + IncDec_16 <= "0110"; + else + --IncDec_16 <= "0010"; + IncDec_16 <= "0110"; + end if; + TStates <= "100"; + Write <= '1'; + I_BTR <= '1'; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + when "10100011" | "10101011" | "10110011" | "10111011" => + -- OUTI, OUTD, OTIR, OTDR + MCycles <= "100"; + case to_integer(unsigned(MCycle)) is + when 1 => + TStates <= "101"; + Set_Addr_To <= aXY; + Set_BusB_To <= "1010"; + Set_BusA_To <= "0000"; + Read_To_Reg <= '1'; + Save_ALU <= '1'; + ALU_Op <= "0010"; + when 2 => + Set_BusB_To <= "0110"; + Set_Addr_To <= aBC; + when 3 => + if IR(3) = '0' then + --IncDec_16 <= "0010"; + IncDec_16 <= "0110"; + else + --IncDec_16 <= "0010"; + IncDec_16 <= "0110"; + end if; + IORQ <= '1'; + Write <= '1'; + I_BTR <= '1'; + when 4 => + NoRead <= '1'; + TStates <= "101"; + when others => null; + end case; + end case; + + end case; + + if Mode = 1 then + if MCycle = "001" then +-- TStates <= "100"; + else + TStates <= "011"; + end if; + end if; + + if Mode = 3 then + if MCycle = "001" then +-- TStates <= "100"; + else + TStates <= "100"; + end if; + end if; + + if Mode < 2 then + if MCycle = "110" then + Inc_PC <= '1'; + if Mode = 1 then + Set_Addr_To <= aXY; + TStates <= "100"; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + end if; + if IRB = "00110110" or IRB = "11001011" then + Set_Addr_To <= aNone; + end if; + end if; + if MCycle = "111" then + if Mode = 0 then + TStates <= "101"; + end if; + if ISet /= "01" then + Set_Addr_To <= aXY; + end if; + Set_BusB_To(2 downto 0) <= SSS; + Set_BusB_To(3) <= '0'; + if IRB = "00110110" or ISet = "01" then + -- LD (HL),n + Inc_PC <= '1'; + else + NoRead <= '1'; + end if; + end if; + end if; + + end process; + +end; diff --git a/Sega - SG1000/rtl/t80/T80_Pack.vhd b/Sega - SG1000/rtl/t80/T80_Pack.vhd new file mode 100644 index 00000000..ac7d34da --- /dev/null +++ b/Sega - SG1000/rtl/t80/T80_Pack.vhd @@ -0,0 +1,208 @@ +-- +-- Z80 compatible microprocessor core +-- +-- Version : 0242 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- + +library IEEE; +use IEEE.std_logic_1164.all; + +package T80_Pack is + + component T80 + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + IORQ : out std_logic; + NoRead : out std_logic; + Write : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DInst : in std_logic_vector(7 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0); + MC : out std_logic_vector(2 downto 0); + TS : out std_logic_vector(2 downto 0); + IntCycle_n : out std_logic; + IntE : out std_logic; + Stop : out std_logic + ); + end component; + + component T80_Reg + port( + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0) + ); + end component; + + component T80_MCode + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + IR : in std_logic_vector(7 downto 0); + ISet : in std_logic_vector(1 downto 0); + MCycle : in std_logic_vector(2 downto 0); + F : in std_logic_vector(7 downto 0); + NMICycle : in std_logic; + IntCycle : in std_logic; + MCycles : out std_logic_vector(2 downto 0); + TStates : out std_logic_vector(2 downto 0); + Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD + Inc_PC : out std_logic; + Inc_WZ : out std_logic; + IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc + Read_To_Reg : out std_logic; + Read_To_Acc : out std_logic; + Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F + Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0 + ALU_Op : out std_logic_vector(3 downto 0); + -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None + Save_ALU : out std_logic; + PreserveC : out std_logic; + Arith16 : out std_logic; + Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI + IORQ : out std_logic; + Jump : out std_logic; + JumpE : out std_logic; + JumpXY : out std_logic; + Call : out std_logic; + RstP : out std_logic; + LDZ : out std_logic; + LDW : out std_logic; + LDSPHL : out std_logic; + Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None + ExchangeDH : out std_logic; + ExchangeRp : out std_logic; + ExchangeAF : out std_logic; + ExchangeRS : out std_logic; + I_DJNZ : out std_logic; + I_CPL : out std_logic; + I_CCF : out std_logic; + I_SCF : out std_logic; + I_RETN : out std_logic; + I_BT : out std_logic; + I_BC : out std_logic; + I_BTR : out std_logic; + I_RLD : out std_logic; + I_RRD : out std_logic; + I_INRC : out std_logic; + SetDI : out std_logic; + SetEI : out std_logic; + IMode : out std_logic_vector(1 downto 0); + Halt : out std_logic; + NoRead : out std_logic; + Write : out std_logic + ); + end component; + + component T80_ALU + generic( + Mode : integer := 0; + Flag_C : integer := 0; + Flag_N : integer := 1; + Flag_P : integer := 2; + Flag_X : integer := 3; + Flag_H : integer := 4; + Flag_Y : integer := 5; + Flag_Z : integer := 6; + Flag_S : integer := 7 + ); + port( + Arith16 : in std_logic; + Z16 : in std_logic; + ALU_Op : in std_logic_vector(3 downto 0); + IR : in std_logic_vector(5 downto 0); + ISet : in std_logic_vector(1 downto 0); + BusA : in std_logic_vector(7 downto 0); + BusB : in std_logic_vector(7 downto 0); + F_In : in std_logic_vector(7 downto 0); + Q : out std_logic_vector(7 downto 0); + F_Out : out std_logic_vector(7 downto 0) + ); + end component; + +end; diff --git a/Sega - SG1000/rtl/t80/T80_Reg.vhd b/Sega - SG1000/rtl/t80/T80_Reg.vhd new file mode 100644 index 00000000..828485fb --- /dev/null +++ b/Sega - SG1000/rtl/t80/T80_Reg.vhd @@ -0,0 +1,105 @@ +-- +-- T80 Registers, technology independent +-- +-- Version : 0244 +-- +-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t51/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0242 : Initial release +-- +-- 0244 : Changed to single register file +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity T80_Reg is + port( + Clk : in std_logic; + CEN : in std_logic; + WEH : in std_logic; + WEL : in std_logic; + AddrA : in std_logic_vector(2 downto 0); + AddrB : in std_logic_vector(2 downto 0); + AddrC : in std_logic_vector(2 downto 0); + DIH : in std_logic_vector(7 downto 0); + DIL : in std_logic_vector(7 downto 0); + DOAH : out std_logic_vector(7 downto 0); + DOAL : out std_logic_vector(7 downto 0); + DOBH : out std_logic_vector(7 downto 0); + DOBL : out std_logic_vector(7 downto 0); + DOCH : out std_logic_vector(7 downto 0); + DOCL : out std_logic_vector(7 downto 0) + ); +end T80_Reg; + +architecture rtl of T80_Reg is + + type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0); + signal RegsH : Register_Image(0 to 7); + signal RegsL : Register_Image(0 to 7); + +begin + + process (Clk) + begin + if Clk'event and Clk = '1' then + if CEN = '1' then + if WEH = '1' then + RegsH(to_integer(unsigned(AddrA))) <= DIH; + end if; + if WEL = '1' then + RegsL(to_integer(unsigned(AddrA))) <= DIL; + end if; + end if; + end if; + end process; + + DOAH <= RegsH(to_integer(unsigned(AddrA))); + DOAL <= RegsL(to_integer(unsigned(AddrA))); + DOBH <= RegsH(to_integer(unsigned(AddrB))); + DOBL <= RegsL(to_integer(unsigned(AddrB))); + DOCH <= RegsH(to_integer(unsigned(AddrC))); + DOCL <= RegsL(to_integer(unsigned(AddrC))); + +end; diff --git a/Sega - SG1000/rtl/t80/T80a.vhd b/Sega - SG1000/rtl/t80/T80a.vhd new file mode 100644 index 00000000..5e189020 --- /dev/null +++ b/Sega - SG1000/rtl/t80/T80a.vhd @@ -0,0 +1,253 @@ +-- +-- Z80 compatible microprocessor core, asynchronous top level +-- +-- Version : 0247 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0208 : First complete release +-- +-- 0211 : Fixed interrupt cycle +-- +-- 0235 : Updated for T80 interface change +-- +-- 0238 : Updated for T80 interface change +-- +-- 0240 : Updated for T80 interface change +-- +-- 0242 : Updated for T80 interface change +-- +-- 0247 : Fixed bus req/ack cycle +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80a is + generic( + Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + MREQ_n : out std_logic; + IORQ_n : out std_logic; + RD_n : out std_logic; + WR_n : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + D : inout std_logic_vector(7 downto 0) + ); +end T80a; + +architecture rtl of T80a is + + signal CEN : std_logic; + signal Reset_s : std_logic; + signal IntCycle_n : std_logic; + signal IORQ : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal MREQ : std_logic; + signal MReq_Inhibit : std_logic; + signal Req_Inhibit : std_logic; + signal RD : std_logic; + signal MREQ_n_i : std_logic; + signal IORQ_n_i : std_logic; + signal RD_n_i : std_logic; + signal WR_n_i : std_logic; + signal RFSH_n_i : std_logic; + signal BUSAK_n_i : std_logic; + signal A_i : std_logic_vector(15 downto 0); + signal DO : std_logic_vector(7 downto 0); + signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser + signal Wait_s : std_logic; + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); + +begin + + CEN <= '1'; + + BUSAK_n <= BUSAK_n_i; + MREQ_n_i <= not MREQ or (Req_Inhibit and MReq_Inhibit); + RD_n_i <= not RD or Req_Inhibit; + + MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z'; + IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z'; + RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z'; + WR_n <= WR_n_i when BUSAK_n_i = '1' else 'Z'; + RFSH_n <= RFSH_n_i when BUSAK_n_i = '1' else 'Z'; + A <= A_i when BUSAK_n_i = '1' else (others => 'Z'); + D <= DO when Write = '1' and BUSAK_n_i = '1' else (others => 'Z'); + + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + Reset_s <= '0'; + elsif CLK_n'event and CLK_n = '1' then + Reset_s <= '1'; + end if; + end process; + + u0 : T80 + generic map( + Mode => Mode, + IOWait => 1) + port map( + CEN => CEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n_i, + HALT_n => HALT_n, + WAIT_n => Wait_s, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => Reset_s, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n_i, + CLK_n => CLK_n, + A => A_i, + DInst => D, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n); + + process (CLK_n) + begin + if CLK_n'event and CLK_n = '0' then + Wait_s <= WAIT_n; + if TState = "011" and BUSAK_n_i = '1' then + DI_Reg <= to_x01(D); + end if; + end if; + end process; + + process (Reset_s,CLK_n) + begin + if Reset_s = '0' then + WR_n_i <= '1'; + elsif CLK_n'event and CLK_n = '1' then + WR_n_i <= '1'; + if TState = "001" then -- To short for IO writes !!!!!!!!!!!!!!!!!!! + WR_n_i <= not Write; + end if; + end if; + end process; + + process (Reset_s,CLK_n) + begin + if Reset_s = '0' then + Req_Inhibit <= '0'; + elsif CLK_n'event and CLK_n = '1' then + if MCycle = "001" and TState = "010" then + Req_Inhibit <= '1'; + else + Req_Inhibit <= '0'; + end if; + end if; + end process; + + process (Reset_s,CLK_n) + begin + if Reset_s = '0' then + MReq_Inhibit <= '0'; + elsif CLK_n'event and CLK_n = '0' then + if MCycle = "001" and TState = "010" then + MReq_Inhibit <= '1'; + else + MReq_Inhibit <= '0'; + end if; + end if; + end process; + + process(Reset_s,CLK_n) + begin + if Reset_s = '0' then + RD <= '0'; + IORQ_n_i <= '1'; + MREQ <= '0'; + elsif CLK_n'event and CLK_n = '0' then + + if MCycle = "001" then + if TState = "001" then + RD <= IntCycle_n; + MREQ <= IntCycle_n; + IORQ_n_i <= IntCycle_n; + end if; + if TState = "011" then + RD <= '0'; + IORQ_n_i <= '1'; + MREQ <= '1'; + end if; + if TState = "100" then + MREQ <= '0'; + end if; + else + if TState = "001" and NoRead = '0' then + RD <= not Write; + IORQ_n_i <= not IORQ; + MREQ <= not IORQ; + end if; + if TState = "011" then + RD <= '0'; + IORQ_n_i <= '1'; + MREQ <= '0'; + end if; + end if; + end if; + end process; + +end; diff --git a/Sega - SG1000/rtl/t80/T80se.vhd b/Sega - SG1000/rtl/t80/T80se.vhd new file mode 100644 index 00000000..ac8886a8 --- /dev/null +++ b/Sega - SG1000/rtl/t80/T80se.vhd @@ -0,0 +1,184 @@ +-- +-- Z80 compatible microprocessor core, synchronous top level with clock enable +-- Different timing than the original z80 +-- Inputs needs to be synchronous and outputs may glitch +-- +-- Version : 0242 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t80/ +-- +-- Limitations : +-- +-- File history : +-- +-- 0235 : First release +-- +-- 0236 : Added T2Write generic +-- +-- 0237 : Fixed T2Write with wait state +-- +-- 0238 : Updated for T80 interface change +-- +-- 0240 : Updated for T80 interface change +-- +-- 0242 : Updated for T80 interface change +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use work.T80_Pack.all; + +entity T80se is + generic( + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + T2Write : integer := 0; -- 0 => WR_n active in T3, /=0 => WR_n active in T2 + IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle + ); + port( + RESET_n : in std_logic; + CLK_n : in std_logic; + CLKEN : in std_logic; + WAIT_n : in std_logic; + INT_n : in std_logic; + NMI_n : in std_logic; + BUSRQ_n : in std_logic; + M1_n : out std_logic; + MREQ_n : out std_logic; + IORQ_n : out std_logic; + RD_n : out std_logic; + WR_n : out std_logic; + RFSH_n : out std_logic; + HALT_n : out std_logic; + BUSAK_n : out std_logic; + A : out std_logic_vector(15 downto 0); + DI : in std_logic_vector(7 downto 0); + DO : out std_logic_vector(7 downto 0) + ); +end T80se; + +architecture rtl of T80se is + + signal IntCycle_n : std_logic; + signal NoRead : std_logic; + signal Write : std_logic; + signal IORQ : std_logic; + signal DI_Reg : std_logic_vector(7 downto 0); + signal MCycle : std_logic_vector(2 downto 0); + signal TState : std_logic_vector(2 downto 0); + +begin + + u0 : T80 + generic map( + Mode => Mode, + IOWait => IOWait) + port map( + CEN => CLKEN, + M1_n => M1_n, + IORQ => IORQ, + NoRead => NoRead, + Write => Write, + RFSH_n => RFSH_n, + HALT_n => HALT_n, + WAIT_n => Wait_n, + INT_n => INT_n, + NMI_n => NMI_n, + RESET_n => RESET_n, + BUSRQ_n => BUSRQ_n, + BUSAK_n => BUSAK_n, + CLK_n => CLK_n, + A => A, + DInst => DI, + DI => DI_Reg, + DO => DO, + MC => MCycle, + TS => TState, + IntCycle_n => IntCycle_n); + + process (RESET_n, CLK_n) + begin + if RESET_n = '0' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + DI_Reg <= "00000000"; + elsif CLK_n'event and CLK_n = '1' then + if CLKEN = '1' then + RD_n <= '1'; + WR_n <= '1'; + IORQ_n <= '1'; + MREQ_n <= '1'; + if MCycle = "001" then + if TState = "001" or (TState = "010" and Wait_n = '0') then + RD_n <= not IntCycle_n; + MREQ_n <= not IntCycle_n; + IORQ_n <= IntCycle_n; + end if; + if TState = "011" then + MREQ_n <= '0'; + end if; + else + if (TState = "001" or (TState = "010" and Wait_n = '0')) and NoRead = '0' and Write = '0' then + RD_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + if T2Write = 0 then + if TState = "010" and Write = '1' then + WR_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + else + if (TState = "001" or (TState = "010" and Wait_n = '0')) and Write = '1' then + WR_n <= '0'; + IORQ_n <= not IORQ; + MREQ_n <= IORQ; + end if; + end if; + end if; + if TState = "010" and Wait_n = '1' then + DI_Reg <= DI; + end if; + end if; + end if; + end process; + +end; diff --git a/Sega - SG1000/rtl/vdp/vdp.vhd b/Sega - SG1000/rtl/vdp/vdp.vhd new file mode 100644 index 00000000..5deab954 --- /dev/null +++ b/Sega - SG1000/rtl/vdp/vdp.vhd @@ -0,0 +1,296 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity vdp is + port ( + cpu_clk: in STD_LOGIC; + vdp_clk: in STD_LOGIC; + RD_n: in STD_LOGIC; + WR_n: in STD_LOGIC; + IRQ_n: out STD_LOGIC; + A: in STD_LOGIC_VECTOR (7 downto 0); + D_in: in STD_LOGIC_VECTOR (7 downto 0); + D_out: out STD_LOGIC_VECTOR (7 downto 0); + x: unsigned(8 downto 0); + y: unsigned(7 downto 0); + vblank: std_logic; + hblank: std_logic; + color: out std_logic_vector (5 downto 0)); +end vdp; + +architecture Behavioral of vdp is + + component vdp_main is + port ( + clk: in std_logic; + vram_A: out std_logic_vector(13 downto 0); + vram_D: in std_logic_vector(7 downto 0); + cram_A: out std_logic_vector(4 downto 0); + cram_D: in std_logic_vector(5 downto 0); + + x: unsigned(8 downto 0); + y: unsigned(7 downto 0); + + color: out std_logic_vector (5 downto 0); + + display_on: in std_logic; + mask_column0: in std_logic; + overscan: in std_logic_vector (3 downto 0); + + bg_address: in std_logic_vector (2 downto 0); + bg_scroll_x: in unsigned(7 downto 0); + bg_scroll_y: in unsigned(7 downto 0); + disable_hscroll: in std_logic; + + spr_address: in std_logic_vector (5 downto 0); + spr_high_bit: in std_logic; + spr_shift: in std_logic; + spr_tall: in std_logic); + end component; + + component vdp_cram is + port ( + cpu_clk: in STD_LOGIC; + cpu_WE: in std_logic; + cpu_A: in std_logic_vector(4 downto 0); + cpu_D: in std_logic_vector(5 downto 0); + vdp_clk: in STD_LOGIC; + vdp_A: in std_logic_vector(4 downto 0); + vdp_D: out std_logic_vector(5 downto 0)); + end component; + + -- helper bits + signal data_write: std_logic; + signal address_ff: std_logic := '0'; + signal to_cram: boolean := false; + + -- vram and cram lines for the cpu interface + signal xram_cpu_A: std_logic_vector(13 downto 0); + signal vram_cpu_WE: std_logic; + signal cram_cpu_WE: std_logic; + signal vram_cpu_D_out: std_logic_vector(7 downto 0); + signal xram_cpu_A_incr: std_logic := '0'; + + -- vram and cram lines for the video interface + signal vram_vdp_A: std_logic_vector(13 downto 0); + signal vram_vdp_D: std_logic_vector(7 downto 0); + signal cram_vdp_A: std_logic_vector(4 downto 0); + signal cram_vdp_D: std_logic_vector(5 downto 0); + + -- control bits + signal display_on: std_logic := '1'; + signal disable_hscroll: std_logic := '0'; + signal mask_column0: std_logic := '0'; + signal overscan: std_logic_vector (3 downto 0) := "0000"; + signal irq_frame_en: std_logic := '0'; + signal irq_line_en: std_logic := '0'; + signal irq_line_count: unsigned(7 downto 0) := (others=>'1'); + signal bg_address: std_logic_vector (2 downto 0) := (others=>'0'); + signal bg_scroll_x: unsigned(7 downto 0) := (others=>'0'); + signal bg_scroll_y: unsigned(7 downto 0) := (others=>'0'); + signal spr_address: std_logic_vector (5 downto 0) := (others=>'0'); + signal spr_shift: std_logic := '0'; + signal spr_tall: std_logic := '0'; + signal spr_high_bit: std_logic := '0'; + + -- various counters + signal last_y0: std_logic := '0'; + signal virq_flag: std_logic := '0'; + signal reset_virq_flag: boolean := false; + signal irq_counter: unsigned(4 downto 0) := (others=>'0'); + signal hbl_counter: unsigned(7 downto 0) := (others=>'0'); + signal vbl_irq: std_logic; + signal hbl_irq: std_logic; + +begin + + vdp_main_inst: vdp_main + port map( + clk => vdp_clk, + vram_A => vram_vdp_A, + vram_D => vram_vdp_D, + cram_A => cram_vdp_A, + cram_D => cram_vdp_D, + + x => x, + y => y, + color => color, + + display_on => display_on, + mask_column0 => mask_column0, + overscan => overscan, + + bg_address => bg_address, + bg_scroll_x => bg_scroll_x, + bg_scroll_y => bg_scroll_y, + disable_hscroll=>disable_hscroll, + + spr_address => spr_address, + spr_high_bit => spr_high_bit, + spr_shift => spr_shift, + spr_tall => spr_tall); + + + vdp_vram_inst : entity work.dpram + generic map + ( + init_file => "vram.hex", + widthad_a => 14 + ) + port map + ( + clock_a => cpu_clk, + address_a => xram_cpu_A(13 downto 0), + wren_a => vram_cpu_WE, + data_a => D_in, + q_a => vram_cpu_D_out, + + clock_b => not vdp_clk, + address_b => vram_vdp_A, + wren_b => '0', + data_b => (others => '0'), + q_b => vram_vdp_D + ); + + vdp_cram_inst: vdp_cram + port map ( + cpu_clk => cpu_clk, + cpu_WE => cram_cpu_WE, + cpu_A => xram_cpu_A(4 downto 0), + cpu_D => D_in(5 downto 0), + vdp_clk => vdp_clk, + vdp_A => cram_vdp_A, + vdp_D => cram_vdp_D); + + + data_write <= not WR_n and not A(0); + cram_cpu_WE <= data_write when to_cram else '0'; + vram_cpu_WE <= data_write when not to_cram else '0'; + + process (cpu_clk) + begin + if rising_edge(cpu_clk) then + if WR_n='0' then + if A(0)='0' then + xram_cpu_A_incr <= '1'; + + else + if address_ff='0' then + xram_cpu_A(7 downto 0) <= D_in; + else + xram_cpu_A(13 downto 8) <= D_in(5 downto 0); + to_cram <= D_in(7 downto 6)="11"; + case D_in is + when "10000000" => + disable_hscroll<= xram_cpu_A(6); + mask_column0 <= xram_cpu_A(5); + irq_line_en <= xram_cpu_A(4); + spr_shift <= xram_cpu_A(3); + when "10000001" => + display_on <= xram_cpu_A(6); + irq_frame_en <= xram_cpu_A(5); + spr_tall <= xram_cpu_A(1); + when "10000010" => + bg_address <= xram_cpu_A(3 downto 1); + when "10000101" => + spr_address <= xram_cpu_A(6 downto 1); + when "10000110" => + spr_high_bit <= xram_cpu_A(2); + when "10000111" => + overscan <= xram_cpu_A(3 downto 0); + when "10001000" => + bg_scroll_x <= unsigned(xram_cpu_A(7 downto 0)); + when "10001001" => + bg_scroll_y <= unsigned(xram_cpu_A(7 downto 0)); + when "10001010" => + irq_line_count <= unsigned(xram_cpu_A(7 downto 0)); + when others => + end case; + end if; + address_ff <= not address_ff; + end if; + + elsif RD_n='0' then + case A(7 downto 6)&A(0) is + when "010" => + D_out <= std_logic_vector(y); + when "011" => + D_out <= std_logic_vector(x(7 downto 0)); + when "100" => + D_out <= vram_cpu_D_out; + xram_cpu_A_incr <= '1'; + when "101" => + D_out(7) <= virq_flag; + D_out(6 downto 0) <= (others=>'0'); + reset_virq_flag <= true; + when others => + end case; + + elsif xram_cpu_A_incr='1' then + xram_cpu_A <= std_logic_vector(unsigned(xram_cpu_A) + 1); + xram_cpu_A_incr <= '0'; + + else + reset_virq_flag <= false; + end if; + end if; + end process; + + + process (vdp_clk) + begin + if rising_edge(vdp_clk) then + if vblank='1' then + vbl_irq <= irq_frame_en; + else + vbl_irq <= '0'; + end if; + end if; + end process; + + process (vdp_clk) + begin + if rising_edge(vdp_clk) then + if x=256 and not (last_y0=std_logic(y(0))) then + last_y0 <= std_logic(y(0)); + if y<192 then + if hbl_counter=0 then + hbl_irq <= irq_line_en; + hbl_counter <= irq_line_count; + else + hbl_counter <= hbl_counter-1; + end if; + else + hbl_counter <= irq_line_count; + end if; + else + hbl_irq <= '0'; + end if; + end if; + end process; + + process (vdp_clk) + begin + if rising_edge(vdp_clk) then + if vbl_irq='1' then + virq_flag <= '1'; + elsif reset_virq_flag then + virq_flag <= '0'; + end if; + end if; + end process; + + process (vdp_clk) + begin + if rising_edge(vdp_clk) then + if vbl_irq='1' or hbl_irq='1' then + irq_counter <= (others=>'1'); + elsif irq_counter>0 then + irq_counter <= irq_counter-1; + end if; + end if; + end process; + IRQ_n <= '0' when irq_counter>0 else '1'; + +end Behavioral; diff --git a/Sega - SG1000/rtl/vdp/vdp_background.vhd b/Sega - SG1000/rtl/vdp/vdp_background.vhd new file mode 100644 index 00000000..6049b89f --- /dev/null +++ b/Sega - SG1000/rtl/vdp/vdp_background.vhd @@ -0,0 +1,136 @@ +library ieee; +use ieee.std_logic_1164.all; +use IEEE.NUMERIC_STD.ALL; + +entity vdp_background is +port ( + clk: in std_logic; + reset: in std_logic; + table_address: in std_logic_vector(13 downto 11); + scroll_x: in unsigned(7 downto 0); + disable_hscroll: in std_logic; + y: in unsigned(7 downto 0); + + vram_A: out std_logic_vector(13 downto 0); + vram_D: in std_logic_vector(7 downto 0); + + color: out std_logic_vector(4 downto 0); + priority: out std_logic +); +end entity; + +architecture rtl of vdp_background is + + signal tile_index : std_logic_vector (8 downto 0); + signal x : unsigned (7 downto 0); + signal tile_y : std_logic_vector (2 downto 0); + signal palette : std_logic; + signal priority_latch: std_logic; + signal flip_x : std_logic; + + signal data0 : std_logic_vector(7 downto 0); + signal data1 : std_logic_vector(7 downto 0); + signal data2 : std_logic_vector(7 downto 0); + signal data3 : std_logic_vector(7 downto 0); + + signal shift0 : std_logic_vector(7 downto 0); + signal shift1 : std_logic_vector(7 downto 0); + signal shift2 : std_logic_vector(7 downto 0); + signal shift3 : std_logic_vector(7 downto 0); + +begin + + process (clk) begin + if (rising_edge(clk)) then + if (reset='1') then + if disable_hscroll='0' or y>=16 then + x <= 240-scroll_x; + else + x <= "11110000"; -- 240 + end if; + else + x <= x + 1; + end if; + end if; + end process; + + process (clk) + variable char_address : std_logic_vector(12 downto 0); + variable data_address : std_logic_vector(11 downto 0); + begin + if (rising_edge(clk)) then + char_address(12 downto 10) := table_address; + char_address(9 downto 5) := std_logic_vector(y(7 downto 3)); + char_address(4 downto 0) := std_logic_vector(x(7 downto 3) + 1); + data_address := tile_index & tile_y; + + case x(2 downto 0) is + when "000" => vram_A <= char_address & "0"; + when "001" => vram_A <= char_address & "1"; + when "011" => vram_A <= data_address & "00"; + when "100" => vram_A <= data_address & "01"; + when "101" => vram_A <= data_address & "10"; + when "110" => vram_A <= data_address & "11"; + when others => + end case; + end if; + end process; + + process (clk) begin + if (rising_edge(clk)) then + case x(2 downto 0) is + when "001" => + tile_index(7 downto 0) <= vram_D; + when "010" => + tile_index(8) <= vram_D(0); + flip_x <= vram_D(1); + tile_y(0) <= y(0) xor vram_D(2); + tile_y(1) <= y(1) xor vram_D(2); + tile_y(2) <= y(2) xor vram_D(2); + palette <= vram_D(3); + priority_latch <= vram_D(4); + when "100" => + data0 <= vram_D; + when "101" => + data1 <= vram_D; + when "110" => + data2 <= vram_D; +-- when "111" => +-- data3 <= vram_D; + when others => + end case; + end if; + end process; + + process (clk) begin + if (rising_edge(clk)) then + case x(2 downto 0) is + when "111" => + if flip_x='0' then + shift0 <= data0; + shift1 <= data1; + shift2 <= data2; + shift3 <= vram_D; + else + shift0 <= data0(0)&data0(1)&data0(2)&data0(3)&data0(4)&data0(5)&data0(6)&data0(7); + shift1 <= data1(0)&data1(1)&data1(2)&data1(3)&data1(4)&data1(5)&data1(6)&data1(7); + shift2 <= data2(0)&data2(1)&data2(2)&data2(3)&data2(4)&data2(5)&data2(6)&data2(7); + shift3 <= vram_D(0)&vram_D(1)&vram_D(2)&vram_D(3)&vram_D(4)&vram_D(5)&vram_D(6)&vram_D(7); + end if; + color(4) <= palette; + priority <= priority_latch; + when others => + shift0(7 downto 1) <= shift0(6 downto 0); + shift1(7 downto 1) <= shift1(6 downto 0); + shift2(7 downto 1) <= shift2(6 downto 0); + shift3(7 downto 1) <= shift3(6 downto 0); + end case; + end if; + end process; + + color(0) <= shift0(7); + color(1) <= shift1(7); + color(2) <= shift2(7); + color(3) <= shift3(7); +end architecture; + diff --git a/Sega - SG1000/rtl/vdp/vdp_cram.vhd b/Sega - SG1000/rtl/vdp/vdp_cram.vhd new file mode 100644 index 00000000..781a1e35 --- /dev/null +++ b/Sega - SG1000/rtl/vdp/vdp_cram.vhd @@ -0,0 +1,44 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity vdp_cram is + port ( + cpu_clk: in STD_LOGIC; + cpu_WE: in STD_LOGIC; + cpu_A: in STD_LOGIC_VECTOR (4 downto 0); + cpu_D: in STD_LOGIC_VECTOR (5 downto 0); + vdp_clk: in STD_LOGIC; + vdp_A: in STD_LOGIC_VECTOR (4 downto 0); + vdp_D: out STD_LOGIC_VECTOR (5 downto 0)); +end vdp_cram; + +architecture Behavioral of vdp_cram is + + type t_ram is array (0 to 31) of std_logic_vector(5 downto 0); + signal ram : t_ram := (others => "111111"); + +begin + + process (cpu_clk) + variable i : integer range 0 to 31; + begin + if rising_edge(cpu_clk) then + if cpu_WE='1'then + i := to_integer(unsigned(cpu_A)); + ram(i) <= cpu_D; + end if; + end if; + end process; + + process (vdp_clk) + variable i : integer range 0 to 31; + begin + if rising_edge(vdp_clk) then + i := to_integer(unsigned(vdp_A)); + vdp_D <= ram(i); + end if; + end process; + +end Behavioral; + diff --git a/Sega - SG1000/rtl/vdp/vdp_main.vhd b/Sega - SG1000/rtl/vdp/vdp_main.vhd new file mode 100644 index 00000000..c89bfe2c --- /dev/null +++ b/Sega - SG1000/rtl/vdp/vdp_main.vhd @@ -0,0 +1,135 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity vdp_main is + port ( + clk: in std_logic; + vram_A: out std_logic_vector(13 downto 0); + vram_D: in std_logic_vector(7 downto 0); + cram_A: out std_logic_vector(4 downto 0); + cram_D: in std_logic_vector(5 downto 0); + + x: unsigned(8 downto 0); + y: unsigned(7 downto 0); + + color: out std_logic_vector (5 downto 0); + + display_on: in std_logic; + mask_column0: in std_logic; + overscan: in std_logic_vector (3 downto 0); + + bg_address: in std_logic_vector (2 downto 0); + bg_scroll_x: in unsigned(7 downto 0); + bg_scroll_y: in unsigned(7 downto 0); + disable_hscroll: in std_logic; + + spr_address: in std_logic_vector (5 downto 0); + spr_high_bit: in std_logic; + spr_shift: in std_logic; + spr_tall: in std_logic); +end vdp_main; + +architecture Behavioral of vdp_main is + + component vdp_background is + port ( + clk: in std_logic; + reset: in std_logic; + table_address: in std_logic_vector(13 downto 11); + scroll_x: in unsigned(7 downto 0); + disable_hscroll: in std_logic; + y: in unsigned(7 downto 0); + vram_A: out std_logic_vector(13 downto 0); + vram_D: in std_logic_vector(7 downto 0); + color: out std_logic_vector(4 downto 0); + priority: out std_logic); + end component; + + component vdp_sprites is + port ( + clk: in std_logic; + table_address: in std_logic_vector(13 downto 8); + char_high_bit: in std_logic; + tall: in std_logic; + x: in unsigned(8 downto 0); + y: in unsigned(7 downto 0); + vram_A: out std_logic_vector(13 downto 0); + vram_D: in std_logic_vector(7 downto 0); + color: out std_logic_vector(3 downto 0)); + end component; + + signal bg_y: unsigned(7 downto 0); + signal bg_vram_A: std_logic_vector(13 downto 0); + signal bg_color: std_logic_vector(4 downto 0); + signal bg_priority: std_logic; + + signal spr_vram_A: std_logic_vector(13 downto 0); + signal spr_color: std_logic_vector(3 downto 0); + + signal line_reset: std_logic; + +begin + + process (y,bg_scroll_y) + variable sum: unsigned(8 downto 0); + begin + sum := ('0'&y)+('0'&bg_scroll_y); + if (sum>=224) then + sum := sum-224; + end if; + bg_y <= sum(7 downto 0); + end process; + + line_reset <= '1' when x=512-16 else '0'; + + vdp_bg_inst: vdp_background + port map ( + clk => clk, + table_address => bg_address, + reset => line_reset, + disable_hscroll=> disable_hscroll, + scroll_x => bg_scroll_x, + y => bg_y, + + vram_A => bg_vram_A, + vram_D => vram_D, + color => bg_color, + priority => bg_priority); + + vdp_spr_inst: vdp_sprites + port map ( + clk => clk, + table_address => spr_address, + char_high_bit => spr_high_bit, + tall => spr_tall, + x => x, + y => y, + + vram_A => spr_vram_A, + vram_D => vram_D, + color => spr_color); + + process (x, y, bg_priority, spr_color, bg_color, overscan) + variable spr_active : boolean; + variable bg_active : boolean; + begin + if x<256 and y<192 and (mask_column0='0' or x>=8) then + spr_active := not (spr_color="0000"); + bg_active := not (bg_color(3 downto 0)="0000"); + if (bg_priority='0' and spr_active) or (bg_priority='1' and not bg_active) then + cram_A <= "1"&spr_color; + else + cram_A <= bg_color; + end if; + else + cram_A <= "1"&overscan; + end if; + end process; + + vram_A <= spr_vram_A when x>=256 and x<384 else bg_vram_A; + + color <= cram_D; + +end Behavioral; + diff --git a/Sega - SG1000/rtl/vdp/vdp_sprite_shifter.vhd b/Sega - SG1000/rtl/vdp/vdp_sprite_shifter.vhd new file mode 100644 index 00000000..8c8d4e9c --- /dev/null +++ b/Sega - SG1000/rtl/vdp/vdp_sprite_shifter.vhd @@ -0,0 +1,48 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity vpd_sprite_shifter is + Port( clk : in std_logic; + x : in unsigned (7 downto 0); + spr_x : in unsigned (7 downto 0); + spr_d0: in std_logic_vector (7 downto 0); + spr_d1: in std_logic_vector (7 downto 0); + spr_d2: in std_logic_vector (7 downto 0); + spr_d3: in std_logic_vector (7 downto 0); + color : out std_logic_vector (3 downto 0); + active: out std_logic); +end vpd_sprite_shifter; + +architecture Behavioral of vpd_sprite_shifter is + + signal count : integer range 0 to 8; + signal shift0 : std_logic_vector (7 downto 0) := (others=>'0'); + signal shift1 : std_logic_vector (7 downto 0) := (others=>'0'); + signal shift2 : std_logic_vector (7 downto 0) := (others=>'0'); + signal shift3 : std_logic_vector (7 downto 0) := (others=>'0'); + +begin + + process (clk) + begin + if rising_edge(clk) then + if spr_x=x then + shift0 <= spr_d0; + shift1 <= spr_d1; + shift2 <= spr_d2; + shift3 <= spr_d3; + else + shift0 <= shift0(6 downto 0)&"0"; + shift1 <= shift1(6 downto 0)&"0"; + shift2 <= shift2(6 downto 0)&"0"; + shift3 <= shift3(6 downto 0)&"0"; + end if; + end if; + end process; + + color <= shift3(7)&shift2(7)&shift1(7)&shift0(7); + active <= shift3(7) or shift2(7) or shift1(7) or shift0(7); + +end Behavioral; + diff --git a/Sega - SG1000/rtl/vdp/vdp_sprites.vhd b/Sega - SG1000/rtl/vdp/vdp_sprites.vhd new file mode 100644 index 00000000..18dbdd95 --- /dev/null +++ b/Sega - SG1000/rtl/vdp/vdp_sprites.vhd @@ -0,0 +1,188 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity vdp_sprites is + port (clk : in std_logic; + table_address : in STD_LOGIC_VECTOR (13 downto 8); + char_high_bit : in std_logic; + tall : in std_logic; + vram_A : out STD_LOGIC_VECTOR (13 downto 0); + vram_D : in STD_LOGIC_VECTOR (7 downto 0); + x : in unsigned (8 downto 0); + y : in unsigned (7 downto 0); + color : out STD_LOGIC_VECTOR (3 downto 0)); +end vdp_sprites; + +architecture Behavioral of vdp_sprites is + + component vpd_sprite_shifter is + port( clk : in std_logic; + x : in unsigned (7 downto 0); + spr_x : in unsigned (7 downto 0); + spr_d0: in std_logic_vector (7 downto 0); + spr_d1: in std_logic_vector (7 downto 0); + spr_d2: in std_logic_vector (7 downto 0); + spr_d3: in std_logic_vector (7 downto 0); + color : out std_logic_vector (3 downto 0); + active: out std_logic); + end component; + + constant WAITING: integer := 0; + constant COMPARE: integer := 1; + constant LOAD_N: integer := 2; + constant LOAD_X: integer := 3; + constant LOAD_0: integer := 4; + constant LOAD_1: integer := 5; + constant LOAD_2: integer := 6; + constant LOAD_3: integer := 7; + + signal state: integer := WAITING; + signal count: integer range 0 to 7; + signal index: unsigned(5 downto 0); + signal data_address: std_logic_vector(13 downto 2); + + type tenable is array (0 to 7) of boolean; + type tx is array (0 to 7) of unsigned(7 downto 0); + type tdata is array (0 to 7) of std_logic_vector(7 downto 0); + signal enable: tenable; + signal spr_x: tx; + signal spr_d0: tdata; + signal spr_d1: tdata; + signal spr_d2: tdata; + signal spr_d3: tdata; + + type tcolor is array (0 to 7) of std_logic_vector(3 downto 0); + signal spr_color: tcolor; + signal active: std_logic_vector(7 downto 0); + +begin + shifters: + for i in 0 to 7 generate + begin + shifter: vpd_sprite_shifter + port map(clk => clk, + x => x(7 downto 0), + spr_x => spr_x(i), + spr_d0=> spr_d0(i), + spr_d1=> spr_d1(i), + spr_d2=> spr_d2(i), + spr_d3=> spr_d3(i), + color => spr_color(i), + active=> active(i)); + end generate; + + with state select + vram_a <= table_address&"00"&std_logic_vector(index) when COMPARE, + table_address&"1"&std_logic_vector(index)&"1" when LOAD_N, + table_address&"1"&std_logic_vector(index)&"0" when LOAD_X, + data_address&"00" when LOAD_0, + data_address&"01" when LOAD_1, + data_address&"10" when LOAD_2, + data_address&"11" when LOAD_3, + (others=>'0') when others; + + process (clk) + variable y9 : unsigned(8 downto 0); + variable d9 : unsigned(8 downto 0); + variable delta : unsigned(8 downto 0); + begin + if rising_edge(clk) then + + if x=255 then + count <= 0; + enable <= (others=>false); + state <= COMPARE; + index <= (others=>'0'); + + else + y9 := "0"&y; + d9 := "0"&unsigned(vram_D); + if d9>=240 then + d9 := d9-256; + end if; + delta := y9-d9; + + case state is + when COMPARE => + if d9=208 then + state <= WAITING; -- stop + elsif 0<=delta and ((delta<8 and tall='0') or (delta<16 and tall='1')) then + enable(count) <= true; + data_address(5 downto 2) <= std_logic_vector(delta(3 downto 0)); + state <= LOAD_N; + else + if index<63 then + index <= index+1; + else + state <= WAITING; + end if; + end if; + + when LOAD_N => + data_address(13) <= char_high_bit; + data_address(12 downto 6) <= vram_d(7 downto 1); + if tall='0' then + data_address(5) <= vram_d(0); + end if; + state <= LOAD_X; + + when LOAD_X => + spr_x(count) <= unsigned(vram_d); + state <= LOAD_0; + + when LOAD_0 => + spr_d0(count) <= vram_d; + state <= LOAD_1; + + when LOAD_1 => + spr_d1(count) <= vram_d; + state <= LOAD_2; + + when LOAD_2 => + spr_d2(count) <= vram_d; + state <= LOAD_3; + + when LOAD_3 => + spr_d3(count) <= vram_d; + if (count<7) then + state <= COMPARE; + index <= index+1; + count <= count+1; + else + state <= WAITING; + end if; + + when others => + end case; + end if; + end if; + end process; + + process (clk) + begin + if rising_edge(clk) then + if enable(0) and active(0)='1' then + color <= spr_color(0); + elsif enable(1) and active(1)='1' then + color <= spr_color(1); + elsif enable(2) and active(2)='1' then + color <= spr_color(2); + elsif enable(3) and active(3)='1' then + color <= spr_color(3); + elsif enable(4) and active(4)='1' then + color <= spr_color(4); + elsif enable(5) and active(5)='1' then + color <= spr_color(5); + elsif enable(6) and active(6)='1' then + color <= spr_color(6); + elsif enable(7) and active(7)='1' then + color <= spr_color(7); + else + color <= (others=>'0'); + end if; + end if; + end process; + +end Behavioral; + diff --git a/Sega - SG1000/rtl/vdp/vdp_vram.vhd b/Sega - SG1000/rtl/vdp/vdp_vram.vhd new file mode 100644 index 00000000..10bfd18a --- /dev/null +++ b/Sega - SG1000/rtl/vdp/vdp_vram.vhd @@ -0,0 +1,44 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; + +library UNISIM; +use UNISIM.vcomponents.all; + +entity vdp_vram is + port ( + cpu_clk: in STD_LOGIC; + cpu_WE: in STD_LOGIC; + cpu_A: in STD_LOGIC_VECTOR (13 downto 0); + cpu_D_in: in STD_LOGIC_VECTOR (7 downto 0); + cpu_D_out: out STD_LOGIC_VECTOR (7 downto 0); + vdp_clk: in STD_LOGIC; + vdp_A: in STD_LOGIC_VECTOR (13 downto 0); + vdp_D_out: out STD_LOGIC_VECTOR (7 downto 0)); +end vdp_vram; + +architecture Behavioral of vdp_vram is +begin + ram_blocks: + for b in 0 to 7 generate + begin + inst: RAMB16_S1_S1 + port map ( + CLKA => cpu_clk, + ADDRA => cpu_A, + DIA => cpu_D_in(b downto b), + DOA => cpu_D_out(b downto b), + ENA => '1', + SSRA => '0', + WEA => cpu_WE, + + CLKB => not vdp_clk, + ADDRB => vdp_A, + DIB => "0", + DOB => vdp_D_out(b downto b), + ENB => '1', + SSRB => '0', + WEB => '0' + ); + end generate; + +end Behavioral; diff --git a/Sega - SG1000/rtl/vdp/vram.hex b/Sega - SG1000/rtl/vdp/vram.hex new file mode 100644 index 00000000..f2bf746c --- /dev/null +++ b/Sega - SG1000/rtl/vdp/vram.hex @@ -0,0 +1,98 @@ +:020000040000FA +:2084000000000000000000000000000000000000000000000000000000000000000000005C +:208420001818181818181818181818181818181818181818000000001818181800000000FC +:208440006C6C6C6C6C6C6C6C000000000000000000000000000000000000000000000000BC +:208460006C6C6C6C6C6C6C6CFEFEFEFE6C6C6C6CFEFEFEFE6C6C6C6C6C6C6C6C000000009C +:20848000181818183E3E3E3E606060603C3C3C3C060606067C7C7C7C1818181800000000AC +:2084A0000000000066666666ACACACACD8D8D8D8363636366A6A6A6ACCCCCCCC0000000064 +:2084C000383838386C6C6C6C6868686876767676DCDCDCDCCECECECE7B7B7B7B0000000000 +:2084E0001818181818181818303030300000000000000000000000000000000000000000FC +:208500000C0C0C0C18181818303030303030303030303030181818180C0C0C0C00000000FB +:2085200030303030181818180C0C0C0C0C0C0C0C0C0C0C0C1818181830303030000000006B +:2085400000000000666666663C3C3C3CFFFFFFFF3C3C3C3C6666666600000000000000000F +:208560000000000018181818181818187E7E7E7E1818181818181818000000000000000083 +:2085800000000000000000000000000000000000000000001818181818181818303030305B +:2085A0000000000000000000000000007E7E7E7E00000000000000000000000000000000C3 +:2085C0000000000000000000000000000000000000000000181818181818181800000000DB +:2085E00003030303060606060C0C0C0C181818183030303060606060C0C0C0C00000000087 +:208600003C3C3C3C666666666E6E6E6E7E7E7E7E76767676666666663C3C3C3C00000000C2 +:2086200018181818383838387878787818181818181818181818181818181818000000009A +:208640003C3C3C3C66666666060606060C0C0C0C18181818303030307E7E7E7E0000000032 +:208660003C3C3C3C66666666060606061C1C1C1C06060606666666663C3C3C3C000000004A +:208680001C1C1C1C3C3C3C3C6C6C6C6CCCCCCCCCFEFEFEFE0C0C0C0C0C0C0C0C0000000042 +:2086A0007E7E7E7E606060607C7C7C7C0606060606060606666666663C3C3C3C000000009A +:2086C0001C1C1C1C30303030606060607C7C7C7C66666666666666663C3C3C3C00000000DA +:2086E0007E7E7E7E06060606060606060C0C0C0C1818181818181818181818180000000002 +:208700003C3C3C3C66666666666666663C3C3C3C66666666666666663C3C3C3C0000000029 +:208720003C3C3C3C66666666666666663E3E3E3E060606060C0C0C0C3838383800000000F9 +:20874000000000001818181818181818000000000000000018181818181818180000000099 +:208760000000000018181818181818180000000000000000181818181818181830303030B9 +:20878000000000000606060618181818606060601818181806060606000000000000000069 +:2087A00000000000000000007E7E7E7E000000007E7E7E7E000000000000000000000000C9 +:2087C0000000000060606060181818180606060618181818606060600000000000000000C1 +:2087E0003C3C3C3C66666666060606060C0C0C0C18181818000000001818181800000000E9 +:208800003C3C3C3C666666665A5A5A5A5A5A5A5A5E5E5E5E606060603C3C3C3C0000000018 +:208820003C3C3C3C66666666666666667E7E7E7E6666666666666666666666660000000058 +:208840007C7C7C7C66666666666666667C7C7C7C66666666666666667C7C7C7C00000000E8 +:208860001E1E1E1E30303030606060606060606060606060303030301E1E1E1E0000000008 +:20888000787878786C6C6C6C6666666666666666666666666C6C6C6C7878787800000000F0 +:2088A0007E7E7E7E60606060606060607878787860606060606060607E7E7E7E00000000E8 +:2088C0007E7E7E7E6060606060606060787878786060606060606060606060600000000040 +:2088E0003C3C3C3C66666666606060606E6E6E6E66666666666666663E3E3E3E0000000090 +:208900006666666666666666666666667E7E7E7E66666666666666666666666600000000CF +:208920003C3C3C3C18181818181818181818181818181818181818183C3C3C3C0000000077 +:208940000606060606060606060606060606060606060606666666663C3C3C3C0000000017 +:20896000C6C6C6C6CCCCCCCCD8D8D8D8F0F0F0F0D8D8D8D8CCCCCCCCC6C6C6C600000000E7 +:208980006060606060606060606060606060606060606060606060607E7E7E7E00000000DF +:2089A000C6C6C6C6EEEEEEEEFEFEFEFED6D6D6D6C6C6C6C6C6C6C6C6C6C6C6C6000000004F +:2089C000C6C6C6C6E6E6E6E6F6F6F6F6DEDEDEDECECECECEC6C6C6C6C6C6C6C6000000002F +:2089E0003C3C3C3C66666666666666666666666666666666666666663C3C3C3C000000009F +:208A00007C7C7C7C66666666666666667C7C7C7C60606060606060606060606000000000C6 +:208A200078787878CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCDCDCDC7E7E7E7E000000002E +:208A40007C7C7C7C66666666666666667C7C7C7C6C6C6C6C66666666666666660000000026 +:208A60003C3C3C3C66666666707070703C3C3C3C0E0E0E0E666666663C3C3C3C00000000FE +:208A80007E7E7E7E181818181818181818181818181818181818181818181818000000009E +:208AA0006666666666666666666666666666666666666666666666663C3C3C3C0000000036 +:208AC000666666666666666666666666666666663C3C3C3C3C3C3C3C1818181800000000F6 +:208AE000C6C6C6C6C6C6C6C6C6C6C6C6D6D6D6D6FEFEFEFEEEEEEEEEC6C6C6C6000000000E +:208B0000C3C3C3C3666666663C3C3C3C181818183C3C3C3C66666666C3C3C3C300000000CD +:208B2000C3C3C3C3666666663C3C3C3C181818181818181818181818181818180000000021 +:208B4000FEFEFEFE0C0C0C0C181818183030303060606060C0C0C0C0FEFEFEFE0000000055 +:208B60003C3C3C3C30303030303030303030303030303030303030303C3C3C3C0000000055 +:208B8000C0C0C0C06060606030303030181818180C0C0C0C060606060303030300000000E1 +:208BA0003C3C3C3C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C3C3C3C3C00000000E5 +:208BC000181818183C3C3C3C666666660000000000000000000000000000000000000000AD +:208BE000000000000000000000000000000000000000000000000000FCFCFCFC0000000085 +:208C000018181818181818180C0C0C0C000000000000000000000000000000000000000064 +:208C200000000000000000003C3C3C3C060606063E3E3E3E666666663E3E3E3E00000000A4 +:208C400060606060606060607C7C7C7C6666666666666666666666667C7C7C7C000000006C +:208C600000000000000000003C3C3C3C6060606060606060606060603C3C3C3C0000000094 +:208C800006060606060606063E3E3E3E6666666666666666666666663E3E3E3E00000000EC +:208CA00000000000000000003C3C3C3C666666667E7E7E7E606060603C3C3C3C00000000C4 +:208CC0001C1C1C1C303030307C7C7C7C303030303030303030303030303030300000000074 +:208CE00000000000000000003E3E3E3E66666666666666663E3E3E3E060606063C3C3C3C4C +:208D000060606060606060607C7C7C7C666666666666666666666666666666660000000003 +:208D20001818181800000000181818181818181818181818181818180C0C0C0C0000000023 +:208D40000C0C0C0C000000000C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C7878787813 +:208D60006060606060606060666666666C6C6C6C787878786C6C6C6C666666660000000083 +:208D80001818181818181818181818181818181818181818181818180C0C0C0C0000000063 +:208DA0000000000000000000ECECECECFEFEFEFED6D6D6D6C6C6C6C6C6C6C6C60000000083 +:208DC00000000000000000007C7C7C7C666666666666666666666666666666660000000043 +:208DE00000000000000000003C3C3C3C6666666666666666666666663C3C3C3C00000000CB +:208E000000000000000000007C7C7C7C66666666666666667C7C7C7C606060606060606042 +:208E200000000000000000003E3E3E3E66666666666666663E3E3E3E0606060606060606E2 +:208E400000000000000000007C7C7C7C66666666606060606060606060606060000000000A +:208E600000000000000000003C3C3C3C606060603C3C3C3C060606067C7C7C7C000000008A +:208E800030303030303030307C7C7C7C3030303030303030303030301C1C1C1C00000000B2 +:208EA0000000000000000000666666666666666666666666666666663E3E3E3E000000005A +:208EC00000000000000000006666666666666666666666663C3C3C3C18181818000000007A +:208EE0000000000000000000C6C6C6C6C6C6C6C6D6D6D6D6FEFEFEFE6C6C6C6C0000000042 +:208F00000000000000000000C6C6C6C66C6C6C6C383838386C6C6C6CC6C6C6C600000000E1 +:208F200000000000000000006666666666666666666666663C3C3C3C181818183030303059 +:208F400000000000000000007E7E7E7E0C0C0C0C18181818303030307E7E7E7E00000000D1 +:208F60000C0C0C0C18181818181818183030303018181818181818180C0C0C0C0000000051 +:208F8000181818181818181818181818181818181818181818181818181818180000000031 +:208FA0003030303018181818181818180C0C0C0C1818181818181818303030300000000081 +:208FC0000000000076767676DCDCDCDC000000000000000000000000000000000000000049 +:208FE000000000000000000000000000000000000000000000000000000000000000000071 +:00000001FF diff --git a/Sega - SG1000/sg1000.qpf b/Sega - SG1000/sg1000.qpf new file mode 100644 index 00000000..c0a2f737 --- /dev/null +++ b/Sega - SG1000/sg1000.qpf @@ -0,0 +1,30 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Full Version +# Date created = 20:36:09 September 21, 2018 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.0" +DATE = "20:36:09 September 21, 2018" + +# Revisions + +PROJECT_REVISION = "sg1000" diff --git a/Sega - SG1000/sg1000.qsf b/Sega - SG1000/sg1000.qsf new file mode 100644 index 00000000..7c9e75b6 --- /dev/null +++ b/Sega - SG1000/sg1000.qsf @@ -0,0 +1,76 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Full Version +# Date created = 20:36:09 September 21, 2018 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# sg1000_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name TOP_LEVEL_ENTITY sg1000_top +set_global_assignment -name ORIGINAL_QUARTUS_VERSION "13.0 SP1" +set_global_assignment -name PROJECT_CREATION_TIME_DATE "20:36:09 SEPTEMBER 21, 2018" +set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1" +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1 +set_global_assignment -name NOMINAL_CORE_SUPPLY_VOLTAGE 1.2V +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name VHDL_FILE rtl/vdp/vdp_sprites.vhd +set_global_assignment -name VHDL_FILE rtl/vdp/vdp_sprite_shifter.vhd +set_global_assignment -name VHDL_FILE rtl/vdp/vdp_main.vhd +set_global_assignment -name VHDL_FILE rtl/vdp/vdp_cram.vhd +set_global_assignment -name VHDL_FILE rtl/vdp/vdp_background.vhd +set_global_assignment -name VHDL_FILE rtl/vdp/vdp.vhd +set_global_assignment -name VHDL_FILE rtl/psg/psg_tone.vhd +set_global_assignment -name VHDL_FILE rtl/psg/psg_noise.vhd +set_global_assignment -name VHDL_FILE rtl/psg/psg.vhd +set_global_assignment -name VHDL_FILE rtl/t80/T80se.vhd +set_global_assignment -name VHDL_FILE rtl/t80/T80_Reg.vhd +set_global_assignment -name VHDL_FILE rtl/t80/T80_Pack.vhd +set_global_assignment -name VHDL_FILE rtl/t80/T80_MCode.vhd +set_global_assignment -name VHDL_FILE rtl/t80/T80_ALU.vhd +set_global_assignment -name VHDL_FILE rtl/t80/T80.vhd +set_global_assignment -name VHDL_FILE rtl/spram.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sg1000_top.sv +set_global_assignment -name VHDL_FILE rtl/dpram.vhd +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Sega - SG1000/sgcpu.png b/Sega - SG1000/sgcpu.png new file mode 100644 index 0000000000000000000000000000000000000000..663c8d619c4b28acb95f06d7b755e4872acf8235 GIT binary patch literal 8216 zcmV+zAm`tSP)zO(E`{83wU5+rgWkxN@O z9W+hsG)3daG0$)d`$rNh3R5c*MJ^@AvRx%qfCNo|#5&ap9JB@Gpe`b#vbdzviVfh1 za*UcmXmM2ukrXN7Q9Sd$c6U1O%zn&%+y`a;Xn?$c#oe8~XXopg=bd+E*FaX<)EKO| z{Q>g-H6$#ngXHS~4PRd;ny!c$Q(^0MLF#g?l!ykmI48^ML-lIePE?l#dA4@a0a6;i9>~|~CFwoa19_l!(ph4r zEy!gxPoj2G5+s|gD>ZD;rztB8DcJ7`T)s~jZuPHa1x8VRGON5NMgw$>>6cS}flZFL9 zw8J{6dmn{V?~W!)%gACQivdwmr2;!%Q}^M^fRtciMUY&`@@o4qzO+J+4trpw>XSCl zud)|re)WZqJ<+~$kaLGSOYy@q>StFDQdQ_*edE8b93)XB`B?e!!%F!*rhV0@F^GKG zKFDcxAt9b4@w^WcP+%&x-pRrHP#j&iDHab{}(}%`S zKwU_q+k2ioeBlAmy6jV3%y0!tNrYOJRqH{@{^4Hz%?E@t-w*TaDSHx|RIukgVMA3l z67igq@gKcx^h%D{OKR3hYXNN&NKD2kdzj}IHuzml#mbWKEa|Wg(O2D!5}8O~J)r_> zpU9q>_^ly`^fA}sV%bY(#e0J>;wH1+BOCihfK|!trN^8k!D&D8l%eMjDg0#W_<;0x z7j{4mdAIHckgbMYT;yR~qhvoK7L}ISnmlhdzMJ*JyJ+FG7DbzaN1tGVLyL5Q8YKvVvnso#d5ji z9U+)qS!d{%x(a{9emK>ckRG`WM>d1VY-q2pk|3eSO2AlXv8U&8R?D!k>&HPrfDX!@ zbH7aSNpL~yjK8L0ba~;~C)kxZ#aWCQ^xtme4PHv=oh+$HUVXV^%}>L8;q>l*xm=y+ zU45RjM~C!Ns-1p|Nvf>JJM5Y3VeBD$-!a~Piv(I6+4DsE$DXtxIeX~Er{*Xtkv)X6 z=K_Ot*wew;Luju|h1BIF+yVRlQhu48jPB&xLmPVZXKV4wf|Bfq!Vj}hme0b}7S5h= z06se-iG^D)1|SWSvL^#vYz9$#Her}1DyiMryrkz)zmD-LWMRo-&pR0nAtP`@1%ikm zA8!L#v-UO~@t^5}srTbS8z^j4NYT0H4PYq9LQrMSp3NEv^PXWpWL1aQI#}c<`=CVB zG z7gG<>o`Itp>+0pBTOg#xkMtVG&3Y`V;R$NbU(N3jk}o~*=W^VjU0l?jPkjm)WQ|3f zVbG%eJ1iHVP=WX7n06q zOBW!;N|>d;WsP6%<&Z=<5zd|u(-AS6pu&@Hvo@mZK z8C5C^cRq@N2raGbjk9Ypbt_{}ubR8q&e?M+2i$YpKu0&9(IL%%DEiU-d{Eh)JUpTB z6Uz^l)Yd=2^3$%BZ|CgckD{L2=FMTAn@p#WYyMib&RPIYuz^5&^e)C8`q+_wdKU%bxG`g)xHJbI@5lh1?ckPtpz+Gxm6F$)`P9Cg+D+q`uh^_>z9IqHJExN$-Qd+8*C-1e z?MdcXF6m@PcGu*1;ds13`@ZoZtKif{@oJBV36Az)CNW}7lqW)OrQZ1doOL(~imN?f zJvPh!mhVnx{qvrd;7G*hHc=wmDTBKq`C{L<#Cz2pe$6bbTs9;`Ay1s%OcKuZt`i* zJM9&6tt&V+oc5fVhjO8?Rn7Sxlw&2DO5P7J@&k3J8;jf ziRGxmkl%Ad|M7x>(0yZy?YVUThn(Ad_T+U`s-xP3;hwI}c2obVT1s4AFu|uxs zmTy}e>j&+2&O$rprt*RlNEq$E4MG~?37hxaYZV-|N4trr{kpoH&wDC<&+R>MEhLw0 z2ym>W0LSmKj!}EmZaV62D2)QLP*$Kh&rJwzFwgCkpShkJQA}cO{-7*WmRg&e_ZYr; z&x_#d36VUJo7pa3)F85ncA`MR1KI{Ryt=@|4d0VE3l!cD=0F&b)+52*QeB2u~ zAUtZYt9@%b-)puvYI|-Kj1-VDbm`7i@%G}h>$%-xM-4ukp9(8EB%?2EzrvlT(Lvza zL!j`(hZuY8c_(FIE}!zUNBS;#;H5A~>bcp6$etHB@y#6?XAkwfSPdeM*5&csB5-4k znQ0rO%3W{rW9qq0wO~!Qg0VwJ_Ry1d3>Bj1ma*8wBfz0CH(r-M&#g!B+`dT+L%4Z9 zB<5y@Od@?I9p2zZ4FX{$FMEEs`Snd#8zTDH<4g3#+!h~+?|=q|+LJwE=a;gF&IjYJ z_RM@3ue&ifEqoc%V}(J8PpH<(D%>!JQ-BLBYS8y&Zi^i?01l~2N{V=4C4a#thu#U% zp11Lcve03VH3So7P@c9o7uZpQKsNPwnD$&@Tvi>=t;f@h15*ll`)=G3l4jgI-hcy&GdDaPEa zr~xy|9!c#_zGKDQ?mJvtjQ0^>$Uhn6Bai>nxOJ1KZ>ls!~?F0nf3c|2$8*gahK zl;}TCD`$W=ltmnrqV#7>yV)l(HOQU<6+(*RXAiBE-E_vF05+7CvAPr1qV_C?cDc2L zvS$V-@)E|}n9p18%kf-lwN`wRi*IMFcnNBck3EETvJU}cVQv%#fU(C4HmWTxIzb1AaNh|$W?Zjz!<#gWMJ+!6?7FB2>D2TBMcw8>zktc{ZCK#ulo`54z8vpSF3b5+ou#l>+!dz#*| z2FM;qdwOG*_FO#HWwQsb<7%n;*=8YYum@NBID4?^Q@j^7TbCkxaPg3_hc8Sr_Ao2U z7#FXz*Wd%K?#XCHC%aDuv}c{pSg5i~$R0BYnN^)bqa;AmNg^Tr54ab!o096BaRsm= z=J+KXC%=Bu-{OXg2=d$Ogp^XkgmGc7f!e)rsJ~sqLo2GsR!a}Cam}%_KlsX+>S9*4 z+uby(Jvte3qXtxa(y}%0vG)Kt+T;E#xs}L5(XRgIc8~Uy4?pTAhEXnzJ+TxB87uAa z&U=!Nc(o^Jls$^%X`ThOSKWqd6Wq->vd7TpKRJs*V3_Ls_5iGUz@t4EE$wlQvIm#& z1jsg}suZZ-Y`Gc3umI$R96K&(O8^J@Jld0{^B!+pjj{(7On{V>-E=ZYQ!FpekRP_S zXL6?=#-3U4u4gM*tjmvG>Ic!|vDH?0(=JyHQYR+cp{WU3Ed^;AU?_P)rgZ**rK zJv>EZPc`nv6FfK9%xlw%N?jqloulO513Y7cpn)0Xl;)=0L@+KULLz&HqPskhI;a$3 z)fL;nYKwLmxhy-JxsQ@V>{4p?wFIm$i*|2UN&m~*1*fb|;mkBDt1x-@ny|4e)N}K_hESHz zsCFlsn26lH)CTNF-ISDAo24sGXTq%pRAW@duRR_@B72BkaH6O>tidBTUh=M<7y1nP z@g(PEPm)efJ?j9-p06IAahfLrDr)I!l+Y;Xq0wkY)+?m3%ku)ZvhWbmEcpvL^$cF_}Y| zBckV)wvp_zqGy$0e=R2Hag_pLB^JvY;y>uSy|W+ZyviaPHDvqV&3#?CS< z)nSilYNvgq$2{!u>~m|zb2F@562%R?)QVU`9nWoKm(L4^&LwG|HL&77w=2>IH9Vf` zym3j&=G^-NF$Of$9&lUSP#~e;S$0g>qsIjgIsBDS${yGKFRy;eidnao zB+1@eo&KDp@uQ&U77EF8&moiKC0^xNW@0Of_WhBVjdEpO&DB!dWXhg5a)G+^SQ6yz z9A$LpO%*bth_bzKaKG>NPRgES)~!ox=wQDIE zAY%uEaIH=fRz3N$+3CF-&#E6yrj(yyBcTM)xv~td~)u6gl&iNph z9W_X1z5Cq6r~x-odm7qQXDQ{|y>{u538J@p!ikhUajn!OWI;=$06jPR9k=9;^aO4b z^$0IzPx*eoe|ej~ES62~oZ@>8oMz^pTg(dy;3}kLBrMF#jqNqaxxbDx?eQ7z?({+G z;%G3rQS{uNQ>gZ6?m)@HSc6`dHDulcVw?aBkLR`oam~XXv@N>iZ42|ur|QLthr_dls^}2BUfyWK66ZYqd0{0J3KYlB$|n zKBV-LB?Sv(%7iSemQL;*#k~gd@*$&H>ww7k@{absJ8qxd#BtbOgXS!}dH8EQY_)Wq z0({=%Gtc`yO+fP3ctq_9nCJbTCLp=B!J5^nB2&egt-iMjIzc#OTFEuW5v;JjOLjx;xA2=#bapv~5(EupLbE@Wn$y&T|};fw8! z=l=$FsMg7dZ96Qr|0Bd?5Wk(rojR_qed?faHaY&K=ydd#(|kD31G%{Omy! z`(;V}VBGIv)L{<`$&~wK|4es>y6}m6t)HRi)^U2{9WSE{B`zk+fm5pW2y13(WTIKH zAHsAXdiaQMBr;TpAGQn6*)xBJDcgY786EShVzmD&hiomdhFW}oEHGZW^fhG49y9eO zmMD@D*#l>-jqGb3b3_F>Q|VJ1vM29{#C|CYPr(1?*f(tG<4s&F;OvQJtviH4owKK3^0zo` znp@p9SjL`d=64+YL{|i5(Ze3&$O{>_G8ua&0_>UXO4u*9pfUC^W1%eiFb{j8=Y*45 z>~Y4+FvA7k=Ga3r(=#7G^PMkZ0cF|*o=03yR->t_*+STpvF ze&O5hWMHJ5^|bEu9k%wo#I`SVJ($W&O=WG!@WL(G?5SwN$CjS@5p2XYtcuMZqOn|_ z`L~32#d#gabP9LALx7y^EK~AO_Czu|Ozcyv%WWVZr;uki+S;SAerYJJf9Cwu{JLtl zxTyaol{37I>=B3LR(!cLPRnnx=W}meL`c;92(}VFI(oo~FuNPgDSMvg#YOhyp~opn z0$=Xz>mKQ~*mKfiPqa04=4V?ahM>9Ow@KNBr0ijvq_j<@Zzp>xPczu zuS?5}RRa@Nw31sCZtggnA#XD6sVrf^8?xs`5XZ}fZ{ZgADFAz;MK>g;$tk|HF`(!e zS29rq$EBX3ASBOBYPwxm_DE+*3=%u2c%uxkUiOs~x_4Njh;C~S$(qq1AlU553J%P0 zHYe$~{Tg7^7(b;*UvNsqBi2lN)c#V~oXpamY0u6A<+%Sg)B$TIe^X@vUuZ7HYmIN5 zJy+I=kWpxj`gYN2v>xZN++ZrZS&Xh!b9WeL&!ZmCtqlUN-Sys4ND;QlntE;t>?Zm3 z_=yZP1hSUr=35w#Ua*f)d$3ZqO{=o6ja>#UYs@#<4 zW;}4Q4rIx*n)RGwX-}=&IeUsPxw(|U-!t+cyhCL!x!NOmZh~?4WR-da_e6>gTH4)c z-lGcanLpKA6C6bCsd>kBuqUp-^5#AH@w&N0qn)`Sd%W7?w=2-0|E`P044C#HTtn@7 z;dZw!=K^wq?h83(r4PiQDfX<%)LNCI^^9SIJ&>}}BN(xE*%M}rJ#j%Oyfqmm3TlrK z0=6R7<(h~!<~@Fkh+)j;<~^wfkdl_NqR4FCleO6sq?*m1hb}Z&;gcpFwOah(GldAg zBix8R=(&j#EJ+Bcun*>V_gF8{OUL*NJ|~FZO8D{=dZfZPb)aq+LBkuHV~>$Md)x2Q z=ufrPhcq4S38NZk&wUbV54m^a+n2(wREBI;dDvB#iZPxCZdb~O9adzWzb3b)xo4cp4;X-zJ z%+3AOp=0*CT!YaW9M4T|BxhZAiysVqCr`AX=LYT?scX^m_N>YOxqzUBdTvdvk=8V< zA+~$5&R&CMnj2gZA!%Ejy_wc>Ia3T>x~psM%B2XIdLxq@e46I}t=fn+-$Qk|DnjBK z>2`Kxl|p=5yZO&3i;(sjsnKP{f`X$&&8nB`-xJLR`@Egh#3lwmq>5n}7QbUJ!CjB} zAQ$%FziYcR@!}|mG0Vm#=m%A!Mf-z9RC`X?A0nFHd+KYoG$&}Pzu+N52d+@mT6hez zKwUD(yYVAW<97?|p4SP9You)RBH8cH>vGuS%O&q4B$hv)B0~jx*!9OOmjQ`vkziP% z5TiNw^0)ml%LXR2ReqRUOQOG4O70q;Yrc)^w>alj{H5cWM}^^KQa zQ>?!|Jt33&W(v;x5S`THAKYlYBHH7%CcZ}zX0@thPOQs!GZOhsxt>gVAYU6ZsQa$>^V+Oat#zSaoR|D8(z>GC0IT~=ESg0t^%Ya*2GGYY8} zVqm`_vl15b?WGS`SbVJ^WWIfMarLyjYmM8x_E%sc0T`uqcV%ZeribV}v`vc_4+5Z6v74)xxp_4}d0000< KMNUMnLSTXj&sT;3 literal 0 HcmV?d00001 diff --git a/Sega - SG1000/sgio.png b/Sega - SG1000/sgio.png new file mode 100644 index 0000000000000000000000000000000000000000..3d62c98213e0b5a39d7ecf2d9526a3ea473721ed GIT binary patch literal 3214 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 AbpQYW literal 0 HcmV?d00001 diff --git a/Sega - SG1000/sgjoy.png b/Sega - SG1000/sgjoy.png new file mode 100644 index 0000000000000000000000000000000000000000..4d374b1abbc103df195d7cbae68e040dc6556b02 GIT binary patch literal 3835 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 bZ({xfkZ5$*Z_5zx00000NkvXXu0mjf9>+N7 literal 0 HcmV?d00001 diff --git a/Sega - SG1000/sgvdp.png b/Sega - SG1000/sgvdp.png new file mode 100644 index 0000000000000000000000000000000000000000..06abf901f8a56fc8615b78954a58fa7367da1870 GIT binary patch literal 8252 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